miércoles, 12 de septiembre de 2012

[Tips&Tricks] Examinando la IAT con Windbg

Hola!,

el otro día un compañero de trabajo me preguntó si sabía como listar las funciones importadas por un programa utilizando Windbg. En ese momento no tenía idea de como hacerlo pero gracias a un par de búsquedas en google pude encontrar una solución aquí que paso a describirles:

1. Primero que nada, cargamos el ejecutable con el cual queremos trabajar en Windbg (CTRL+E).

2. Primero, utilizaremos el comando "!lmi". Este comando muestra información detallada acerca de un módulo. En nuestro caso, como parámetro, indicaremos el nombre de un ejecutable, en este caso notepad.exe, para obtener algo de información acerca del mismo:

0:001> !lmi notepad.exe
Loaded Module Info: [notepad.exe]
Module: notepad
Base Address: 01000000
Image Name: notepad.exe
Machine Type: 332 (I386)
Time Stamp: 48025287 Sun Apr 13 15:35:51 2008
Size: 14000
CheckSum: 18700
Characteristics: 10f
Debug Data Dirs: Type Size VA Pointer
CODEVIEW 24, 18f0, cf0 RSDS - GUID: {506F162C-C6A5-453B-8F9E-DB55AF72CD9B}
Age: 1, Pdb: notepad.pdb
Symbol Type: DEFERRED - No error - symbol load deferred
Load Report: no symbols loaded
De todos ellos, nos interesa "Base Address".

3. El comando "!dh" sirve para mostrar los headers de un módulo. Tiene algunos parámetros como "-a" para mostrar toda la información de los headers, "-s" para mostrar los sections headers y "-f" para mostrar solo file headers. En nuestro caso, lo que queremos obtener es el address y el size de la IT (ImportTable) listado en los DataDirectories, con lo cual, utilizaremos el parámetro "-f" ya que solo queremos los file headers.

La sintaxis es la siguiente: !dh -f address:

0:000> !dh -f 01000000

File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (i386)
3 number of sections
48025287 time date stamp Sun Apr 13 15:35:51 2008

0 file pointer to symbol table
0 number of symbols
E0 size of optional header
10F characteristics
Relocations stripped
Executable
Line numbers stripped
Symbols stripped
32 bit word machine

OPTIONAL HEADER VALUES
10B magic #
7.10 linker version
7800 size of code
A600 size of initialized data
0 size of uninitialized data
739D address of entry point
1000 base of code
----- new -----
01000000 image base
1000 section alignment
200 file alignment
2 subsystem (Windows GUI)
5.01 operating system version
5.01 image version
4.00 subsystem version
14000 size of image
400 size of headers
18700 checksum
00040000 size of stack reserve
00011000 size of stack commit
00100000 size of heap reserve
00001000 size of heap commit
8000 DLL characteristics
Terminal server aware
0 [ 0] address [size] of Export Directory
7604 [ C8] address [size] of Import Directory
B000 [ 8948] address [size] of Resource Directory
0 [ 0] address [size] of Exception Directory
0 [ 0] address [size] of Security Directory
0 [ 0] address [size] of Base Relocation Directory
1350 [ 1C] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
18A8 [ 40] address [size] of Load Configuration Directory
250 [ D0] address [size] of Bound Import Directory
1000 [ 348] address [size] of Import Address Table Directory
0 [ 0] address [size] of Delay Import Directory
0 [ 0] address [size] of COR20 Header Directory
0 [ 0] address [size] of Reserved Directory
Como podemos observar, el RVA donde comienza la IAT es 0x1000 y su tamaño es 0x348.

Estos datos los vamos a necesitar en el próximo paso.

4. Por último, vamos a utilizar el comando "dps". Este comando se utiliza para mostrar el contenido de la memoria de un proceso en un rango dado. La sintaxis es "dps [Options] range". En nuestro caso, sería algo así: "dps 01000000+1000 L348/4", donde:

- 01000000: ImageBase de nuestro programa.
- 1000: RVA del inicio de la IAT.
- 348: Size de la IAT.

Con la letra "L" le indicamos el tamaño del ranto que en este caso es el Size de la IAT dividido 4 porque cada entrada en la IAT ocupa 4 bytes (DWORD).

Este es el resultado:

0:001> dps 0x01000000+0x1000 L348/4
01001000 77dd6fef ADVAPI32!RegQueryValueExW
01001004 77dd6c17 ADVAPI32!RegCloseKey
01001008 77dfba25 ADVAPI32!RegCreateKeyW
0100100c 77dfbd05 ADVAPI32!IsTextUnicode
01001010 77dd7aab ADVAPI32!RegQueryValueExA
01001014 77dd7842 ADVAPI32!RegOpenKeyExA
01001018 77ddd757 ADVAPI32!RegSetValueExW
0100101c 00000000
01001020 773dd270 COMCTL32!CreateStatusWindowW
01001024 00000000
01001028 77f2dc19 GDI32!EndPage
0100102c 77f44a05 GDI32!AbortDoc
01001030 77f2dea9 GDI32!EndDoc
01001034 77f16e5f GDI32!DeleteDC
01001038 77f2f456 GDI32!StartPage
0100103c 77f17f9d GDI32!GetTextExtentPoint32W
01001040 77f1be28 GDI32!CreateDCW
[...]
Hay muchas más entradas pero solo coloque unas pocas.

Espero que les sea útil.

Hasta la próxima!.