本文介绍了C ++:从64位进程注入32位目标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在C ++中写了一个DLL-Injector,其要求如下

I have written a DLL-Injector in C++ recently, for which the requirements were the following


  • INJECTING PROCESS (我们称之为Injector)以及64位和32位变量中存在的 DLL TO BE INJECTED (注入)。根据目标,尝试注入匹配版本的注入。

  • 即使注射器在64位运行,也必须注入32位(WOW64)的目标进程bit

  • The INJECTING PROCESS (let's call it the 'Injector') as well as the DLL TO BE INJECTED (Injection) exist in 64 and 32 bit variants. Depending on the target, the matching version of the injection is tried to be injected.
  • It must be possible to inject target processes that are 32 bit (WOW64) even with the Injector running in 64 bit

我很快注意到,在 GetProcAddress(LoadLibraryA)注入器返回一个不可用句柄,因为32位目标有另一个kernel32.dll加载,并且函数的地址不同,因此注入失败(远程线程不能使用返回的地址/句柄启动)。此外,32位进程的kernel32.dll加载在不同的基地址,这使得远程线程的创建更不可能。

It came quickly to my notice, that the call of GetProcAddress("LoadLibraryA") in the Injector returns an "unusable" handle as the 32 bit target has another kernel32.dll loaded and the address of the function there is different, so injection fails (The remote thread can not be started using the returned address/handle). Furthermore, the 32 bit process has the kernel32.dll loaded at a different base address, which makes creation of the remote thread even more impossible.

清楚我的意思,会发生以下情况:

To make clear what I mean, the following happens:


  • Injector具有64位版本的 kernel32.dll 0x12340000

  • Injector从此kernel32.dll检索 LoadLibraryA 0x00005678的句柄

  • 目标具有32位版本的 kernel32.dll 加载到0xABCD0000

  • 此kernel32.dll的 LoadLibrary 句柄预计为0x0000EFAB

  • 在目标中用函数0x12345678启动远程线程,但需要0xABCDEFAB

  • Injector has 64 bit version of kernel32.dll loaded at 0x12340000
  • Injector retrieves handle for LoadLibraryA 0x00005678 from this kernel32.dll
  • Target has 32 bit version of kernel32.dll loaded at 0xABCD0000
  • The handle for LoadLibrary of this kernel32.dll is expected to be 0x0000EFAB
  • Injector tries to start remote thread in target with function 0x12345678, but 0xABCDEFAB is expected

当从64位进程注入64位进程时, 32位从32位,通常没有问题,因为kernel32.dll是(最可能的)在相同的基地址加载和相同的函数地址可以使用 - 这是我迄今为止的不知道。

When injecting a 64 bit process from a 64 bit process, and 32 bit from 32 bit, there is usually no problem, as the kernel32.dll is (most likely) loaded at the same base address and the same function address can be used - that's my unterstanding so far. In this case however the conditions differ.

为了克服这个问题,我做了以下步骤:

To overcome the problem I did the following steps:


  • 64位Injector使用 EnumProcessModulesEx()(应为0xABCD000)检索由32位目标加载的kernel32.dll的地址

  • kernel32.dll ,解析PE标头并获取 LoadLibraryA (应为0x000EFAB)的RVA

  • 此时, 在32位目标中加载 kernel32.dll ,并从此DLL中加载函数的地址。

  • 64位Injector启动远程线程, ImageBase + Function RVA ,在这种情况下是神奇的0xABCDEFAB

  • 64 bit Injector retrieves address of kernel32.dll loaded by 32 bit target using EnumProcessModulesEx() (should be 0xABCD000)
  • Get filename of that kernel32.dll, parse the PE header and get the RVA of LoadLibraryA (should be 0x000EFAB)
  • At this point, we know where kernel32.dll is loaded in the 32 bit target and the address of the function from this DLL.
  • 64 bit Injector starts remote thread in 32 bit target with ImageBase + Function RVA, in this case the magical 0xABCDEFAB

这种方法实际上效果很好,不能摆脱这是总开销的想法,并且必须有一个更简单的解决方案,从64位注入器注入32位目标。

This approach actually works very well, but I can't get rid of the thought that this is total overhead and there must be a more simpler solution to inject 32 bit targets from 64 bit injectors.

我有两个问题,对此我非常感谢,如果他们可以在这里回答:

I have two questions, for which I am very grateful if they could be answered here:


  1. 有没有更简单的方法来实现这种注射? / li>
  2. 我一直在想的方法可能有问题吗?

任何答案都非常感谢,谢谢!

Any answers are very much appreciated, thanks!

编辑:哦,我的天啊...我只是意识到,我描述的情况错了我的最初的职位。 INJECTOR是64位,TARGET是32位(最初是相反的,但我已经纠正它)。 Ben Voigt的下面的评论是完全正确的,对EnumProcessModulesEx的调用将失败。一个大的BIG抱歉的混乱:(

Oh my gosh... I just realized, that I described the situation wrong in my initial post. The INJECTOR is 64 bit, and the TARGET is 32 bit (Initially it was the other way around, but I already corrected it). Ben Voigt's comments down below are totally true, the call to EnumProcessModulesEx would fail. A big big BIG sorry for that confusion :(

推荐答案

我想你可以使用调试符号API保存自己解析PE头和导出表,这个路由应该产生32位注入器所需的信息; 64位目标情况,虽然我还是不知道如何将64位地址传递给 CreateRemoteThread

I think you could use the debug symbols API to save yourself parsing the PE header and export table. This route should yield the required information for the 32-bit injector; 64-bit target case as well, although I still don't see how you're going to pass a 64-bit address to CreateRemoteThread.





  • EnumerateLoadedModules64
  • SymFromName
  • ImageRvaToVa

通常这些调试符号函数需要一个.pdb或.sym文件来操作,但我很确定他们也从DLL导出表中获取信息(只是从经验的调试器显示的文件,我没有符号存在)。

Normally these debug symbol functions require a .pdb or .sym file to operate, however I'm pretty sure they also get information from a DLL export table (just going from experience of what a debugger shows for files where I don't have symbols present).

这篇关于C ++:从64位进程注入32位目标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-25 07:17