Entender "Import Table" e "Import Address Table" de un EXE Win generado por MASM

Iniciado por SubAtomicParticula, 8 Agosto 2016, 10:29 AM

0 Miembros y 2 Visitantes están viendo este tema.

SubAtomicParticula

Saludos, estoy trabajando en un programa de Ensamblador/Desensamblador pero no consigo entender como trabajan las llamadas CALL a DLL. En un EXE generado por MASM que solo tiene el siguiente código:

.data
Titulo db "Mensaje",0
Texto  db "Hola Mundo",0
.code

start:
    invoke MessageBox,0 , offset Texto, offset Titulo,1
    invoke ExitProcess,eax

end start

Utilizo PEExplorer para Desensamblar el código Generado y las 2 llamadas a dll aparecen como:

Direccion     Bytes(Hex)
0040100E  E807000000                        call   jmp_user32.dll!MessageBoxA
00401013  50                                      push   eax
00401014  E807000000                        call   jmp_kernel32.dll!ExitProcess
----------------
0040101A  FF2508204000                     jmp   [user32.dll!MessageBoxA]
00401020  FF2500204000                     jmp   [kernel32.dll!ExitProcess]

Obteniendo las direcciones 402000h y 402008h de la sección .rdata. Mirando en dicha sección obtengo la siguiente Import Table/Import Address Table:

Direccion     Bytes(Hex)
00402000  76200000                                         dd   ??
00402004  00000000                                         dd   00000000
00402008  5C200000                                         dd   ??
0040200C  00000000                                         dd   00000000
00402010  54200000                                         dd   00002054h
00402014  00000000                                         dd   00000000h
00402018  00000000                                         dd   00000000h
0040201C  6A200000                                         dd   0000206Ah
00402020  08200000                                         dd   00002008h
00402024  4C200000                                         dd   0000204Ch
00402028  00000000                                         dd   00000000h
0040202C  00000000                                         dd   00000000h
00402030  84200000                                         dd   00002084h
00402034  00200000                                         dd   00002000h
00402038  00000000                                         dd   00000000h
0040203C  00000000                                         dd   00000000h
00402040  00000000                                         dd   00000000h
00402044  00000000                                         dd   00000000h
00402048  00000000                                         dd   00000000h
0040204C  76200000                                         dd   00002076h
00402050  00000000                                         dd   00000000h
00402054  5C200000                                         dd   0000205Ch
00402058  00000000                                         dd   00000000h
0040205C  B101                                                dw   01B1h
0040205E  4D657373616765426F784100         db   'MessageBoxA',0
0040206A  7573657233322E646C6C00            db   'user32.dll',0
00402075  00                                                db   00h
00402076  9B00                                                dw   009Bh
00402078  4578697450726F6365737300            db   'ExitProcess',0
00402084  6B65726E656C33322E646C6C00         db   'kernel32.dll',0
00402091  00                                                db   00h

Lo que yo entiendo es que en la dirección 402000h esta el desplazamiento 2076h que me lleva a un Word que no se para que sirve (seguro que no esta ahí por casualidad) y al Texto del nombre de la función "ExitProcess" pero desconozco como llego a obtener "Kernel32.dll" aunque deduzco que hay que llegar a la dirección 402030h donde obtengo el desplazamiento 2084h que es donde está el Texto de la DLL. Si alguien puede explicarme como se estructura estas Tablas. Entiendo que Windows cuando carga un ejecutable en memoria Traduce todo esto a posiciones de memoria donde está cargada la DLL y que habrá muchas cosas más que desconozco, pero de momento me basta con poder generar a mano con un programa C++ un Ejecutable con su sección .rdata y sus llamadas a DLL tal y como lo hace MASM. Muchas gracias.

Eternal Idol

Si lees la especificacion completa del PE o al menos el articulo explicativo lo vas a entender seguro:
https://en.wikipedia.org/wiki/Portable_Executable#Import_Table
https://msdn.microsoft.com/en-us/library/ms809762.aspx

Lo que pasa es que esa que estas viendo es informacion de entrada que es resuelta en tiempo de ejecucion por el loader de Windows. Si en lugar de desensamblar depuras tu programa vas a ver que ese offset se termina transformando en un puntero a la direccion de la funcion en cuestion.

Ejemplo, poniendo el evento Load Module como enabled y handled:
hola!start:
00071000 6a01            push    1
00071002 6800400700      push    offset hola!MessageBoxA <PERF> (hola+0x4000) (00074000)
00071007 6808400700      push    offset hola!MessageBoxA <PERF> (hola+0x4008) (00074008)
0007100c 6a00            push    0
0007100e e807000000      call    hola!MessageBoxA (0007101a)
00071013 c3              ret
00071014 cc              int     3
00071015 cc              int     3
0:000> u
hola!start+0x16:
00071016 cc              int     3
00071017 cc              int     3
00071018 cc              int     3
00071019 cc              int     3
hola!MessageBoxA:
0007101a ff2500500700    jmp     dword ptr [hola!_imp__MessageBoxA (00075000)]

0:000> dd 00075000 L1
00075000  00005088

0:000> db hola+5088
00075088  46 02 4d 65 73 73 61 67-65 42 6f 78 41 00 55 53  F.MessageBoxA.US
00075098  45 52 33 32 2e 64 6c 6c-00 00 00 00 00 00 00 00  ER32.dll........

Eso es lo que viste hasta ahora; deshabilito el evento y dejo cargar el programa hasta el primer breakpoint:

0:000> dd 00075000 L1
00075000  76e274c0

Ya no hay mas un offset, hay un puntero:
0:000> dps 00075000 L1
00075000  76e274c0 USER32!MessageBoxA
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

MCKSys Argentina

MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


SubAtomicParticula

Gracias por responder, los ejemplos me llevan al puntero que según entiendo queda después de que Windows sustituya User32!MessageBoxA a una posición de memoria, pero esto es algo que me servirá en un futuro, pero ahora solo necesito saber como Windows obtiene la información "User32.dll" y "MessageBoxA". Entiendo que Windows lee el Call y consigue obtener la cadena "MessageBoxA" siguiendo los Offset.

Explicado de otra manera, estoy programando un Desensamblador que cuando lee una instrucción Call consigue llegar a través de los diferentes Offsets a la posición del EXE donde se almacena el nombre de la función dll "MessageBoxA", pero no entiendo cuales son los cálculos que realiza Windows o cualquier Desensamblador comercial para obtener el texto "User32.dll".

Muchas gracias por vuestra colaboración.

Eternal Idol

Notese que en los enlaces que te dejamos lo explican.

!dh hola

       0 [       0] address [size] of Export Directory
    5060 [      3C] address [size] of Import Directory
       0 [       0] address [size] of Resource Directory
       0 [       0] address [size] of Exception Directory
       0 [       0] address [size] of Security Directory
    6000 [      10] address [size] of Base Relocation Directory
    3000 [      38] 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
       0 [       0] address [size] of Load Configuration Directory
       0 [       0] address [size] of Bound Import Directory
    5000 [      60] 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


IMAGE_IMPORT_DESCRIPTOR.

0:000> dd hola+0x5060 hola+0x5060+0x3c
00f15060  000050cc 00000000 00000000 0000510a
00f15070  00005030 0000509c 00000000 00000000
00f15080  00005124 00005000 00000000 00000000
00f15090  00000000 00000000 00000000 00005116

0:000> da hola+0000510a
00f1510a  "USER32.dll"

0:000> da hola+00005124
00f15124  "KERNEL32.dll"
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

SubAtomicParticula

Gracias, desconocía el significado de las estructuras IMAGE_DATA_DIRECTORY y IMAGE_IMPORT_DESCRIPTOR, por eso no entendía como resolver el problema.

Muchas gracias por vuestra paciencia y por la información. ;-)

Eternal Idol

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón