本文共 3982 字,大约阅读时间需要 13 分钟。
//网上得到一篇好文章 ,但是拿里面的代码来使用的时候发现并没有太多效果 //于是修改之,终于实现了最初的目标 //由于直接搜索内存,跟系统调度没什么关系,所以能够枚举到各种方法隐藏的进程 包括断链、抹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; } 转载地址:http://vxuio.baihongyu.com/