我正在使用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体系结构丢弃了所有INC
和DEC
操作码,以便用REX前缀替换它们,而指令本身则用两字节的等效代码替换。这意味着,如果x86代码包含编码为一个字节的INC
或DEC
,则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位的代码。