Una de tantas técnicas que usan algunas muestras de
malware es la conocida como
API Hooking aunque en este artículo lo que me interesa es darle una función buena a esta técnica para poder facilitarnos un análisis a alguna muestra de software malicioso. Vamos a repasar un poco antes para entender el proceso.
Introducción
Los procesadores
X86 de
Intel y compatibles tienen
4 niveles de privilegios que son conocidos como "
anillos" o
Ring 0 a
Ring 3. En los sistemas operativos
Win32, tal y como se explica en el libro de
Máxima Seguridad en Windows, solamente se hace uso de los niveles de
Ring 0 y de
Ring 3 y donde nosotros trabajaremos con las aplicaciones será en nivel de usuario que es el conocido como
Ring 3.
Ring 0: Mayor privilegio (nivel kernel del Sistema Operativo)
Ring 1
Ring 2
Ring 3: menor privilegio (nivel usuario)
Cuando trabajamos con
Ring 3 estaremos invocando a las
APIs del sistema
Microsoft Windows de nivel de usuario que proveen la funcionalidad del sistema que permite a un programador hacer que un programa funcione sobre este sistema operativo. Estas funciones de la
API de
Ring 3 cuando necesitan un acceso privilegiado lo que hace es entrar a nivel
kernel Ring 0 a ejecutarse, y después retornar a nivel usuario para de esta forma aislar el programa del nivel de
Ring 0.
Ahora bien, crear un gancho o
Hook para alguna función de la
API es simple y existen diversos métodos. Uno de esos métodos que es muy sencillo pero a la vez muy útil es el conocido como
Método del Columpio, que se basa en inyectar una librería
DLL al proceso. Se le llama así porque la primera instrucción que se coloca al iniciar la función de la
API que es una redirección a nuestro código inyectado.
La idea con
API Hooking es que si podemos enganchar no una, sino todas las
APIs del sistema, por ejemplo las de manipulación de archivos o las de conexiones de red, entonces se podría crear un registro en un fichero
LOG con todo lo que va modificando el binario cuando se ejecuta, tal y como hacen herramientas de análisis profesional de
malware. Esto tiene algunos pros y contras ya que me he encontrado algunos bichos que detectan y eliminan algunos ganchos ya que es una de las técnicas para poder evadir algunas
sandbox de análisis de
malware, por ejemplo la famosa
Cucko Sandbox.
Un ejemplo de API Hooking
En este ejemplo vamos a hacer una pequeña prueba para monitorizar un supuesto fichero malicioso para guardar en un fichero todo lo que haga en nuestro sistema relativo a ficheros y claves de registro. Comenzaremos con el código de este proyecto que se encarga de incluir nuestra
DLL dentro del proceso del
malware. cargando el proceso suspendido con la función de la
API CreateProcess.
En este caso el proceso será nuestro supuesto
malware al que he llamado
virulo.exe. Posteriormente hacemos espacio en el proceso e incluimos nuestra
DLL con
VirtualAllocEx y
WriteProcessMemory. Para terminar se crea un hilo en la
DLL que inyectamos y con
ResumeThread conseguimos que siga ejecutándose el proceso suspendido ya con la
DLL que se encargará del resto:
|
Figura 1: Inyectando la DLL |
Ahora pasemos al código de la
DLL encargada de hacer el gancho donde lo que está remarcado en rojo es quizá lo mas importante para entender cómo funciona. Lo primero que hacemos es obtener la ruta donde está ubicada la librería que contiene la
API que nos interesa y así obtener con
GetProcAddress el offset de la
API. Posteriormente hacemos una llamada a “
inyector” que es una rutina que he añadido a la
DLL para poder enganchar varias y no solo una
API, aunque en este artículo no entraré en tantos detalles. Los parámetro que pide y su contenido son:
|
Figura 2: DLL que hace el hook de la API |
Direcciones: El offset de la API.
Bytesoriginales: Dirección del buffer donde guardaremos los bytes reales.
Bandera: Contiene la dirección a donde queremos redirigir nuestro gancho.
Como verán, el código esta comentado y básicamente lo que hace es guardar en uno de los parámetros que coloqué los bytes originales para mantenerlos y si queremos después volver a colocarlos en su lugar.
|
Figura 3: Parámetros para volver a reparar el estado |
Ya guardado todo, pasa a cambiar los permisos a escritura a la zona donde se inicia la
API que queremos enganchar, pues para poder escribir los primeros bytes debemos cambiar el permiso si no saltaría una excepción y no pasaría nada. Después escribe algunos bytes, como son
0x68 que es el offset de mi redirección y
0xc3 que corresponden a un
“Push + dirección” y un “
RET”. Esto podríamos verlo dentro del
debugger, por ejemplo en la
API MessageBox.
|
Figura 4: Cambiando los permisos y hookeando la API |
Esto es básicamente el gancho y ya tenemos
hookeada nuestra
API lo cual es un columpio hacia nuestro código. En este momento podríamos hacer algunas cosas como registrar todos los movimientos que hace. Apoyándonos con el
stack o pila en una
API que de acceso al registro como
"RegQueryValueExA" podríamos ver en la pila:
|
Figura 5: Valores en la Pila del proceso |
Recuerden que ya estamos en el mismo proceso por lo tanto manipular los parámetros que tiene el
stack es simple pues el registro
ESP contiene siempre el inicio de la pila. Sumando un
ESP+4,
ESP+8, etcétera podríamos obtener los datos de qué es lo que lee, crea, etcétera la
API o las
APIs hookeadas y hacer un registro de acciones realizadas por el proceso, que era la idea principal de la herramienta, pero también podríamos jugar creando filtros para saber exactamente en qué parte del registro hace los cambios, por ejemplo:
|
Figura 6: Filtrando los cambios en el registro de Windows |
Si queremos restaurar lo que hemos hecho para que todo actúe otra vez normal sin ganchos o redirecciones, podemos hacerlo entrando a otra rutina que nombré como “
repairbytes” cuyos parámetros son:
DireccionesAPI: Dirección de la API a restaurar.
Bytesoriginalesencurso: buffer que contiene los bytes originales que guardamos.
Esta rutina es similar a la anterior que escribía al inicio de la
API, solo que en lugar de guardar los bytes originales, los saca del buffer y los ubica donde estaban originalmente:
|
Figura 7: Para dejar el sistema como estaba |
Las últimas pruebas que hice fueron monitorizar las actividades del registro y manipulación de archivos, guardando en un fichero de
LOG con extensión
.ini toda esa información:
|
Figura 8: El fichero de LOG con los datos de actividad |
Conclusiones
Con este ejemplo se puede ver cómo funciona el
API Hooking en
Ring 3 con el
Método del Columpio, utilizado para analizar
malware o para hacer proyectos de ingeniería inversa en cualquier otro índole, como por ejemplo las técnicas de
cracking, exploiting o
fuzzing para hacer auditoría de seguridad de binarios. Mi idea es seguir desarrollando estas técnicas y hacer una herramienta de monitorización que funcione con solo hacer
drag and drop de un binario a una
sandbox y genere un informe de actividad, así que si alguien se anima a colaborar que contacte conmigo.
Autor: Alejandro Torres (TorresCrack)
Twitter: @TorresCrack248