Bound Import Directory - PE header

Tamaño de letra:

Bound Import RVA & Size

Hablando de estructuras del PE (Portable Executable) header. Me parece un tema muy interesante y que está muy poco comentado en la red. Mi atención hacia el Bound Import Directory vino cuando sobre el año 2009 programando Add PE bytes, me di cuenta que al añadir una nueva sección en un ejecutable compilado con Visual Basic 6,  el ejecutable final daba un error: "La aplicación no se pudo iniciar correctamente (0xc000007b). Haga clic en Aceptar para cerrarla.". Entonces fui probando otros programas editores del PE header y me di cuenta que la mayoría daban este error. Una solución que tomé hace tiempo es poner tanto el valor Bound Import RVA como Bound Import Size a cero. Entonces sí que funcionaba. Pero...vamos a conocer un poco más a fondo este tema tan peculiar.

 

Bound Import Directory

En estos momentos estoy programando la nueva versión de Add PE bytes y descubro que al añadir una nueva sección a un ejecutable compilado con VB6 el resultante no funciona. ¿por qué? Pues es debido a que el Bound Import Directory es pisoteado. Releyendo lo que nos dice Matt Pietrek en un artículo en la MSDN (ver apartado Binding) destaco con mis propias palabras lo siguiente:

Ya sabes que en cada ejecución, cuando un programa se carga en memoria, la IAT (Import Address Table) se rellena correctamente según los datos obtenidos de la IID (Image Import Descriptor) de cada librería. Es decir, el loader de Windows, en cada ejecución tiene que encontrar la dirección real (Virtual Address) de cada función y ponerla correctamente en la IAT del programa en cuestión.

En algunos casos, por ejemplo con el entorno de programación Visual Basic 6 y Windows XP, cuando generas tu proyecto.exe verás que la IAT queda rellenada con direcciones reales (Virtual Address) de la librería de VB6: msvbvm60.dll. Dicha librería (estoy ahora en Windows XP), tiene una image base que hace que msvbvm60.dll se cargue en una determinada dirección en memoria y esto puede ocurrir tanto en mi ordenador como en el tuyo. Otra de las formas que explica Matt para conseguir que la IAT se rellenara con datos reales podría ser tras una instalación, esto es algo muy coherente y a mi modo de ver una excelente opción si no la mejor. Por otra parte, la librería IMAGEHLP.DLL nos proporciona la API BindImageEx.

Viendo el párrafo anterior, para mejorar la carga de estos ejecutables y poder usar directamente los datos ya existentes en la IAT del programa, existe el Bound Import Directory. Cuando estos datos existen en el encabezado (Bound Import RVA y Bound Import Size) el loader de Windows verifica si los mismos (y a los que apunta) son correctos y de ese modo optimizamos la carga del ejecutable. En algunos tutoriales que he leido en inglés, mucha gente se pregunta (incluído yo) si realmente esta verificación optimiza en gran medida la ejecución de un programa. Desde mi punto de vista, se debe realizar una comprobación exacta si no estaríamos indefensos ante posibles infecciones.

Así a primera vista, y después de lo explicado, ya puedes intuir por qué si pongo el valor de Bound Import RVA y Size a cero el programa funciona correctamente (Yoda en un tutorial sobre el PE header, no le da importancia a este dato y nos induce a resetearlo, literalmente dice lo siguiente: -"Set the Bound Import Directory header to zero, as this directory is not very important to execute a PE file"). Yo no estoy totalmente de acuerdo con esto, es cierto que no es un dato muy importante y el programa funcionará pero si tenemos la opción de optimizarlo, ¿por qué no vamos a hacerlo?

 

Bound Import - Examinando el PE header

Para entenderlo un poco más vamos a hacer un ejemplo. Voy a usar el programa "ejemplo9.exe" que hay en la descarga del tutorial sobre cómo modificar programas: Enlace - cómo modificar programas

Si lo analizas con un visor PE y examinas los datos del IMAGE DATA DIRECTORY en lo relativo al tema que tratamos hoy, verás lo siguiente:

            |    RVA    |    Size    |
BoundImport | 00000228  |  00000020  |

Como puedes observar, tanto RVA como Size son dos dword. Ahora simplemente voy a analizarlo desde un editor hexadecimal yendo a la RVA 228 y observando los 20 bytes (hex.). Si no sabes llegar ahí te recomiendo que uses mi programa File Location Calculator, que es el que voy a usar yo:

00000228  46 BF 02 48 10 00 00 00 00 00 00 00 00 00 00 00  F¿H.............
00000238  4D 53 56 42 56 4D 36 30 2E 44 4C 4C 00 00 00 00  MSVBVM60.DLL....

Esos bytes que ves ahí se corresponden con una estructura denominada: IMAGE BOUND IMPORT DESCRIPTOR. Un ejecutable (bound executable) contiene una lista de estas estructuras. Como la mayoría de información es en inglés y no he encontrado una traducción exacta voy a nombrar bound como vinculado. Cada estructura IMAGE BOUND IMPORT DESCRIPTOR representa el sello time/date de una dll importada que ha sido vinculada. Los elementos que dicha estructura tiene son los siguientes:

typedef struct IMAGE_BOUND_IMPORT_DESCRIPTOR
{
    DWORD   TimeDateStamp;
    WORD    OffsetModuleName;
    WORD    NumberOfModuleForwarderRefs;
}

  • TimeDateStamp: Contiene el "sello" time/date de la DLL importada.
  • OffsetModuleName: Contiene el offset hacia la cadena de texto de la DLL importada.
  • NumberOfModuleForwardefRefs: Contiene el número de estructuras IMAGE_BOUND_FORWARDER_REF

Ahora echa un vistado al anterior RVA 228 y vamos a definir los elementos con estos colores:
TimeDateStampOffsetModuleNameNumberOfModuleForwardefRefs

00000228  46 BF 02 48 10 00 00 00 00 00 00 00 00 00 00 00  F¿H.............
00000238  4D 53 56 42 56 4D 36 30 2E 44 4C 4C 00 00 00 00  MSVBVM60.DLL....

TimeDateStamp: Es el sello time/date. Es decir, la DLL importada debe tener ese sello y lo puedes comprobar abriendo la librería MSVBVM60.DLL y viendo este dato. En nuestro ejemplo es: 4802BF46 que se corresponde con la fecha: Lunes, 14 de abril de 2008. Hora 02:19:50

OffsetModuleName: 0010. Sencillo, si realizas la operación: 00000228h + 10h = 00000238h que se corresponde con la cadena de texto MSVBVM60.DLL, que como sabes es la librería usada con Visual Basic.

NumberOfModuleForwardefRefs: 0000. No le sigue ninguna estructura IMAGE_BOUND_FORWARDER_REF.

Si lo miro en un programa visor de PE me encuentro con el resumen de lo que acabo de explicar:

Bound Import Directory

En el siguiente artículo veremos la estructura IMAGE_BOUND_FORWARDER_REF.

Última actualización: Lunes, 12 Septiembre 2011
Comentarios  
0 # Danyfirex 03-10-2012 21:02
Excelente Material Sr Karmany

No tiene privilegios para responder a los comentarios.


 
Visitas: 8487633