2

我正在研究 x86 dll 注入器,我想将 x86 代码注入 x64 进程线程并执行它。首先,我在 x64 进程上调用CreateRemoteThread失败,导致错误代码 5。然后我发现了这个技巧,我能够用它创建远程线程。但是当我尝试ResumeThread并在 x64 进程中执行该 x86 代码时,整个进程崩溃。

将 x86 注入 x86 效果很好,问题仅在于 x86 到 x64。

所以,我的问题是——是否有可能模拟和运行在 x64 进程中复制的 x86 代码?我知道这样做的一种方法是拥有相同代码的两个版本,并根据远程进程的体系结构选择一个,但我认为这不是最好的方法。

谢谢。

4

3 回答 3

5

段选择器确定位数,因此您所做的只是使用正确的段选择器进行“某种形式的远跳”。在 64 位中,不再有那么多方法可以做到这一点。retf仍然有效。

未经测试,但你明白了:

sub rsp, 8
mov dword [rsp+4], 0x23   // 32 bit segment selector
mov dword [rsp], offset some32bitcode
retf

就是这样,您现在处于 32 位模式。它可能会导致重大损坏(特别是如果您尝试调用任何 Windows 函数),但您可以这样做 - 您可以做到(只是不要)。

您可以更轻松地切换回来:

jmp far 33h:some64bitcode // 64 bit segment selector

在 64 位模式下,直接远跳转不可编码。间接远跳转/远调用仍然存在,远返回,这显然也是间接的。

23h 和 33h 是 windows 的值,在其他操作系统上可能(并且可能)不同。

当然,这仍然意味着您必须以不同的方式处理 64 位进程。

于 2012-07-27T21:08:27.450 回答
3

您不能在 x64 进程内运行 x86 代码,反之亦然。时期。操作系统根本不允许。您只能将 x86 代码注入 x86 进程,并将 x64 代码注入 x64 进程。

于 2012-07-27T19:48:22.980 回答
-1

我真的怀疑这是否会正常工作。请记住,AMD64 架构丢弃了所有的INCDEC操作码,以便用 REX 前缀替换它们,而指令本身则被替换为两字节等效项。这意味着如果您的 x86 代码包含 aINCDEC编码为一个字节,则 CPU 在 x64 中工作时会将其视为 REX 前缀,并将尝试将指令流中的下一个字节解码为普通指令,这将最由于指令被解码为不合理的东西,肯定会导致一般保护错误或类似的东西。

这是一个例子。假设我想使用以下代码(NASM)在循环中访问一个数组。

bits 32
mov ecx, 200
myloop:
 dec ecx
 mov eax, [myarray+ecx*4+0x100]
 jnz myloop
myarray resb 10

将其编译为平面二进制文件并将其反汇编为 64 位代码后,ndisasm将返回以下内容:

00000000  B9C8000000        mov ecx,0xc8
00000005  498B048D0F010000  mov rax,[rcx*4+0x10f]
0000000D  75F6              jnz 0x5

如您所见,“循环”不再是真正的循环,因为它的计数器永远不会递减,并且根据最后修改零标志的指令进行跳转。这清楚地表明指令解码器在 32 位和 64 位模式下的工作方式非常不同,在 64 位模式下运行时,您实际上无法运行汇编为 32 位的代码。

于 2012-07-27T21:43:11.763 回答