miércoles, 29 de marzo de 2017

Reversig II: Formato PE – Un análisis de las cabeceras

Como mencionamos en la primera entrada de esta serie de notas de reversing, donde hablamos del direccionamiento en memoria, los archivos ejecutables de Windows tienen las cabeceras “Image File Header”, “Image Optional Header”, “Image Section Header” e “Image Data Directory” que proporcionan mucha información sobre el ejecutable en sí. Ahora que ya entendemos que son las direcciones virtuales (VA) y las direcciones virtuales relativas (RVA) podemos meternos en el análisis de las cabeceras del formato PE (Portable Executable) que son los ejecutables de Windows.

La mayoría de las cabeceras PE cuentan con numerosas entradas y hasta incluso estructuras enteras con sus propias entradas dentro. En este artículo voy a mencionar las cabeceras, estructuras y entradas mas relevantes.

IMAGE FILE HEADER
Las entradas mas relevantes de esta cabecera son:

  • Machine: Indica el tipo de arquitectura en la cual se podrá ejecutar el ejecutable (válgase la redundancia xD).
  • NumberOfSections: Cantidad de secciones dentro del ejecutable (.code, .data, .rsrc son algunos nombres típicos de secciones).



IMAGE OPTIONAL HEADER
Las entradas mas relevantes de esta cabecera son:

  • Magic: Indica si el ejecutable es para x86 o x64.
  • AddressOfEntryPoint: RVA hacia la primera instrucción del programa (el Entry Point es lo que llamamos el punto de partida del código del ejecutable).
  • BaseOfCode: RVA del inicio de la sección de código (.code).
  • BaseOfData: RVA del inicio de la sección de datos (.data).
  • ImageBase: VA de preferencia donde se cargará el ejecutable. Esta entrada ya la estudiamos en el artículo anterior, el valor de preferencia suele ser 0x00400000.
  • SizeOfImage: Tamaño a reservar en memoria para cargar el ejecutable.
  • SizeOfHeaders: Tamaño de todas las cabeceras PE juntas.
  • SizeOfStackReserve: Tamaño a reservar para el stack (la pila).
  • SizeOfHeapReserve: Tamaño a reservar para el Heap.       




IMAGE SECTION HEADER
Las entradas de esta cabecera se replican por cada sección del ejecutable indicando los siguientes valores sobre cada una de ellas:
  •  Name: Contiene el nombre de la sección.
  • VirtualSize: Tamaño que ocupará la sección en memoria.
  • VirtualAddress: RVA de la primera dirección de la sección en memoria.
  • SizeOfRawData: Tamaño de la sección en disco.
  • PointerToRawData: Posición del primer byte se la sección en disco.




IMAGE DATA DIRECTORY
Esta es la cabecera más compleja, se compone por estructuras completas que tienen sus propias entradas. A continuación, mencionaré las estructuras más importantes con sus entradas más relevantes.

Export Directory
Esta estructura contiene información acerca de las funciones a las cuales, mediante enlace dinámico, pueden acceder otros archivos ejecutables y DLLs. Generalmente quienes contienen esta sección son las librerías (DLL).
  • Export Directory Table: dentro de todas sus entradas, esta tabla provee información general sobre el directorio de exportación, por ejemplo, el RVA que apunta al nombre de la primera librería exportada, el primer ordinal desde el cual se inician las exportaciones, etc.
  • Export Addres Table: RVA correspondientes a cada función exportada.
  • Name Pointer Table: RVA a las cadenas de los nombres de las funciones exportadas.
  • Ordinal Table: Contiene los índices (o números ordinales) de cada función exportada.   


 Import Directory
Generalmente los archivos ejecutables tienen importaciones, es decir, enlazan funciones de librerías propias o del sistema durante su ejecución. Estas importaciones están definidas a través de las diferentes entradas de la estructura Import Directory, que son las siguientes:
  •  Name RVA: es el RVA a la cadena del nombre de la librería a importar.
  • Ordinal Number: Contiene el ordinal (número de 2 bytes) con el cuál se hará la importación.
  • Original First Thunk y First Thunk: estas dos entradas contienen los mismos valores en disco pero en memoria no. En memoria, First Thunk se carga con una dirección de memoria que corresponde a la función que se va a importar, mientras que Original First Thunk contiene un RVA que apunta a la cadena con el nombre de la función a importar.
  • Ordinal Name Flag: Si este bit está establecido en 1 la importación se llevará a cabo por ordinales, de lo contrario (si es 0) se hará por nombres.
  • Name Table RVA: Apunta a otra estructura que detalla la importación por nombre y se utilizará solo si el flag “Ordinal Name Flag” está en cero.




Resource Directory
Su principal utilidad es dar información de los recursos que tiene el ejecutable (íconos, imágenes, etc.) esta información se encuentra en una sección nombrada “.rsrc”.






Relocation Directory
Tal como mencionamos en la nota anterior, podría pasar que la VA del ImageBase donde el ejecutable se quiere cargar esté ocupada. Entonces si el ejecutable se carga en otra base distinta, se utiliza el Relocation Directory ya que provee el mecanismo para reubicar las direcciones estáticas de manera que todo funcione bien. El desplazamiento se obtiene restando el ImageBase actual al ImageBase original, cuyo resultado se lo conoce como “delta” y a eso se le suma el VA de las direcciones a reubicar.

TLS Directory (Thread Local Storage)
Es una clase especial de almacenamiento que soporta Windows, y contiene información utilizada cada vez que se crea un nuevo hilo de ejecución.

Bound Import Directory
Cuando un ejecutable utiliza este mecanismo, lo que hace es guardar en el directorio Import Address Table las direcciones virtuales de las funciones de las librerías importadas, es decir, no guarda los RVA sino las direcciones reales.  Esto ayuda para optimizar ya que el ejecutable no necesitará volver a cargar cada función importada sino únicamente la librería y verificar que las direcciones que tiene no sean obsoletas. Si no están obsoletas, entonces se ahorra volver a cargar la función, de lo contario, cuenta con la información necesaria para volver a realizar la carga nuevamente. 




Bueno, espero que no se hayan aburrido con tanta teoría xD en la próxima entrega de estas notas sobre reversing veremos algunas cosas más prácticas sobre cómo podemos alterar esta información de las cabeceras PE para lograr modificaciones interesantes en la carga de los ejecutables.

Vuelvo a dejar el link de la nota anterior donde pueden encontrar documentos y herramientas útiles:  https://mega.nz/#F!11ljSKQB!IoZ_umxtwFUxewL1uIbAXA.

====== NOTAS DE LA SAGA DE REVERSING ======

No hay comentarios.:

Publicar un comentario