首页
社区
课程
招聘
[原创]实现简易ARK工具(4) SSDT Hook
发表于: 2025-7-21 20:54 1124

[原创]实现简易ARK工具(4) SSDT Hook

2025-7-21 20:54
1124

​ 大家好,本篇文章讨论XP/WIN7 32位下通过SSDTHook实现对系统调用的监控,所以得先知道什么是SSDT,而明白SSDT得先懂门的机制,懂门的机制得先懂GDT表....=.=
作者也是小白, 如有错误恳请指正,谢谢你的时间!

​ [专题四]Rootkit的学习与研究-编程技术-看雪-安全社区|安全招聘|kanxue.com,我发现查阅windwos基础的文章得从后往前翻。翻到前辈的文章后就陷入了自我怀疑,别人08年玩烂的东西现在学是否有意义,大家怎么看呢?

SSDT(System Service Descriptor Table)是Windows内核维护的系统服务分发表,记录了所有系统调用(Nt*函数)的内核实现地址。

WRK中观察,SSDT和ShadowSSDT是两个导出的表结构。 //win7 32位后不导出

img

windbg中观察 输入dd nt!KeServiceDescriptorTable L4 ,第一个值就是他的函数地址表地址,第三个值代表地址有几项

img

我们dds 地址表地址 ,解析成函数指针,就可以查阅SSDT。

img

既然SSDT表存储的是所有系统调用的函数地址,那么如果我们修改SSDT表中的函数指针,不就能改变系统调用最终的去向吗?

我们的目的是通过hook 内核函数实现对R3的监控,有几种思路:

1:可以通过Ntdll拿到想要hook的R3的API call的服务编号,去改相应的SSDT表项。

2:inlinehook内核API。

由于内核API不像R3的API在开头有mov edi edi.push ebp,mov ebp,esp这样主动提供的5字节hook点,inlineHook不好找点。显然修改表项更稳定。

3.替换MSR

MSR[175]是EIP,我们可以替换这个值,实现对系统快速调用的代理函数Hook,同时对EAX(系统服务号)做判断来选择针对的api。显然这种方法很好检查,读一下MSR的值就知道对不对劲了。

4.直接对KiFastCallEntry函数inlineHook,但是这样兼容性也不好,这个代码会更新

5.对某个进程做个假表 Ethread->ServiceTable

img

监控目标程序的创建进程,把他的服务表替换了。这也不难检测,可以遍历枚举进程,对比所有进程的服务表做判断。

6.新时代的对抗 不懂不懂....

SSDTHook的缺陷

这里有个Nt* 与Zw*函数的问题:

在R3(用户层)时,Zw和Nt其实是同一个导出地址,最终通过int 2Eh或syscall指令,带着服务号进入内核,由SSDT查表找到真正的内核实现。

在R0(内核层)时,Zw函数会无条件地通过SSDT查表,即使已经在内核态,也会走一遍“查表”流程。

Nt函数(如NtOpenProcess)内部是具体实现功能的代码,不会再通过SSDT查表。

举例说明

用户层调用ZwOpenProcess:

R3 → ZwOpenProcess → 系统调用指令(int 2Eh/syscall)→ SSDT查表 → NtOpenProcess实现

内核层调用ZwOpenProcess:

R0 → ZwOpenProcess → SSDT查表 → NtOpenProcess实现

内核层调用NtOpenProcess:

R0 → NtOpenProcess(直接实现,不查表)

如果内核驱动强制调Nt,就可以绕过SSDT表的Hook,结果就是hook不到驱动。

所以,SSDT hook适合监控用户层的系统调用,但对内核层直接调用Nt无能为力。

下图可以看到ZwOpenProcess内部也是传一个服务号然后call系统服务。

img

本文具体实现通过修改SSDT表中的函数指针实现hook

拆解一下思路 :

1.获取SSDT表地址

2.R3通过控制码传服务号

3.R0收到服务号后修改SSDT[服务号]的值为我们干活的函数地址,并保存原函数指针。

4.在hook函数内部收集信息并调用原函数指针(否则破坏系统功能),将信息放到R3能读取到的一块缓冲区

5.R3读取数据显示在UI上,实现对系统调用的监控。

6.干完活或者软件关闭,需要恢复被修改的SSDT表项为保存的原函数指针。

第一种方法,特征KeAddSystemServiceTable

第二种方法,拿全局变量直接用,但是win7 32位后就不导出了,要解析pdb

但是通过这个结构体,我们只能拿到函数地址和知道有几项服务函数,不知道函数名。

由于我写的玩具要在XP上跑,所以让ai把windbg的SSDT表信息硬编码为数组。高版本系统可以集成网上各种的开源pdb解析工具(基本都是64位的) 获取函数名。

这没什么好说的,确认好要hook什么函数写个枚举类表示服务号,非常老实

由于我们hook函数后需要发监控的数据给R3,所以我使用mdl申请了一块共享内存,每次R3发控制码,R0都返回了这个共享内存的地址。后续R0写入,R3读取。

注意:MmMapLockedPagesSpecifyCache必须在目标用户进程的上下文下调用,才能把内核内存映射到R3进程空间。我一开始把这个初始化函数放在了DriverEntry,排查了好几个小时- -

主要是拿到符号号后替换SSDT中函数指针,伪代码:

这里需要考虑重入和引用计数问题:

如果有线程进入FakeNtCreateProcessEx但是在还没返回,此时驱动卸载了,线程继续跑被释放的代码内存,导致蓝屏。

所以我们需要确保所有函数调用完才DriverUnload

重入问题:比如你在HookedNtOpenProcess里做日志、权限检查、甚至调用其他API时,间接又触发了NtOpenProcess,就会再次进入Hook函数本身,所以我们需要添加引用计数。

我最后是搞了张表存储Hook需要的数据,详细代码请看文末。

通过收到的服务号查表进行函数指针的替换实现hook

我在hook函数内部拿信息信息,封装成PROCESS_EVENT,R3也按这个格式读。

这里我纯属折腾,给共享内存维护了一个环形缓冲区,R0控制WriteIndex只写,R3控制ReadIndex只读。
假设R0写完7,WriteIndex就会变为0从头开始覆写,实现固定缓冲区大小的生产消费。数据结构不是主题,下文会贴出代码。

最省事的可以R3调Readfile读。也可以让R3调DeviceIoControl,R0收到后拷贝数据到systembuffer,在缓冲区满时清空这个缓冲区。

这里有同步问题:现在不仅仅是R0和R3两个线程在操作缓冲区,而是R0侧的每个被 hook 的 SSDT 函数都可能在不同的线程中并发地往同一个缓冲区写入数据。
这意味着R0端是多生产者(多线程写),R3端是单消费者(单线程读),存在数据竞争,记得加锁?有没有什么比较优雅的方法....0.0

这里顺便查阅了一下内核的读写锁:

KSPIN_LOCK:自旋锁,适合保护极短临界区,不支持多读单写。

KMUTEX / FAST_MUTEX:互斥体,只能单线程独占,不支持多读。

KSEMAPHORE:信号量,可实现计数型同步,但不直接支持读写锁语义。

KEVENT:事件,适合信号通知,不适合实现锁。

ERESOURCE:专为多读单写设计的内核对象,支持递归、死锁检测。这个XP能用

SpinLock从vista开始支持读取器/写入器自旋锁 - Windows drivers | Microsoft Learn,Xp好像只能用ERESOURCE。ERESOURCE 例程简介 - Windows drivers | Microsoft Learn
读锁允许多个线程同时读取同一份数据,但禁止写线程在此期间修改数据,避免写线程正在修改时,读线程读到不完整数据。

一般是开一个线程轮询读共享内存的数据写到数据结构,UI再读缓冲区展示数据,这样会导致日志线程和UI主线程的读写同步问题,记得处理。好奇:由于imgu每一帧都会刷新UI。可以在每一帧渲染前/后,顺便轮询一次共享内存,把新日志读出来,推到UI展示队列,会不会卡?

展示在UI上的结构体:

1)手动控制hook,R3发控制码,让R0将函数指针替换回去。

2)上文描述过的引用计数问题:程序退出的时候,如果贸然卸载驱动,线程继续跑被释放的代码内存,导致蓝屏。先卸载hook,再依靠引用计数确保hook函数都跑完了代码,最后卸载驱动。

拿的信息比较简陋

image-20250721201345541

image-20250721201345541

其实写ssdthook的时候感觉麻烦的是代码的设计和多线程数据竞争的处理方式,安全知识倒是不复杂。
SSDTHook在XP虚拟机里多hook几个函数就会非常的卡,让我分辨不出是hook导致的卡还是我代码写的不好,蓝廋~
后续应该是注册系统回调

//WRK中他就长这样
typedef struct _KSERVICE_TABLE_DESCRIPTOR {
    PULONG_PTR Base;//函数地址表指针
    PULONG Count;   // 指向计数器的指针 不管它就行
    ULONG Limit;    // 实际的服务数量  这个和"Count"很容易混淆
    PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
 
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable //声明直接用
//WRK中他就长这样
typedef struct _KSERVICE_TABLE_DESCRIPTOR {
    PULONG_PTR Base;//函数地址表指针
    PULONG Count;   // 指向计数器的指针 不管它就行
    ULONG Limit;    // 实际的服务数量  这个和"Count"很容易混淆
    PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
 
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable //声明直接用
R3                      R0
  |                      |
  |通过DeviceIoCtl传服务号i|
  |--------------------->|
  |                      | 获取SSDT表地址
  |                      | 保存原始函数指针SSDT[i]
  |                      | 修改SSDT表项为Hook函数
  |                      |
  |                      | 系统服务会调用Hook函数,收集信息
  |                      | 写入共享缓冲区
  |<---------------------|
  | 开线程轮询读取缓冲区
  | 展示在UI上
   
结束的时候
  | 发送卸载命令(DeviceIoCtl)
  |--------------------->|
  |                      | 等待所有hook调用结束
  |                      | 恢复SSDT表项
  |                      | 释放共享缓冲区
  |<---------------------|
R3                      R0
  |                      |
  |通过DeviceIoCtl传服务号i|
  |--------------------->|
  |                      | 获取SSDT表地址
  |                      | 保存原始函数指针SSDT[i]
  |                      | 修改SSDT表项为Hook函数
  |                      |
  |                      | 系统服务会调用Hook函数,收集信息
  |                      | 写入共享缓冲区
  |<---------------------|
  | 开线程轮询读取缓冲区
  | 展示在UI上
   
结束的时候
  | 发送卸载命令(DeviceIoCtl)
  |--------------------->|
  |                      | 等待所有hook调用结束
  |                      | 恢复SSDT表项
  |                      | 释放共享缓冲区
  |<---------------------|
void GetSSDT() {
    UNICODE_STRING ustrName;
    RtlInitUnicodeString(&ustrName, L"KeAddSystemServiceTable");
    UCHAR* pCode = MmGetSystemRoutineAddress(&ustrName);
     
    // 搜索特征码 0x83 0xB8 (cmp eax, xxx)
    for (int i = 0; i < 100; i++) {
        if (pCode[i] == 0x83 && pCode[i + 1] == 0xB8) {
            KeServiceDescriptorTable = *(PKSERVICE_TABLE_DESCRIPTOR*)(pCode + i + 2);
            break;
        }
    }
}
void GetSSDT() {
    UNICODE_STRING ustrName;
    RtlInitUnicodeString(&ustrName, L"KeAddSystemServiceTable");
    UCHAR* pCode = MmGetSystemRoutineAddress(&ustrName);
     
    // 搜索特征码 0x83 0xB8 (cmp eax, xxx)
    for (int i = 0; i < 100; i++) {
        if (pCode[i] == 0x83 && pCode[i + 1] == 0xB8) {
            KeServiceDescriptorTable = *(PKSERVICE_TABLE_DESCRIPTOR*)(pCode + i + 2);
            break;
        }
    }
}
//WRK中他就长这样
typedef struct _KSERVICE_TABLE_DESCRIPTOR {
    PULONG_PTR Base;//函数地址表指针
    PULONG Count;   // 指向计数器的指针 不管它就行
    ULONG Limit;    // 实际的服务数量  这个和"Count"很容易混淆
    PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
 
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable //声明直接用
//WRK中他就长这样
typedef struct _KSERVICE_TABLE_DESCRIPTOR {
    PULONG_PTR Base;//函数地址表指针
    PULONG Count;   // 指向计数器的指针 不管它就行
    ULONG Limit;    // 实际的服务数量  这个和"Count"很容易混淆
    PUCHAR Number;
} KSERVICE_TABLE_DESCRIPTOR, *PKSERVICE_TABLE_DESCRIPTOR;
 
extern PKSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable //声明直接用
SSDT_INFO g_SSDT_XP_SP3_Table[] = {
    {0, (PVOID)0x805a5614, "NtAcceptConnectPort"},
    {1, (PVOID)0x805f1adc, "NtAccessCheck"},
    {2, (PVOID)0x805f5312, "NtAccessCheckAndAuditAlarm"},
    {3, (PVOID)0x805f1b0e, "NtAccessCheckByType"},
    ....
SSDT_INFO g_SSDT_XP_SP3_Table[] = {
    {0, (PVOID)0x805a5614, "NtAcceptConnectPort"},
    {1, (PVOID)0x805f1adc, "NtAccessCheck"},
    {2, (PVOID)0x805f5312, "NtAccessCheckAndAuditAlarm"},
    {3, (PVOID)0x805f1b0e, "NtAccessCheckByType"},
    ....
typedef enum : ULONG {
    HOOK_CREATE_PROCESS = 48,     // NtCreateProcessEx
    HOOK_OPEN_PROCESS = 122,      // NtOpenProcess
    HOOK_DEBUG_PROCESS = 57,      // NtDebugActiveProcess
    HOOK_SUSPEND_PROCESS = 253,   // NtSuspendProcess
    HOOK_RESUME_PROCESS = 205,    // NtResumeProcess
    HOOK_TERMINATE_PROCESS = 257  // NtTerminateProcess
} HOOK_SSDT_Index, * PHOOK_SSDT_Index;
typedef enum : ULONG {
    HOOK_CREATE_PROCESS = 48,     // NtCreateProcessEx
    HOOK_OPEN_PROCESS = 122,      // NtOpenProcess
    HOOK_DEBUG_PROCESS = 57,      // NtDebugActiveProcess
    HOOK_SUSPEND_PROCESS = 253,   // NtSuspendProcess
    HOOK_RESUME_PROCESS = 205,    // NtResumeProcess
    HOOK_TERMINATE_PROCESS = 257  // NtTerminateProcess
} HOOK_SSDT_Index, * PHOOK_SSDT_Index;
BOOL ArkR3::StartSSDTHook(HOOK_SSDT_Index flag)
{
    PVOID sharedMemAddr = NULL;
 
    // 发送监控标志给驱动
    DWORD dwRetBytes = 0;
    BOOL bResult = DeviceIoControl(m_hDriver, CTL_START_SSDTHOOK,
        &flag, sizeof(HOOK_SSDT_Index),
       &sharedMemAddr,sizeof(PVOID),  //返回R3共享内存地址 保存到pSharedLogBuffer_
        &dwRetBytes, NULL);
...
BOOL ArkR3::StartSSDTHook(HOOK_SSDT_Index flag)
{
    PVOID sharedMemAddr = NULL;
 
    // 发送监控标志给驱动
    DWORD dwRetBytes = 0;
    BOOL bResult = DeviceIoControl(m_hDriver, CTL_START_SSDTHOOK,
        &flag, sizeof(HOOK_SSDT_Index),
       &sharedMemAddr,sizeof(PVOID),  //返回R3共享内存地址 保存到pSharedLogBuffer_
        &dwRetBytes, NULL);
...
PVOID g_SharedMemory = NULL; //共享内存地址 R0用
PVOID g_SharedLogBuffer = NULL;//映射到R3的内存地址 R3用
PMDL g_SharedMdl = NULL;
 
// 初始化共享内存
NTSTATUS InitSharedMemory() {
 
    // 分配内核内存
    g_SharedMemory = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOG_BUFFER), 'SLOG');
    if (!g_SharedMemory) {
        Log("[test] InitSharedMemory: !g_SharedMemory");
        return STATUS_NO_MEMORY;
    }
 
    RtlZeroMemory(g_SharedMemory, sizeof(LOG_BUFFER));
 
    // 创建MDL
    g_SharedMdl = IoAllocateMdl(g_SharedMemory, sizeof(LOG_BUFFER), FALSE, FALSE, NULL);
    if (!g_SharedMdl) {
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        Log("[test] InitSharedMemory: IoAllocateMdl STATUS_NO_MEMORY");
        return STATUS_NO_MEMORY;
    }
 
    // 构建MDL
    MmBuildMdlForNonPagedPool(g_SharedMdl);
 
    // 映射到用户空间
    g_SharedLogBuffer = MmMapLockedPagesSpecifyCache(g_SharedMdl, UserMode,
        MmNonCached, NULL, FALSE, NormalPagePriority);
    if (!pSharedLogBuffer_) {
        Log("[test] InitSharedMemory: 映射到用户空间失败");
        IoFreeMdl(g_SharedMdl);
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        return STATUS_NO_MEMORY;
    }
 
    Log("[test] 共享内存初始化成功: 内核地址=%p, 用户地址=%p", g_SharedMemory, pSharedLogBuffer_);
    return STATUS_SUCCESS;
}
 
// 清理共享内存
void CleanupSharedMemory() {
    if (g_SharedLogBuffer) {
        MmUnmapLockedPages(g_SharedLogBuffer, g_SharedMdl);
        g_SharedLogBuffer = NULL;
    }
    if (g_SharedMdl) {
        IoFreeMdl(g_SharedMdl);
        g_SharedMdl = NULL;
    }
    if (g_SharedMemory) {
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        g_SharedMemory = NULL;
    }
}
PVOID g_SharedMemory = NULL; //共享内存地址 R0用
PVOID g_SharedLogBuffer = NULL;//映射到R3的内存地址 R3用
PMDL g_SharedMdl = NULL;
 
// 初始化共享内存
NTSTATUS InitSharedMemory() {
 
    // 分配内核内存
    g_SharedMemory = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOG_BUFFER), 'SLOG');
    if (!g_SharedMemory) {
        Log("[test] InitSharedMemory: !g_SharedMemory");
        return STATUS_NO_MEMORY;
    }
 
    RtlZeroMemory(g_SharedMemory, sizeof(LOG_BUFFER));
 
    // 创建MDL
    g_SharedMdl = IoAllocateMdl(g_SharedMemory, sizeof(LOG_BUFFER), FALSE, FALSE, NULL);
    if (!g_SharedMdl) {
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        Log("[test] InitSharedMemory: IoAllocateMdl STATUS_NO_MEMORY");
        return STATUS_NO_MEMORY;
    }
 
    // 构建MDL
    MmBuildMdlForNonPagedPool(g_SharedMdl);
 
    // 映射到用户空间
    g_SharedLogBuffer = MmMapLockedPagesSpecifyCache(g_SharedMdl, UserMode,
        MmNonCached, NULL, FALSE, NormalPagePriority);
    if (!pSharedLogBuffer_) {
        Log("[test] InitSharedMemory: 映射到用户空间失败");
        IoFreeMdl(g_SharedMdl);
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        return STATUS_NO_MEMORY;
    }
 
    Log("[test] 共享内存初始化成功: 内核地址=%p, 用户地址=%p", g_SharedMemory, pSharedLogBuffer_);
    return STATUS_SUCCESS;
}
 
// 清理共享内存
void CleanupSharedMemory() {
    if (g_SharedLogBuffer) {
        MmUnmapLockedPages(g_SharedLogBuffer, g_SharedMdl);
        g_SharedLogBuffer = NULL;
    }
    if (g_SharedMdl) {
        IoFreeMdl(g_SharedMdl);
        g_SharedMdl = NULL;
    }
    if (g_SharedMemory) {
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        g_SharedMemory = NULL;
    }
}
// 保存原始函数指针
OriginalNtOpenProcess = SSDT[0x23];
 
// 替换为自定义Hook函数
SSDT[0x23] = HookedNtOpenProcess;
 
// Hook函数内部
NTSTATUS HookedNtOpenProcess(...) {
    // 记录日志、收集信息
    ...
    // 调用原始实现
    return OriginalNtOpenProcess(...);
}
// 保存原始函数指针
OriginalNtOpenProcess = SSDT[0x23];
 
// 替换为自定义Hook函数
SSDT[0x23] = HookedNtOpenProcess;
 
// Hook函数内部
NTSTATUS HookedNtOpenProcess(...) {
    // 记录日志、收集信息
    ...
    // 调用原始实现
    return OriginalNtOpenProcess(...);
}
// 线程A执行到这里
NTSTATUS NTAPI FakeNtCreateProcessEx(...) {
    // 此时驱动被卸载,代码段被释放
    // 但线程A还在执行...
 
    NTSTATUS Status = g_NtCreateProcessEx(...);  // 访问已释放的内存!
    // 蓝屏!
    return Status;
}
// 线程A执行到这里
NTSTATUS NTAPI FakeNtCreateProcessEx(...) {
    // 此时驱动被卸载,代码段被释放
    // 但线程A还在执行...
 
    NTSTATUS Status = g_NtCreateProcessEx(...);  // 访问已释放的内存!
    // 蓝屏!
    return Status;
}
volatile LONG RefCount = 0;
 
// Hook函数
NTSTATUS HookedNtOpenProcess(...) {
    InterlockedIncrement(&RefCount); // 进入时原子自增
 
    // ... 记录日志
    NTSTATUS status = OriginalNtOpenProcess(...);
    // ... 其他处理
 
    InterlockedDecrement(&RefCount); // 离开时原子自减
    return status;
}
  
// 卸载时 等待所有函数全部调用完
LARGE_INTEGER Time = { 0 };
Time.QuadPart = 10000;
while (g_nRefCount != 0) {
  KeDelayExecutionThread(KernelMode, FALSE, &Time);
}
volatile LONG RefCount = 0;
 
// Hook函数
NTSTATUS HookedNtOpenProcess(...) {
    InterlockedIncrement(&RefCount); // 进入时原子自增
 
    // ... 记录日志
    NTSTATUS status = OriginalNtOpenProcess(...);
    // ... 其他处理
 
    InterlockedDecrement(&RefCount); // 离开时原子自减
    return status;
}
  
// 卸载时 等待所有函数全部调用完
LARGE_INTEGER Time = { 0 };
Time.QuadPart = 10000;
while (g_nRefCount != 0) {
  KeDelayExecutionThread(KernelMode, FALSE, &Time);
}
typedef struct _HOOK_ENTRY {
    HOOK_SSDT_Index SsdtIndex;      // SSDT服务号
    PVOID* OriginalFunction;        // 原始函数指针的存放地址
    PVOID HookFunction;             // Hook后的函数
    const char* FunctionName;       // 函数名
    BOOLEAN IsHooked;               // 是否已Hook
    LONG RefCount;                  // 正在执行hook的线程数
} HOOK_ENTRY;
 
HOOK_ENTRY g_HookTable[] = {
    { HOOK_CREATE_PROCESS,   (PVOID*)&g_NtCreateProcessEx,  HookedNtCreateProcessEx,  "NtCreateProcessEx",   FALSE, 0 },
    { HOOK_OPEN_PROCESS,     (PVOID*)&g_NtOpenProcess,      HookedNtOpenProcess,      "NtOpenProcess",       FALSE, 0 },
   ...
};
#define HOOK_TABLE_SIZE (sizeof(g_HookTable) / sizeof(HOOK_ENTRY))
typedef struct _HOOK_ENTRY {
    HOOK_SSDT_Index SsdtIndex;      // SSDT服务号
    PVOID* OriginalFunction;        // 原始函数指针的存放地址
    PVOID HookFunction;             // Hook后的函数
    const char* FunctionName;       // 函数名
    BOOLEAN IsHooked;               // 是否已Hook
    LONG RefCount;                  // 正在执行hook的线程数
} HOOK_ENTRY;
 
HOOK_ENTRY g_HookTable[] = {
    { HOOK_CREATE_PROCESS,   (PVOID*)&g_NtCreateProcessEx,  HookedNtCreateProcessEx,  "NtCreateProcessEx",   FALSE, 0 },
    { HOOK_OPEN_PROCESS,     (PVOID*)&g_NtOpenProcess,      HookedNtOpenProcess,      "NtOpenProcess",       FALSE, 0 },
   ...
};
#define HOOK_TABLE_SIZE (sizeof(g_HookTable) / sizeof(HOOK_ENTRY))
NTSTATUS SetHookByFlag(HOOK_SSDT_Index flag) {
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].SsdtIndex == flag && g_HookTable[i].HookFunction) {
            // 检查是否已经被Hook
            if (g_HookTable[i].IsHooked) {
                Log("[test] Hook已存在,跳过: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
                return STATUS_SUCCESS;  // 返回成功,避免重复Hook
            }
             
            // 设置Hook
            *(ULONG*)g_HookTable[i].OriginalFunction = KeServiceDescriptorTable->Base[flag];
            KeServiceDescriptorTable->Base[flag] = (ULONG)g_HookTable[i].HookFunction;
            g_HookTable[i].IsHooked = TRUE;  // 标记为已Hook
             
            Log("[test] Hook设置成功: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
            return STATUS_SUCCESS;
        }
    }
    Log("[test] 未找到Hook项: %d ", flag);
    return STATUS_UNSUCCESSFUL;
}
 
NTSTATUS UnsetHookByFlag(HOOK_SSDT_Index flag) {
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].SsdtIndex == flag && g_HookTable[i].OriginalFunction) {
            // 检查是否已经被Hook
            if (!g_HookTable[i].IsHooked) {
                Log("[test] Hook不存在,跳过: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
                return STATUS_SUCCESS;  // 返回成功,避免重复取消Hook
            }
             
            // 恢复Hook
            KeServiceDescriptorTable->Base[flag] = *(ULONG*)g_HookTable[i].OriginalFunction;
            g_HookTable[i].IsHooked = FALSE;  // 标记为未Hook
             
            Log("[test] Hook恢复成功: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
            return STATUS_SUCCESS;
        }
    }
    return STATUS_UNSUCCESSFUL;
}
     
NTSTATUS NTAPI HookedNtCreateProcessEx(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, HANDLE ParentProcess, ULONG Flags, HANDLE SectionHandle, HANDLE DebugPort, HANDLE ExceptionPort, ULONG JobMemberLevel)
{
    InterlockedIncrement(&g_HookTable[0].RefCount);
 
    NTSTATUS status = STATUS_UNSUCCESSFUL;
 
    //调原函数
    if (g_NtCreateProcessEx) {
        status = g_NtCreateProcessEx(ProcessHandle, DesiredAccess,
            ObjectAttributes, ParentProcess, Flags, SectionHandle,
            DebugPort, ExceptionPort, JobMemberLevel);
    }
 
    //做点什么 拿信息写到共享内存里...
    AddProcessEvent(HOOK_CREATE_PROCESS, *ProcessHandle, status);
 
    InterlockedDecrement(&g_HookTable[0].RefCount);
    return status;
}
NTSTATUS SetHookByFlag(HOOK_SSDT_Index flag) {
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].SsdtIndex == flag && g_HookTable[i].HookFunction) {
            // 检查是否已经被Hook
            if (g_HookTable[i].IsHooked) {
                Log("[test] Hook已存在,跳过: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
                return STATUS_SUCCESS;  // 返回成功,避免重复Hook
            }
             
            // 设置Hook
            *(ULONG*)g_HookTable[i].OriginalFunction = KeServiceDescriptorTable->Base[flag];
            KeServiceDescriptorTable->Base[flag] = (ULONG)g_HookTable[i].HookFunction;
            g_HookTable[i].IsHooked = TRUE;  // 标记为已Hook
             
            Log("[test] Hook设置成功: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
            return STATUS_SUCCESS;
        }
    }
    Log("[test] 未找到Hook项: %d ", flag);
    return STATUS_UNSUCCESSFUL;
}
 
NTSTATUS UnsetHookByFlag(HOOK_SSDT_Index flag) {
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].SsdtIndex == flag && g_HookTable[i].OriginalFunction) {
            // 检查是否已经被Hook
            if (!g_HookTable[i].IsHooked) {
                Log("[test] Hook不存在,跳过: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
                return STATUS_SUCCESS;  // 返回成功,避免重复取消Hook
            }
             
            // 恢复Hook
            KeServiceDescriptorTable->Base[flag] = *(ULONG*)g_HookTable[i].OriginalFunction;
            g_HookTable[i].IsHooked = FALSE;  // 标记为未Hook
             
            Log("[test] Hook恢复成功: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
            return STATUS_SUCCESS;
        }
    }
    return STATUS_UNSUCCESSFUL;
}
     
NTSTATUS NTAPI HookedNtCreateProcessEx(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, HANDLE ParentProcess, ULONG Flags, HANDLE SectionHandle, HANDLE DebugPort, HANDLE ExceptionPort, ULONG JobMemberLevel)
{
    InterlockedIncrement(&g_HookTable[0].RefCount);
 
    NTSTATUS status = STATUS_UNSUCCESSFUL;
 
    //调原函数
    if (g_NtCreateProcessEx) {
        status = g_NtCreateProcessEx(ProcessHandle, DesiredAccess,
            ObjectAttributes, ParentProcess, Flags, SectionHandle,
            DebugPort, ExceptionPort, JobMemberLevel);
    }
 
    //做点什么 拿信息写到共享内存里...
    AddProcessEvent(HOOK_CREATE_PROCESS, *ProcessHandle, status);
 
    InterlockedDecrement(&g_HookTable[0].RefCount);
    return status;
}
typedef struct PROCESS_EVENT {
    CHAR SourceProcessName[16];        // 调用者进程名
    ULONG SourceProcessId;             // 调用者进程ID
    ULONG Action;                      // 动作 (HOOK_SSDT_Index)
    ULONG TargetProcessId;             // targetPID
    LONG Result;                       // 操作结果
} PROCESS_EVENT, * PPROCESS_EVENT;
typedef struct PROCESS_EVENT {
    CHAR SourceProcessName[16];        // 调用者进程名
    ULONG SourceProcessId;             // 调用者进程ID
    ULONG Action;                      // 动作 (HOOK_SSDT_Index)
    ULONG TargetProcessId;             // targetPID
    LONG Result;                       // 操作结果
} PROCESS_EVENT, * PPROCESS_EVENT;
void AddProcessEvent(ULONG Action, HANDLE TargetHandle, NTSTATUS Result){
    PEPROCESS CurrentProcess = PsGetCurrentProcess();// 获取当前进程信息
    HANDLE CurrentPid = PsGetCurrentProcessId();
    PUCHAR CurrentProcessName = PsGetProcessImageFileName(CurrentProcess);
    PLOG_BUFFER pLogBuffer = (PLOG_BUFFER)g_SharedMemory;//写到共享内存
 
    ULONG currentReadIndex = pLogBuffer->ReadIndex;
 
    // 获取目标进程PID
    ULONG TargetPid = 0;
    if (TargetHandle) {
        PEPROCESS TargetProcess = NULL;
        NTSTATUS lookupStatus = ObReferenceObjectByHandle(TargetHandle,
            PROCESS_QUERY_INFORMATION,
            *PsProcessType,
            KernelMode,
            (PVOID*)&TargetProcess,
            NULL);
 
        if (NT_SUCCESS(lookupStatus)) {
            TargetPid = (ULONG)PsGetProcessId(TargetProcess);
            ObDereferenceObject(TargetProcess);
        }
    }
 
    //写入共享内存...
}
void AddProcessEvent(ULONG Action, HANDLE TargetHandle, NTSTATUS Result){
    PEPROCESS CurrentProcess = PsGetCurrentProcess();// 获取当前进程信息
    HANDLE CurrentPid = PsGetCurrentProcessId();
    PUCHAR CurrentProcessName = PsGetProcessImageFileName(CurrentProcess);
    PLOG_BUFFER pLogBuffer = (PLOG_BUFFER)g_SharedMemory;//写到共享内存
 
    ULONG currentReadIndex = pLogBuffer->ReadIndex;
 
    // 获取目标进程PID
    ULONG TargetPid = 0;
    if (TargetHandle) {
        PEPROCESS TargetProcess = NULL;
        NTSTATUS lookupStatus = ObReferenceObjectByHandle(TargetHandle,
            PROCESS_QUERY_INFORMATION,
            *PsProcessType,
            KernelMode,
            (PVOID*)&TargetProcess,
            NULL);
 
        if (NT_SUCCESS(lookupStatus)) {
            TargetPid = (ULONG)PsGetProcessId(TargetProcess);
            ObDereferenceObject(TargetProcess);
        }
    }
 
    //写入共享内存...
}
+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
  ^                   ^
ReadIndex         WriteIndex
+---+---+---+---+---+---+---+---+
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+---+---+---+---+---+---+---+---+
  ^                   ^
ReadIndex         WriteIndex
typedef struct PROCESS_EVENT {
    CHAR SourceProcessName[16];        // 调用者进程名
    ULONG SourceProcessId;             // 调用者进程ID
    ULONG Action;                      // 动作 (HOOK_SSDT_Index)
    ULONG TargetProcessId;             // targetPID
    LONG Result;                       // 操作结果
} PROCESS_EVENT, * PPROCESS_EVENT;
typedef struct PROCESS_EVENT {
    CHAR SourceProcessName[16];        // 调用者进程名
    ULONG SourceProcessId;             // 调用者进程ID
    ULONG Action;                      // 动作 (HOOK_SSDT_Index)
    ULONG TargetProcessId;             // targetPID
    LONG Result;                       // 操作结果
} PROCESS_EVENT, * PPROCESS_EVENT;
VOID Unload(__in struct _DRIVER_OBJECT* DriverObject)
{
    UNREFERENCED_PARAMETER(DriverObject);
    UNICODE_STRING usSymbolicLinkName;
 
    // 先恢复所有Hook
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].IsHooked) {
            UnsetHookByFlag(g_HookTable[i].SsdtIndex);
            Log("[test] 恢复Hook: %s", g_HookTable[i].FunctionName);
        }
    }
 
    // 等待所有Hook函数调用完成
    LARGE_INTEGER Time = { 0 };
    Time.QuadPart = -100000;  // 10ms (负数表示相对时间)
     
    Log("[test] 开始等待Hook函数调用完成...");
     
    while (1) {
        BOOLEAN allClear = TRUE;
         
        // 检查所有Hook的引用计数
        for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
            if (g_HookTable[i].RefCount > 0) {
                allClear = FALSE;
                break;
            }
        }
         
        if (allClear) {
            break;
        }
         
        KeDelayExecutionThread(KernelMode, FALSE, &Time);  
    }
     
 
    // 删除符号链接
    RtlInitUnicodeString(&usSymbolicLinkName, SYMBOL_NAME);
    IoDeleteSymbolicLink(&usSymbolicLinkName);
 
    // 删除设备对象
    if (DriverObject->DeviceObject != nullptr) {
        IoDeleteDevice(DriverObject->DeviceObject);
    }
 
    Log("[test] Unload 完成 ");
}
VOID Unload(__in struct _DRIVER_OBJECT* DriverObject)
{
    UNREFERENCED_PARAMETER(DriverObject);
    UNICODE_STRING usSymbolicLinkName;
 
    // 先恢复所有Hook
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].IsHooked) {
            UnsetHookByFlag(g_HookTable[i].SsdtIndex);
            Log("[test] 恢复Hook: %s", g_HookTable[i].FunctionName);
        }
    }
 
    // 等待所有Hook函数调用完成
    LARGE_INTEGER Time = { 0 };
    Time.QuadPart = -100000;  // 10ms (负数表示相对时间)
     
    Log("[test] 开始等待Hook函数调用完成...");
     
    while (1) {
        BOOLEAN allClear = TRUE;
         
        // 检查所有Hook的引用计数
        for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
            if (g_HookTable[i].RefCount > 0) {
                allClear = FALSE;
                break;
            }
        }
         
        if (allClear) {
            break;
        }
         
        KeDelayExecutionThread(KernelMode, FALSE, &Time);  
    }
     
 
    // 删除符号链接
    RtlInitUnicodeString(&usSymbolicLinkName, SYMBOL_NAME);
    IoDeleteSymbolicLink(&usSymbolicLinkName);
 
    // 删除设备对象
    if (DriverObject->DeviceObject != nullptr) {
        IoDeleteDevice(DriverObject->DeviceObject);
    }
 
    Log("[test] Unload 完成 ");
}
//R0的
 
//NTSTATUS DispatchDeviceControl中
case CTL_START_SSDTHOOK:
    {
        PHOOK_SSDT_Index pIndex = (PHOOK_SSDT_Index)Irp->AssociatedIrp.SystemBuffer;
        __try {
 
            //第一次开启hook时初始化共享内存
            if (g_isInitShareMemory == false) {
                InitSharedMemory();
                g_isInitShareMemory = true;
            }
 
            HOOK_SSDT_Index index = *pIndex;
 
            Log("[test] CTL_START_SSDTHOOK: index=%d funcname=%s ", index, GetHookNameByIndex(index));
 
            status = SetHookByFlag(index);
 
            if (NT_SUCCESS(status)) {
                //将共享内存地址复制到输出缓冲区
                    * (PVOID*)Irp->AssociatedIrp.SystemBuffer = pSharedLogBuffer_;
                info = sizeof(pSharedLogBuffer_);
                Log("[test]返回共享内存地址: %p ", pSharedLogBuffer_);
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            status = STATUS_UNSUCCESSFUL;
            Log("[test] CTL_START_SSDTHOOK exception ");
        }
    }
    break;
    case CTL_END_SSDTHOOK:
    {
        PHOOK_SSDT_Index pIndex = (PHOOK_SSDT_Index)Irp->AssociatedIrp.SystemBuffer;
        __try {
            HOOK_SSDT_Index index = *pIndex;
            Log("[test] CTL_END_SSDTHOOK: index=%d funcname=%s", index, GetHookNameByIndex(index));
 
            status = UnsetHookByFlag(index);
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            status = STATUS_UNSUCCESSFUL;
            Log("[test] CTL_START_SSDTHOOK exception ");
        }
    }
    break;
 
 
NTSTATUS(NTAPI* g_NtCreateProcessEx)(
    __out PHANDLE ProcessHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in HANDLE ParentProcess,
    __in ULONG Flags,
    __in_opt HANDLE SectionHandle,
    __in_opt HANDLE DebugPort,
    __in_opt HANDLE ExceptionPort,
    __in ULONG JobMemberLevel
    );
 
NTSTATUS(NTAPI* g_NtOpenProcess)(
    __out PHANDLE ProcessHandle,
    __in ACCESS_MASK DesiredAccess,
    __in POBJECT_ATTRIBUTES ObjectAttributes,
    __in_opt PCLIENT_ID ClientId
    );
 
NTSTATUS(NTAPI* g_NtDebugActiveProcess)(
    __in HANDLE ProcessHandle,
    __in HANDLE DebugObjectHandle
    );
 
NTSTATUS(NTAPI* g_NtSuspendProcess)(
    __in_opt HANDLE ProcessHandle
    );
 
NTSTATUS(NTAPI* g_NtResumeProcess)(
    __in_opt HANDLE ProcessHandle
    );
 
NTSTATUS(NTAPI* g_NtTerminateProcess)(
    __in_opt HANDLE ProcessHandle,
    __in NTSTATUS ExitStatus
    );
 
 
typedef struct _HOOK_ENTRY {
    HOOK_SSDT_Index SsdtIndex;
    PVOID* OriginalFunction;
    PVOID HookFunction;
    const char* FunctionName;
    BOOLEAN IsHooked;
    LONG RefCount;
} HOOK_ENTRY;
 
HOOK_ENTRY g_HookTable[] = {
    { HOOK_CREATE_PROCESS,   (PVOID*)&g_NtCreateProcessEx,  HookedNtCreateProcessEx,  "NtCreateProcessEx",   FALSE, 0 },
    { HOOK_OPEN_PROCESS,     (PVOID*)&g_NtOpenProcess,      HookedNtOpenProcess,      "NtOpenProcess",       FALSE, 0 },
    { HOOK_DEBUG_PROCESS,    (PVOID*)&g_NtDebugActiveProcess, HookedNtDebugActiveProcess, "NtDebugActiveProcess", FALSE, 0 },
    { HOOK_SUSPEND_PROCESS,  (PVOID*)&g_NtSuspendProcess,   HookedNtSuspendProcess,   "NtSuspendProcess",    FALSE, 0 },
    { HOOK_RESUME_PROCESS,   (PVOID*)&g_NtResumeProcess,    HookedNtResumeProcess,    "NtResumeProcess",     FALSE, 0 },
    { HOOK_TERMINATE_PROCESS, (PVOID*)&g_NtTerminateProcess, HookedNtTerminateProcess, "NtTerminateProcess",  FALSE, 0 }
};
#define HOOK_TABLE_SIZE (sizeof(g_HookTable) / sizeof(HOOK_ENTRY))
 
// 根据SSDT索引获取函数名
const char* GetHookNameByIndex(HOOK_SSDT_Index index) {
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].SsdtIndex == index) {
            return g_HookTable[i].FunctionName;
        }
    }
    return "Unknown";
}
 
void AddProcessEvent(ULONG Action, HANDLE TargetHandle, NTSTATUS Result)
{
    if (!g_SharedMemory) {
        Log("[EVENT] 错误:g_SharedMemory 为空");
        return;
    }
 
    // 获取当前进程信息
    PEPROCESS CurrentProcess = PsGetCurrentProcess();
    HANDLE CurrentPid = PsGetCurrentProcessId();
    PUCHAR CurrentProcessName = PsGetProcessImageFileName(CurrentProcess);
    PLOG_BUFFER pLogBuffer = (PLOG_BUFFER)g_SharedMemory;
 
    ULONG currentReadIndex = pLogBuffer->ReadIndex;
 
    // 获取目标进程PID
    ULONG TargetPid = 0;
    if (TargetHandle) {
        PEPROCESS TargetProcess = NULL;
        NTSTATUS lookupStatus = ObReferenceObjectByHandle(TargetHandle,
            PROCESS_QUERY_INFORMATION,
            *PsProcessType,
            KernelMode,
            (PVOID*)&TargetProcess,
            NULL);
 
        if (NT_SUCCESS(lookupStatus)) {
            TargetPid = (ULONG)PsGetProcessId(TargetProcess);
            ObDereferenceObject(TargetProcess);
        }
    }
 
    // 计算下一个写入位置
    ULONG nextWriteIndex = (pLogBuffer->WriteIndex + 1) % 1000;
    // Log("[EVENT] 检测,nextWriteIndex:%d currentReadIndex:%d", nextWriteIndex, currentReadIndex);
 
    // 如果写入位置追上读取位置,移动读取索引
    if (nextWriteIndex == currentReadIndex) {
        Log("[EVENT] 缓冲区满,nextWriteIndex:%d currentReadIndex:%d", nextWriteIndex, currentReadIndex);
        pLogBuffer->ReadIndex = (currentReadIndex + 1) % 1000;
    }
 
    // 写入数据到WriteIndex
    PPROCESS_EVENT pEvent = &pLogBuffer->Logs[pLogBuffer->WriteIndex];
    pEvent->Action = Action;
    pEvent->SourceProcessId = (ULONG)CurrentPid;
    pEvent->TargetProcessId = TargetPid;
    pEvent->Result = Result;
    RtlStringCbCopyA(pEvent->SourceProcessName, sizeof(pEvent->SourceProcessName), (const char*)CurrentProcessName);
 
    // 更新写入索引
    pLogBuffer->WriteIndex = nextWriteIndex;
 
    Log("[EVENT]   Action=%d, SourcePid=%d, TargetPid=%d, Result=0x%08X,SourceName=%s",
        pEvent->Action, pEvent->SourceProcessId, pEvent->TargetProcessId, pEvent->Result,pEvent->SourceProcessName);
 
    //日志数量++
    if (pLogBuffer->LogCount < 1000) {
        InterlockedIncrement((LONG*)&pLogBuffer->LogCount);
    }
}
 
NTSTATUS SetHookByFlag(HOOK_SSDT_Index flag) {
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].SsdtIndex == flag && g_HookTable[i].HookFunction) {
            // 检查是否已经被Hook
            if (g_HookTable[i].IsHooked) {
                Log("[test] Hook已存在,跳过: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
                return STATUS_SUCCESS;  // 返回成功,避免重复Hook
            }
             
            // 设置Hook
            *(ULONG*)g_HookTable[i].OriginalFunction = KeServiceDescriptorTable->Base[flag];
            KeServiceDescriptorTable->Base[flag] = (ULONG)g_HookTable[i].HookFunction;
            g_HookTable[i].IsHooked = TRUE;  // 标记为已Hook
             
            Log("[test] Hook设置成功: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
            return STATUS_SUCCESS;
        }
    }
    Log("[test] 未找到Hook项: %d ", flag);
    return STATUS_UNSUCCESSFUL;
}
 
NTSTATUS UnsetHookByFlag(HOOK_SSDT_Index flag) {
    for (ULONG i = 0; i < HOOK_TABLE_SIZE; i++) {
        if (g_HookTable[i].SsdtIndex == flag && g_HookTable[i].OriginalFunction) {
            // 检查是否已经被Hook
            if (!g_HookTable[i].IsHooked) {
                Log("[test] Hook不存在,跳过: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
                return STATUS_SUCCESS;  // 返回成功,避免重复取消Hook
            }
             
            // 恢复Hook
            KeServiceDescriptorTable->Base[flag] = *(ULONG*)g_HookTable[i].OriginalFunction;
            g_HookTable[i].IsHooked = FALSE;  // 标记为未Hook
             
            Log("[test] Hook恢复成功: %s (索引:%d) ", g_HookTable[i].FunctionName, flag);
            return STATUS_SUCCESS;
        }
    }
    return STATUS_UNSUCCESSFUL;
}
 
// 初始化共享内存
NTSTATUS InitSharedMemory() {
 
    // 分配内核内存
    g_SharedMemory = ExAllocatePoolWithTag(NonPagedPool, sizeof(LOG_BUFFER), 'SLOG');
    if (!g_SharedMemory) {
        Log("[test] InitSharedMemory: !g_SharedMemory");
        return STATUS_NO_MEMORY;
    }
 
    RtlZeroMemory(g_SharedMemory, sizeof(LOG_BUFFER));
 
    // 创建MDL
    g_SharedMdl = IoAllocateMdl(g_SharedMemory, sizeof(LOG_BUFFER), FALSE, FALSE, NULL);
    if (!g_SharedMdl) {
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        Log("[test] InitSharedMemory: IoAllocateMdl STATUS_NO_MEMORY");
        return STATUS_NO_MEMORY;
    }
 
    // 构建MDL
    MmBuildMdlForNonPagedPool(g_SharedMdl);
 
    // 映射到用户空间
    pSharedLogBuffer_ = MmMapLockedPagesSpecifyCache(g_SharedMdl, UserMode,
        MmNonCached, NULL, FALSE, NormalPagePriority);
    if (!pSharedLogBuffer_) {
        Log("[test] InitSharedMemory: 映射到用户空间失败");
        IoFreeMdl(g_SharedMdl);
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        return STATUS_NO_MEMORY;
    }
 
    Log("[test] 共享内存初始化成功: 内核地址=%p, 用户地址=%p", g_SharedMemory, pSharedLogBuffer_);
    return STATUS_SUCCESS;
}
 
// 清理共享内存
void CleanupSharedMemory() {
    if (pSharedLogBuffer_) {
        MmUnmapLockedPages(pSharedLogBuffer_, g_SharedMdl);
        pSharedLogBuffer_ = NULL;
    }
    if (g_SharedMdl) {
        IoFreeMdl(g_SharedMdl);
        g_SharedMdl = NULL;
    }
    if (g_SharedMemory) {
        ExFreePoolWithTag(g_SharedMemory, 'SLOG');
        g_SharedMemory = NULL;
    }
}
//R0的
 
//NTSTATUS DispatchDeviceControl中
case CTL_START_SSDTHOOK:
    {
        PHOOK_SSDT_Index pIndex = (PHOOK_SSDT_Index)Irp->AssociatedIrp.SystemBuffer;
        __try {
 
            //第一次开启hook时初始化共享内存
            if (g_isInitShareMemory == false) {
                InitSharedMemory();
                g_isInitShareMemory = true;
            }
 
            HOOK_SSDT_Index index = *pIndex;
 
            Log("[test] CTL_START_SSDTHOOK: index=%d funcname=%s ", index, GetHookNameByIndex(index));
 
            status = SetHookByFlag(index);
 
            if (NT_SUCCESS(status)) {
                //将共享内存地址复制到输出缓冲区
                    * (PVOID*)Irp->AssociatedIrp.SystemBuffer = pSharedLogBuffer_;
                info = sizeof(pSharedLogBuffer_);
                Log("[test]返回共享内存地址: %p ", pSharedLogBuffer_);
            }
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            status = STATUS_UNSUCCESSFUL;
            Log("[test] CTL_START_SSDTHOOK exception ");
        }
    }
    break;
    case CTL_END_SSDTHOOK:
    {
        PHOOK_SSDT_Index pIndex = (PHOOK_SSDT_Index)Irp->AssociatedIrp.SystemBuffer;
        __try {
            HOOK_SSDT_Index index = *pIndex;
            Log("[test] CTL_END_SSDTHOOK: index=%d funcname=%s", index, GetHookNameByIndex(index));
 
            status = UnsetHookByFlag(index);
        }
        __except (EXCEPTION_EXECUTE_HANDLER) {
            status = STATUS_UNSUCCESSFUL;
            Log("[test] CTL_START_SSDTHOOK exception ");
        }
    }
    break;
 
 
NTSTATUS(NTAPI* g_NtCreateProcessEx)(
    __out PHANDLE ProcessHandle,
    __in ACCESS_MASK DesiredAccess,
    __in_opt POBJECT_ATTRIBUTES ObjectAttributes,
    __in HANDLE ParentProcess,
    __in ULONG Flags,
    __in_opt HANDLE SectionHandle,
    __in_opt HANDLE DebugPort,
    __in_opt HANDLE ExceptionPort,
    __in ULONG JobMemberLevel
    );
 
NTSTATUS(NTAPI* g_NtOpenProcess)(
    __out PHANDLE ProcessHandle,
    __in ACCESS_MASK DesiredAccess,
    __in POBJECT_ATTRIBUTES ObjectAttributes,
    __in_opt PCLIENT_ID ClientId
    );
 
NTSTATUS(NTAPI* g_NtDebugActiveProcess)(
    __in HANDLE ProcessHandle,
    __in HANDLE DebugObjectHandle
    );
 
NTSTATUS(NTAPI* g_NtSuspendProcess)(
    __in_opt HANDLE ProcessHandle
    );
 
NTSTATUS(NTAPI* g_NtResumeProcess)(
    __in_opt HANDLE ProcessHandle
    );
 
NTSTATUS(NTAPI* g_NtTerminateProcess)(
    __in_opt HANDLE ProcessHandle,
    __in NTSTATUS ExitStatus
    );
 
 

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-8-13 21:39 被X66iaM编辑 ,原因:
收藏
免费 12
支持
分享
最新回复 (6)
雪    币: 961
活跃值: (1821)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2

写完感觉基础不行

最后于 2025-7-22 22:38 被X66iaM编辑 ,原因:
2025-7-22 01:16
0
雪    币: 0
活跃值: (728)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢,不错。
2025-7-22 03:02
0
雪    币: 2815
活跃值: (12067)
能力值: (RANK:385 )
在线值:
发帖
回帖
粉丝
4
初始化函数放在了DriverEntry,排查了好几个小时 
2025-7-22 09:53
1
雪    币: 2653
活跃值: (7246)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
谢谢分享
2025-9-19 07:42
0
雪    币: 201
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
2312
2025-10-6 16:36
0
雪    币: 205
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
谢谢分享
1天前
0
游客
登录 | 注册 方可回帖
返回