新创建的挂起进程的 EIP 仅在 Windows XP 上失败 - kernel32.dll 映像下的 EIP?

2023-12-12

我的程序在 Windows Vista Ultimate 和 Windows 7 上完美运行,但在 Windows XP 上失败。

首先,我的应用程序创建一个系统文件的进程,它调用 GetThreadContext(remote_thread) 并将 LPVOID 值设置为值 context->Eip,然后检查从 VirtualQueryEx 设置的结构 MEMORY_BASIC_INFORMATION 中的值。

以下是 VirtualQueryEx 调用时返回的值:

视窗XP

  • 0 - 分配基础
  • 0 - 分配保护
  • 2088828928 - 基址
  • 1 - 保护
  • 983040 - 区域大小
  • 65536-状态
  • 0 - type

Windows 7的

  • 2003959808 - 分配基数
  • 128 - 分配保护
  • 2004025344 - 基址
  • 32 - 保护
  • 876544 - 区域大小
  • 分段阅读_第 4096 章
  • 16777216 - 类型

视窗Vista

  • 2006122496 - 分配基数
  • 128 - 分配保护
  • 2006536192 - 基址
  • 32 - 保护
  • 389120 - 区域大小
  • 分段阅读_第 4096 章
  • 16777216 - 类型

为什么当我在 Windows XP 上运行我的应用程序时,它没有分配基础,没有分配保护,并且与 Windows 7 和 Windows Vista 的值完全不同。

我计划在地址(context->Eip)上使用VirtualProtectEx,所以如果这些是XP上的值,那么VirtualProtectEx将不可避免地失败,因为我将访问无法访问的内存。

这是我创建流程的方法:

    if ( CreateProcessW(m_pwszContainerPath, NULL, NULL, NULL, FALSE, DETACHED_PROCESS | CREATE_SUSPENDED, NULL, NULL, &m_stStartInfo, &m_stProcessHandles) == TRUE )
    {
    // Get context of thread
    m_stContext.ContextFlags = CONTEXT_FULL;
    if ( GetThreadContext(m_stProcessHandles.hThread, &m_stContext) == FALSE )
        goto _CLEANUP;
    // Grab, Eip
    m_pvLdrInitEip = (LPVOID)m_stContext.Eip;
        }

事实是:这在 Windows 7 和 Windows Vista 上都能完美运行。

我在这里缺少什么吗? 感谢您的任何帮助。

编辑-这是一张图片:

Windows 7 Windows XP Windows XP displaying where the EIP in memory is.. Windows 7 showing the address is in ntdll Here is a picture of two instances of olly running the executable, one in the XP virtual machine, one outside. From what I notice, the XP picture (bottom one) has it's EIP set to ModuleEntryPoint while the Windows 7 Instance has it set to ntdll..

我进一步调查,发现 EIP 实际上位于 kernel32.dll 映像中(在 Windows XP 上),而不是应有的 ntdll.dll 中。


创建一个流程CREATE_SUSPENDED意味着在运行代码之前主进程不会完成初始化。 XP和Vista/7之间加载程序的实现方式造成了不同的效果,并且由于CREATE_SUSPENDED文档不授予任何您不能真正依赖该方法的进程初始化。这CREATE_SUSPENDED标志仅表明进程是在主线程挂起的情况下创建的。
目前尚不清楚 OP 希望实现什么目标,但我想到了一些实现类似目标的方法:

  1. 编写调试器而不是远程操作另一个进程。可以找到简单的教程和代码示例Here。调试器为每个生成的线程获取一个事件,您可能可以使用它。

  2. 修改 PE 以在任何其他代码之前执行您的代码,方法是为您的代码创建一个新部分并在 PE 中放置一个 TLS 条目以在进程的内存空间内执行代码。然后,您的代码将在进程的 EntryPoint 之前但在其初始化之后运行。

  3. 修改PE并替换EntryPoint在 PE 标头中添加您自己的代码,只需确保您自己执行原始入口点即可。一些初始化将丢失,但所有 PE 代码部分将被加载。

  4. 通过创建挂起的 DLL 并从不同的线程加载 DLL 或任何其他方法,将 DLL 注入到进程的内存地址中。This文章列出了一些,你可以谷歌了解更多。如果您由于类似问题而想要初始化进程,我不确定这是否适用于所有情况,但我确实认为调用 LoadLibrary 将为您带来所需的效果。这也是一种将代码放入另一个进程并对其进行操作的干净方法,同时比使用调试器更加隐蔽。

  5. 您还可以尝试在进程挂起时扫描整个内存以查找要操作的代码块,这可能也适用于 XP。

  6. 您可以尝试创建未挂起的进程,并让它运行一小段时间,然后再挂起线程。经过计时和一些测试后,您将对初始化需要多少时间有一个合理的感觉。这有点冒险,但可能有效。

创建调试器将是最简单、最强大/通用的方法,但缺点是容易被检测到(尽管您可以使用反反调试技巧)。如果您希望不被操纵的进程检测到(如果它有任何反调试技巧),则加载 DLL 将是最好的方法。如果您需要针对您的特定需求的更多建议或推荐,请编辑并详细描述您到底想要什么完成,因为您的问题尚不清楚。有关该程序的更多详细信息(例如,它是本机的还是 .net)也会有所帮助。

编辑: 朋友提出的另一个猜测是,当系统调用返回并且您调用时,内核尚未完成进程初始化VirtualQueryEx。他说打电话WaitForSingleObject一旦进程完全初始化,进程句柄上的 就会返回,您可以访问所有信息并随后恢复执行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

新创建的挂起进程的 EIP 仅在 Windows XP 上失败 - kernel32.dll 映像下的 EIP? 的相关文章

随机推荐