【问题标题】:Values of Registers at Windows 10 Entry Point x64Windows 10 入口点 x64 处的寄存器值
【发布时间】:2021-06-06 10:51:40
【问题描述】:

我最近编写了一个小程序,它使用 winapi 简单地显示一个弹出对话框。我在 x64dbg 调试器中启动它,看看它是如何编译的,并学习了一些关于汇编的知识。

我注意到的第一件事是主线程没有在我的代码入口点开始执行:它开始在ntdll.dll 的某个地方执行。这段代码似乎在最终调用kernel32 之前进行了几次函数调用,后者调用了入口点。

在入口点,寄存器已经加载了一些值。我知道它们一定很重要,因为在调试器中将它们归零会导致我的程序崩溃。 rax 似乎加载了入口点,但我不确定其他人的值是做什么的。

那么在我的入口点之前所有代码到底做了什么,它加载到寄存器中的值是什么?

【问题讨论】:

  • 入口处唯一定义的寄存器是堆栈指针。所有其他的都是实施细节,随时可能发生变化。

标签: windows assembly windows-10 x86-64 entry-point


【解决方案1】:

Windows 进程执行在 NT 加载程序中开始,这就是在 ntdll.dll / kernel32.dll 中发生的事情。如果您想了解所有这些的详细信息,请查看 Windows Internals 书籍。

对于 Visual C++ 程序,进程的“入口点”是 mainCRTstartup,它位于 Visual C/C++ 运行时中。它初始化 CRT,处理全局初始化,然后分派到 mainwmainWinMain 等。

可以在 Visual Studio 安装中找到 CRT 的源代码:C:\Program Files (x86)\Microsoft Visual Studio\201?\<edition>\VC\ools\MSVC\<msvctoolset>\crt\src\vcruntime。请注意,此函数实际上不带任何参数。

只有一个定义为 __fastcall 的 x64 “ABI”,并记录在 Microsoft Docs 上。根据这个定义:RCXRDXR8R9 是函数的前四个参数(除非它是一个浮点数/双精度数,它不会用于入口点)。 RAXRCXRDXR8R9R10R11 都是 volatile 的,RAX 是返回值。因为这个函数不接受任何参数,所以它不关心这些寄存器的值是什么。任何预计为非易失性的其他寄存器在归零时都会导致问题--有关详细信息,请参阅this page

Visual C++ 也有一个__vectorcall,但这仅用于内部 SIMD 过程调用,不用于跨进程或系统调用。见Microsoft Docs

【讨论】:

  • 对于 OP 观察到在调用 mainCRTstartup 时弄乱寄存器值会导致崩溃的任何猜测?既然它没有参数,那不可能。也许更改调用保留(“非易失性”)regs 会破坏最终返回给调用者的东西?
  • @PeterCordes 原始发帖人可能更改了 RSP 或段寄存器之类的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 2022-06-22
  • 1970-01-01
  • 2021-01-28
相关资源
最近更新 更多