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.
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
Agrego un poco más de info (en realidad es lo mismo, pero quizás de otra forma) sobre lo que dijo Eternal Idol:
http://www.karmany.net/ingenieria-inversa/19-ingenieria-inversa-novatos/146-pe-header-que-es-la-iat-import-address-table (http://www.karmany.net/ingenieria-inversa/19-ingenieria-inversa-novatos/146-pe-header-que-es-la-iat-import-address-table)
http://sandsprite.com/CodeStuff/Understanding_imports.html (http://sandsprite.com/CodeStuff/Understanding_imports.html)
http://win32assembly.programminghorizon.com/pe-tut6.html (http://win32assembly.programminghorizon.com/pe-tut6.html)
Saludos!
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.
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"
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. ;-)
De nada ::)