Enero 16, 2018, 09:44:35 pm

Autor Tema: Tutorial Introduccion a la estructura PE  (Leído 14245 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado jep

  • Night Elf Druid
  • Moderador
  • *****
  • Mensajes: 1770
  • Sexo: Masculino
    • Ver Perfil
Tutorial Introduccion a la estructura PE
« en: ſeptiembre 27, 2010, 12:29:37 pm »
Esta es una pequeña introducción de como funcionan los archivos PE

Que es?
El archivo PE (Portable Executable) es el formato que utiliza windows para los ejecutables. En fin, en pocas palabras es un .exe o un .dll

Para que sirve conocerlo?
En Ing inversa muchas veces no es necesario conocer con mucho detalle la estructura que tiene este archivo, sin embargo, para problemas más complicados si resultará util conocerlo.
Nos permite separar las secciones del exe, analizarlas por separado, crear nuevas secciones, o modificar las existentes.
Las aplicaciones son bastantes, pero lo mas importante es que con esto se entenderá mejor porque pasan algunas cosas y como podemos resolverlas

Estructura basica:
vamos por parte, primero con una división a grandes razgos de las partes del archivo, y despues vamos ir entrando en detalle en las mas importantes

El archivo PE simplemente un archivo binario, que tiene una estructura, que es basicamente esta:
Código: You are not allowed to view links. Register or Login
--------------------
|  ENCABEZADO DOS  |
--------------------
|  STUB DOS        |
--------------------
|  ENCABEZADO NT   |
--------------------
|  ENCABEZADO SEC  |
--------------------
|  STUB NT         |
--------------------
Como se ve el archivo tiene 5 partes, asi de simple XD, los encabezados tienen un tamaño constante y en ellos están definidas todas las propiedades del archivo. Los stub contienen al programa en sí, los analizaremos por parte.



Sobre el Encabezado DOS y el Stub DOS
Tanto el encabezado DOS como el stub DOS no nos interesará tanto, están ahi por una especie de compatibilidad, si estamos ejecutando el programa en windows se ignorará toda esta parte.
generalmente eso contiene un pequeño programa en DOS que solamente imprime en pantalla algo como esto:
"This program cannot be run in DOS mode."
para indicar que estamos tratando de ejecutar un archivo que no corre en DOS.

Encabezado DOS
El encabezado DOS, asi como ya dije, es una estructura de datos que contiene variables que definen el programa, las variables que contiene este encabezado las podemos sacar de la ayuda de windows (msdn.microsoft.com)
Código: (c) You are not allowed to view links. Register or Login
typedef struct _IMAGE_DOS_HEADER
{
     WORD e_magic;
     WORD e_cblp;
     WORD e_cp;
     WORD e_crlc;
     WORD e_cparhdr;
     WORD e_minalloc;
     WORD e_maxalloc;
     WORD e_ss;
     WORD e_sp;
     WORD e_csum;
     WORD e_ip;
     WORD e_cs;
     WORD e_lfarlc;
     WORD e_ovno;
     WORD e_res[4];
     WORD e_oemid;
     WORD e_oeminfo;
     WORD e_res2[10];
     DWORD e_lfanew;
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
esto es el encabezado, no nos interesa tanto, lo importante aqui es que, para leer todo el archivo debemos por lo menos saber el tamaño que ocupa este encabezado, y lo mas importante es que en este encabezado está la variable que indica donde comienza el encabezado del NT (que es realmente el encabezado que nos interesa)
dentro de esta variable e_lfanew se indica donde comienza el encabezado NT, vamos a ver con un ejemplo, esto es lo que se ve con un editor hexa
Código: You are not allowed to view links. Register or Login
"000000000  4D 5A 90 00 03 00 00 00-04 00 00 00 FF FF 00 00   |MZ##############|"
"000000010  B8 00 00 00 00 00 00 00-40 00 00 00 00 00 00 00   |########@#######|"
"000000020  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000030  00 00 00 00 00 00 00 00-00 00 00 00 80 00 00 00   |################|"

"000000040  0E 1F BA 0E 00 B4 09 CD-21 B8 01 4C CD 21 54 68   |######.#!##L#!Th|"
"000000050  69 73 20 70 72 6F 67 72-61 6D 20 63 61 6E 6E 6F   |is program canno|"
"000000060  74 20 62 65 20 72 75 6E-20 69 6E 20 44 4F 53 20   |t be run in DOS |"
"000000070  6D 6F 64 65 2E 0D 0D 0A-24 00 00 00 00 00 00 00   |mode....$#######|"
"000000080  50 45 00 00 4C 01 05 00-24 A9 8A 4C 00 6C 00 00   |PE##L###$##L#l##|"
ahora hay que fijarse en la estructura del DOS_HEADER y lo que se ve en el archivo.
el tamaño del encabezado podemos calcular 30*WORD+1*DWORD = 64 bytes el encabezado tiene 64 bytes = 0x40 bytes (resulta mas comodo leer todo en hexa)
en el archivo separé con una linea, donde termina este encabezado, es exactamente en el offset 0x40.
Ahora vamos a leer la variable que nos interesa (DWORD e_lfanew), que son los ultimos 4 bytes del encabezado. en el archivo vemos que en esos 4 bytes tenemos "80 00 00 00" no hay que perder de vista que, dentro del archivo las variables se guardan con el byte menos significativo a la izquierda, asi que, si queremos leer esto como un numero hexa, debemos invertir este valor, tomando de 2 en 2, este valor en hexa será 0x00000080 (si no se entendió coloco aqui un ejemplo, si vemos en el archivo una variable asi "01 02 03 04" el valor en hexa de esa variable es 0x04030201, se debe invertir los numero  de 2 en 2)

bueno, con esto ya podemos leer donde empieza el encabezado del NT, está en el offset 0x00000080
Código: You are not allowed to view links. Register or Login
"000000070  6D 6F 64 65 2E 0D 0D 0A-24 00 00 00 00 00 00 00   |mode....$#######|"

"000000080  50 45 00 00 4C 01 05 00-24 A9 8A 4C 00 6C 00 00   |PE##L###$##L#l##|"
"000000090  31 03 00 00 E0 00 07 03-0B 01 02 38 00 5A 00 00   |1##########8#Z##|"
"0000000A0  00 68 00 00 00 0C 00 00-30 11 00 00 00 10 00 00   |#h######0#######|"
aqui vemos, separando con una linea donde comienza.

Stub DOS
El codigo en DOS realmente no nos interesa, pero solo para marcarlo, donde comienza y donde termina, está a continuación del Encabezado DOS y termina antes del encabezado del NT, asi que, en este caso, lo que tenemos en el stub del DOS es esto:
Código: You are not allowed to view links. Register or Login
"000000040  0E 1F BA 0E 00 B4 09 CD-21 B8 01 4C CD 21 54 68   |######.#!##L#!Th|"
"000000050  69 73 20 70 72 6F 67 72-61 6D 20 63 61 6E 6E 6F   |is program canno|"
"000000060  74 20 62 65 20 72 75 6E-20 69 6E 20 44 4F 53 20   |t be run in DOS |"
"000000070  6D 6F 64 65 2E 0D 0D 0A-24 00 00 00 00 00 00 00   |mode....$#######|"
como se puede ver, ahi esta el texto que dice que la aplicación no corre en DOS


Encabezado NT
El encabezado NT es un poco mas complicado que el de DOS, veamos su estructura
Código: (c) You are not allowed to view links. Register or Login
typedef struct _IMAGE_NT_HEADERS {
  DWORD                 Signature;
  IMAGE_FILE_HEADER     FileHeader;
  IMAGE_OPTIONAL_HEADER OptionalHeader;
} IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
esta es su definición, la podemos encontrar en esta pagina You are not allowed to view links. Register or Login
Esta estructura todavia no nos dice mucho, solo que tiene un DWORD, que es un valor de referencia, siempre vale 0x00004550, realmente conviene leer esta variable como un char* "50 45 00 00", en ascii significa 'PE\0\0', esto se puede ver facilmente y permite identificar donde comienza el encabezado NT sin tener que hacer el cálculo que hicimos hace un rato.
Esto lo vemos aqui, (ver los primeros 4 bytes)
Código: You are not allowed to view links. Register or Login
"000000080  50 45 00 00 4C 01 05 00-24 A9 8A 4C 00 6C 00 00   |PE##L###$##L#l##|"


Veamos las estructuras contenidas en esta estructura: IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER

IMAGE_FILE_HEADER
Código: (c) You are not allowed to view links. Register or Login
typedef struct _IMAGE_FILE_HEADER {
  WORD  Machine;
  WORD  NumberOfSections;
  DWORD TimeDateStamp;
  DWORD PointerToSymbolTable;
  DWORD NumberOfSymbols;
  WORD  SizeOfOptionalHeader;
  WORD  Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
No vamos a ver con detalle todas las variables de este encabezado, solo las que nos interesan
WORD  Machine: nos dice el tipo de maquina para la que fue compilado: 386,486,586,...
DWORD NumberOfSections: numero de secciones del archivo, esto es importante, si es que queremos agregar secciones.
DWORD TimeDateStamp: la fecha en la que fue compilado
DWORD PointerToSymbolTable: puntero a la tabla de simbolos
DWORD NumberOfSymbols: numero de simbolos (despues veremos esto en detalle)
WORD  SizeOfOptionalHeader: tamaño del IMAGE_OPTIONAL_HEADER, esto es interesante ya que, haciendo unas operaciones podemos llegar al stub del NT (donde comienza realmente el codigo) del encabezado DOS tenemos el offset del inicio de esta estructura, si a eso le sumamos el tamaño del IMAGE_FILE_HEADER y del IMAGE_OPTIONAL_HEADER, llegaremos al inicio del Stub NT (despues veremos en detalle como hacer este calculo)

sigamos con el IMAGE_OPTIONAL_HEADER
Código: (c) You are not allowed to view links. Register or Login
typedef struct _IMAGE_OPTIONAL_HEADER {
  WORD                 Magic;
  BYTE                 MajorLinkerVersion;
  BYTE                 MinorLinkerVersion;
  DWORD                SizeOfCode;
  DWORD                SizeOfInitializedData;
  DWORD                SizeOfUninitializedData;
  DWORD                AddressOfEntryPoint;
  DWORD                BaseOfCode;
  DWORD                BaseOfData;
  DWORD                ImageBase;
  DWORD                SectionAlignment;
  DWORD                FileAlignment;
  WORD                 MajorOperatingSystemVersion;
  WORD                 MinorOperatingSystemVersion;
  WORD                 MajorImageVersion;
  WORD                 MinorImageVersion;
  WORD                 MajorSubsystemVersion;
  WORD                 MinorSubsystemVersion;
  DWORD                Win32VersionValue;
  DWORD                SizeOfImage;
  DWORD                SizeOfHeaders;
  DWORD                CheckSum;
  WORD                 Subsystem;
  WORD                 DllCharacteristics;
  DWORD                SizeOfStackReserve;
  DWORD                SizeOfStackCommit;
  DWORD                SizeOfHeapReserve;
  DWORD                SizeOfHeapCommit;
  DWORD                LoaderFlags;
  DWORD                NumberOfRvaAndSizes;
  IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
 DWORD SizeOfCode; indica el tamaño total del code, osea, es la suma de los tamaños de las secciones que contienen codigo.
  DWORD AddressOfEntryPoint; direccion del EntryPoint
  DWORD BaseOfCode esto indica donde empieza la seccion que contiene el codigo (generalmente la seccion .text)
  DWORD BaseOfData; indica donde empieza la seccion que contiene las constantes del programa (generalmente .data)
  DWORD ImageBase; todas las direcciones virtuales están colocadas relativas a esta direccion, asi que a todas hay que sumarle este valor para sacar la direccion
  DWORD SectionAlignment; Alineacion de las secciones, en memoria
  DWORD FileAlignment; alineacion de las secciones, en el archivo
  DWORD SizeOfImage; suma de los tamaños de las secciones
  DWORD SizeOfHeaders; suma de los tamaños de los encabezados de las secciones
  DWORD NumberOfRvaAndSizes; esto da el numero de secciones y tamaños de cada seccion, esto es necesario para leer la info de IMAGE_DATA_DIRECTORY DataDirector, esta estructura que contiene la direccion de las secciones en el archivo, y los tamaños de estas secciones.
  estas secciones son secciones especiales, que siempre deben estar en los programas, ya vamos a ver que tienen una relacion con las secciones reales del programa, pero en nuestro programa podemos tener otras secciones que no estén en esta tabla.
las secciones de esta tabla son:
{"Export Table","Import Table","Resource Table","Exception Table","Certificate Table","Base Relocation Table","Debug","Architecture","Global Ptr","TLS Table","Load Config Table","Bound Import","IAT","Delay Import Descriptor","COM+ Runtime Header","Reserved"}
si alguna de estas secciones no existe en el programa se coloca su direccion 0x0 y tamaño 0x0, como podremos ver en los programas reales
  
aqui se puede ver la definicion de esa estructura  
Código: (c) You are not allowed to view links. Register or Login
typedef struct _IMAGE_DATA_DIRECTORY {
  DWORD VirtualAddress;
  DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;  

El IMAGE_OPTIONAL_HEADER en el ejecutable de ejemplo se puede ver aqui: (comienza en el offset 0x000000098 y termina en el 000000177)
Código: You are not allowed to view links. Register or Login
"000000090  31 03 00 00 E0 00 07 03-0B 01 02 38 00 5A 00 00   |1##########8#Z##|"
"0000000A0  00 68 00 00 00 0C 00 00-30 11 00 00 00 10 00 00   |#h######0#######|"
"0000000B0  00 70 00 00 00 00 40 00-00 10 00 00 00 02 00 00   |#p####@#########|"
"0000000C0  04 00 00 00 01 00 00 00-04 00 00 00 00 00 00 00   |################|"
"0000000D0  00 B0 00 00 00 04 00 00-A9 4C 01 00 03 00 00 00   |#########L######|"
"0000000E0  00 00 20 00 00 10 00 00-00 00 10 00 00 10 00 00   |## #############|"
"0000000F0  00 00 00 00 10 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000100  00 A0 00 00 B8 04 00 00-00 00 00 00 00 00 00 00   |################|"
"000000110  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000120  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000130  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000140  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000150  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000160  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000170  00 00 00 00 00 00 00 00-2E 74 65 78 74 00 00 00   |########.text###|"

aqui vemos eso mismo, pero ordenando cada variable (visto con el ollydebg):
hice un salto de linea donde comienza la tabla de secciones (esto no es el encabezado de las secciones, que está a continuación)
Código: You are not allowed to view links. Register or Login
00400098        0B01         DW 010B              ; MagicNumber = PE32
0040009A        02           DB 02                ;  MajorLinkerVersion = 2
0040009B        38           DB 38                ;  MinorLinkerVersion = 38 (56.)
0040009C        005A0000     DD 00005A00          ;  SizeOfCode = 5A00 (23040.)
004000A0        00680000     DD 00006800          ;  SizeOfInitializedData = 6800 (26624.)
004000A4        000C0000     DD 00000C00          ;  SizeOfUninitializedData = C00 (3072.)
004000A8        30110000     DD 00001130          ;  AddressOfEntryPoint = 1130
004000AC        00100000     DD 00001000          ;  BaseOfCode = 1000
004000B0        00700000     DD 00007000          ;  BaseOfData = 7000
004000B4        00004000     DD 00400000          ; ImageBase = 400000
004000B8        00100000     DD 00001000          ;  SectionAlignment = 1000
004000BC        00020000     DD 00000200          ;  FileAlignment = 200
004000C0        0400         DW 0004              ;  MajorOSVersion = 4
004000C2        0000         DW 0000              ;  MinorOSVersion = 0
004000C4        0100         DW 0001              ;  MajorImageVersion = 1
004000C6        0000         DW 0000              ;  MinorImageVersion = 0
004000C8        0400         DW 0004              ;  MajorSubsystemVersion = 4
004000CA        0000         DW 0000              ;  MinorSubsystemVersion = 0
004000CC        00000000     DD 00000000          ;  Reserved
004000D0        00B00000     DD 0000B000          ;  SizeOfImage = B000 (45056.)
004000D4        00040000     DD 00000400          ;  SizeOfHeaders = 400 (1024.)
004000D8        A94C0100     DD 00014CA9          ;  CheckSum = 14CA9
004000DC        0300         DW 0003              ;  Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI
004000DE        0000         DW 0000              ;  DLLCharacteristics = 0
004000E0        00002000     DD 00200000          ;  SizeOfStackReserve = 200000 (2097152.)
004000E4        00100000     DD 00001000          ;  SizeOfStackCommit = 1000 (4096.)
004000E8        00001000     DD 00100000          ;  SizeOfHeapReserve = 100000 (1048576.)
004000EC        00100000     DD 00001000          ;  SizeOfHeapCommit = 1000 (4096.)
004000F0        00000000     DD 00000000          ;  LoaderFlags = 0
004000F4        10000000     DD 00000010          ;  NumberOfRvaAndSizes = 10 (16.)

004000F8        00000000     DD 00000000          ;  Export Table address = 0
004000FC        00000000     DD 00000000          ;  Export Table size = 0
00400100        00A00000     DD 0000A000          ;  Import Table address = A000
00400104        B8040000     DD 000004B8          ;  Import Table size = 4B8 (1208.)
00400108        00000000     DD 00000000          ;  Resource Table address = 0
0040010C        00000000     DD 00000000          ;  Resource Table size = 0
00400110        00000000     DD 00000000          ;  Exception Table address = 0
00400114        00000000     DD 00000000          ;  Exception Table size = 0
00400118        00000000     DD 00000000          ;  Certificate File pointer = 0
0040011C        00000000     DD 00000000          ;  Certificate Table size = 0
00400120        00000000     DD 00000000          ;  Relocation Table address = 0
00400124        00000000     DD 00000000          ;  Relocation Table size = 0
00400128        00000000     DD 00000000          ;  Debug Data address = 0
0040012C        00000000     DD 00000000          ;  Debug Data size = 0
00400130        00000000     DD 00000000          ;  Architecture Data address = 0
00400134        00000000     DD 00000000          ;  Architecture Data size = 0
00400138        00000000     DD 00000000          ;  Global Ptr address = 0
0040013C        00000000     DD 00000000          ;  Must be 0
00400140        00000000     DD 00000000          ;  TLS Table address = 0
00400144        00000000     DD 00000000          ;  TLS Table size = 0
00400148        00000000     DD 00000000          ;  Load Config Table address = 0
0040014C        00000000     DD 00000000          ;  Load Config Table size = 0
00400150        00000000     DD 00000000          ;  Bound Import Table address = 0
00400154        00000000     DD 00000000          ;  Bound Import Table size = 0
00400158        00000000     DD 00000000          ;  Import Address Table address = 0
0040015C        00000000     DD 00000000          ;  Import Address Table size = 0
00400160        00000000     DD 00000000          ;  Delay Import Descriptor address = 0
00400164        00000000     DD 00000000          ;  Delay Import Descriptor size = 0
00400168        00000000     DD 00000000          ;  COM+ Runtime Header address = 0
0040016C        00000000     DD 00000000          ;  Import Address Table size = 0
00400170        00000000     DD 00000000          ;  Reserved
00400174        00000000     DD 00000000          ;  Reserved


Diferencia entre Dirección RAW y Virtual
Para poder entender el significado de algunas de estas variables, hace falta una pequeña introduccion de como las secciones se colocan en memoria.
Cuando se coloca un programa en memoria, para ejecutarlo, no se coloca exactamente como está en el archivo, en el archivo se tiene todo en forma mas compactada.
en memoria se alinean las secciones, generalmente de a 0x1000 bytes (esto depende de la variable que se encuentra en este encabezado, SectionAlignment es la variable que dice el valor de la alineacion, solo que generalmente vale 0x1000), esto hace mas rapida la lectura, sin embargo las secciones en el archivo, no hace falta que se separen unas de otras, aunque tambien son alineadas (la variable FileAlignment tiene el valor al cual se alinea en el archivo)

ademas de esta diferencia, el codigo del programa no comienza de la direccion 0x0 como pasa en el archivo, asi que una direccion en el archivo es totalmente distinta a una direccion en memoria. en el encabezado, cuando se refiere a memoria Rva se refiere a la memoria en el archivo, y cuando habla de memoria virtual se refiere al programa ya colocado en memoria para la ejecución
eso es necesario diferenciar para entender el encabezado.
Si queremos encontrar, donde empieza una seccion en el archivo, debemos buscar su direccion RVA, si queremos ver donde empieza esa misma seccion en memoria, debemos buscar su direccion Virtual (mas adelante veremos como identificar eso, con unos ejemplos)



seguido de esto viene el encabezado de las secciones
esta es la estructura de cada encabezado de seccion
Código: (c) You are not allowed to view links. Register or Login
typedef struct _IMAGE_SECTION_HEADER {
  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME]; /* IMAGE_SIZEOF_SHORT_NAME = 8 bytes */
  union {
    DWORD PhysicalAddress;
    DWORD VirtualSize;
  } Misc;
  DWORD VirtualAddress;
  DWORD SizeOfRawData;
  DWORD PointerToRawData;
  DWORD PointerToRelocations;
  DWORD PointerToLinenumbers;
  WORD  NumberOfRelocations;
  WORD  NumberOfLinenumbers;
  DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
por la union no hay que preocuparse, considerese solo una variable, que indica el tamaño (VirtualSize)

la cantidad de secciones tenemos ya, del encabezado NT, al ir leyendo todos los encabezados de las secciones, tendremos su posicion en el archivo (PointerToRawData), y en memoria (VirtualAddress), el tamaño es el mismo, la diferencia es que, estando en memoria, se llena de 0x0 hasta ajustarse a la alineación

en fin, despues de esto solo se tiene que ir leyendo las secciones.

.text es generalmente la seccion que contiene el codigo
.data y .rdata  contiene constantes, son secciones de solo lectura.
.bss es una seccion de lectura y escritura, se usa para las variables globales generalmente, las variables locales se colocan en el stack (eso lo veremos en otro tuto)
.idata es la tabla de importacion de funciones
.edata es la tabla de exportacion de funciones (es mas comun en los DLL, aunque un exe tambien lo puede tener)

en nuestro code de ejemplo aqui esta el encabezado de las secciones
Código: You are not allowed to view links. Register or Login
"000000170  00 00 00 00 00 00 00 00-2E 74 65 78 74 00 00 00   |########.text###|"
"000000180  E8 59 00 00 00 10 00 00-00 5A 00 00 00 04 00 00   |#Y#######Z######|"
"000000190  00 00 00 00 00 00 00 00-00 00 00 00 60 00 50 60   |############`#P`|"
"0000001A0  2E 64 61 74 61 00 00 00-44 00 00 00 00 70 00 00   |.data###D####p##|"
"0000001B0  00 02 00 00 00 5E 00 00-00 00 00 00 00 00 00 00   |#####^##########|"
"0000001C0  00 00 00 00 40 00 30 C0-2E 72 64 61 74 61 00 00   |####@#0#.rdata##|"
"0000001D0  20 05 00 00 00 80 00 00-00 06 00 00 00 60 00 00   | ############`##|"
"0000001E0  00 00 00 00 00 00 00 00-00 00 00 00 40 00 60 40   |############@#`@|"
"0000001F0  2E 62 73 73 00 00 00 00-78 0A 00 00 00 90 00 00   |.bss####x.######|"
"000000200  00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00   |################|"
"000000210  00 00 00 00 80 00 40 C0-2E 69 64 61 74 61 00 00   |######@#.idata##|"
"000000220  B8 04 00 00 00 A0 00 00-00 06 00 00 00 66 00 00   |#############f##|"
"000000230  00 00 00 00 00 00 00 00-00 00 00 00 40 00 30 C0   |############@#0#|"

seguido a esto (hay un espacio lleno de 0x0 donde se pueden agregar mas encabezados de secciones), y luego ya están las secciones en sí (a lo que le llamé Stub NT)

Esto es todo, se supone que con esto se debe entender como es el formato del ejectuable de windows ( iba ser mas facil si supiese explicar mejor las cosas, pero eso me cuesta XD )



a continuacion veremos un ejemplo de como encontrar una zona especifica de un programa, en memoria y en el archivo.

Para empezar buscaremos el famoso EntryPoint, esta direccion indica el lugar donde se comienza a ejecutar el code, asi que, se supone que debe caer dentro de la seccion de code, ( en el caso del ejemplo solo tiene una seccion con code .text )

Dentro del OptionalHeader tenemos una variable llamada AddressOfEntryPoint, para encontrarlo en el archivo, vamos al inicio de la estructura del OptionalHeader, y contamos los tamaños de las variables que están antes WORD+2*BYTE+3*DWORD = 0x10 bytes (16 en decimal)
sabemos que el inicio de esa estructura esta en 0x000000098 (eso ya lo vimos mas arriba), asi que la direccion del EntryPint debe estar en el Offset 0x0000000A8, tambien sabemos que ocupa 1 DWORD = 4 bytes
Código: You are not allowed to view links. Register or Login
"0000000A0  00 68 00 00 00 0C 00 00-30 11 00 00 00 10 00 00   |#h######0#######|"
"0000000B0  00 70 00 00 00 00 40 00-00 10 00 00 00 02 00 00   |#p####@#########|"
vemos que en el archivo es este el valor "30 11 00 00", como ya dijimos hay que voltearlo de 2 en 2 para tener el valor en Hexa  0x00001130, listo esta es la direccion del entrypoint, pero, tambien como vimos, todas estas direcciones estan referidas al ImageBase, de la misma forma que buscamos el valor del EntryPoint busquemos el ImageBase, esta variable está 3 Dword abajo del entrypoint, osea 8bytes, 0x0000000A8 + 0xC = 0x0000000B4  y ocupa 4 bytes, este es el valor "00 00 40 00" volteando = 0x00400000, bien, asi que el EntryPoint está realmente en 0x00400000 + 0x00001130 = 0x00401130 (eso lo podemos comprobar con algun otro programa como el olly)

que pasa si queremos ver ese entrypoint en el archivo, como lo vemos?
primero hay que saber a que seccion corresponde, en este caso, es evidente que corresponde a .text
veamos El VirtualAdress de .text, y el tamaño para acegurarnos de que está en esa seccion
este es el encabezado de esa seccion (comienza en 0x000000178)
Código: You are not allowed to view links. Register or Login
"000000170  00 00 00 00 00 00 00 00-2E 74 65 78 74 00 00 00   |########.text###|"
"000000180  E8 59 00 00 00 10 00 00-00 5A 00 00 00 04 00 00   |#Y#######Z######|"
"000000190  00 00 00 00 00 00 00 00-00 00 00 00 60 00 50 60   |############`#P`|"
su VirtualAdress esta a 8 Bytes + 1 Dword del inicio del encabezado, osea a 0xC bytes "00 10 00 00" = 0x00001000
tambien nos hara falta conocer el PointerToRawData "00 04 00 00"= 0x00000400

El virtual adress sabemos que es relativo al ImageBase, pero solo nos interesa saber la distancia a la que está el EntryPoint del inicio de esa seccion. asi que ese Offset sera EntryPint - VirtualAdress = 0x130
Ese es el offset desde el inicio de la seccion, en el archivo esa seccion inicia en el PointerToRawData, asi que, el entrypoint en el archivo está en PointerToRawData + 0x130 = 0x530

Vemos el archivo
Código: You are not allowed to view links. Register or Login
"000000530  55 89 E5 83 EC 18 C7 04-24 01 00 00 00 FF 15 50   |U#######$######P|"
"000000540  A1 40 00 E8 D8 FE FF FF-90 8D B4 26 00 00 00 00   |#@#########&####|"
"000000550  55 89 E5 53 83 EC 14 8B-45 08 8B 00 8B 00 3D 91   |U##S####E#####=#|"
"000000560  00 00 C0 77 3B 3D 8D 00-00 C0 72 4B BB 01 00 00   |###w;=####rK####|"
"000000570  00 C7 44 24 04 00 00 00-00 C7 04 24 08 00 00 00   |##D$#######$####|"
y lo comparamos con el dump del Entrypoint en memoria (visto con el Ollydbg)
Código: You are not allowed to view links. Register or Login
00401130  55 89 E5 83 EC 18 C7 04 24 01 00 00 00 FF 15 50  U.å.ì.Ç.$......P
00401140  A1 40 00 E8 D8 FE FF FF 90 8D B4 26 00 00 00 00  .@.èØþ....&....
00401150  55 89 E5 53 83 EC 14 8B 45 08 8B 00 8B 00 3D 91  U.åS.ì..E.....=.
00401160  00 00 C0 77 3B 3D 8D 00 00 C0 72 4B BB 01 00 00  ..Àw;=..ÀrK....
00401170  00 C7 44 24 04 00 00 00 00 C7 04 24 08 00 00 00  .ÇD$.....Ç.$....
podemos ver que el code coincide exactamente, ya que estamos parados en el mismo lugar XD


Espero que haya servido de algo esto,
Saludos, y gracias por leerlo



Si bien este tuto lo escribí solo, no pude haberlo hecho sin aprender este tema, estos son los materiales que utilicé para aprender
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login
You are not allowed to view links. Register or Login

Un gran agadecimiento a la gente de CLS que hizo estos tutos
« Última modificación: Diciembre 03, 2010, 01:01:50 pm por jep »

Desconectado [CronuX]

  • Me das tu IP?
  • *
  • Mensajes: 66
  • Sexo: Masculino
  • OllyDBG
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #1 en: ſeptiembre 27, 2010, 12:44:00 pm »
Felicitaciones jep gran tutorial y se espera la continuacion, un saludo amigo!


Desconectado PeterPunk77

  • Me das tu IP?
  • *
  • Mensajes: 121
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #2 en: ſeptiembre 28, 2010, 10:51:17 am »
Enhorabuena por el tuto jep.
Espero que sea valorado como se merece y que sea de utilidad para el resto de los aficionados a la ingeniería inversa.

Saludos.

Desconectado jep

  • Night Elf Druid
  • Moderador
  • *****
  • Mensajes: 1770
  • Sexo: Masculino
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #3 en: ſeptiembre 28, 2010, 11:13:43 am »
gracias PeterPunk, es bueno verte por estos lares, espero que aparezcas mas seguido

Saludos

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #4 en: ſeptiembre 28, 2010, 09:52:19 pm »
Gran tutorial, no esta para nada mal explicado, no te engañes....

Nunca me habia enterado de esos dos nuevos articulos de CL (291,292), Cuande con mas tiempito me los voy a tener que leer

Saludos.!

Desconectado myguestp

  • Yo vivo en CPH
  • ***
  • Mensajes: 1469
  • A storm comin that the weatherman couldn’t predict
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #5 en: ſeptiembre 29, 2010, 02:15:07 am »
jeje, gracias, me ayudara a conocer mejor la estructura de los ejecutables ;)

You are not allowed to view links. Register or Login

Desconectado soez

  • Yo vivo en CPH
  • ***
  • Mensajes: 1283
  • Sexo: Masculino
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #6 en: Octubre 11, 2010, 01:44:52 pm »
Buen tutorial ;) esto es muy muy util para el diseño de malware (crypters... etc) que por cierto se podria hacer algun taller!! Saludos.


PD. Buenos tutoriales los de Ans-Gari buen acompañamiento a tu explicacion. Ya me ha quedado claro :)

PD2. Donde has encontrado los tutos de Ans-Gari? por estar atento a su tercero que hablará de la IAT
« Última modificación: Octubre 11, 2010, 02:40:31 pm por soez »
You are not allowed to view links. Register or Login
01001010 01100001 01110110 01101001 01100101 01110010

Desconectado jep

  • Night Elf Druid
  • Moderador
  • *****
  • Mensajes: 1770
  • Sexo: Masculino
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #7 en: Octubre 13, 2010, 11:45:27 am »
Encontré ahi mismo, donde está el link que puse. Es la base de datos de los manuales de CracksLatinos

entrá aqui
You are not allowed to view links. Register or Login
fijate que estan separados por números y hay un buscador de teorias, que es una base de datos para ayudarte a encontrar lo que necesites.
Hay unos tutoriales sobre IAT que escribió Ricardo Narvaja

Saludos

Desconectado soez

  • Yo vivo en CPH
  • ***
  • Mensajes: 1283
  • Sexo: Masculino
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #8 en: Octubre 13, 2010, 11:47:25 am »
Thanks voy a echar un vistazo ;)


PD. Este post deberia estar en las FAQ
« Última modificación: Octubre 26, 2010, 06:51:20 pm por soez »

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #9 en: Noviembre 24, 2010, 11:05:13 am »
You are not allowed to view links. Register or Login

Desconectado jep

  • Night Elf Druid
  • Moderador
  • *****
  • Mensajes: 1770
  • Sexo: Masculino
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #10 en: Noviembre 24, 2010, 11:15:24 am »
Si, pero antes quiero reordenar un poco las facs, hay varios otros tutoriales interesantes que deberian quedar ahi

Desconectado WaesWaes

  • Actualmente es
  • Colaborador
  • ****
  • Mensajes: 4402
  • You are not prepared!
    • Ver Perfil
Re: Tutorial Introduccion a la estructura PE
« Respuesta #11 en: Noviembre 24, 2010, 06:34:40 pm »
Sentite libre de hacer cualquier cosa con mi post yo las arme asi nomas porque no habia mod en aquel entonces ;)

Saludos


xx
~ [Tutorial] Introducción a NSIS ~

Iniciado por DarkSkull

0 Respuestas
3104 Vistas
Último mensaje Agosto 31, 2008, 06:36:36 pm
por DarkSkull
xx
Tutorial:Introducción al C by TheSamuxD

Iniciado por NetPirate

3 Respuestas
1267 Vistas
Último mensaje Mayo 20, 2009, 11:08:48 am
por NetPirate
xx
Java - Pequeña introduccion - Tutorial

Iniciado por Castor1991

2 Respuestas
1731 Vistas
Último mensaje ſeptiembre 03, 2007, 03:23:47 pm
por zXxOsirisxXz
exclamation
Tutorial - Introducción y creación de virus Macros

Iniciado por messerschmitt

9 Respuestas
8716 Vistas
Último mensaje Mayo 27, 2012, 12:31:55 pm
por dark_master_999
xx
[introducción + código] Introducción al manejo de bases de datos MySQL en Python

Iniciado por blozzter

1 Respuestas
1976 Vistas
Último mensaje ſeptiembre 02, 2011, 05:17:22 pm
por bendroide
question
Estructura EXE

Iniciado por biyonder87

1 Respuestas
1315 Vistas
Último mensaje ſeptiembre 29, 2009, 07:36:17 pm
por Ni0
xx
Estructura de While

Iniciado por JaAViEr

2 Respuestas
2326 Vistas
Último mensaje Mayo 05, 2009, 11:09:31 pm
por JaAViEr
xx
Estructura de la Web

Iniciado por shevchenko

1 Respuestas
1148 Vistas
Último mensaje Marzo 10, 2009, 05:07:12 am
por Pifias
xx
Estructura de una web

Iniciado por shevchenko

0 Respuestas
1397 Vistas
Último mensaje Agosto 01, 2008, 09:53:43 am
por shevchenko
xx
Estructura De Los Virus

Iniciado por InfiltratorElement

0 Respuestas
704 Vistas
Último mensaje Febrero 28, 2011, 04:03:05 pm
por InfiltratorElement