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
NetInternals –
Disponible 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
API ‘
BurpSuite 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
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?
ResponderEliminarSaludos
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')
ResponderEliminarEs 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!
ResponderEliminarNo 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.
ResponderEliminarUn saludo
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?
ResponderEliminarSaludos
Saludos