El Formato PE (Portable Executable) Parte II

En este post continuaremos con nuestro análisis sobre el formato PE. Aquí puedes encontrar el enlace a la parte 1.

 

El Formato PE (Portable Executable) Parte I

 

 

6.       Section Headers (Encabezados de Sección)

Esta sección sigue inmediatamente con el primer Byte después de terminar el encabezado opcional (de existir). Debido a que no existe un puntero que indique exactamente esta dirección, es necesario que calcularla utilizando la dirección de inicio de OptionalHeaders + SizeOfOptionalHeaders. En nuestro ejemplo, la dirección donde comienza el encabezado opcional es 0x108 y su tamaño es de 0xE0. Al hacer la suma obtenemos que la dirección donde comienzan los encabezados de sección debe ser 0x1E8, que como podemos comprobar en la siguiente imagen, coincide de forma exacta con el primer Byte que estamos buscando.

El número de secciones que siguen corresponde al valor de NumberOfSections (en nuestro ejemplo son 0x03). Las entradas en estas secciones se numeran comenzando con el valor “1”. Cada encabezado de sección contiene la siguiente información para un total de 40 Bytes por entrada.

Name (Nombre de Sección)

pe43Este campo indica el nombre de la sección en codificación UTF-8 y rellenado con caracteres nulos 0x00 hasta abarcar por completo los 8 Bytes de los que se compone. Si el nombre llegara a componerse de exactamente 8 Bytes, no existe un caracter de fin. En archivos ejecutables no se soportan nombres mayores a 8 Bytes. El nombre puede ser cualquier cosa aunque generalmente se utilizan nombres comunes como .text ó .data. En nuestro ejemplo el valor de la primer sección es “.text”.

VirtualSize (Tamaño virtual en memoria)

pe44Este valor de 4 Bytes corresponde al tamaño total utilizado por la sección al cargarse en memoria. Si el valor es mayor a SizeOfRawData, la sección se rellena con caracteres nulos 0x00. En nuestro caso el valor es 0x000126b0.

VirtualAddress (Dirección Virtual)

pe45Este valor de 4 Bytes indica la dirección del primer Byte de la sección cuando es cargada en memoria. Su valor es de 0x00001000.

SizeOfRawData (Tamaño de datos crudos)

pe46

Este valor de 4 Bytes corresponde al tamaño de los datos de inicialización en disco. Si el archivo no contiene esta información, el valor debe ser cero. Su valor debe ser un múltiplo de FileAlignment. Si su valor es menor a VirtualSize, el resto de la sección se rellena con caracteres nulos 0x00. Este valor también podría ser mayor a VirtualSize, porque es un valor redondeado y VirtualSize no. Su valor en nuestro ejemplo es: 0x00012800.

PointerToRawData (Puntero a los datos crudos)

pe47Los siguientes 4 Bytes indican el valor del puntero a la primera página del archivo en disco, su valor en un múltiplo de FileAlignment. Si no existen datos de inicialización, este valor debe ser cero. En nuestro caso el valor es 0x00000400. Si tomamos en cuenta que el valor de FileAlignment en el encabezado opcional dice que la alineación del archivo en disco se da en páginas de 512 Bytes, significa que el primer byte de los datos crudos se encontrará en una página cuya posición redondeada sea un múltiplo de 512. Más adelante veremos que la dirección donde terminan los encabezados de sección está aproximadamente en un offset 0x0250 que en decimal equivale a 592 Bytes, número ya ha ocupado una página de 512 y se encuentra ocupando la segunda que terminará en 1023 Bytes. Debido a esto la siguiente página a la que se puede redondear comenzará en el Byte 1024. Si sacamos el valor decimal de PointerToRawData recién obtenido veremos que su equivalente decimal corresponde en efecto a 1024, offset en el cuál encontraremos el primer Byte que corresponde a esta sección.

PointerToRelocations (Puntero de relocalización)

pe48Los siguientes 4 Bytes indican el puntero de relocalización en disco, dicho valor no es utilizado en archivos ejecutables. Su valor en nuestro ejemplo es 0x00000000.

PointerToLineNumbers (Puntero al número de líneas)

pe49Los siguientes 4 Bytes indican el puntero al inicio de las entradas de número de líneas. Este valor no es utilizado en archivos ejecutables. Su valor es 0x00000000.

NumberOfRelocations (Número de relocalizaciones)

pe50Los siguientes 2 Bytes indican el número de secciones que se pueden relocalizar en memoria. En archivos ejecutables este valor no se usa. Su valor es 0x0000.

NumberOfLineNumbers (Número de líneas de números)

pe51Los siguientes 2 Bytes indican el número de líneas numeradas. Este valor no es usado en archivos ejecutables. Su valor es 0x0000.

Characteristics (Características)

pe52Los siguientes 4 Bytes corresponden a una seria de flags que describen la sección. Con esto termina el encabezado de sección. De haber más secciones, la siguiente comenzará con el siguiente Byte. El valor de los flags es de 0x60000020. Cada uno de estos bits corresponde a uno de los valores que se muestran en la siguiente lista.

Flag                                                                 Value                 Description

0x00000000     Reservado para uso futuro.

0x00000001     Reservado para uso futuro.

0x00000002     Reservado para uso futuro.

0x00000004     Reservado para uso futuro.

IMAGE_SCN_TYPE_NO_PAD                    0x00000008     La sección no se debe rellenar. Fue reemplazado por IMAGE_SCN_ALIGN_1BYTES. Usado sólo para archivos de objetos.

0x00000010     Reservado para uso futuro.

IMAGE_SCN_CNT_CODE                             0x00000020     La sección contiene código ejecutable.

IMAGE_SCN_CNT_INITIALIZED_DATA      0x00000040     La sección contiene datos de inicialización.

IMAGE_SCN_CNT_UNINITIALIZED_ DATA                            0x00000080   La sección contiene datos no iniciados.

IMAGE_SCN_LNK_OTHER                           0x00000100     Reservado para uso futuro.

IMAGE_SCN_LNK_INFO                              0x00000200     La sección contiene comentarios u otra información. Es válida solo para archivos de objetos.

0x00000400     Reservado para uso futuro.

IMAGE_SCN_LNK_REMOVE                       0x00000800     La sección no será parte de esta imagen. Es válido sólo para archivos de objetos.

IMAGE_SCN_LNK_COMDAT                      0x00001000     La sección contiene datos COMDAT. Es válido solo para archivos de objetos.

IMAGE_SCN_GPREL                                     0x00008000     La sección contiene datos referenciados a través del global pointer (GP).

IMAGE_SCN_MEM_PURGEABLE               0x00020000     Reservado para uso futuro.

IMAGE_SCN_MEM_16BIT                          0x00020000     La sección contiene código Thumb para máquinas ARM.

IMAGE_SCN_MEM_LOCKED                      0x00040000     Reservado para uso futuro.

IMAGE_SCN_MEM_PRELOAD                   0x00080000     Reservado para uso futuro.

IMAGE_SCN_ALIGN_1BYTES                      0x00100000     Datos alíneados con límite de 1 byte.

IMAGE_SCN_ALIGN_2BYTES                      0x00200000     Datos alineados con límite de 2 bytes.

IMAGE_SCN_ALIGN_4BYTES                      0x00300000     Datos alineados con límite de 4 bytes.

IMAGE_SCN_ALIGN_8BYTES                      0x00400000     Datos alineados con límite de 8 bytes.

IMAGE_SCN_ALIGN_16BYTES                    0x00500000     Datos alineados con límite de 16 bytes.

IMAGE_SCN_ALIGN_32BYTES                    0x00600000     Datos alineados con límite de 32 bytes.

IMAGE_SCN_ALIGN_64BYTES                    0x00700000     Datos alineados con límite de 64 bytes.

IMAGE_SCN_ALIGN_128BYTES                 0x00800000     Datos alineados con límite de 128 bytes.

IMAGE_SCN_ALIGN_256BYTES                 0x00900000     Datos alineados con límite de 256 bytes.

IMAGE_SCN_ALIGN_512BYTES                 0x00A00000    Datos alineados con límite de 512 bytes.

IMAGE_SCN_ALIGN_1024BYTES               0x00B00000     Datos alineados con límite de 1024 bytes.

IMAGE_SCN_ALIGN_2048BYTES               0x00C00000     Datos alineados con límite de 2048 bytes.

IMAGE_SCN_ALIGN_4096BYTES               0x00D00000    Datos alineados con límite de 4096 bytes.

IMAGE_SCN_ALIGN_8192BYTES               0x00E00000     Datos alineados con límite de 8192 bytes.

IMAGE_SCN_LNK_NRELOC_OVFL             0x01000000     La sección contiene relocalizaciones extendidas.

IMAGE_SCN_MEM_DISCARDABLE            0x02000000     La sección se puede descartar.

IMAGE_SCN_MEM_NOT_CACHED            0x04000000     La sección no se puede meter a cache.

IMAGE_SCN_MEM_NOT_PAGED              0x08000000     La sección no se puede paginar.

IMAGE_SCN_MEM_SHARED                      0x10000000     La sección se puede compartir en memoria.

IMAGE_SCN_MEM_EXECUTE                    0x20000000     La sección se puede ejecutar como código.

IMAGE_SCN_MEM_READ                          0x40000000     La sección se puede leer.

IMAGE_SCN_MEM_WRITE                         0x80000000     Se puede escribir en la sección.

En nuestro ejemplo de calc.exe, los flags indican lo siguiente:

pe53

Para este caso, los flags indican lo siguiente:

Bit 5: La sección contiene código ejecutable.

Bit 29: La sección se puede ejecutar como código.

Bit 30: La sección se puede leer.

La información aquí presentada se repite por cada una de las secciones que contiene el ejecutable.

 

7.       Sections (Secciones)

El resto de los datos del archivo contiene las secciones ya propiamente dichas. Estas siguen inmediatamente después de terminada la sección de encabezados sólo que no comienzan en el siguiente Byte alineado con el parámetro FileAlignment (para los datos en disco) y SectionAlignment (para los datos en memoria). Veamos esto con los datos que tenemos de nuestro archivo calc.exe.

Final de encabezados = 0x25F

FileAlignment = 0x200

PointerToRawData = 0x400

SizeOfRawData = 0x012800

Con esta información podemos ver que el final de los encabezados está en la dirección 0x20F (en decimal 607) por lo que la siguiente dirección a la que se puede redondear será 0x400 (1024 en decimal) lo que coincide con el PointerToRawData para la primera sección del archivo (recuerde que hay tres secciones por lo que hay tres PointerToRawData cada uno redondeado con el mismo método).

El espacio disponible antes de la dirección 0x400 se rellena con ceros como se muestra en la siguiente imagen donde estamos ubicando el inicio de la primera sección .text, aquí podemos confirmar que la línea 0x3F0 se encuentra rellenada con ceros como es de esperarse.

pe54El final de la sección se puede ubicar sumando SizeOfRawData a PointerToRawData, que en nuestro caso es 0x400 + 0x12800 -1 = 0x012BFF. Observe que el siguiente Byte (0x012C00) marca el inicio de la siguiente sección .data cuyo PointerToRawData es exactamente esta dirección.

pe55Finalmente, secciones puede haber varias, sin embargo las más típicas son:

.text: contiene código ejecutable y se distingue porque la sección de características dentro del encabezado de sección tiene en “1” al menos los flags: ‘IMAGE_SCN_CNT_CODE’, ‘IMAGE_SCN_MEM_EXECUTE’ e ‘IMAGE_SCN_MEM_READ’. En algún lugar de esta sección se encuentra la dirección de la primera instrucción que se debe ejecutar (AddressToEntryPoint).

.data: contiene los datos inicializados. Esto se refiere a variables que han sido definidas y que contienen un valor inicial. Contiene al menos los siguientes flags con valor “1”: IMAGE_SCN_CNT_INITIALIZED_DATA’, ‘IMAGE_SCN_MEM_READ’ e ‘IMAGE_SCN_MEM_WRITE’.

.bss: contiene los datos no inicializados. Esto se refiere a variables que han sido definidas pero que no tienen un valor asignado desde el inicio, sino que aceptarán algún valor durante la ejecución. Debe tener un valor de “1” al menos en el flag ‘IMAGE_SCN_CNT_UNINITIALIZED_DATA’.

.rsrc: contiene recursos que se utilizarán durante la ejecución, generalmente, menús, cuadros de dialogo e íconos. Debe contar con al menos los siguientes flags: ‘IMAGE_SCN_CNT_INITIALIZED_DATA’ e ‘IMAGE_SCN_MEM_READ’.

 

Recuerda que puedes mandarnos tus preguntas y comentarios a nuestra cuenta de Twitter: @redinskala donde encontrarás más información y tips de seguridad.

Gracias por tu visita!

 

2 thoughts on “El Formato PE (Portable Executable) Parte II

  1. Pingback: El Formato PE (Portable Executable) Parte I | RedinSkala

  2. Pingback: Cómo encontrar el Entry Point en Memoria y Disco | RedinSkala

Comments are closed.