查找进程加载到内存中的EntryPoint
工作中遇到了这样的问题:
创建了一个子进程并将其挂起后,想获取该子进程的EntryPoint,已知通过GetModuleInformation(HANDLE hProcess, HMODULE hModule)(HModule就是模块的基地址)可以获取到Module的EntryPoint,但尝试通过CreateToolhelp32Snapshot 或者 EnumProcessModules 来遍历进程的module,进而获取HMODULE时总会失败,GetLastError返回299(仅完成部分的 ReadProcessMemory 或 WriteProcessMemory 请求),这与进程被挂起有关。但这里又必须在创建进程后将其挂起(需要修改进程入口点的指令以注入DLL),这种情况下该怎么办呢?
这里补充一下:虽然在Xp系统下,进程加载到内存中后的虚基址总是0x410000,但在Win7中却是变化的。
下面就是我用的办法:
先通过 NtQueryInformationProcess API来获取到进程的PROCESS_BASIC_INFORMATION,然后再获取到PEB结构的地址,再 ReadProcessMemory 获取到 ImageBaseAddress,再用 ImageLoad 获取到 EntryPoint 的地址!
代码如下:
#include <imagehlp.h> #pragma comment(lib,"Imagehlp.lib") typedef struct { DWORD ExitStatus; DWORD PebBaseAddress; DWORD AffinityMask; DWORD BasePriority; ULONG UniqueProcessId; ULONG InheritedFromUniqueProcessId; } PROCESS_BASIC_INFORMATION; typedef LONG (WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG); LPBYTE GetExeEntryPoint(HANDLE procHdl, const char* ansiExeFilePath) { LPBYTE entryPoint = NULL; PROCNTQSIP NtQueryInformationProcess = (PROCNTQSIP)GetProcAddress(GetModuleHandleA("ntdll"), "NtQueryInformationProcess"); if (!NtQueryInformationProcess) return entryPoint; LONG status; DWORD dwParentPID = (DWORD)-1; PROCESS_BASIC_INFORMATION pbi; // Retrieve information status = NtQueryInformationProcess(procHdl, 0, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL ); DWORD bytesRead = 0; HINSTANCE baseAddr = NULL; ReadProcessMemory(procHdl, (PVOID)(pbi.PebBaseAddress + 8), // 这个8就是 ImageBaseAddress 在 PEB 结构中的偏移 &baseAddr, sizeof(baseAddr), &bytesRead); PLOADED_IMAGE pImage = ImageLoad(ansiExeFilePath, NULL); // ImageLoad 只支持ANSI编码。。。 if(pImage == NULL) return entryPoint; PIMAGE_NT_HEADERS pNTHeader = pImage->FileHeader; entryPoint = (LPBYTE)baseAddr + pNTHeader->OptionalHeader.AddressOfEntryPoint; ImageUnload(pImage); return entryPoint; }