驱动开发:内核枚举PspCidTable句柄表( 三 )

运行后即可得到动态地址,我们可以验证一下是否一致:

驱动开发:内核枚举PspCidTable句柄表

文章插图
继续增加对与三级表的动态解析代码 , 最终代码如下所示:
#include <ntifs.h>#include <windef.h>// 获取 PspCidTable// By: LyShark.comBOOLEAN get_PspCidTable(ULONG64* tableAddr){ // 获取 PsLookupProcessByProcessId 地址 UNICODE_STRING uc_funcName; RtlInitUnicodeString(&uc_funcName, L"PsLookupProcessByProcessId"); ULONG64 ul_funcAddr = MmGetSystemRoutineAddress(&uc_funcName); if (ul_funcAddr == NULL) {return FALSE; } DbgPrint("PsLookupProcessByProcessId addr = %p \n", ul_funcAddr); // 前 40 字节有 call(PspReferenceCidTableEntry) /* 0: kd> uf PsLookupProcessByProcessIdnt!PsLookupProcessByProcessId:fffff802`0841cfe0 48895c2418      mov     qword ptr [rsp+18h],rbxfffff802`0841cfe5 56              push    rsifffff802`0841cfe6 4883ec20        sub     rsp,20hfffff802`0841cfea 48897c2438      mov     qword ptr [rsp+38h],rdifffff802`0841cfef 488bf2          mov     rsi,rdxfffff802`0841cff2 65488b3c2588010000 mov   rdi,qword ptr gs:[188h]fffff802`0841cffb 66ff8fe6010000  dec     word ptr [rdi+1E6h]fffff802`0841d002 b203            mov     dl,3fffff802`0841d004 e887000000      call    nt!PspReferenceCidTableEntry (fffff802`0841d090)fffff802`0841d009 488bd8          mov     rbx,raxfffff802`0841d00c 4885c0          test    rax,raxfffff802`0841d00f 7435            je      nt!PsLookupProcessByProcessId+0x66 (fffff802`0841d046)  Branch */ ULONG64 ul_entry = 0; for (INT i = 0; i < 100; i++) {// fffff802`0841d004 e8 87 00 00 00      call    nt!PspReferenceCidTableEntry (fffff802`0841d090)if (*(PUCHAR)(ul_funcAddr + i) == 0xe8){ul_entry = ul_funcAddr + i;break;} } if (ul_entry != 0) {// 解析 call 地址INT i_callCode = *(INT*)(ul_entry + 1);DbgPrint("i_callCode = %p \n", i_callCode);ULONG64 ul_callJmp = ul_entry + i_callCode + 5;DbgPrint("ul_callJmp = %p \n", ul_callJmp);// 来到 call(PspReferenceCidTableEntry) 内找 PspCidTable/*0: kd> uf PspReferenceCidTableEntrynt!PspReferenceCidTableEntry+0x115:fffff802`0841d1a5 488b0d8473f5ff  mov     rcx,qword ptr [nt!PspCidTable (fffff802`08374530)]fffff802`0841d1ac b801000000      mov     eax,1fffff802`0841d1b1 f0480fc107      lock xadd qword ptr [rdi],raxfffff802`0841d1b6 4883c130        add     rcx,30hfffff802`0841d1ba f0830c2400      lock or dword ptr [rsp],0fffff802`0841d1bf 48833900        cmp     qword ptr [rcx],0fffff802`0841d1c3 0f843fffffff    je      nt!PspReferenceCidTableEntry+0x78 (fffff802`0841d108)  Branch*/for (INT i = 0; i < 0x120; i++){// fffff802`0841d1a5 48 8b 0d 84 73 f5 ff  mov     rcx,qword ptr [nt!PspCidTable (fffff802`08374530)]if (*(PUCHAR)(ul_callJmp + i) == 0x48 && *(PUCHAR)(ul_callJmp + i + 1) == 0x8b && *(PUCHAR)(ul_callJmp + i + 2) == 0x0d){// 解析 mov 地址INT i_movCode = *(INT*)(ul_callJmp + i + 3);DbgPrint("i_movCode = %p \n", i_movCode);ULONG64 ul_movJmp = ul_callJmp + i + i_movCode + 7;DbgPrint("ul_movJmp = %p \n", ul_movJmp);// 得到 PspCidTable*tableAddr = ul_movJmp;return TRUE;}} } return FALSE;}/* 解析一级表// By: LyShark.comBaseAddr:一级表的基地址index1:第几个一级表index2:第几个二级表*/VOID parse_table_1(ULONG64 BaseAddr, INT index1, INT index2){ // 遍历一级表(每个表项大小 16 ) , 表大小 4k,所以遍历 4096/16 = 526 次 PEPROCESS p_eprocess = NULL; PETHREAD p_ethread = NULL; INT i_id = 0; for (INT i = 0; i < 256; i++) {if (!MmIsAddressValid((PVOID64)(BaseAddr + i * 16))){DbgPrint("非法地址= %p \n", BaseAddr + i * 16);continue;}ULONG64 ul_recode = *(PULONG64)(BaseAddr + i * 16);// 解密ULONG64 ul_decode = (LONG64)ul_recode >> 0x10;ul_decode &= 0xfffffffffffffff0;// 判断是进程还是线程i_id = i * 4 + 1024 * index1 + 512 * index2 * 1024;if (PsLookupProcessByProcessId(i_id, &p_eprocess) == STATUS_SUCCESS){DbgPrint("进程PID: %d | ID: %d | 内存地址: %p | 对象: %p \n", i_id, i, BaseAddr + i * 0x10, ul_decode);}else if (PsLookupThreadByThreadId(i_id, &p_ethread) == STATUS_SUCCESS){DbgPrint("线程TID: %d | ID: %d | 内存地址: %p | 对象: %p \n", i_id, i, BaseAddr + i * 0x10, ul_decode);} }}/* 解析二级表// By: LyShark.comBaseAddr:二级表基地址index2:第几个二级表*/VOID parse_table_2(ULONG64 BaseAddr, INT index2){ // 遍历二级表(每个表项大小 8),表大小 4k,所以遍历 4096/8 = 512 次 ULONG64 ul_baseAddr_1 = 0; for (INT i = 0; i < 512; i++) {if (!MmIsAddressValid((PVOID64)(BaseAddr + i * 8))){DbgPrint("非法二级表指针(1):%p \n", BaseAddr + i * 8);continue;}if (!MmIsAddressValid((PVOID64)*(PULONG64)(BaseAddr + i * 8))){DbgPrint("非法二级表指针(2):%p \n", BaseAddr + i * 8);continue;}ul_baseAddr_1 = *(PULONG64)(BaseAddr + i * 8);parse_table_1(ul_baseAddr_1, i, index2); }}/* 解析三级表// By: LyShark.comBaseAddr:三级表基地址*/VOID parse_table_3(ULONG64 BaseAddr){ // 遍历三级表(每个表项大小 8),表大小 4k , 所以遍历 4096/8 = 512 次 ULONG64 ul_baseAddr_2 = 0; for (INT i = 0; i < 512; i++) {if (!MmIsAddressValid((PVOID64)(BaseAddr + i * 8))){continue;}if (!MmIsAddressValid((PVOID64)* (PULONG64)(BaseAddr + i * 8))){continue;}ul_baseAddr_2 = *(PULONG64)(BaseAddr + i * 8);parse_table_2(ul_baseAddr_2, i); }}VOID UnDriver(PDRIVER_OBJECT driver){ DbgPrint(("Uninstall Driver Is OK \n"));}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){ DbgPrint(("hello lyshark.com \n")); ULONG64 tableAddr = 0; get_PspCidTable(&tableAddr); DbgPrint("PspCidTable Address = %p \n", tableAddr); // 获取 _HANDLE_TABLE 的 TableCode ULONG64 ul_tableCode = *(PULONG64)(((ULONG64)*(PULONG64)tableAddr) + 8); DbgPrint("ul_tableCode = %p \n", ul_tableCode); // 取低 2位(二级制11 = 3) INT i_low2 = ul_tableCode & 3; DbgPrint("i_low2 = %X \n", i_low2); // 一级表 if (i_low2 == 0) {// TableCode 低 2位抹零(二级制11 = 3)parse_table_1(ul_tableCode & (~3), 0, 0); } // 二级表 else if (i_low2 == 1) {// TableCode 低 2位抹零(二级制11 = 3)parse_table_2(ul_tableCode & (~3), 0); } // 三级表 else if (i_low2 == 2) {// TableCode 低 2位抹零(二级制11 = 3)parse_table_3(ul_tableCode & (~3)); } else {DbgPrint("LyShark提示: 错误,非法! ");return FALSE; } Driver->DriverUnload = UnDriver; return STATUS_SUCCESS;}

推荐阅读