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 );