change this to spicfy the correct possble intrgity offset #include <windows.h>
#include <iostream>
#include <fstream>
#include <shlobj.h>
#include <string>
#include <atomic>
#include <vector>

// Global Variables
std::atomic<bool> GuardRemoved(false);
static std::vector<DWORD64> GuardedAddresses; // Stores addresses with guard pages
static HANDLE TestVEHHandle = NULL;
static DWORD TestVEHOldProtect = 0;
static std::atomic<bool> ExitQueued(false);
static HANDLE GuardEvent = NULL;

// Function to log messages to a file in the user's documents folder
void LogToFile(const std::string& message) {
    char docPath[MAX_PATH];
    if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, 0, docPath))) {
        std::string logFilePath = std::string(docPath) + "\\log.txt";
        std::ofstream logFile(logFilePath, std::ios_base::app);
        if (logFile.is_open()) {
            logFile << message << std::endl;
            logFile.close();
        }
    }
}

// Function to get the current module's base address
DWORD64 GetModuleBaseAddress() {
    return reinterpret_cast<DWORD64>(GetModuleHandle(NULL));
}

// Function to retrieve the .text section boundaries
bool GetTextSectionBoundaries(DWORD64 baseAddress, DWORD64& sectionStart, DWORD64& sectionEnd) {
    // Access DOS Header
    PIMAGE_DOS_HEADER dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(baseAddress);
    if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
        LogToFile("[x] Invalid DOS Signature");
        return false;
    }

    // Access NT Headers
    PIMAGE_NT_HEADERS ntHeaders = reinterpret_cast<PIMAGE_NT_HEADERS>(baseAddress + dosHeader->e_lfanew);
    if (ntHeaders->Signature != IMAGE_NT_SIGNATURE) {
        LogToFile("[x] Invalid NT Signature");
        return false;
    }

    // Iterate through sections to find .text
    PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(ntHeaders);
    for (unsigned int i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i, ++section) {
        if (strcmp(reinterpret_cast<char*>(section->Name), ".text") == 0) {
            sectionStart = baseAddress + section->VirtualAddress;
            sectionEnd = sectionStart + section->Misc.VirtualSize;
            LogToFile("[+] Found .text section");
            LogToFile("    Start: " + std::to_string(sectionStart));
            LogToFile("    End  : " + std::to_string(sectionEnd));
            return true;
        }
    }

    LogToFile("[x] .text section not found");
    return false;
}

// Function to set guard pages on the .text section
bool SetGuardPages(DWORD64 sectionStart, DWORD64 sectionEnd) {
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    DWORD pageSize = sysInfo.dwPageSize;

    // Align addresses to page boundaries
    DWORD64 current = sectionStart;
    while (current < sectionEnd) {
        // Apply guard protection to each page in the .text section
        DWORD oldProtect;
        if (!VirtualProtect(reinterpret_cast<LPVOID>(current), pageSize, PAGE_EXECUTE_READ | PAGE_GUARD, &oldProtect)) {
            LogToFile("[x] VirtualProtect failed at address: " + std::to_string(current));
            return false;
        }
        GuardedAddresses.push_back(current);
        current += pageSize;
    }

    LogToFile("[+] Guard pages set successfully");
    return true;
}

// Vectored Exception Handler
LONG WINAPI TestVEH(EXCEPTION_POINTERS* pExceptionInfo) {
    if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) {
        DWORD64 faultAddress = reinterpret_cast<DWORD64>(pExceptionInfo->ExceptionRecord->ExceptionAddress);
        LogToFile("[+] Guard Page Violation at Address: " + std::to_string(faultAddress));

        // Calculate the page-aligned address
        SYSTEM_INFO sysInfo;
        GetSystemInfo(&sysInfo);
        DWORD64 pageSize = sysInfo.dwPageSize;
        DWORD64 pageStart = faultAddress & ~(pageSize - 1);

        // Log relative RIP if needed
        DWORD64 moduleBase = GetModuleBaseAddress();
        DWORD64 relativeRip = faultAddress - moduleBase;
        LogToFile("[+] RIP relative offset: " + std::to_string(relativeRip));

        GuardRemoved = true;
        SetEvent(GuardEvent); // Signal the monitoring thread

        return EXCEPTION_CONTINUE_EXECUTION;
    }

    return EXCEPTION_CONTINUE_SEARCH;
}

// Function to remove all guard pages
void RemoveGuardPages() {
    SYSTEM_INFO sysInfo;
    GetSystemInfo(&sysInfo);
    DWORD pageSize = sysInfo.dwPageSize;

    for (auto addr : GuardedAddresses) {
        DWORD oldProtect;
        // Restore original protection (assuming PAGE_EXECUTE_READ, adjust if different)
        if (!VirtualProtect(reinterpret_cast<LPVOID>(addr), pageSize, PAGE_EXECUTE_READ, &oldProtect)) {
            LogToFile("[x] Failed to restore protection at address: " + std::to_string(addr));
        }
    }

    GuardedAddresses.clear();
    LogToFile("[+] Guard pages removed");
}

// Function to set up the Vectored Exception Handler
bool SetTestVEH() {
    if (TestVEHHandle || !GuardedAddresses.empty()) {
        return false;
    }

    TestVEHHandle = AddVectoredExceptionHandler(1, TestVEH);
    if (!TestVEHHandle) {
        LogToFile("[x] Failed to add Vectored Exception Handler");
        return false;
    }

    LogToFile("[+] Vectored Exception Handler set");
    return true;
}

// Function to remove the Vectored Exception Handler
void RemoveTestVEH() {
    if (TestVEHHandle && !GuardedAddresses.empty()) {
        if (!RemoveVectoredExceptionHandler(TestVEHHandle)) {
            LogToFile("[x] Failed to remove Vectored Exception Handler");
        } else {
            LogToFile("[+] Vectored Exception Handler removed");
        }
        TestVEHHandle = NULL;
    }
}

// Monitoring Thread Function
DWORD WINAPI VEHThread(LPVOID) {
    DWORD64 baseAddress = GetModuleBaseAddress();
    DWORD64 sectionStart = 0, sectionEnd = 0;

    if (!GetTextSectionBoundaries(baseAddress, sectionStart, sectionEnd)) {
        LogToFile("[x] Failed to retrieve .text section boundaries");
        return 1;
    }

    if (!SetGuardPages(sectionStart, sectionEnd)) {
        LogToFile("[x] Failed to set guard pages on .text section");
        return 1;
    }

    if (!SetTestVEH()) {
        LogToFile("[x] Failed to set Vectored Exception Handler");
        RemoveGuardPages();
        return 1;
    }

    // Create an Event for synchronization
    GuardEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (!GuardEvent) {
        LogToFile("[x] Failed to create event");
        RemoveTestVEH();
        RemoveGuardPages();
        return 1;
    }

    LogToFile("[+] Monitoring thread started");

    while (!ExitQueued) {
        if (GuardRemoved) {
            // Reapply guard protection to all guarded addresses
            DWORD oldProtect;
            for (auto addr : GuardedAddresses) {
                if (!VirtualProtect(reinterpret_cast<LPVOID>(addr), sysInfo.dwPageSize, PAGE_EXECUTE_READ | PAGE_GUARD, &oldProtect)) {
                    LogToFile("[x] Failed to reapply guard to address: " + std::to_string(addr));
                } else {
                    LogToFile("[+] Reapplied guard to address: " + std::to_string(addr));
                }
            }

            GuardRemoved = false;
            ResetEvent(GuardEvent);
        }
        Sleep(50); // Prevent high CPU usage
    }

    // Cleanup
    RemoveGuardPages();
    RemoveTestVEH();
    if (GuardEvent) {
        CloseHandle(GuardEvent);
        GuardEvent = NULL;
    }
    LogToFile("[+] Monitoring thread exiting");
    return 0;
}

// DLL Main Entry Point
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) {
    if (dwReason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hInstance);
        CreateThread(NULL, 0, VEHThread, NULL, 0, NULL);
    }
    else if (dwReason == DLL_PROCESS_DETACH) {
        ExitQueued = true;
    }
    return TRUE;
}