查找进程加载到内存中的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;
}

 

你可能感兴趣的:(查找进程加载到内存中的EntryPoint)