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

Jam*_*mes 3 c c++ winapi reverse-engineering process

我的程序在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;
        }
Run Code Online (Sandbox Code Playgroud)

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

这里有什么我想念的吗?感谢您的任何帮助.

编辑 - 这是一张图片:

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

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

Nir*_*Izr 5

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

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

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

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

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

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

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

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

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