Memory / Win32调试API中进程的实际起始地址

时间:2012-11-30 19:33:54

标签: c++ debugging winapi entry-point

起初,我是c ++和debuging的新手。我使用带有DEBUG_ONLY_THIS_PROCESS参数的CreateProcess api,然后等待CREATE_PROCESS_DEBUG_EVENT。收到后,我检查Eip寄存器以获取该点的地址。我认为这一点是主要功能的地址。

要验证这个想法,我使用ollydbg来查看exe的起始地址。但它与我的不一样。我用debug apis找到的那个是0x77a364d8,但olly说它是0x00401000。然后我没有停下来检查olly中的地址0x77a364d8。我找到了地址并在那里设置了一个断点。

然后我重新加载了olly并且看到olly首先进入0x77a364d8地址并且继续进程然后转到0x00401000地址并在那里等待。 0x77a364d8地址指向一些ntdll函数,以便将进程加载到内存中,如我所见。

如果这是真的,我怎么能通过代码得到0x00401000地址(c ++,我是新手,请穿过t :) :),它是Main函数的地址还是什么?

3 个答案:

答案 0 :(得分:3)

收到CREATE_PROCESS_DEBUG_EVENT后,您应该可以访问工会的CREATE_PROCESS_DEBUG_INFO成员。它有一个名为lpStartAddress的成员。

您的调试事件循环应如下所示:

DWORD dwContinueDebugStatus = DBG_CONTINUE;
while(dwContinueDebugStatus)
{
    DEBUG_EVENT debugEvt;
    WaitForDebugEvent(&debugEvt, INFINITE);
    switch(debugEvt.dwDebugEventCode)
    {
    case CREATE_PROCESS_DEBUG_EVENT:
        // Grab the main thread entry point.
        LPTHREAD_START_ROUTINE exentry = debugEvt.u.CreateProcessInfo.lpStartAddress;
        break;
        /* Handle the rest of your debug events here. */
    }
    ContinueDebugEvent(debugEvt.dwProcessId, debugEvt.dwThreadId, dwContinueDebugStatus);
}

修改 我忘了提几件事......

通过任何这些方式获取入口点可能是调用main()的CRT函数。在使用main()时,没有可靠的方法来获取dbghelp.dll没有符号查询。

此外,约翰罗宾斯的书Debugging Applications有一章介绍如何使用一些示例代码创建一个小调试器。这可能是我发现的最好的文档/示例(但我希望它更好)。它可以很便宜,所以值得一看。

答案 1 :(得分:1)

入口点(至少通常)与main相同。入口点的签名是void entrypoint(void);。这必须检索命令行,将其解析为单独的参数等,以准备调用main(并且在调用WinMain之前,有一个完全独立的检索必要的“东西”。一个GUI程序)。

如果您想要main的实际地址,您可能希望至少尝试使用SymFromName作为名称_main和/或_wmain(或者,如果您可能正在处理一个GUI程序,WinMain / wWinmain)来获取目标程序的代码,而不是几乎没有人见过的库模块。

答案 2 :(得分:0)

这完全来自内存,因此可能包含一些错误。

为了在新进程中找到EXE的入口点地址,您需要读取此进程的PEB字段ImageBaseAddress。 PEB始终处于固定地址,但这取决于您的EXE是32位还是64位,您必须事先确定(WOW64有32位PEB但我认为它可能尚未初始化)在那时候)。

请注意,您不能仅从EXE获取此内容,因为它可能会因ASLR而重新定位。完成此操作后,您可以使用ReadProcessMemory读取EXE的PE标头,并从AddressOfEntryPoint结构中获取IMAGE_OPTIONAL_HEADER字段。这是一个RVA,所以将它添加到之前找到的基地址,瞧,你有入口点地址。