是否可以使用相同字节的机器代码来确定它们是以32位还是64位模式运行,然后执行不同的操作?
即写多语言机器代码.
通常,您可以在构建时使用#ifdef宏检测.或者在C中,您可以编写一个if()以编译时常量作为条件,并让编译器优化它的另一面.
这仅适用于奇怪的情况,例如代码注入,或只是为了查看是否可能.
另请参见:多语言ARM/x86机器代码,用于分支到不同的地址,具体取决于解码字节的架构.
Pet*_*des 11
最简单的方法是使用inc在64位模式下重新用作REX前缀的单字节操作码.REX前缀不起作用jcc,因此您可以:
xor eax,eax ; clear ZF
db 0x40 ; 32bit: inc eax. 64bit: useless REX prefix
jz .64bit_mode ; REX jcc works fine
Run Code Online (Sandbox Code Playgroud)
下面是一个使用一个完整的Linux/NASM程序#ifdef __x86_64__到sizeof(void*)如果运行的64位,或syscall到exit(1)如果运行的32位.
BITS 32和BITS 64的使用确保它以任何方式组装到相同的机器代码.(是的,我检查过int 0x80显示原始机器码字节)
即便如此,我用exit(0)代替objdump -d,这样可以很清楚有什么特别的.
BITS 32
global _start
_start:
xor eax,eax ; clear ZF
db 0x40 ; 32bit: inc eax. 64bit: useless REX prefix
jz .64bit_mode ; REX jcc still works
;jmp .64bit_mode ; uncomment to test that the 64bit code does fault in a 32bit binary
.32bit_mode:
xor ebx,ebx
mov eax, 1 ; exit(0)
int 0x80
BITS 64
.64bit_mode:
lea rdx, [rel _start] ; An instruction that won't assemble in 32-bit mode.
;; arbitrary 64bit code here
mov edi, 1
mov eax, 231 ; exit_group(1).
syscall ; This does SIGILL if this is run in 32bit mode on Intel CPUs
Run Code Online (Sandbox Code Playgroud)
;;;;; Or as a callable function:
BITS 32
am_i_32bit: ;; returns false only in 64bit mode
xor eax,eax
db 0x40 ; 32bit: inc eax
; 64bit: REX.W=0
;nop ; REX nop is REX xchg eax,eax
ret ; REX ret works normally, too
Run Code Online (Sandbox Code Playgroud)
经过测试和工作.我构建它两次以获得围绕相同机器代码的不同ELF元数据.
$ yasm -felf64 -Worphan-labels -gdwarf2 x86-polyglot-32-64.asm && ld -o x86-polyglot.64bit x86-polyglot-32-64.o
$ yasm -felf32 -Worphan-labels -gdwarf2 x86-polyglot-32-64.asm && ld -melf_i386 -o x86-polyglot.32bit x86-polyglot-32-64.o
$ ./x86-polyglot.32bit && echo 32bit || echo 64bit
32bit
$ ./x86-polyglot.64bit && echo 32bit || echo 64bit
64bit
Run Code Online (Sandbox Code Playgroud)
(在64位系统(GNU工具链)上构建来自汇编32位二进制文件的命令,从x86标记wiki中的FAQ部分链接).
| 归档时间: |
|
| 查看次数: |
789 次 |
| 最近记录: |