標 題: 【原創】ring0檢測隱藏進程
作 者: 墮落天才 時 間: 2007-05-10,13:28 鏈 接: http://bbs.pediy.com/showthread.php?t=44243 //網上得到一篇好文章 Ring0下搜索內存枚舉隱藏進程 ,但是拿裏面的代碼來使用的時候發現並沒有太多效果 //於是修改之,終於實現了最初的目標 //由於直接搜索內存,跟系統調度沒什麼關係,所以能夠枚舉到各種方法隱藏的進程 包括斷鏈、抹PspCidTable... //甚至能枚舉到已經"死掉"的進程,本程序通過進程的ExitTime來判斷進程是不是已經結束 //除非能夠把EProcess結構修改掉,但這個實現難度可能比較大,不知有沒有哪位大俠試過(PID我修改過),歡迎討論 // //作者:墮落天才 //時間:2007年5月10日 //參考: uty Ring0下搜索內存枚舉隱藏進程 http://www.cnxhacker.net/Article/show/3412.html //下面代碼在XP SP2測試通過 #include<ntddk.h> ///////////////////////////不同的windows版本下面的偏移值不同 #define EPROCESS_SIZE 0x25C //EPROCESS結構大小 #define PEB_OFFSET 0x1B0 #define FILE_NAME_OFFSET 0x174 #define PROCESS_LINK_OFFSET 0x088 #define PROCESS_ID_OFFSET 0x084 #define EXIT_TIME_OFFSET 0x078 #define OBJECT_HEADER_SIZE 0x018 #define OBJECT_TYPE_OFFSET 0x008 #define PDE_INVALID 2 #define PTE_INVALID 1 #define VALID 0 ULONG pebAddress; //PEB地址的前半部分 PEPROCESS pSystem; //system進程 ULONG pObjectTypeProcess; //進程對象類型 ULONG VALIDpage(ULONG addr) ; //該函數直接複製自 Ring0下搜索內存枚舉隱藏進程 BOOLEAN IsaRealProcess(ULONG i); //該函數複製自 Ring0下搜索內存枚舉隱藏進程 VOID WorkThread(IN PVOID pContext); ULONG GetPebAddress(); //得到PEB地址前半部分 VOID EnumProcess(); //枚舉進程 VOID ShowProcess(ULONG pEProcess); //顯示結果 VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { HANDLE hThread; DriverObject -> DriverUnload = OnUnload; pSystem = PsGetCurrentProcess(); pebAddress = GetPebAddress(); pObjectTypeProcess = *(PULONG)((ULONG)pSystem - OBJECT_HEADER_SIZE +OBJECT_TYPE_OFFSET); PsCreateSystemThread(&hThread, (ACCESS_MASK)0, NULL, (HANDLE)0, NULL, WorkThread, NULL ); return STATUS_SUCCESS; } ////////////////////////////////////////////// VOID WorkThread(IN PVOID pContext) { EnumProcess(); PsTerminateSystemThread(STATUS_SUCCESS); } //////////////////////////////////////////////////////// ULONG GetPebAddress() { ULONG Address; PEPROCESS pEProcess; //由於system進程的peb總是零 我們只有到其他進程去找了 pEProcess = (PEPROCESS)((ULONG)((PLIST_ENTRY)((ULONG)pSystem + PROCESS_LINK_OFFSET))->Flink - PROCESS_LINK_OFFSET); Address = *(PULONG)((ULONG)pEProcess + PEB_OFFSET); return (Address & 0xFFFF0000); } /////////////////////////////////////////////////////// VOID EnumProcess() { ULONG uSystemAddress = (ULONG)pSystem; ULONG i; ULONG Address; ULONG ret; DbgPrint("-------------------------------------------"); DbgPrint("EProcess PID ImageFileName"); DbgPrint("---------------------------------"); for(i = 0x80000000; i < uSystemAddress; i += 4){//system進程的EPROCESS地址就是最大值了 ret = VALIDpage(i); if (ret == VALID){ Address = *(PULONG)i; if (( Address & 0xFFFF0000) == pebAddress){//每個進程的PEB地址都是在差不多的地方,地址前半部分是相同的 if(IsaRealProcess(i)){ ShowProcess(i - PEB_OFFSET); i += EPROCESS_SIZE; } } }else if(ret == PTE_INVALID){ i -=4; i += 0x1000;//4k }else{ i-=4; i+= 0x400000;//4mb } } ShowProcess(uSystemAddress);//system的PEB總是零 上面的方法是枚舉不到的 不過我們用PsGetCurrentProcess就能得到了 DbgPrint("-------------------------------------------"); } ///////////////////////////////////////////////////////// VOID ShowProcess(ULONG pEProcess) { PLARGE_INTEGER ExitTime; ULONG PID; PUCHAR pFileName; ExitTime = (PLARGE_INTEGER)(pEProcess + EXIT_TIME_OFFSET); if(ExitTime->QuadPart != 0) //已經結束的進程的ExitTime爲非零 return ; PID = *(PULONG)(pEProcess + PROCESS_ID_OFFSET); pFileName = (PUCHAR)(pEProcess + FILE_NAME_OFFSET); DbgPrint("0x%08X %04d %s",pEProcess,PID,pFileName); } ///////////////////////////////////////////////////////////// ULONG VALIDpage(ULONG addr) { ULONG pte; ULONG pde; pde = 0xc0300000 + (addr>>22)*4; if((*(PULONG)pde & 0x1) != 0){ //large page if((*(PULONG)pde & 0x80) != 0){ return VALID; } pte = 0xc0000000 + (addr>>12)*4; if((*(PULONG)pte & 0x1) != 0){ return VALID; }else{ return PTE_INVALID; } } return PDE_INVALID; } //////////////////////////////////////////////////////////////// BOOLEAN IsaRealProcess(ULONG i) { NTSTATUS STATUS; PUNICODE_STRING pUnicode; UNICODE_STRING Process; ULONG pObjectType; ULONG ObjectTypeAddress; if (VALIDpage(i- PEB_OFFSET) != VALID){ return FALSE; } ObjectTypeAddress = i - PEB_OFFSET - OBJECT_HEADER_SIZE + OBJECT_TYPE_OFFSET ; if (VALIDpage(ObjectTypeAddress) == VALID){ pObjectType = *(PULONG)ObjectTypeAddress; }else{ return FALSE; } if(pObjectTypeProcess == pObjectType){ //確定ObjectType是Process類型 return TRUE; } return FALSE; } //////////////////////////////////////////////////////////////////// |
ring0檢測隱藏進程
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.