驱动开发:内核枚举DpcTimer定时器( 二 )

如上汇编代码KiSetTimerEx中就是DPC加密细节 , 如果需要解密只需要逆操作即可 , 此处我就具体分析下加密细节 , 分析这个东西我建议你使用记事本带着色的 。
分析思路是这样的 , 首先这里要传入待加密的DPC数据 , 然后经过KiWaitNeverKiWaitAlways对数据进行xor,ror,bswap等操作 。

驱动开发:内核枚举DpcTimer定时器

文章插图
将解密流程通过代码的方式实现 。
#include <ntddk.h>#include <ntstrsafe.h>// 解密DPCvoid DPC_Print(PKTIMER ptrTimer){ULONG_PTR ptrDpc = (ULONG_PTR)ptrTimer->Dpc;KDPC* DecDpc = NULL;DWORD nShift = (p2dq(ptrKiWaitNever) & 0xFF);// _RSI->Dpc = (_KDPC *)v19;// _RSI = Timer;ptrDpc ^= p2dq(ptrKiWaitNever);// v19 = KiWaitNever ^ v18;ptrDpc = _rotl64(ptrDpc, nShift);// v18 = __ROR8__((unsigned __int64)Timer ^ _RBX, KiWaitNever);ptrDpc ^= (ULONG_PTR)ptrTimer;ptrDpc = _byteswap_uint64(ptrDpc);// __asm { bswaprbx }ptrDpc ^= p2dq(ptrKiWaitAlways);// _RBX = (unsigned __int64)DPC ^ KiWaitAlways;// real DPCif (MmIsAddressValid((PVOID)ptrDpc)){DecDpc = (KDPC*)ptrDpc;DbgPrint("DPC = %p | routine = %p \n", DecDpc, DecDpc->DeferredRoutine);}}VOID UnDriver(PDRIVER_OBJECT driver){DbgPrint("卸载完成... \n");}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){DbgPrint("hello lyshark.com");PKTIMER ptrTimer = NULL;DPC_Print(ptrTimer);Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}接着将这些功能通过代码实现 , 首先得到我们需要的函数地址 , 这些地址包括 。
ULONG_PTR ptrKiProcessorBlock = 0xfffff80770a32cc0;ULONG_PTR ptrOffsetKTimerTable = 0x3680;ULONG_PTR ptrKiWaitNever = 0xfffff80770a316f8;ULONG_PTR ptrKiWaitAlways = 0xfffff80770a318e8;此处我把它分为三步走 , 第一步找到KiProcessorBlock函数地址 , 第二步找到KeSetTimer并从里面寻找KeSetTimerEx , 第三步根据KiSetTimerEx地址 , 搜索到KiWaitNever(),KiWaitAlways()这两个函数内存地址 , 最终循环链表并解密DPC队列 。
第一步: 找到KiProcessorBlock函数地址 , 该地址可通过__readmsr()寄存器相加偏移得到 。
在WinDBG中可以输入rdmsr c0000082得到MSR地址 。
驱动开发:内核枚举DpcTimer定时器

文章插图
MSR寄存器使用代码获取也是很容易 , 只要找到MSR地址在加上0x20即可得到KiProcessorBlock的地址了 。
/*lyshark.com 0: kd> dp !KiProcessorBlockfffff807`70a32cc0fffff807`6f77c180 ffffbe81`3cee0180fffff807`70a32cd000000000`00000000 00000000`00000000fffff807`70a32ce000000000`00000000 00000000`00000000fffff807`70a32cf000000000`00000000 00000000`00000000fffff807`70a32d0000000000`00000000 00000000`00000000fffff807`70a32d1000000000`00000000 00000000`00000000fffff807`70a32d2000000000`00000000 00000000`00000000fffff807`70a32d3000000000`00000000 00000000`00000000*/#include <ntddk.h>#include <ntstrsafe.h>// 得到KiProcessorBlock地址ULONG64 GetKiProcessorBlock(){ULONG64 PrcbAddress = 0;PrcbAddress = (ULONG64)__readmsr(0xC0000101) + 0x20;if (PrcbAddress != 0){// PrcbAddress 是一个地址 这个地址存放了某个 CPU 的 _KPRCB 的地址return *(ULONG_PTR*)PrcbAddress;}return 0;}VOID UnDriver(PDRIVER_OBJECT driver){DbgPrint("卸载完成... \n");}NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath){DbgPrint("hello lyshark.com \n");ULONG64 address = GetKiProcessorBlock();if (address != 0){DbgPrint("KiProcessorBlock = %p \n", address);}Driver->DriverUnload = UnDriver;return STATUS_SUCCESS;}

经验总结扩展阅读