4 dic 2020

Herpaderping: un vistazo simplificado (Parte II)

En un post anterior vimos un nuevo exploit de Windows que permite ofuscar procesos maliciosos sin ser detectados (al menos por algunos antivirus). Una vez comprendida bien la vulnerabilidad y cómo funciona por detrás el exploit, vamos a la parte más sencilla (y más divertida) que es usarlo. 

Cómo usarlo

Pues el primer paso es clonar el código de github y compilar el proyecto. Una vez compilado, ya tenemos el ejecutable ProcessHerpaderping.exe.

Lo primero que se mira siempre.

Para usarlo, es necesario indicar la ruta al SourceFile, que es el programa que queremos ejecutar, y la ruta al TargetFile, que es el fichero intermediario que va a usar el exploit para copiar el código del SourceFile, ejecutar el proceso y sobrescribirlo con un patrón (por defecto) o con un binario elegido por nosotros como tercer argumento (ReplacedWith). Realmente no es necesario ni que exista el fichero TargetFile. Con especificar cualquier nombre, el exploit se encargará de crearlo si no existe (y no tiene por qué tener una extensión .exe). Ojo, que aunque la opción del patrón esté por defecto, es necesario configurarla nosotros en el código. Si no lo hacemos, el exploit simplemente sobrescribe el archivo con la cadena "roflroflrofl" hasta alcanzar el tamaño del original.

El objeto Pattern simplemente es la cadena "rofl" en hexadecimal.
Si nos queremos currar un patrón y dejar niquelado el exploit, hay que añadirlo a partir de la línea 296 del main.cpp.

Así queda el archivo una vez sobrescrito.

Algo similar ocurre si marcamos la opción -r o --random-obfuscation. En ese caso, el exploit sobrescribe el TargetFile con una cadena de bytes aleatorios. Desde mi experiencia, la ofuscación con patrón o con números aleatorios (únicamente) no da buenos resultados (aunque todo es ir probando). De alguna manera, Windows Defender sigue detectando el proceso malicioso, lo que me lleva a cuestionarme si es por culpa del patrón en sí o más bien del proceso interno que sigue el exploit a la hora de sobrescribirlo, ya que en este caso no hay firma ni nada. En cualquier caso, vayamos a la opción más cómoda y más efectiva, que es la de pasar como tercer argumento la ruta a un binario confiable. Después de realizar varias pruebas, os advierto que no sirve cualquier binario "no malicioso" para engañar al antivirus. Los que mejor resultado dan son aquellos que van firmados, y los que son infalibles (por el momento) son los servicios críticos de sistema: lsass.exe, csrss.exe, smss.exe, svchost.exe, wininit.exe, etc.

Pongamos como ejemplo la ejecución de mimikatz.exe, hoy en día bloqueada por la mayoría de antivirus. Supongamos que tenemos un binario, que no ha borrado el antivirus, pero en cuanto lo queramos ejecutar lo detectará y bloqueará su ejecución (y en ese caso seguramente lo borre también). Lo único que debemos hacer para conseguir ejecutarlo sin ser detectado es llamar al exploit de la forma siguiente:

Herpaderpeando mimikatz.
Ejecución exitosa con Windows Defender activado.

En el momento de la ejecución pasan dos cosas muy curiosas. Si inspeccionamos el proceso (con process hacker por ejemplo), veremos que el proceso hijo creado, "soybueno.exe", presenta el logo y la descripción de mimikatz pero está firmado por Microsoft Windows Publisher

Inspección del proceso creado con Process Hacker.

Propiedades del proceso.

Si inspeccionamos el propio fichero, veremos algo similar, y además podremos ver que el contenido ya está reemplazado por el del binario que pasamos como tercer argumento. Si no marcamos la opción -r, se añade el patrón (por defecto "roflrofl") hasta alcanzar el tamaño del SourceFile, en el caso en el que el binario utilizado para reemplazarlo sea de menor tamaño. Siempre es recomendable añadir la opción de random-obfuscation para que el fichero se rellene con bytes aleatorios, o mejorar el patrón de ofuscación.

Propiedades del TargetFile en disco mientras se está ejecutando el proceso. Descripción y logo de mimikatz pero firma de Microsoft.
Propiedades del TargetFile en disco una vez cerrado el proceso. Descripción y firma de lsass.exe.

Por otro lado, mientras se esté ejecutando el proceso creado, sigue siendo posible ejecutar otros procesos en paralelo simplemente haciendo doble click en el TargetFile (si le hemos puesto una extensión que Windows reconozca como ejecutable obviamente). El proceso padre ya no será ProcessHerparderping.exe, sino explorer.exe (el explorador de Windows), pero el proceso ejecutado seguirá siendo el del SourceFile. Esto es realmente sorprendente, ya que, como hemos visto antes, el archivo a esas alturas ya está sobrescrito. Al autor del exploit también le llamó la atención este comportamiento y, tras investigarlo, llegó a la conclusión de que los datos en memoria de la imagen cacheada (image section) que se utilizó para crear el primer proceso se reutilizan para crear los otros procesos (se trataría de una especie de optimización), aunque estos procesos sean independientes unos de otros. Recomiendo leer la explicación detallada del autor para entenderlo mejor. Una vez cerrado el primer proceso, ya no es posible volver a ejecutarlo ya que esta vez se utilizaría el contenido del binario ya reemplazado.

Ejecución de varios procesos en paralelo a partir del binario en disco.

Dos nuevos procesos se crean a partir del proceso padre explorer.exe.

A raíz de este descubrimiento, el autor añadió la opción -e o --exclusive, que lo que hace es no permitir que otros procesos tengan acceso al TargetFile mientras el primer proceso tenga abierto el handle, que además se fuerza a que se mantenga abierto el mayor tiempo posible. Puede que sea por esto último (o por otra razón que habría que investigar más en profundidad) que Defender acaba detectando que el proceso es malicioso si se utiliza esta opción (al menos en el caso de mimikatz).

Utilizando la opción "exclusive" da un error al intentar ejecutar otros procesos en paralelo mientras se está ejecutando todavía el primer proceso.

Finalmente, el resto de opciones no afectan directamente al comportamiento que ya hemos visto, ya que son sólo pequeñas modificaciones en el funcionamiento a bajo nivel del exploit. La opción -u o --do-not-flush-file evita que se llame a la función FlushFileBuffers cada vez que se realiza una operación de escritura. Esto se suele hacer para forzar al sistema operativo a que escriba los datos en disco en vez de almacenarlos en un búfer interno. La opción -c o --close-file-early fuerza a que se cierre el archivo (el handle) antes de crear el hilo del proceso. Esto modifica el orden por defecto, que es write -> map -> modify -> execute -> close, por write -> map -> modify -> close -> execute, pero en este caso el orden de los factores no altera el producto. Y finalmente, la opción -k o --kill, que tiene sentido si queremos ejecutar un proceso que se ejecute y termine de forma automatizada, pero que no sirve de nada para programas interactivos.

Una vez hemos comprendido bien la vulnerabilidad y sabemos cómo utilizar el exploit, sólo falta experimentar un poco con él y aprovechar el potencial que tiene (que no es poco).

Saludos!



No hay comentarios:

Publicar un comentario