¡Feliz días, cazadores!
En el anterior artículo vimos de una manera práctica la creación de procesos y algunas variaciones que existen sobre ello.
Hoy hablaremos sobre como los actores maliciosos utilizan variaciones en la creación de procesos para evadir detecciones.
Aunque técnicas para la ejecución de código hay muchísimas, aquí nos centraremos en las que implican interacción con la API de Windows, ya que son las más usadas por el malware tanto en binarios como en documentos maliciosos.
En la técnica de ATT&CK de Mitre “Native API” podemos ver cómo una larga lista de actores han sido observados utilizando estas técnicas, y no es de extrañar, ya que ejecutar código es algo básico.
Vamos a hablar, intentando profundizar un poco, sobre dos técnicas muy diferentes:
- Parent Process ID Spoofing (PPID Spoofing)
- Process Hollowing
Luke, yo no soy tu padre – PPID Spoofing
En el anterior artículo ya hablamos un poco sobre esta técnica y sobre cómo “AppInfo” la utiliza para generar procesos hijos de otros procesos.
Para entender esta técnica, primero un poco de teoría. Breve, lo prometo.
Estructura de un proceso
Un proceso no es una estructura de datos simple, sino que en el espacio de memoria de un proceso conviven varias estructuras de datos con funciones diferentes.
Existen dos espacios de memoria reservados para un proceso, uno en la parte de usuario y otra en la parte del Kernel. En la siguiente figura se muestra un diagrama simple de dicha estructura.
Dentro del espacio de memoria del Kernel hay una estructura de datos llamada “EPROCESS”, o “Process object” en el diagrama. Esta estructura guarda mucha información muy relevante para el funcionamiento del proceso y uno de esos datos es el “Parent Process ID” o ID del proceso padre.
Mucha de esta información se establece en el momento de la creación del proceso, como es el caso del PPID, que es asignado por el sistema si nosotros no le indicamos lo contrario.
PPID Spoofing en C++
Como en los ejercicios anteriores, voy a utilizar la API de Windows desde C++.
En este caso, al llamar a la función “CreateProcess” vamos a utilizar uno de los argumentos más útiles de la función, el argumento “CreationFlags”.
Estos argumentos permiten parametrizar la creación de procesos de muchísimas maneras, desde asignarle una prioridad al proceso, crear un proceso protegido o, como en este caso, asignarle una información de inicio personalizada.
En este enlace os dejo todas las posibles opciones que se pueden incluir en este argumento.
Lo que hay que hacer implica primero conseguir un manejador para el proceso del futuro padre, después se necesita la estructura de datos “STARTUPINFOEX”. En esta estructura se almacenará la información necesaria para la creación del proceso, que en este caso se llama “attList”. En ella se almacenará la información del proceso padre que se desea poner como padre.
Más tarde, se usará “attList” para asignarle dichos datos al proceso que se creará.
No he querido poner todo el código aquí por no ensuciar el artículo, pero podéis encontrarlo aquí.
Es importante darse cuenta de que el proceso padre que se quiera asignar debe ser accesible por el usuario que ejecute la aplicación. Si se asigna un proceso con privilegios elevados y la aplicación es ejecutada con privilegios intermedios, fallará al no poder acceder a él para conseguir un manejador.
Es un programa sencillo y muy mejorable, pero cumple su misión. Cuando es ejecutado genera una consola de comandos en la que el padre es el proceso que se haya designado, en este caso “Explorer”.
Si os acordáis, es el mismo comportamiento que tuvo “AppInfo” en el artículo anterior, pero esta vez bajo nuestro control.
La parte importante aquí es que Sysmon, al detectar la creación del proceso en el momento de crearse, cree que la creación del proceso la ha hecho “Explorer”.
Sysmon no nos vale para detectar esta técnica mediante el evento 1 únicamente, aunque si os acordáis, he mencionado que nuestro programa necesitará acceder a “Explorer” para poder tener un manejador que utilizar después, y eso Sysmon sí que lo registra mediante el evento 10: “Process accessed”.
Así que únicamente con el evento 1 no es posible detectar esta técnica, pero con la correlación de ambos eventos si sería posible tener una sospecha fundada de que algo raro ha ocurrido.
Incluso mediante el identificador “GrantedAccess” se puede saber que permisos fueron los que solicitó el proceso sobre el proceso objetivo. En este enlace se puede ver el listado completo con sus indicadores.
En el próximo artículo se tratarán otras técnicas de detección de PPID Spoofing.
¡Este no es mi cuerpo! – Process Hollowing
Esta técnica es mucho más avanzada que la anterior e intentaré explicarla sin mucho detalle ya que llevaría demasiado tiempo y no es la intención de este artículo.
Quizá en un artículo futuro nos centremos en ella ya que es muy interesante.
Esta técnica es utilizada por actores maliciosos ya que permite que un proceso parezca ser lo que no es, ya que su cabecera pertenecerá a un proceso legítimo pero su código será malicioso.
Proceso
En este caso, el proceso es muy diferente y aunque existen variaciones sobre ciertas partes del proceso, casi todas se basan en ciertos patrones que en el siguiente artículo intentaremos encontrar.
En esta técnica entran en juego tres elementos:
- El proceso actual, el que ejecuta la acción.
- El binario del proceso que va a ser vaciado, que será un proceso legítimo.
- El binario del proceso que va a ser introducido en el proceso vaciado, que es normalmente el binario malicioso.
Una vez están presentados los actores de la función, las acciones serían las siguientes:
- Se crea un proceso con el binario legítimo “CreateProcessA”, pero en el que el hilo principal está suspendido, mediante la “Flag” de creación “CREATE_SUSPENDED”.
- Se abre el binario malicioso “CreateFileA” con permisos de lectura.
- Se abre un nuevo espacio de memoria en el proceso suspendido de tamaño superior al proceso malicioso “VirtualAllocEx”.
- Tras realizar comprobaciones en la memoria del proceso y ajustar las direcciones de las cabeceras, se escribe en la memoria del proceso vaciado el contenido de las cabeceras y secciones de código del proceso malicioso.
- Se ajusta el contenido del “Process Enviroment Block” para que todo funcione correctamente.
- Se reactiva el hilo principal del proceso.
Parece un proceso complejo y realmente lo es. Existen varios proyectos abiertos que se pueden encontrar por internet que ofrecen su solución a esta técnica y de los que se puede aprender.
Para verlo en acción, yo voy a utilizar el proceso del block de notas “Notepad” para ejecutar el “creador de procesos” del que hablamos en la anterior entrada.
El creador de procesos, dentro del proceso hueco de “Notepad”, ejecutará la consola de comandos, de tal manera que parecerá que es “Notepad” el que crea la consola de comandos.
Poniendo un “Breakpoint” justo después de “CreateProcessA”, se puede ver cómo el proceso “Hollow.exe” crea a “Notepad” suspendido.
Y cuando activa la ejecución del hilo principal después de todo el proceso, se puede observar como no hay ni rastro del “Creador de Procesos”.
Si se utiliza la herramienta “Process Hacker” se puede ver cómo la sección de memoria que se creó durante el proceso, aparece marcada como ejecutable “RWX” y no asociada a ningún binario, algo bastante sospechoso.
Conclusiones
Hoy he intentado explicar dos técnicas famosas que pueden ser utilizadas para engañar al cazador, relacionadas con la creación de procesos.
Técnicas de inyección de procesos como el “Process Hollowing” hay multitud y llegar a controlarlas es un proceso complejo que requiere un conocimiento avanzado de programación en Windows. Existen cursos como los desarrollados por Pavel Yosifovich, que además de enseñar las técnicas de desarrollo, explican el funcionamiento interno de Windows de una manera accesible y que son muy recomendables.
En la siguiente entrada hablaremos sobre la detección de este tipo de técnicas.
Espero no haberos asustado mucho con estas técnicas y hay que pensar que las presas fáciles de cazar no hicieron experto a ningún cazador ;)
Un saludo y ¡feliz caza!
Hola Luis, genial articulo y genial serie de entradas en general.
Justo estos días he estado trasteando también con parent process spoofing. En mi caso me he centrado en el evento 4688 de security y en el evento id 1 de sysmon, llegando a la misma conclusión que tú: estos eventos no son suficientes para su detección. No obstante me he fijado que ambos traen el campo “execution processId”, que debería traer el pid del proceso que originalmente lanzo el nuevo proceso. Esto en teoría, porque a la hora de llevarlo a la práctica, es que siempre logea un pid 4 de system (en el evento 4688) o el pid 240 en sysmon. Aunque no he encontrado información al respecto de cómo funciona ese campo, o si es posible tocar la auditoría de windows para que funcione de forma correcta, si me he encontrado algunas evidencias de que, al menos en el evento 1 de sysmon, debería ser posible, de forma que al comparar si el “execution processId” y el “parent processid” son distintos, podríamos detectar el ataque. Te dejo un par de ejemplos con capturas del evento que confirman la teoría, aunque yo no he sido capaz de llevarlo a cabo en la práctica:
https://www.ired.team/offensive-security/defense-evasion/parent-process-id-ppid-spoofing
https://www.ultimatewindowssecurity.com/securitylog/encyclopedia/event.aspx?eventid=90001
Me interesaría mucho tu opinión.
¡Buenas Rafa!
Muchas gracias por tu comentario y me alegra mucho que te gusten los artículos :)
Como tu bien dices, no es posible hacerlo con los eventos 1 de Sysmon y 4688 De Security.
-Alerta de spoiler-
La correlación del “ParentProcessID” y el “Execution ProcessID” se hace mediante los eventos ETW de “Microsoft-Windows-Kernel-Process” que es de lo que trata el siguiente artículo de la serie :)
Los eventos ETW son todo un mundo por descubrir y te invito a trastear con ellos y cualquier cosa encantado de hablar de ello.
Gracias de nuevo y ¡un saludo!