C/C++遍历某进程的模块

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. **

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

效果图:

C/C++遍历某进程的模块

PEB

对于应用层,直接使用 fs/gs 寄存器获取 peb 地址,对于内核层,使用 _EPROCESS + 偏移的方式获取 peb:

C/C++遍历某进程的模块

_PEB 中有一个 _PEB_LDR_DATA 类型的成员 Ldr:

C/C++遍历某进程的模块

Ldr 中有有一个 _LIST_ENTRY 类型的成员 InMemoryOrderModuleList :

C/C++遍历某进程的模块

这个 _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 );
上一篇:Cutting Game POJ2311(SG函数)


下一篇:C语言const