Process Hiding: Direct Kernel Object Manipulation
Bien, este es uno de los temas que más me apasionan, podría escribir por la eternidad sobre esto, pero hoy hablaremos de una de las técnicas que usan los rootkits para ocultar procesos de software que corre en modo usuario y monitorea procesos.
Herramientas como Task Manager, Process Explorer, Process Hacker, etc. La forma en que enumeran los procesos es recorriendo el ActiveProcessLinks.
ActiveProcessLinks
Cuando se crea un proceso, el kernel crea una estructura EPROCESS para identificarlo. Los EPROCESS contienen varios campos, entre ellos ActiveProcessLinks. Lo que hace es enlazar dos punteros por cada proceso: Flink y Blink. La estructura EPROCESS vive en kernel space y no es accesible directamente desde user mode, aunque el kernel expone parte de su información a través de APIs como NtQuerySystemInformation que es justamente lo que usan las herramientas mencionadas
Como podemos ver, el offset de esta propiedad (ActiveProcessLinks) en Windows 10 es +0x448:
1
dt nt!_EPROCESS
Un poco más de EPROCESS
La forma de imaginar los EPROCESS es como una lista enlazada que vincula el Flink y Blink de cada proceso. FLINK contiene la dirección del siguiente proceso y BLINK contiene la dirección del proceso anterior.
Esta imagen ayuda a visualizar lo que estoy describiendo:
Pongamos un ejemplo si queremos referenciar el ActiveProcessLinks de un EPROCESS, tomamos la dirección base de ese EPROCESS y le sumamos el offset +0x448. Y si queremos acceder a FLINK o BLINK específicamente, sumamos sus offsets correspondientes: FLINK = +0x000 y BLINK = +0x008 (más adelante veremos cómo hacer cada cosa en práctica).
Process Hiding
Luego de ver los conceptos de cómo funcionan las cosas, veremos cómo ocultar procesos. Tomaremos cmd.exe como nuestro proceso objetivo, pero en la práctica este puede ser el proceso de nuestro rootkit, etc.
Vemos cómo nuestro proceso cmd.exe es visible con las herramientas mencionadas:
Vamos con esto para ocultarnos.
Identificamos el EPROCESS address de cmd.exe:
1
!process 0 0 cmd.exe
Ahora necesitamos la dirección del proceso anterior y del siguiente. Para eso inspeccionamos los campos FLINK y BLINK de nuestro EPROCESS:
1
dt nt!_LIST_ENTRY ffff88869dcb5080+0x448
Ya que tenemos las dos direcciones del ActiveProcessLinks del proceso anterior y el siguiente, tenemos que:
- Modificar el
FLINKdel proceso anterior para que apunte al siguiente proceso - Modificar el
BLINKdel siguiente proceso para que apunte al proceso anterior
Modificamos el FLINK del proceso anterior:
1
eq 0xffff8886`9d32d4c8 0xffff8886`9e22d4c8
Modificamos el BLINK del siguiente proceso:
1
eq 0xffff8886`9e22d4c8+0x008 0xffff8886`9d32d4c8
Ahora ponemos en NULL los valores FLINK y BLINK de nuestro EPROCESS:
1
eq ffff88869dcb5080+0x448 0x0
1
eq ffff88869dcb5080+0x448+0x008 0x0
Para el demo los ponemos en NULL, pero en la práctica se hace self-referencing para evitar romperlo
Validamos los cambios:
1
dt nt!_LIST_ENTRY ffff88869dcb5080+0x448
Y continuamos con la ejecución:
1
g
Como podemos ver, ocultamos exitosamente nuestro proceso cmd.exe.
Eso es todo nerds.








