根据提供的文件信息,本文将详细解释如何在Windows内核模式下获取特定系统调用的当前地址与原始地址,以及如何实现这些操作的具体方法。 ### 一、获取函数当前地址 在Windows内核模式编程中,有时我们需要获取某些系统服务例程(即系统调用)的地址,以便进行调试或Hook等操作。下面我们将详细分析如何获取函数当前地址,并对代码进行逐行解释。 #### 1.1 获取当前地址的函数实现 ```c ULONG GetFunctionAddr(PCWSTR str) { UNICODE_STRING Old_NtProcess; ULONG Old_Addr; RtlInitUnicodeString(&Old_NtProcess, str); Old_Addr = (ULONG)MmGetSystemRoutineAddress(&Old_NtProcess); // 获取NtOpenProcess的地址 return Old_Addr; } ``` **函数说明**: 该函数用于获取指定系统服务例程的地址。其参数为一个宽字符字符串,通常表示所需服务例程的名字。 **变量说明**: - `UNICODE_STRING Old_NtProcess;`:定义了一个`UNICODE_STRING`类型的结构体变量,用来存储服务例程名称。 - `ULONG Old_Addr;`:定义了一个`ULONG`类型变量,用于存放获取到的服务例程地址。 **关键步骤解析**: 1. **初始化字符串**: ```c RtlInitUnicodeString(&Old_NtProcess, str); ``` 这一行代码使用RtlInitUnicodeString函数初始化`Old_NtProcess`结构体,其中`str`为服务例程名称的指针。 2. **获取服务例程地址**: ```c Old_Addr = (ULONG)MmGetSystemRoutineAddress(&Old_NtProcess); ``` 使用`MmGetSystemRoutineAddress`函数来获取由`Old_NtProcess`指定的服务例程的地址,并将其转换为`ULONG`类型赋值给`Old_Addr`变量。 #### 1.2 Hook函数实现 接下来,我们来看如何通过调用`GetFunctionAddr`函数获取多个系统服务例程的地址。 ```c VOID Hook_() { // 获取当前地址 ULONG t_addr; t_addr = (ULONG)KeServiceDescriptorTable->ServiceTableBase; g_NtOpenProcess = *(PULONG)(t_addr + 0x7A * 4); g_NtOpenThread = *(PULONG)(t_addr + 0x80 * 4); g_NtReadVirtualMemory = *(PULONG)(t_addr + 0xBA * 4); g_NtWriteVirtualMemory = *(PULONG)(t_addr + 0x115 * 4); // 获取原始地址 g_KiAttachProcess = GetFunctionAddr(L"KeAttachProcess"); g_PsCreateSystemThread = GetFunctionAddr(L"PsCreateSystemThread"); // 输出结果 if (g_NtOpenProcess) { DbgPrint("NtOpenProcess地址:%08X\n", g_NtOpenProcess); } else { DbgPrint("获取NtOpenProcess地址失败"); } // 其他系统服务例程的处理逻辑类似 } ``` **函数说明**: `Hook_()`函数用于获取一系列常用系统服务例程的当前地址和原始地址。 **变量说明**: - `ULONG t_addr;`:定义了一个`ULONG`类型变量,用于存储服务描述符表基址。 - `g_NtOpenProcess`, `g_NtOpenThread`, `g_NtReadVirtualMemory`, `g_NtWriteVirtualMemory`: 定义了一系列全局变量,分别用来存储获取到的系统服务例程地址。 **关键步骤解析**: 1. **获取服务描述符表基址**: ```c t_addr = (ULONG)KeServiceDescriptorTable->ServiceTableBase; ``` 这一行代码获取了服务描述符表基址,并将其转换为`ULONG`类型赋值给`t_addr`。 2. **计算系统服务例程地址**: 通过偏移量计算出各个系统服务例程的地址,并将其保存到相应的全局变量中。 3. **调用`GetFunctionAddr`函数获取原始地址**: 调用`GetFunctionAddr`函数来获取`KeAttachProcess`和`PsCreateSystemThread`的原始地址。 4. **输出结果**: 使用`DbgPrint`函数输出获取到的地址信息。 ### 总结 本文详细介绍了如何在Windows内核模式下获取特定系统服务例程的当前地址和原始地址。首先通过`MmGetSystemRoutineAddress`函数获取原始地址,然后利用服务描述符表基址计算当前地址。这种方法对于内核驱动开发、系统安全等领域具有重要的应用价值。理解这些技术细节有助于深入掌握Windows内核编程的基础知识。
{
UNICODE_STRING Old_NtProcess;
ULONG Old_Addr;
RtlInitUnicodeString(&Old_NtProcess,str);
Old_Addr=(ULONG)MmGetSystemRoutineAddress(&Old_NtProcess);//取得NtOpenProcess的地址
//KdPrint(("取得原函数NtOpenProcess的值为 %x",Old_Addr));
return Old_Addr;
}
VOID Hook_()
{
//获取函数当前地址
ULONG t_addr;
t_addr=(ULONG)KeServiceDescriptorTable->ServiceTableBase;
g_NtOpenProcess = *(PULONG)(t_addr+0x7A*4);
g_NtOpenThread = *(PULONG)(t_addr+0x80*4);//KeServiceDescriptorTable->ServiceTableBase[0x80*4];
g_NtReadVirtualMemory = *(PULONG)(t_addr+0xBA*4);//KeServiceDescriptorTable->ServiceTableBase[0xBA*4];
g_NtWriteVirtualMemory = *(PULONG)(t_addr+0x115*4);//KeServiceDescriptorTable->ServiceTableBase[0x115*4];
//获取函数原地址
g_KiAttachProcess = GetFunctionAddr(L"KeAttachProcess");
g_PsCreateSystemThread = GetFunctionAddr(L"PsCreateSystemThread");
if (g_NtOpenProcess)
{
//memcpy((PVOID)g_NtOpenProcessSave, (PVOID)g_NtOpenProcess, sizeof(g_NtOpenProcessSave));
DbgPrint("NtOpenProcess 地址:%08X\n", g_NtOpenProcess);
}
else
{
- 粉丝: 0
- 资源: 1
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助