内存中进程的实际起始地址/W32调试API
Real Starting Address Of A Process in Memory / Win32 Debug APIs
起初,我是c++和调试的新手。我使用带有DEBUG_ONLY_THIS_PROCESS参数的CreateProcess api,然后等待CREATE_PROCESS_DEBUG_EVENT。收到后,我检查Eip寄存器以获得点的地址。我认为这一点是Main函数的地址。
为了验证这个想法,我使用ollydbg来查看exe的起始地址。但这和我的不一样。我在调试api中找到的是0x77a364d8,但olly说它是0x00401000。然后我没有停下来,检查olly中的地址0x77a364d8。我找到了地址并在那里设置了一个断点。
然后我重新加载olly,看到olly首先进入0x77a364d8地址并加载进程,然后进入0x00401000地址并在那里等待。0x77a364d8地址指向一些ntdll函数,以便将进程加载到内存中,如我所见。
如果这是真的,我如何通过代码(c++,我是一个新手,请交叉t:)获得0x00401000地址,它是Main函数的地址还是什么?
收到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函数。在使用dbghelp.dll
时,没有可靠的方法可以在不进行符号查找的情况下获得main()
。
此外,John Robbins的《调试应用程序》一书中有一章介绍了如何使用一些示例代码创建一个小型调试器。这可能是我找到的最好的文档/示例(但我希望它更好)。它可以很便宜,所以可能值得一看。
入口点将而不是(至少在正常情况下)与main
相同。入口点的签名是void entrypoint(void);
。这必须检索命令行,将其解析为单独的参数等,为调用main
做准备(在GUI程序中调用WinMain
之前,有一个完全独立的命令行可以检索相当不同的"东西")。
如果您想要main
的实际地址,您可能至少需要尝试使用SymFromName
作为名称_main
和/或_wmain
(或者,如果您可能正在处理GUI程序,WinMain
/wWinmain
),以获得真正属于目标程序的代码,而不是来自库模块的代码,几乎没有人见过。
这都来自内存,因此可能包含一些错误。
为了在新进程中找到EXE的入口点地址,您需要读取该进程的PEB字段ImageBaseAddress
。PEB总是在一个固定的地址,但这取决于你的EXE是32位还是64位,你必须事先确定(WOW64有一个32位的PEB,但我认为它可能还没有初始化)。
请注意,您不能仅从EXE中获取此文件,因为它可能会由于ASLR而被重新定位。一旦有了这个,就可以使用ReadProcessMemory
读取EXE的PE头,并从IMAGE_OPTIONAL_HEADER
结构中获取AddressOfEntryPoint
字段。这是一个RVA,所以把它添加到前面找到的基地址中,瞧,你就有了入口点地址。
- 将数组的地址分配给变量并删除
- 空基优化子对象的地址
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 如何在c++程序中找到函数的地址
- 向量元素的引用地址与它所指向的向量元素的地址不同.为什么
- 被解释为低级别const的const对象的地址
- 将地址分配给本地指针后,公共对象的变量将消失
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 内联程序集printf将整数解释为地址
- 为什么指针不写入类的地址?
- 如何在C++中获取该对象的类声明中对象的地址?
- 通过按地址访问变量
- 当一个新对象被分配到它的地址时,对象是否必须被销毁
- 函数名是c中该函数的第一条指令的地址吗
- Visual Studio(或任何其他工具)能否将地址解释为调用堆栈(boost上下文)的开头
- ReadProcessMemory() 不适用于像 0x2840C6C68D8 这样的长地址
- CUDA:统一内存和指针地址的更改
- 当我们从/tp地址中添加/减去一个整数时会发生什么
- 内存中进程的实际起始地址/W32调试API