通过特征码定位内核中的未导出函数(以PspTerminateProcess函数为例)

其实很简单,由于驱动本来就在0环跑,所以不用担心权限不够,直接拿着函数的一堆特征码到内存中1字节1字节的比对就行,这里是以定位并调用未导出函数 PspTerminateProcess 为例:

 1 #include <ntifs.h>
 2 
 3 NTSTATUS PsLookupProcessByProcessId(IN HANDLE ProcessId,OUT PEPROCESS *Process);
 4 
 5 VOID DriverUnload(PDRIVER_OBJECT pDriverObject) {
 6     DbgPrint("已卸载!\n");
 7 }
 8 
 9 PVOID GetUndocumentFunctionAddress(PUCHAR pStartAddress,PUCHAR pShellcode)
10 {
11     int index = 0;
12     int maxSize = 0x30000;
13 
14     if(!MmIsAddressValid(pStartAddress))
15     {
16         DbgPrint("地址不合法,或者地址指向内存不可读!\n");
17         return NULL;
18     }
19 
20     DbgPrint("地址合法,开始查找...\n");
21     PUCHAR tmp = pStartAddress;
22 
23     for(index=0;index<maxSize;index++)
24     {
25         tmp = pStartAddress + index;
26         for(int x=0;x<=17;x++)
27         {
28             if(tmp[x] == pShellcode[x])
29             {
30                 if(x == 17)
31                 {
32                     return tmp;
33                 }
34                 continue;
35             }
36             else
37                 break;
38         }
39     }
40 
41     DbgPrint("查找结束,最后查找的起始地址为:%x\n",tmp);
42     return NULL;
43 }
44 
45 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) {
46 
47     DbgPrint("启动!\n");
48     pDriverObject->DriverUnload = DriverUnload;
49 
50     UCHAR shellcode[19] = "\x8b\xff\x55\x8b\xec\x56\x64\xa1\x24\x01\x00\x00\x8b\x75\x08\x3b\x70\x44";
51 
52     PVOID p = GetUndocumentFunctionAddress((PUCHAR)0x805c0000,shellcode);
53 
54     if(p != NULL)
55     {
56         DbgPrint("成功找到函数首地址:%x\n",p);
57         DbgPrint("开始尝试调用函数...\n");
58         /****** 调用PspTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus)函数 ******/
59         PEPROCESS hProcess;
60         PsLookupProcessByProcessId((HANDLE)424,&hProcess);
61         _asm{
62             push 0;
63             push hProcess;
64             call p;
65         }
66         /****** 调用PspTerminateProcess(IN PEPROCESS Process, IN NTSTATUS ExitStatus)函数 ******/
67         DbgPrint("函数调用结束.\n");
68     }
69     else
70         DbgPrint("查找失败!\n");
71 
72     return STATUS_SUCCESS;
73 }

有一点需要注意,由于进程PID是硬编码进去的,所以测试的流程为:

  (1) 在系统中运行任意程序,并通过任务管理器查看PID

  (2) 把代码中的 PID 改成你自己在任务管理器中看到的

  (3) 编译驱动,并扔到测试机中跑

posted @ 2020-07-11 15:08  Dubh3  阅读(700)  评论(0编辑  收藏  举报