Manual VEH Injection - Full Demo (C++)

 #include <windows.h>
#include <iostream>

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

// Fake VEH node matching Windows' internal structure
struct VEH_NODE {
    LIST_ENTRY ListEntry;   // Flink, Blink
    PVOID      Handler;     // Our function
};

// Our custom VEH handler
LONG WINAPI MyVEH(EXCEPTION_POINTERS* ExceptionInfo) {
    MessageBoxA(NULL, "Manual VEH Hook Triggered!", "Ghost Mode", MB_OK);
    return EXCEPTION_CONTINUE_EXECUTION;
}

int main() {
    std::cout << "[*] Setting up manual VEH...\n";

    // Step 1: Allocate memory for our node
    VEH_NODE* vehNode = (VEH_NODE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(VEH_NODE));
    if (!vehNode) {
        std::cout << "HeapAlloc failed.\n";
        return 1;
    }

    vehNode->Handler = (PVOID)MyVEH;  // Set handler

    // Step 2: Find the internal LdrpVectoredExceptionList
    HMODULE ntdll = GetModuleHandleA("ntdll.dll");
    if (!ntdll) {
        std::cout << "Cannot find ntdll!\n";
        return 1;
    }

    LIST_ENTRY* pLdrpList = (LIST_ENTRY*)((BYTE*)ntdll + 0x18E370); // WARNING: hardcoded offset for demo!!

    // Step 3: Insert into the doubly-linked list
    vehNode->ListEntry.Flink = pLdrpList->Flink;
    vehNode->ListEntry.Blink = pLdrpList;

    pLdrpList->Flink->Blink = &vehNode->ListEntry;
    pLdrpList->Flink = &vehNode->ListEntry;

    std::cout << "[*] Manual VEH successfully linked!\n";

    // Step 4: Trigger exception to test
    __debugbreak();  // Triggers an exception -> our manually inserted VEH will catch it!

    return 0;
}

Comments

Popular posts from this blog

Avoiding detection when injecting a DLL into a game process

Some global variable set, mystery function

FULL REFLECTIVE INJECTION PACK