标签:
枚举进程模块的方法有很多种,常见的有枚举PEB和内存搜索法,今天,先来看看实现起来最简单的枚举PEB实现获取进程模块列表。
首先,惯例是各种繁琐的结构体定义。需要包含 ntifs.h 和 WinDef.h, 此处不再列出,各位看官根据情况自行添加。
typedef PPEB (__stdcall *PFNPsGetProcessPeb)(PEPROCESS pEProcess); typedef ULONG PPS_POST_PROCESS_INIT_ROUTINE; typedef struct _PEB_LDR_DATA { BYTE Reserved1[8]; PVOID Reserved2[3]; LIST_ENTRY InMemoryOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _RTL_USER_PROCESS_PARAMETERS { BYTE Reserved1[16]; PVOID Reserved2[10]; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; BYTE Reserved4[104]; PVOID Reserved5[52]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved6[128]; PVOID Reserved7[1]; ULONG SessionId; } PEB, *PPEB; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; DWORD SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; DWORD Flags; WORD LoadCount; WORD TlsIndex; LIST_ENTRY HashLinks; PVOID SectionPointer; DWORD CheckSum; DWORD TimeDateStamp; PVOID LoadedImports; PVOID EntryPointActivationContext; PVOID PatchInformation; }LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
下面进入真正的实现代码:
NTSTATUS GetProcessModules(ULONG ulProcessId) { NTSTATUS nStatus; //PEB结构指针 PPEB pPEB = NULL; //EPROCESS结构指针 PEPROCESS pEProcess = NULL; //查找的函数名称 UNICODE_STRING uniFunctionName; //进程参数信息 PRTL_USER_PROCESS_PARAMETERS pParam = NULL; //LDR数据结构 PPEB_LDR_DATA pPebLdrData = NULL; //LDR链表入口 PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL; //链表头节点、尾节点 PLIST_ENTRY pListEntryStart = NULL; PLIST_ENTRY pListEntryEnd = NULL; //函数指针 PFNPsGetProcessPeb PsGetProcessPeb = NULL; //保存APC状态 KAPC_STATE KAPC ={0}; //是否已经附加到进程 BOOLEAN bIsAttached = FALSE; //获取进程的EPROCESS结构指针 nStatus = PsLookupProcessByProcessId((HANDLE)ulProcessId, &pEProcess); if (!NT_SUCCESS(nStatus)) { return STATUS_UNSUCCESSFUL; } //查找函数地址 RtlInitUnicodeString(&uniFunctionName, L"PsGetProcessPeb"); PsGetProcessPeb = (PFNPsGetProcessPeb)MmGetSystemRoutineAddress(&uniFunctionName); if (PsGetProcessPeb == NULL) { KdPrint(("Get PsGetProcessPeb Failed~!\n")); return STATUS_UNSUCCESSFUL; } //获取PEB指针 pPEB = PsGetProcessPeb(pEProcess); if (pPEB == NULL) { KdPrint(("Get pPEB Failed~!\n")); return STATUS_UNSUCCESSFUL; } //附加到进程 KeStackAttachProcess(pEProcess, &KAPC); bIsAttached = TRUE; //指向LDR pPebLdrData = pPEB->Ldr; //头节点、尾节点 pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink; //开始遍历_LDR_DATA_TABLE_ENTRY do { //通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构 pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart,LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks); //输出DLL全路径 KdPrint(("%wZ \n", &pLdrDataEntry->FullDllName)); pListEntryStart = pListEntryStart->Flink; }while(pListEntryStart != pListEntryEnd); //Detach进程 if (bIsAttached != FALSE) { KeUnstackDetachProcess(&KAPC); } //减少引用计数 if (pEProcess != NULL) { ObDereferenceObject(pEProcess); pEProcess = NULL; } return STATUS_SUCCESS; }
下面是运行截图:
本帖为原创,转帖请说明出处,谢谢合作。
本帖地址:http://blog.csdn.net/sonsie007/article/details/22622177
标签:
原文地址:http://www.cnblogs.com/kuangke/p/5761429.html