1. Module32Next
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); // 进程快照句柄
PROCESSENTRY32 process = {sizeof(PROCESSENTRY32)}; // 快照信息
// 遍历进程,找到 QQMusic.exe
while (Process32Next(hProcessSnap,&process)){
string s_szExeFile = process.szExeFile; // char* 转 string
if(s_szExeFile == "QQMusic.exe"){
// 初始化
CString strModule; // 模块名称
HANDLE hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,process.th32ProcessID); // 模块快照句柄
MODULEENTRY32 me32 = {0}; // 模块入口
me32.dwSize = sizeof(MODULEENTRY32); // 申请空间
// 打印模块名
while(::Module32Next(hModuleSnap,&me32)){
strModule.Format("%s",me32.szModule);
cout << strModule.GetBuffer() << endl;
}
}
}
2. CreateTool
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,10620);
if (INVALID_HANDLE_VALUE == hSnapshot){return 0; }
MODULEENTRY32 mi;
mi.dwSize = sizeof(MODULEENTRY32);
BOOL bRet = Module32First(hSnapshot,&mi);
while (bRet)
{
std::wcout.imbue(std::locale("chs"));
cout << hex << "dwSize:" << (DWORD)mi.dwSize << endl;
cout << hex << "th32ModuleID:" << (DWORD)mi.th32ModuleID << endl;
cout << hex << "th32ProcessID:" << (DWORD)mi.th32ProcessID << endl;
cout << hex << "GlblcntUsage:" << (DWORD)mi.GlblcntUsage << endl;
cout << hex << "ProccntUsage:" << (DWORD)mi.ProccntUsage << endl;
cout << hex << "modBaseAddr:" << (ULONG32)mi.modBaseAddr << endl;
cout << hex << "modBaseSize:" << (DWORD)mi.modBaseSize << endl;
cout << hex << "hModule:" << (HMODULE)mi.hModule << endl;
wcout << "szModule:" << mi.szModule << endl;
wcout << "szExePath:" << mi.szExePath << endl;
cout << "" << endl;
bRet = Module32Next(hSnapshot,&mi);
}
效果图:
PEB
对于应用层,直接使用 fs/gs 寄存器获取 peb 地址,对于内核层,使用 _EPROCESS + 偏移的方式获取 peb:
_PEB 中有一个 _PEB_LDR_DATA 类型的成员 Ldr:
Ldr 中有有一个 _LIST_ENTRY 类型的成员 InMemoryOrderModuleList :
这个 _LIST_ENTRY 是一个 _LDR_DATA_TABLE_ENTRY 结构的双向链表,遍历这个链表就可以枚举到进程内所有的模块:
nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x010 InMemoryOrderLinks : _LIST_ENTRY
+0x020 InInitializationOrderLinks : _LIST_ENTRY
+0x030 DllBase : Ptr64 Void
+0x038 EntryPoint : Ptr64 Void
+0x040 SizeOfImage : Uint4B
+0x048 FullDllName : _UNICODE_STRING
+0x058 BaseDllName : _UNICODE_STRING
+0x068 FlagGroup : [4] UChar
+0x068 Flags : Uint4B
+0x068 PackagedBinary : Pos 0, 1 Bit
+0x068 MarkedForRemoval : Pos 1, 1 Bit
+0x068 ImageDll : Pos 2, 1 Bit
+0x068 LoadNotificationsSent : Pos 3, 1 Bit
+0x068 TelemetryEntryProcessed : Pos 4, 1 Bit
+0x068 ProcessStaticImport : Pos 5, 1 Bit
+0x068 InLegacyLists : Pos 6, 1 Bit
+0x068 InIndexes : Pos 7, 1 Bit
+0x068 ShimDll : Pos 8, 1 Bit
+0x068 InExceptionTable : Pos 9, 1 Bit
+0x068 ReservedFlags1 : Pos 10, 2 Bits
+0x068 LoadInProgress : Pos 12, 1 Bit
+0x068 LoadConfigProcessed : Pos 13, 1 Bit
+0x068 EntryProcessed : Pos 14, 1 Bit
+0x068 ProtectDelayLoad : Pos 15, 1 Bit
+0x068 ReservedFlags3 : Pos 16, 2 Bits
+0x068 DontCallForThreads : Pos 18, 1 Bit
+0x068 ProcessAttachCalled : Pos 19, 1 Bit
+0x068 ProcessAttachFailed : Pos 20, 1 Bit
+0x068 CorDeferredValidate : Pos 21, 1 Bit
+0x068 CorImage : Pos 22, 1 Bit
+0x068 DontRelocate : Pos 23, 1 Bit
+0x068 CorILOnly : Pos 24, 1 Bit
+0x068 ChpeImage : Pos 25, 1 Bit
+0x068 ReservedFlags5 : Pos 26, 2 Bits
+0x068 Redirected : Pos 28, 1 Bit
+0x068 ReservedFlags6 : Pos 29, 2 Bits
+0x068 CompatDatabaseProcessed : Pos 31, 1 Bit
+0x06c ObsoleteLoadCount : Uint2B
+0x06e TlsIndex : Uint2B
+0x070 HashLinks : _LIST_ENTRY
+0x080 TimeDateStamp : Uint4B
+0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT
+0x090 Lock : Ptr64 Void
+0x098 DdagNode : Ptr64 _LDR_DDAG_NODE
+0x0a0 NodeModuleLink : _LIST_ENTRY
+0x0b0 LoadContext : Ptr64 _LDRP_LOAD_CONTEXT
+0x0b8 ParentDllBase : Ptr64 Void
+0x0c0 SwitchBackContext : Ptr64 Void
+0x0c8 BaseAddressIndexNode : _RTL_BALANCED_NODE
+0x0e0 MappingInfoIndexNode : _RTL_BALANCED_NODE
+0x0f8 OriginalBase : Uint8B
+0x100 LoadTime : _LARGE_INTEGER
+0x108 BaseNameHashValue : Uint4B
+0x10c LoadReason : _LDR_DLL_LOAD_REASON
+0x110 ImplicitPathOptions : Uint4B
+0x114 ReferenceCount : Uint4B
+0x118 DependentLoadFlags : Uint4B
+0x11c SigningLevel : UChar
EnumProcessModules
HMODULE* phMods = NULL;
HANDLE hProcess = NULL;
DWORD dwNeeded = 0;
DWORD i = 0;
TCHAR szModName[MAX_PATH] = {};
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
if (NULL == hProcess)
{
printf("不能打开进程[ID:0x%x]句柄,错误码:0x%08x\n",dwProcessId);
return;
}
EnumProcessModules(hProcess, NULL, 0, &dwNeeded);
phMods = (HMODULE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwProcessId);
if( EnumProcessModules(hProcess, phMods, dwNeeded, &dwNeeded))
{
for ( i = 0; i < (dwNeeded / sizeof(HMODULE)); i++ )
{
ZeroMemory(szModName,MAX_PATH*sizeof(TCHAR));
//在这如果使用GetModuleFileName,有的模块名称获取不到,函数返回无法找到该模块的错误
if ( GetModuleFileNameEx(hProcess, phMods[i], szModName,MAX_PATH))
{
printf("%ws\n", szModName);
}
}
}
HeapFree(GetProcessHeap(), 0, phMods);
CloseHandle( hProcess );