3

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

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

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

如果是真的,我如何通过代码获取 0x00401000 地址(c++,我是新手,请越过 t 的 :)),它是 Main 函数的地址还是什么?

4

3 回答 3

4

收到后,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(). 没有一种可靠的方法可以main()在 using 中获取无符号查找dbghelp.dll

此外,John Robbins的《调试应用程序》一书中有一章是关于使用一些示例代码创建一个小型调试器。这可能是我找到的最好的文档/示例(但我希望它更好)。它可以很便宜,所以它可能值得一看。

于 2012-11-30T19:53:04.740 回答
1

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

如果您想要 的实际地址main,您可能至少要尝试使用SymFromNamefor 名称_main和/或_wmain(或者,如果您可能正在处理 GUI 程序,WinMain/ wWinmain)以获取真正属于目标程序的代码,而不是几乎没有人见过的图书馆模块中的东西。

于 2012-11-30T20:49:26.887 回答
0

这都是凭记忆,所以可能包含一些错误。

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

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

于 2012-11-30T19:52:42.820 回答