PE header: ¿Qué es la IAT (Import Address Table)?

Tamaño de letra:

¿Qué es la IAT?

Seguro que en muchísimos tutoriales sobre ingeniería inversa has oído hablar sobre la IAT; que si hay que reconstruir o reparar la IAT, que si está incorrecta, que si hay que calcular su tamaño... IAT son las siglas de Import Address Table (tabla de direcciones de importación) y aunque está íntimamente relacionada con la IT, no son lo mismo. Basándome en diversos escritos a los que hago referencia al final del artículo y en mi experiencia, intentaré que entiendas qué es la IAT, para qué sirve, diferencia con la IT, los saltos característicos a la IAT y mostraré un caso práctico.

Diferencia IAT - IT. IID

La IAT son las siglas de Import Address Table que normalmente no es traducido, usándose la abreviatura IAT - traduzco literalmente: tabla de direcciones de importación - y es muy importante que lo/la conozcas si sueles depurar tus aplicaciones buscando errores. Antes de comenzar, quiero que sepas que también existe la IT - Import Table - Tabla de Importaciones. Aunque la IAT y la IT están relacionadas, ¡no son lo mismo! y la IT (o sección idata, como dice la ayuda de Microsoft) en el PE header, está asignada mediante una dirección y un tamaño. La IT se inicia con una serie de estructuras IMAGE_IMPORT_DESCRIPTORs (IID) que son las que nos van a indicar las dll (librerías etc...) y funciones que el loader de Windows va a cargar. Pero esto es otro amplísimo tema, vamos a centrarnos solamente en la IAT.

De forma muy simple y para que se entienda, cuando ejecutas un programa, el loader de Windows busca en el PE header las importaciones (normalmente librerías dll, ocx...). En esas librerías, cada función, es posible que en tu ordenador esté en una dirección diferente que en el mío (olvidándonos también de Bound Import Directory). Por este y otros motivos, el loader de Windows obtiene la dirección de cada función y para que no se pierda, pueda usarla y hacer referencia a ella, la tiene que guardar en algún sitio. La guarda en la IAT.

Resumen, de forma muy general:

  • La IT es una tabla con toda la información de las funciones y librerías que van a ser importadas.
  • La IAT es una tabla que contiene las direcciones virtuales (virtual address) con la información obtenida de la IT

Ejemplo teórico

Imagina que en tu programa haces uso de la siguiente API:

GetModuleHandleA

Dicha función, se encuentra dentro de la librería kernel32.dll de Windows. En mi ordenador está exactamente en la dirección 75CBD8F3, que posiblemente es diferente a la tuya.

Observo (en el siguiente apartado mostraré un caso práctico para entender esto), que la dirección de la IAT donde se rellena este valor es en:

00403238

Verifico, con un editor hexadecimal, que antes de ejecutar el programa ese valor muestra lo siguiente:

00403238  00000000

Sin embargo, si cargo el programa en OllyDBG y voy a esa dirección, observo que su valor ha sido modificado y ahora tiene:

00403238  75CBD8F3  kernel32.GetModuleHandleA

Espero que, a grandes rasgos, puedas entenderlo. La dirección de la IAT para la función GetModuleHandleA es 00403238 y el loader de Windows, durante la carga del programa, la rellena automáticamente con la dirección 75CBD8F3. Seguro que te preguntarás... ¿y cómo sé dónde está la IAT en un programa?. Bien sencillo, vamos a hacer un caso práctico y entenderemos también esto último.

Ejemplo práctico. Encontrando la IAT.

Descarga el siguiente archivo zip:

Vamos a trabajar con el ejecutable que hay en la carpeta asm02, llamado asm02.exe. Yo voy a utilizar la versión 2 de OllyDBG. Existen muchas formas de encontrar la IAT, para este primer artículo vamos a ver algo básico que es muy utilizado.

Carga asm02.exe en OllyDBG 2. Si has seguido estos pasos, te encontrarás en la dirección 00401000, con el siguiente código:

CPU Disasm
Address   Hex dump          Command                            Comments
00401000  /.  6A 00         push 0                             ; /ModuleName = NULL
00401002  |.  E8 C5010000   call 004011CC                      ; \KERNEL32.GetModuleHandleA
00401007  |.  A3 00304000   mov dword ptr ds:[403000],eax
0040100C  |.  E8 FD010000   call 0040120E                      ; Jump comctl32.InitCommonControls
...
 

Observa que en la dirección 00401002 tenemos una llamada a la función GetModuleHandleA con la call 004011CC. Bien, vamos a ponernos sobre esa call y pulsamos la tecla enter para ir a la dirección 004011CC. Veremos lo siguiente:

CPU Disasm
Address    Command
004011C6   jmp dword ptr ds:[402010]
004011CC   jmp dword ptr ds:[40200C]
004011D2   jmp dword ptr ds:[402008]
004011D8   jmp dword ptr ds:[402034]
004011DE   jmp dword ptr ds:[402020]
004011E4   jmp dword ptr ds:[402018]
004011EA   jmp dword ptr ds:[40201C]
004011F0   jmp dword ptr ds:[402038]
004011F6   jmp dword ptr ds:[402024]
004011FC   jmp dword ptr ds:[402028]
00401202   jmp dword ptr ds:[40202C]
00401208   jmp dword ptr ds:[402030]
0040120E   jmp dword ptr ds:[402000]
 

¡13 saltos jmp!. Estos saltos se suelen denominar saltos a la IAT, y no existen siempre en todos los programas. En nuestro caso, vemos un:

...
004011CC jmp dword ptr ds:[40200C]
 

Es decir, vamos a saltar a la dirección contenida en 40200C. Si en este caso te pones sobre jmp dword ptr ds:[40200C] y pulsas enter, irás directamente a la función GetModuleHandleA en kernel32.dll. Esto significa que la dirección de la función GetModuleHandleA está escrita en 40200C. Vamos a ir allí en la ventana de dumpeado. Para esto, vuelve atrás si estás en kernel32.dll y ponte encima de jmp dword ptr ds:[40200C], pulsa el botón derecho del ratón y selecciona: Follow in Dump -> Memory address. Ahora verás en la ventana de dumpeado (abajo a la izquierda) algo parecido a esto:

CPU Dump
Address   Hex dump
0040200C  F3 D8 CB 75 | E2 BB CC 75 | 00 00 00 00 | BB 42 3B 77
0040201C  14 3D 3E 77 | A3 3B 3B 77 | AD 64 38 77 | 11 EA 3D 77
0040202C  60 AD 38 77 | A9 F2 38 77 | 42 CF 3C 77 | 08 16 3B 77
0040203C  00 00 00 00

Cuando se tiene algo de experiencia, ya se puede apreciar que eso parecen direcciones. OllyDBG tiene una buena opción para mostrar a qué API o función corresponde cada dirección, para hacer esto pulsamos en la ventada de dump con el botón derecho del ratón y seleccionamos: Integer -> Address. Y ahí podrás ver exactamente toda la IAT:

CPU Dump
Address    Value      Comments
00402000   745C1541  ; comctl32.InitCommonControls
00402004   00000000
00402008   75CA9121  ; kernel32.lstrcmp
0040200C   75CBD8F3  ; kernel32.GetModuleHandleA
00402010   75CCBBE2  ; kernel32.ExitProcess
00402014   00000000
00402018   773B42BB  ; user32.GetDlgItem
0040201C   773E3D14  ; user32.GetDlgItemTextA
00402020   773B3BA3  ; user32.EndDialog
00402024   773864AD  ; user32.LoadIconA
00402028   773DEA11  ; user32.MessageBoxA
0040202C   7738AD60  ; user32.SendMessageA
00402030   7738F2A9  ; user32.ShowWindow
00402034   773CCF42  ; user32.DialogBoxParamA
00402038   773B1608  ; user32.LoadBitmapA
0040203C   00000000

Esta es la IAT y seguro que ahora lo ves todo mucho mejor. Como puedes observar entre cada librería existe un dword con valor 0, típico.

Calculando el tamaño de la IAT

Una de las cosas que habrás visto muchas veces en tutoriales, es que se calcula el tamaño de la IAT. Este dato es importante, sobretodo a la hora de reconstruirla. En este caso la IAT comienza en 00402000. La forma sencilla para que lo entiendas sería contar los bytes totales de la IAT (contando también los dword 0). De forma sencilla, ¿cuántas líneas ves en la IAT anterior? Voy a hacer un simple cálculo:

16 líneas x 4 bytes = 64 bytes. 64d bytes en decimal son 40h bytes en hexadecimal.

Es decir, el tamaño de la IAT es de 40h bytes. Después en el último apartado de este artículo verás que este dato está también en el PE header.

Sin embargo, para que no te lleve a confusión, en muchos tutoriales verás que calculan la IAT restando (por ejemplo en nuestro caso):

0040203C - 00402000 = 3Ch bytes

Debes entender, que aunque el tamaño de la IAT son 40h bytes, al hacer la resta anterior lo que hacemos es eliminar y obviar el último dword 0 que hay en 0040203C. Piensa que ese valor no es necesario para reconstruir la IAT y que se añadirá posteriormente.

Mostrar la IAT en el archivo físico

Ya te he enseñado a encontrar la IAT, a calcular su tamaño, ahora verás que en el archivo físico no se encuentra rellenada tal que así y que es el loader de Windows quien escribe los datos.

Aunque no lo voy a explicar en este tutorial, para no alargarlo demasiado, voy a calcular el offset que corresponde en el archivo físico a la dirección virtual de la IAT. En este ejecutable "asm02.exe", la dirección virtual 00402000 1 corresponde en el archivo físico con el offset 800 2. Esto lo puedes calcular con mi programa File Location Calculator y será también explicado (pero hoy no):

File Location Calculator

Ahora voy a abrir asm02.exe desde un editor hexadecimal, por ejemplo, desde el propio OllyDBG 2. Así que en OllyDBG 2 voy al menú View -> File, y como he dicho vamos al offset 800 y voy a mostrar los 64d bytes de la IAT. Veremos lo siguiente:

File C:\asm02.exe
Address   Hex dump
00000800  A0 22 00 00 | 00 00 00 00 | F6 21 00 00 | E2 21 00 00
00000810  D4 21 00 00 | 00 00 00 00 | 2E 22 00 00 | 3C 22 00 00
00000820  22 22 00 00 | 5C 22 00 00 | 68 22 00 00 | 76 22 00 00
00000830  86 22 00 00 | 10 22 00 00 | 4E 22 00 00 | 00 00 00 00

Y para que compares, ahora muestro la IAT con asm02.exe cargado en OllyDBG 2:

CPU Dump
Address   Hex dump
00402000  41 15 5C 74 | 00 00 00 00 | 21 91 CA 75 | F3 D8 CB 75
00402010  E2 BB CC 75 | 00 00 00 00 | BB 42 3B 77 | 14 3D 3E 77
00402020  A3 3B 3B 77 | AD 64 38 77 | 11 EA 3D 77 | 60 AD 38 77
00402030  A9 F2 38 77 | 42 CF 3C 77 | 08 16 3B 77 | 00 00 00 00

Otra forma de encontrar la IAT

Forma I

Esta forma que he comentado es muy utilizada para encontrar la IAT, aunque en muchos programas viene también indicada en el PE header. Vamos a verlo de forma muy sencilla. Abre asm02.exe con un editor o visor de PE header cualquiera. En dicho editor tendrás seguramente una opción denominada Directories, púlsala y verás esto:

Visor PE header - Directories

Ahí la he marcado en amarillo. Puedes observar que el tamaño de la IAT es de 40h bytes y que RVA del comienzo es 0002000 y si observas la imagen de File Location Calculator que he puesto antes, comprobarás que la RVA 2000 corresponde con la Virtual Address 00402000.

Forma II

Otra forma que no voy a explicar aquí, pero que también nos indicará dónde está la IAT es observando la estructura IID (Image Import Descriptor).

Referencias

Última actualización: Miércoles, 04 Abril 2012
Comentarios  
0 # Jose 10-09-2020 00:22
Existen mecanismos como el Dynamic IAT resolution que hacen los malware, deberias hacer un tutorial sobre ello. Saludos
Responder | Responder con una citación | Citar
0 # editor 08-03-2017 15:22
Que editor de formato pe usas que te muestra el import table de esa manera a mi me lo muestra de la siguiente manera:
RVA : 2144
Size: 50
Responder | Responder con una citación | Citar
0 # karmany 08-03-2017 19:39
En este tutorial utilicé 3 programas:
1.- Lo que ves en fondo de color azul es un copia-pega de OllyDBG
2.- La primera imagen con los números 1 y 2, es un programa propio que hice hace ya algunos años (no sé si será compatible con Windows 10, tendría que actualizarlo) llamado File Location Calculator
3.- La última imagen con el número 3 corresponde a un programa llamado PE voyeur.

Pero hay muchos editores de PE...
Responder | Responder con una citación | Citar
0 # L0ngin0s 14-08-2012 21:51
Hola Karmany. Con tu permiso he puesto una referencia a esta publicación en mi blog:

http://longinox.blogspot.com.es/2012/08/solucion-al-reto-unpackme-fsg-131-dulek.html

Me parece que es una de las mejores explicaciones que he leído.

Gracias.
Responder | Responder con una citación | Citar
0 # karmany 15-08-2012 14:12
Has hecho un buen artículo de desempacado. Lo que no estoy seguro es si has calculado correctamente el tamaño de la IAT. En vez de hacerlo con valores en hex se suele buscar el inicio y final en OllyDBG 1.10 pulsando en el Dump botón derecho ? Long ? Address.
De esa forma se puede apreciar mejor inicio-final y posibles entradas no válidas.
Simplemente te lo comento porque cuando seleccionas el final de la IAT hay después unas API del kernel32.dll que no sé si pertenecen a la IAT.
PERO muy buen artículo.
Responder | Responder con una citación | Citar
Escribir un comentario
Antes de publicar un comentario, usted debe aceptar nuestras condiciones de uso: Condiciones de uso. Debido al spam, todos los comentarios serán moderados. Normalmente se responde en unos minutos, refresca los comentarios para comprobarlo.



 

También te puede interesar. Relacionados:

Visitas: 8489844