【问题标题】:Does rcx always point to the PEB at the process entrypoint?rcx 是否总是指向进程入口点的 PEB?
【发布时间】:2020-08-24 07:11:08
【问题描述】:

64 位 Windows 似乎使用 rcx = r8 = &PEBrdx = r9 = &entrypoint 调用 exe 的入口点,就好像入口点被声明为 entrypoint(PEB *peb, void *entry)

这些细节是否在任何地方指定,或者这些细节没有记录并且不值得依赖?

【问题讨论】:

  • 它必须记录在某个地方,但请注意,要求外部文档或资源的问题不在本网站的主题范围内。我仍然对答案感兴趣。
  • 现代 Windows(vista + 或 win7)使用单个参数调用 exe 入口点 - PEB 地址。这与 64 位无关。这对任何人来说。这没有记录
  • 扯掉话题问题,但 RbMm 上面的评论听起来像是一个答案。
  • 但是你可以依赖它,比如在 wdk 中存在 static nt.lib,它实现了一些最小的 nt crt。可能是为启动执行应用程序设计的,它只能使用 ntdll api。这个 lib use 事实上第一个参数是 PEB 指针。你可以链接到这个库,在这种情况下——为了你的应用程序不会崩溃——微软以后不能改变那个exe入口点指向PEB。但如果说是真的,这不是很有用 - 没有这个就可以使用 PEB 指针
  • @fuz:IMO 这个问题很好。它询问的是一个特定的事实,而不是只是文档。 “这发生在一个案例中;为什么?”形式的问题。或“一般情况下/便携式是否正确”通过引用文档来支持答案,例如ISO C++ 标准。如果这是一个问题,最后一句话可以改写为“所有 Windows 版本都这样做,依赖它是否安全?”没有明确提及文档。

标签: c windows winapi assembly x86-64


【解决方案1】:

从 vista windows 调用 exe 入口点开始,带有一个参数 - PEB 的地址 所以exe入口点的签名必须是next

ULONG __stdcall ep(PEB* ); 

因为在 x64 中,第一个参数是通过 rcx 寄存器传递的 - 您可以在此处查看 PEB 的地址。另一个寄存器中的值是随机的。但我怎么说 - 这与 64 位无关。在所有 Windows 版本中,第一个参数中的 PEB 的地址。

这没有记录,但我确信非常可靠并且不会在新的 Windows 版本中更改。

wdk 中存在 nt.lib。这是静态(非导入)库 - 为只能使用 ntdll.dll 的应用程序实现微型 crt 导入(主启动执行应用程序,如 autochk.exe)此库实现 exe (NtProcessStartup[W]) 的入口点,然后使用通常的参数调用您的 [w]main。和NtProcessStartup[W] 当前实现使用指向PEB 从第一个(和单个)agrument 的指针。假设我们链接到当前的 nt.lib 实现。因为这是静态库 - NtProcessStartup[W] 的代码将在您的 exe 中并且尚未更改。如果 Windows 不再将在第一个参数中传递 PEB 的地址 - 所有与当前 nt.lib 链接的 exe 将在启动时崩溃。所以我认为这已经没有改变了

【讨论】:

  • 请注意,对于通过RtlCreateUserProcess(链接到应符合 Server 2003 的 ReactOS 实现的链接)创建本机进程,NT 总是将 PEB 地址传递给启动例程。这在 Vista 中并不新鲜。您可以在RtlInitializeContext 中看到RtlCreateUserThread 如何为x86 设置堆栈。
  • 在Vista之前,WINAPI CreateProcessW通过BaseCreateStackBaseInitializeContext创建初始上下文,在x86中设置上下文以在寄存器EAX和@中传递启动地址和PEB地址987654339@ 到 BaseProcessStartThunk.
  • 但是,thunk 只在调用BaseProcessStartup 时推送EAX(起始地址)。忽略EBX 中的PEB 地址,调用实际的图像起始地址,不带参数。再说一遍,这是在 Vista 之前。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 2021-08-03
相关资源
最近更新 更多