起初,我是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函数的地址还是什么?
答案 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,所以将它添加到之前找到的基地址,瞧,你有入口点地址。