将x86代码注入x64进程

inject x86 code into x64 process

本文关键字:x64 进程 注入 代码 x86      更新时间:2023-10-16

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

将x86注入x86运行良好,问题仅限于x86到x64。

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

谢谢。

分段选择器决定比特度,所以您所做的只是使用右侧分段选择器进行"某种形式的跳远"。而在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位进程。

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

我真的怀疑这是否能正常工作。请记住,AMD64体系结构丢弃了所有INCDEC操作码,以便用REX前缀替换它们,而指令本身则用两字节的等效代码替换。这意味着,如果x86代码包含编码为一个字节的INCDEC,则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

正如您所看到的,"循环"不再是真正的循环,因为它的计数器从未递减,并且跳转是根据最后修改Zero Flag的指令执行的。这清楚地表明,指令解码器在32位和64位模式下的工作方式非常不同,有效地禁止您在64位模式中运行汇编为32位的代码。