💻
My Personal Hacking Path
  • 👓Wellcome
    • My Personal Hacking Path
      • Whoami
  • 📚Mi Metodología de Pentesting
    • Tipos de evaluaciones
      • El día a día en pentesting
    • Metodología Propia
      • OWASP
      • OSSTMM
      • PTES
      • CEH Hacking Metodology (CHM)
      • Cyber Kill Chain
      • MITRE Att&ck
    • Fase 0 - Pre Evalaución
    • Fase 1 - Reconocimiento
      • Web / Host
      • SubDominios
      • Descubrimiento de correos electrónicos
      • Escaneo de Puertos
      • Credenciales y brechas de seguridad
      • ¿Sin Ideas?
    • Fase 2 - Explotación
      • Shells
        • Diferencia entre una WebShell y Reverse Shell
      • Payload
      • Network Penetration Services
        • 20|21 - FTP
        • 22 - SSH
        • 139|445- SMB
        • 80|443 - HTTP/HTTPS
    • Fase 3 - Post Explotación
      • Enumeración
      • Linux
        • Enumeración
        • Privilege Escalation
      • Windows
        • Revershell
        • Windows Enum
        • Privilege Escalation
    • Fase 4 - Reporting
      • CVSS
        • v4.0
      • Toma de notas
  • 👾Malware
    • Malware DevOps
    • Arquitectura de Windows
      • Windows API
      • Procesos de Windows
      • Estructuras no documentadas
    • PE
      • DLL
    • Almacenamiento del Payload
      • .data & .rdata
      • .text
      • .rsrc
    • Cifrado de Payload
      • XOR
      • RC4
      • AES
    • Ofuscación de Payload
      • IPv4/IPv6Fuscation
      • MACFucscation
      • UUIDFuscation
    • Process Injectión
      • DLL Injection
      • Shellcode Injection
      • APC Injection
  • 🌐Web-Pentesting
    • Metodología para Pentesting Web
    • Footprinting
      • Identificación Tecnologías web
        • WordPress
        • Joomla
        • Drupal
        • Magento
      • Fuzzing
      • Validación de los certificados
    • Vulnerabilidades comunes
      • File Upload
      • SQL Injection
      • Cross-site scripting
      • XXE Injection
      • LFI - Local File Inclusion
        • Log Poisoning
      • RFI - Remote File Inclusión
      • CSRF - Cross-Site Request Forgery
      • SSRF - Server-Side Request Forgery
      • SSTI - Server-Side Template Injection
      • CSTI - Client-Side Template Injection
      • Padding Oracle Attack
      • NoSQL Injection
      • LDAP Injection
    • Laboratorios
  • ☁️AWS Pentesting
    • Introducción a Amazon Web Services AWS
    • Acceso Inicial
    • IAM
      • Políticas de IAM
      • Enumeraciones
      • Privesc-Paths
        • Permisos de IAM
        • Permisos sobre políticas
        • AssumeRolePolicy Update
        • IAM:PassRole*
          • PassExistingRoleToCloudFormation
    • S3
      • Enumeración
      • S3_public
      • OSINT
    • Lambda
      • Enum Lambda
      • Enum API Gateway
      • Privesc-Paths
        • RCE sobre Lambda
        • PassExistingRoleToNewLambdaThenInvoke
        • PassRoleToNewLambdaThenTrigger
        • EditExistingLambdaFunctionWithRole
    • EC2
      • Enumeración
      • Privesc-Paths
        • EC2_SSRF
        • CreateEC2WhithExistingIP
        • PassExistingRoleToNewGlueDevEndpoint
        • ECS_takeover
    • VPC
      • Enumeración
      • PivotingInTheCloud
    • Bases de Datos
      • RDS
        • Enumeración
      • DynamoDB
        • Enumeración
    • ECS
      • Enum ECR
      • Enum ECS
      • Enum EKS
    • AWS Secrets Manager
      • Enumeración
    • Análisis de vulnerabilidades Automatizado
    • Blue Team AWS
      • CloudTrail
      • CloudWatch
      • GuardDuty
      • AWS Inspector
      • AWS Shield
      • Web Application Firewall
    • Notas
      • Terraform
  • 🔫Red_Team
    • Introducción a Red Team
      • Assume breach
    • ¿Qué es MITRE ATT&CK?
      • Guia de uso de Invoke-AtomicRedTeam
    • C2 Comando y control
      • Sliver C2
        • Instalación
        • Beacons y Sesiones
        • Perfiles
        • mTLS y WiewGuard
        • HTTP / HTTPS
        • DNS
        • Stagers: Basics
        • Stagers: Proccess Injection
        • Basics de Implates
        • Ejecución de Assembly
        • Sideload
        • SpawnDLL
        • Sliver Extensions
  • 💾Active Directory
    • Teoria
      • Componentes Físicos
      • Componentes Lógicos
      • GPO VS ACL
      • Kerberos
        • Funcionamiento de Kerberos
      • Usuarios por defecto
    • Enumeraciones
      • ¿Por qué enumerar?
      • Enumeración manual
      • Enumeración con PowerView
    • Ataques en AD
      • Mimikats
        • Comandos
      • Password Spraying
      • LLMNR Poisoning
      • Relay Attacks
        • NTLM
      • Kerberoasting
    • Tools
      • AuxRecon
      • Powershell
      • PowerView.ps1
      • ADPeas
      • Mimikatz
        • Comandos
    • AD Lab
  • 🌩️Azure Coud Pentesting
    • Introducción a Azure y Office 365
    • Introducción a Microsoft Indentity Services
    • Enumeración
    • Azure Files
      • Encontrar Fuga de Datos
    • Microsoft Graph
    • Notas
  • 📱Mobile Pentesting
    • Análisis de Aplicaciones Móviles en MobSF
    • ¿Cómo interceptar tráfico de una aplicación Flutter Android con Burp?
  • 📶Wireless
    • Terminología
    • Tipos de Wireless Networks
    • Formas de Autenticación
    • Cifrados
      • WEP
      • WPA
      • WPA2
      • WPA3
    • Ataques
  • 😎Extras
    • Docker
      • Port Forward y volúmenes
      • Docker Compose
      • Container Breakouts
    • Comandos Utiles
    • Fliper Zero
    • Páginas útiles
  • Kali Set Up
Con tecnología de GitBook
En esta página
  • Introducción
  • Estructura de los PE
  • DOS Header (IMAGE_DOS_HEADER)
  • DOS Stub
  • NT Header (IMAGE_NT_HEADERS)
  • File Header (IMAGE_FILE_HEADER)
  • Opcional Header (IMAGE_OPTIONAL_HEADER)
  • Data Directory
  • Secciones PE
  • Referencias
  1. Malware

PE

Portable Executable

AnteriorEstructuras no documentadasSiguienteDLL

Última actualización hace 1 año

Introducción

Los Portable Executable (PE) es el formato de archivo para ejecutables en Windows. Algunos ejemplos de extensiones de archivos PE son .exe, .dll, .sys y .scr. En esta página se abordará de forma introductoria la estructura PE, que es importante conocer al construir o realizar ingeniería inversa de malware.

Estructura de los PE

La siguiente imagen muestra una estructura simplificada de un Portable Executable. Cada encabezado que se muestra en la imagen se define como una estructura de datos que contiene información sobre el archivo PE.

DOS Header (IMAGE_DOS_HEADER)

El primer encabezado de un archivo PE siempre está precedido por dos bytes, 0xAD y 0x5A, comúnmente conocidos como MZ. Estos bytes representan la firma del encabezado DOS, que se utiliza para confirmar que el archivo que se está analizando o inspeccionando es un archivo PE válido. El encabezado DOS es una estructura de datos definida de la siguiente manera:

typedef struct _IMAGE_DOS_HEADER {    // Encabezado DOS de un archivo .EXE
    WORD e_magic;                     // Número mágico
    WORD e_cblp;                      // Bytes en la última página del archivo
    WORD e_cp;                        // Páginas en el archivo
    WORD e_crlc;                      // Relocalizaciones
    WORD e_cparhdr;                   // Tamaño del encabezado en párrafos
    WORD e_minalloc;                  // Párrafos adicionales mínimos necesarios
    WORD e_maxalloc;                  // Párrafos adicionales máximos necesarios
    WORD e_ss;                        // Valor SS inicial (relativo)
    WORD e_sp;                        // Valor SP inicial
    WORD e_csum;                      // Suma de comprobación
    WORD e_ip;                        // Valor IP inicial
    WORD e_cs;                        // Valor CS inicial (relativo)
    WORD e_lfarlc;                    // Dirección de archivo de la tabla de reubicación
    WORD e_ovno;                      // Número de overlay
    WORD e_res[4];                    // Palabras reservadas
    WORD e_oemid;                     // Identificador OEM (para e_oeminfo)
    WORD e_oeminfo;                   // Información OEM; e_oemid específico
    WORD e_res2[10];                  // Palabras reservadas
    LONG e_lfanew;                    // Desplazamiento hacia el encabezado NT
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;

Los miembros más importantes de la estructura son e_magic y e_lfanew.

  • e_magic ocupa 2 bytes y tiene un valor fijo de 0x5A4D o MZ.

  • e_lfanew es un valor de 4 bytes que contiene el desplazamiento al inicio del encabezado NT. Cabe destacar que e_lfanew siempre se encuentra en un desplazamiento de 0x3C.

DOS Stub

Antes de pasar a la estructura del encabezado NT, está el DOS stub, que es un mensaje de error que imprime "Este programa no se puede ejecutar en modo DOS" en caso de que el programa se cargue en modo DOS o "Disk Operating Mode". Vale la pena señalar que el mensaje de error puede ser modificado por el programador en tiempo de compilación. Esto no es un encabezado PE, pero es bueno tenerlo en cuenta.

NT Header (IMAGE_NT_HEADERS)

El encabezado NT es esencial ya que incorpora otros dos encabezados de imagen: FileHeader y OptionalHeader, que incluyen una gran cantidad de información sobre el archivo PE. Al igual que el encabezado DOS, el encabezado NT contiene un miembro de firma que se utiliza para verificarlo. Por lo general, el elemento de firma es igual a la cadena "PE", que está representada por los bytes 0x50 y 0x45. Pero como la firma es de tipo DWORD, la firma se representa como 0x50450000, que sigue siendo "PE", excepto que está rellenada con dos bytes nulos. El encabezado NT se puede acceder utilizando el miembro e_lfanew dentro del encabezado DOS.

La estructura del encabezado NT varía según la arquitectura de la máquina.

Estructura para 32 bits

typedef struct _IMAGE_NT_HEADERS {
  DWORD                   Signature;
  IMAGE_FILE_HEADER       FileHeader;
  IMAGE_OPTIONAL_HEADER32 OptionalHeader;
} IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32;

Estructura para 64 bits

typedef struct _IMAGE_NT_HEADERS64 {
    DWORD                   Signature;
    IMAGE_FILE_HEADER       FileHeader;
    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
} IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64;

La única diferencia entre ambas versiones de bits es el OptionalHeader, IMAGE_OPTIONAL_HEADER32 e IMAGE_OPTIONAL_HEADER64.

File Header (IMAGE_FILE_HEADER)

Se puede tener acceso por medio de la estructura NT con la siguiente estructura:

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;

Los campos mas importantes de la estructura son:

  • NumberOfSections - El número de secciones en el archivo PE (se discutirá más adelante).

  • Characteristics - Banderas que especifican ciertos atributos sobre el archivo ejecutable, como si es una biblioteca de vínculos dinámicos (DLL) o una aplicación de consola.

  • SizeOfOptionalHeader - El tamaño del siguiente encabezado opcional.

Opcional Header (IMAGE_OPTIONAL_HEADER)

El encabezado opcional es importante y aunque se le llama "opcional", es esencial para la ejecución del archivo PE. Se le llama opcional porque algunos tipos de archivo no lo tienen.

El encabezado opcional tiene dos versiones, una para sistemas de 32 bits y otra para sistemas de 64 bits. Ambas versiones tienen miembros casi idénticos en su estructura de datos, con la diferencia principal siendo el tamaño de algunos miembros. Se utiliza ULONGLONG en la versión de 64 bits y DWORD en la versión de 32 bits. Además, la versión de 32 bits tiene algunos miembros que no se encuentran en la versión de 64 bits.

Estructura 32 bits

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_HEADER32, *PIMAGE_OPTIONAL_HEADER32;

Estructura 64 bits

typedef struct _IMAGE_OPTIONAL_HEADER64 {
  WORD                 Magic;
  BYTE                 MajorLinkerVersion;
  BYTE                 MinorLinkerVersion;
  DWORD                SizeOfCode;
  DWORD                SizeOfInitializedData;
  DWORD                SizeOfUninitializedData;
  DWORD                AddressOfEntryPoint;
  DWORD                BaseOfCode;
  ULONGLONG            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;
  ULONGLONG            SizeOfStackReserve;
  ULONGLONG            SizeOfStackCommit;
  ULONGLONG            SizeOfHeapReserve;
  ULONGLONG            SizeOfHeapCommit;
  DWORD                LoaderFlags;
  DWORD                NumberOfRvaAndSizes;
  IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64;

El encabezado opcional contiene una gran cantidad de información que se puede utilizar. A continuación se muestran algunos de los miembros de la estructura que se utilizan comúnmente:

  • Magic: Describe el estado del archivo de imagen (imagen de 32 o 64 bits).

  • MajorOperatingSystemVersion: El número de versión principal del sistema operativo requerido (por ejemplo, 11, 10).

  • MinorOperatingSystemVersion: El número de versión secundario del sistema operativo requerido (por ejemplo, 1511, 1507, 1607).

  • SizeOfCode: El tamaño de la sección .text (se discutirá más adelante). AddressOfEntryPoint: Desplazamiento al punto de entrada del archivo (normalmente la función principal).

  • BaseOfCode: Desplazamiento al inicio de la sección .text.

  • SizeOfImage: El tamaño del archivo de imagen en bytes.

  • ImageBase: Especifica la dirección preferida en la que se cargará la aplicación en memoria cuando se ejecute. Sin embargo, debido a los mecanismos de protección de memoria de Windows como la Distribución Aleatoria del Espacio de Direcciones (ASLR), es raro ver una imagen mapeada en su dirección preferida, ya que el Cargador PE de Windows asigna el archivo a una dirección diferente. Esta asignación aleatoria realizada por el cargador PE de Windows puede causar problemas en la implementación de técnicas futuras porque algunas direcciones que se consideran constantes fueron modificadas. El cargador PE de Windows luego pasa por la reubicación de PE para corregir estas direcciones.

  • DataDirectory: Uno de los miembros más importantes en el encabezado opcional. Es un arreglo de IMAGE_DATA_DIRECTORY, que contiene los directorios en un archivo PE (se discutirán a continuación).

Data Directory

El Data Directory o Directorio de Datos se puede acceder desde el último miembro del encabezado opcional. Es un arreglo del tipo de dato IMAGE_DATA_DIRECTORY que tiene la siguiente estructura de datos:

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

El arreglo de Directorios de Datos tiene un tamaño de IMAGE_NUMBEROF_DIRECTORY_ENTRIES, que es un valor constante de 16. Cada elemento en el arreglo representa un directorio de datos específico que incluye información sobre una sección PE o una Tabla de Datos (el lugar donde se guarda información específica sobre el PE).

Se puede acceder a un directorio de datos específico utilizando su índice en el arreglo.

#define IMAGE_DIRECTORY_ENTRY_EXPORT          0   // Export Directory
#define IMAGE_DIRECTORY_ENTRY_IMPORT          1   // Import Directory
#define IMAGE_DIRECTORY_ENTRY_RESOURCE        2   // Resource Directory
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION       3   // Exception Directory
#define IMAGE_DIRECTORY_ENTRY_SECURITY        4   // Security Directory
#define IMAGE_DIRECTORY_ENTRY_BASERELOC       5   // Base Relocation Table
#define IMAGE_DIRECTORY_ENTRY_DEBUG           6   // Debug Directory
#define IMAGE_DIRECTORY_ENTRY_ARCHITECTURE    7   // Architecture Specific Data
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR       8   // RVA of GP
#define IMAGE_DIRECTORY_ENTRY_TLS             9   // TLS Directory
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG    10   // Load Configuration Directory
#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT   11   // Bound Import Directory in headers
#define IMAGE_DIRECTORY_ENTRY_IAT            12   // Import Address Table
#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT   13   // Delay Load Import Descriptors
#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14   // COM Runtime descriptor

Directorio de Exportación

El directorio de exportación de un PE es una estructura de datos que contiene información sobre las funciones y variables que se exportan desde el ejecutable. Contiene las direcciones de las funciones y variables exportadas, que pueden ser utilizadas por otros archivos ejecutables para acceder a las funciones y datos. El directorio de exportación generalmente se encuentra en las DLL que exportan funciones (por ejemplo, kernel32.dll exportando CreateFileA).

Tabla Importación de Direcciones

La tabla de importación de direcciones es una estructura de datos en un PE que contiene información sobre las direcciones de las funciones importadas desde otros archivos ejecutables. Las direcciones se utilizan para acceder a las funciones y datos en los otros ejecutables (por ejemplo, Application.exe importando CreateFileA desde kernel32.dll).

Secciones PE

Las secciones PE contienen el código y los datos utilizados para crear un programa ejecutable. Cada sección PE tiene un nombre único y generalmente contiene código ejecutable, datos o información de recursos. No hay un número constante de secciones PE, ya que diferentes compiladores pueden agregar, eliminar o fusionar secciones según la configuración. Algunas secciones también se pueden agregar posteriormente de forma manual, por lo que es dinámico y el campo IMAGE_FILE_HEADER.NumberOfSections ayuda a determinar ese número.

Las siguientes secciones o segmentos PE son las más importantes y existen en casi todos los PE:

  • .text: Contiene el código ejecutable escrito.

  • .data: Contiene datos inicializados, es decir, variables inicializadas en el código.

  • .rdata: Contiene datos de solo lectura. Estas son variables constantes precedidas por "const".

  • .idata: Contiene las tablas de importación. Estas son tablas de información relacionadas con las funciones llamadas desde el código. Esto es utilizado por el Cargador PE de Windows para determinar qué archivos DLL cargar en el proceso, junto con qué funciones se utilizan en cada DLL.

  • .reloc: Contiene información sobre cómo corregir las direcciones de memoria para que el programa pueda cargarse en la memoria sin errores.

  • .rsrc: Se utiliza para almacenar recursos como iconos y mapas de bits.

Recordemos que la estructura IMAGE_SECTION_HEADER es la siguiente:

typedef struct _IMAGE_SECTION_HEADER {
  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];
  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;

Al analizar los elementos, cada uno de ellos es altamente valioso e importante:

  • Name: El nombre de la sección (por ejemplo, .text, .data, .rdata).

  • PhysicalAddress o VirtualSize: El tamaño de la sección cuando está en memoria.

  • VirtualAddress: Desplazamiento del inicio de la sección en la memoria.

Referencias

Cada sección PE tiene una estructura de datos que contiene información valiosa sobre ella. Estas estructuras se guardan bajo los encabezados NT en un archivo PE y se apilan una encima de la otra, donde cada estructura representa una sección.

PE Overview -

DOS Header, DOS Stub and Rich Header -

NT Headers -

Data Directories, Section Headers and Sections -

PE Imports (Import Directory Table, ILT, IAT) -

👾
IMAGE_SECTION_HEADER
https://0xrick.github.io/win-internals/pe2/
https://0xrick.github.io/win-internals/pe3/
https://0xrick.github.io/win-internals/pe4/
https://0xrick.github.io/win-internals/pe5/
https://0xrick.github.io/win-internals/pe6/
IMAGE_FILE_HEADER (winnt.h) - Win32 appsdocsmsft
Logo
IMAGE_DATA_DIRECTORY (winnt.h) - Win32 appsMicrosoftLearn
Logo
A dive into the PE file format - PE file structure - Part 1: Overview0xRick's Blog