RawrXD PE Writer - Implementação Completa
Visão Geral
Este é um gravador PE32+ completo e emissor de código de máquina implementado em assembly puro x64 MASM, sem dependências e sem uso de CRT. Ele gera executáveis Windows funcionais do zero.
Arquitetura
O gravador PE segue uma abordagem de designer de backend, fornecendo uma API limpa para:
- Criar contextos de executáveis PE
- Adicionar imports com estruturas IAT/INT adequadas
- Emitir código de máquina com gerenciamento de seções
- Escrever arquivos PE completos com todos os cabeçalhos necessários
Componentes Principais
1. Estruturas Definidas
- IMAGE_DOS_HEADER: Cabeçalho DOS padrão com ponteiro e_lfanew
- IMAGE_NT_HEADERS64: Cabeçalhos NT com cabeçalho de arquivo e cabeçalho opcional
- IMAGE_SECTION_HEADER: Cabeçalhos de seção para .text, .rdata, .idata
- IMAGE_IMPORT_DESCRIPTOR: Descritores de tabela de importação
- PE_CONTEXT: Estrutura de contexto interna para construir arquivos PE
2. Funções Principais
PEWriter_CreateExecutable
- Entrada: RCX = base da imagem (0 = padrão), RDX = RVA do ponto de entrada
- Saída: RAX = handle do contexto PE (0 = falha)
- Propósito: Aloca e inicializa a estrutura de contexto PE completa
Detalhes de Implementação:
- Aloca memória para cabeçalho DOS, cabeçalhos NT, cabeçalhos de seção
- Inicializa o cabeçalho DOS com assinatura adequada e e_lfanew
- Configura cabeçalhos NT com tipo de máquina AMD64 e magic PE32+
- Configura cabeçalho opcional com base da imagem, alinhamento de seção/arquivo
- Aloca buffer de código e tabelas de importação
- Define endereços virtuais e offsets de arquivo padrão
PEWriter_AddImport
- Entrada: RCX = contexto PE, RDX = nome da DLL, R8 = nome da função
- Saída: RAX = 1 sucesso, 0 falha
- Propósito: Constrói a tabela de importação com estruturas IAT/INT adequadas
Detalhes de Implementação:
- Gerencia descritores de importação para múltiplas DLLs
- Cria entradas da tabela de busca de importação (INT)
- Configura entradas da tabela de endereços de importação (IAT)
- Trata estruturas de importação por nome
- Rastreia contagem de imports e valida limites
PEWriter_AddCode
- Entrada: RCX = contexto PE, RDX = buffer de código, R8 = tamanho do código
- Saída: RAX = RVA do código (0 = falha)
- Propósito: Gerencia a emissão de código de máquina com gerenciamento adequado de seções
Detalhes de Implementação:
- Copia código de máquina para buffer interno
- Valida tamanho do código contra limites máximos
- Calcula e retorna o RVA do código
- Atualiza o rastreamento interno do tamanho do código
- Gerencia conteúdo da seção .text
PEWriter_WriteFile
- Entrada: RCX = contexto PE, RDX = nome do arquivo
- Saída: RAX = 1 sucesso, 0 falha
- Propósito: Gravação completa do arquivo com todos os cabeçalhos, seções e tabela de importação
Detalhes de Implementação:
- Cria arquivo de saída com chamadas adequadas da API Win32
- Escreve cabeçalho DOS e stub DOS
- Calcula e atualiza valores finais do cabeçalho NT
- Escreve cabeçalhos de seção para .text, .rdata, .idata
- Implementa preenchimento e alinhamento adequados de arquivo
- Escreve dados das seções com tabela de importação
- Lida com todos os cálculos de RVA e offsets de arquivo
Gerenciamento de Memória
A implementação usa APIs de heap do Windows:
- GetProcessHeap(): Obtém o heap do processo atual
- HeapAlloc(): Aloca memória inicializada com zero
- HeapFree(): Libera memória alocada na limpeza
Toda alocação de memória inclui tratamento adequado de erros e limpeza.
Layout da Estrutura do Arquivo
DOS Header (64 bytes)
DOS Stub (variável, preenchido até 0x80)
NT Headers (248 bytes para PE32+)
Section Headers (40 bytes × 3 seções)
Padding até alinhamento de arquivo (0x400)
.text Section (código)
- Código de máquina
- Preenchido até alinhamento de arquivo
.rdata Section (dados somente leitura)
- Constantes de string, recursos
- Preenchido até alinhamento de arquivo
.idata Section (dados de importação)
- Descritores de importação
- Tabela de busca de importação
- Tabela de endereços de importação
- Estruturas de importação por nome
- Preenchido até alinhamento de arquivo
Layout de Endereço Virtual
0x1000: seção .text (SECTION_ALIGNMENT)
0x2000: seção .rdata
0x3000: seção .idata
0x4000: Próximo endereço virtual disponível
Constantes e Padrões
- Base da Imagem: 0x140000000 (padrão para x64)
- Alinhamento de Seção: 0x1000 (4KB)
- Alinhamento de Arquivo: 0x200 (512 bytes)
- Ponto de Entrada: RVA configurável
- Subsistema: Aplicativo de console (IMAGE_SUBSYSTEM_WINDOWS_CUI)
Exemplo de Uso
; Create PE context
mov rcx, 0 ; Default image base
mov rdx, 1000h ; Entry point RVA
call PEWriter_CreateExecutable
mov rbx, rax ; Save context
; Add kernel32.dll imports
mov rcx, rbx
mov rdx, offset dll_kernel32
mov r8, offset func_GetStdHandle
call PEWriter_AddImport
; Add machine code
mov rcx, rbx
mov rdx, offset code_buffer
mov r8, code_size
call PEWriter_AddCode
; Write executable file
mov rcx, rbx
mov rdx, offset filename
call PEWriter_WriteFile
Instruções de Compilação
- Certifique-se de que MASM64 e Windows SDK estejam instalados
- Execute
build.bat para compilar o gravador PE e o exemplo
- Execute
PE_Writer_Example.exe para gerar hello.exe
- Teste o executável gerado
Tratamento de Erros
Todas as funções retornam 0 em caso de falha e não zero em caso de sucesso. A implementação inclui:
- Verificações de falha na alocação de memória
- Tratamento de erros de E/S de arquivo
- Validação de entrada
- Limpeza adequada de recursos
- Verificação de limites para buffers
Limitações
- Máximo de 99 imports (MAX_IMPORTS - 1)
- Tamanho máximo de código de 64KB (MAX_CODE_SIZE)
- Três seções fixas (.text, .rdata, .idata)
- Apenas subsistema console
- Sem suporte a realocações
- Sem assinaturas digitais
Funcionalidades Avançadas
A implementação fornece uma base sólida para:
- Criação de seções personalizadas
- Vinculação complexa de imports
- Incorporação de recursos
- Assinatura digital
- Suporte a realocações
- Tabelas de tratamento de exceções
Notas Técnicas
- Assembly puro x64 MASM - sem dependências de CRT
- Usa heap do Windows para gerenciamento de memória
- Gera formato PE32+ para x64
- Compatível com Windows Vista e posteriores
- Segue a especificação PE da Microsoft
- Nenhuma dependência de biblioteca externa, exceto kernel32.dll
Esta implementação fornece um gravador PE32+ completo e pronto para produção, adequado para backends de geração de código, compiladores personalizados e empacotadores de executáveis.