jueves, enero 08, 2015

API Hooking para inyectar DLLs .NET con NetInternals

Probablemente todos conocéis o habéis escuchado en qué consisten las técnicas de API hooking que pueden ser usadas por rootkits o que puedes usar para analizar el comportamiento de binarios. Para quien a ni siquiera le suene, ésta técnica consiste en la modificación del flujo de ejecución de un programa para interceptar y/o modificar su comportamiento mediante la alteración de los parámetros de entrada/salida de la API que se esté hookeando – ¡Bueno, realmente no tiene por qué consistir exclusivamente en una API, pudiendo ser cualquier función existente en la aplicación! -.

Figura 1: API Hooking para inyectar DLLs .NET con NetInternals

Personalmente, esto es algo que siempre me ha llamado la atención debido a la gran cantidad de ‘hacks’ (¿Alguien ha dicho latchear API’s?) que se pueden realizar sobre un software, por lo que llevaba bastante tiempo pensando en hacer un sistema que permitiera interactuar a bajo nivel con procesos de Windows. Por lo tanto, en mi idea inicial se encontraba que permitiera, entre otras cosas, realizar hookeos a las API’s que utilizan los procesos remotos, y así hace unos meses me animé a iniciar NetInternalsDisponible en un repositorio GitHub - , una librería en .Net. ¡Aviso! El proyecto se encuentra aún en una fase muy inicial de desarrollo.

A continuación paso a explicar un poco más a bajo nivel pero muy brevemente como actúa la librería para realizar el proceso de hooking. El primer paso consiste en la ejecución de código en el proceso remoto. Para conseguir este propósito se realiza la inyección de una librería. El procedimiento es muy sencillo, con la ayuda de la API VirtualAlloc se reserva espacio en el proceso remoto para cargar la ruta en la que se encuentra la DLL que se va a inyectar. Posteriormente con WriteProcessMemory se escribe la ruta física de la DLL en la dirección de memoria que se ha reservado, y para finalizar se lanza un hilo remoto haciendo uso de CreateRemoteThread sobre LoadLibrary, pasándole como argumento la dirección de memoria que se había reservado.

Figura 2: Inyección de una DLL no manejada

¡Hey! ¡Un momento! ¿Y cómo dices que ejecutas código .Net (código manejado a partir de ahora) en un proceso no manejado? Sí, esto es posible mediante la inyección de código no manejado que cargue el framework .Net y posteriormente cargue la librería manejada (.Net). Ésta técnica está muy bien documentada en el artículo ‘Injecting .Net Assemblies Into Unmanaged Processes’ de Pero Matíc, el cual recomiendo. En la siguiente imagen se muestra cuáles serían los pasos para la carga de la misma.

Figura 3: Carga de código manejado desde código no manejado

A partir de este momento, el código manejado se encuentra cargado y en ejecución en el proceso remoto. ¡Es hora de realizar el hook! NetInternals realiza la técnica de ‘InLine hooking’ la cual consiste básicamente en la sobrescritura de las primeras instrucciones de la API para lograr un salto a otra zona de memoria.


Figura 4: Primeras instrucciones de la API "send" (WS2_32.dll)

A la hora de realizar el hook, NetInternals realiza distintas acciones. Una de ellas es la sobrescritura de los primeros 14 bytes (MOV EAX, [dir] y JMP EAX) de la API original. Con esto se consigue llevar el flujo de ejecución al código no manejado desde el cual NetInternals hace la modificación de los valores de entrada/salida de la API.

La segunda tarea a realizar es devolver el flujo de ejecución, pero tenemos un problema y es que al hacer el JMP a nuestro código, hemos sobrescrito código de la API que no se ejecutará nunca, por lo que será necesario antes de haber realizado dicha sobrescritura realizar una copia de la API original en otra zona de memoria. Esa copia de la API ejecutará las primeras instrucciones (contenidas en los primeros 14 bytes) y luego se le establecerá un JMP a la dirección de la API original más 14 bytes, que son los que se han sobrescrito. De este modo, cuando nuestro código manejado finalice la ejecución, hará otro salto a la dirección en donde hemos realizado la copia de la API, completando así el círculo y consiguiendo un correcto flujo de ejecución, como se muestra a en el siguiente gráfico.

Figura 5: Flujo de ejecución

Pero aquí no termina todo, ¿Qué facilidad aportaría NetInternals si hubiera que implementar la funcionalidad del tratado de las entradas/salidas de la llamada a la API en la propia librería? Exacto, ninguna. Por ello, y complicando un poco más el flujo, NetInternals es capaz de ‘migrar’ el flujo de ejecución a un proceso remoto mediante el uso de Pipes para la intercomunicación de procesos mediante WCF (Windows Communication Foundation).

Figura 6: Migración del flujo de funcionamiento

De este modo, desde una aplicación externa que haga uso de NetInternals es posible realizar todo este proceso con apenas un par de líneas de código, y obtener en el propio proceso las llamadas a la API que está ejecutando un proceso remoto.


Figura 7: Modificando las entradas/salidas de la API

Para terminar me gustaría mostrar un par de capturas de pantalla de una pequeña aplicación que hace uso de ‘NetInternals’ (Aplicación incluida en el proyecto de GitHub) para la interceptación y modificación de llamas a la APIBurpSuite Style’.

Figura 8: Editando memoria del proceso remoto

Espero que os haya resultado de interés o que el proyecto os sirva para alguna idea que tengáis en mente. ¡Un saludo!

Autor: Manu "The Sur"
Eleven Paths

5 comentarios:

  1. Buenas, entiendo que con esto sería realmente fácil hacer "desktop scrapping" o incluso un keylogger capaz de ver no sólo las entradas, sino también las salidas (los valores de salida escritos a un textbox, por ejemplo). ¿Me equivoco?
    Saludos

    ResponderEliminar
  2. Hola Javi, no entiendo bien que quieres decir con los valores de salida escritos a un textbox, pero si. Cualquier llamada que haga puede ser analizada, o incluso modificarla si quieres alterar el comportamiento de un textbox (que al apretas la tecla 'a' te escriba 'b')

    ResponderEliminar
  3. Es similar a lo que estuve trabajando en otro post solo que esto esta mas avanzado y de verdad te ha quedado muy bien!, Me gusta! espero poder seguir hechando mano y probando, saludos!

    ResponderEliminar
  4. No es por desprestigiar el proyecto, pero no entiendo la innovación, ésto es bien conocido(exageradamente) en el mundo del game cheating. Cualquier foro de informática tiene exactamente la misma información desde hace muchos años.

    Un saludo

    ResponderEliminar
  5. Anonimo, desprestigio ninguno. En ningun momento del articulo se habla de innovación, sin embargo me da la sensación de que no lo has entendido. El articulo no solo hace un API hooking, sino que explica como esta libreria, framework o como quieras llamarlo realiza el hook para facilitar el desarrolo de los mismos desde aplicaciones externas. Proyectos similares para desarrollos en .net que permitan lo mismo que este solo conozco Deviare (codigo cerrado y de pago) y EasyHook. ¿Porque no nos dices cuales más existen?

    Saludos

    Saludos

    ResponderEliminar