新创建的暂停进程的EIP仅在Windows XP上失败 – 在kernal32.dll映像下的EIP?

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

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

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

Windows XP

  • 0 – 分配基础
  • 0 – 分配保护
  • 2088828928 – 基地址
  • 1 – 保护
  • 983040 – 地区大小
  • 65536 – 状态
  • 0 – 类型

Windows 7的

  • 2003959808 – 分配基础
  • 128 – 分配保护
  • 2004025344 – 基地址
  • 32 – 保护
  • 876544 – 区域大小
  • 4096 – 国家
  • 16777216 – 类型

Windows 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 XPWindows XP显示内存中EIP的位置..显示地址的Windows 7在ntdll中 下面是两个运行可执行文件的实例的图片,一个在XP虚拟机中,一个在外面。 从我注意到,XP图片(底部的)将其EIP设置为ModuleEntryPoint,而Windows 7实例将其设置为ntdll ..

我进一步调查,发现EIP实际上是在kernel32.dll映像(在Windows XP上),而不是ntdll.dll,因为它应该是..

使用CREATE_SUSPENDED创建进程意味着主进程在运行代码之前不会完成初始化。 实现加载程序的方式导致XP和Vista / 7之间的不同影响,并且由于CREATE_SUSPENDED文档没有授予任何进程初始化,因此您无法真正依赖该方法。 CREATE_SUSPENDED标志仅表示在主线程挂起的情况下创建进程。
目前还不清楚OP希望实现什么,但是想到了一些实现类似目标的方法:

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

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

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

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

  5. 您还可以尝试扫描整个内存,以查找在进程暂停时要操作的代码块,这些代码块也可能在XP上运行。

  6. 您可以尝试创建未悬浮的进程,并让它在挂起线程之前运行一小段时间。 在计时和一些测试之后,你会得到一个关于初始化需要多长时间的合理论述。 这有点风险,但可能会奏效。

创建一个调试器将是最简单,最强大/通用的方法,但是会有很容易被检测到的缺点(尽管你可以使用反反调试技巧)。 加载DLL将是最好的方法,如果你想被操纵过程保持不可检测(如果它有任何反调试技巧)如果你想要更多的建议或建议满足你的特定需求请编辑和详细描述你想要什么完成,因为你的问题不清楚。 关于程序的更多细节(例如本机,或.net)也会有所帮助。

编辑:朋友建议的另一个猜测是,在syscall返回并调用VirtualQueryEx时,内核没有完成进程初始化。 他说,一旦进程完全初始化,就会返回在进程句柄上调用WaitForSingleObject ,然后你可以访问所有信息并在之后恢复执行。

CreateProcess(CREATE_SUSPENDED)仅进行部分初始化。 您可以尝试VirtualAllocEx() EIP区域并显式COMMIT它,然后VirtualProtectEx ,当然这是一个快速入侵,您可以进行测试,我不确定这是否可以解决问题。 顺便说一下,你这样做的真正目的是什么? 如果你打算在流程执行的早期阶段挂钩,修补PE头的入口点会更好,因为当指令控制流到达入口点时,进程必须已经完成初始化,但是这也有它的缺点,例如TLS回调在入口点执行之前调用。