X86-32 / X86-64通晓多国语言机器code,它在运行时检测到64位模式片段? [英] x86-32 / x86-64 polyglot machine-code fragment that detects 64bit mode at run-time?

查看:172
本文介绍了X86-32 / X86-64通晓多国语言机器code,它在运行时检测到64位模式片段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能为同一字节机器code,以弄清楚他们在32位或64位模式是否正在运行,然后做不同的事情?

Is it possible for the same bytes of machine code to figure out whether they're running in 32 or 64 bit mode, and then do different things?

即。写通晓多国机code。

通常情况下,你可以使用 #IFDEF 宏在编译时检测。或C,你可以写一个如果()与编译时间常数的条件,让编译器优化掉了它的另一面。

Normally you can detect at build time with #ifdef macros. Or in C, you could write an if() with a compile-time constant as the condition, and have the compiler optimize away the other side of it.

这是只对怪异的情况下非常有用,如可能code注射液,或者只是看它是否是可能的。

This is only useful for weird cases, like maybe code injection, or just to see if it's possible.

另请参阅: ARM / x86机器code 跳转到这取决于架构是不同的地址解码字节

See also: a polyglot ARM / x86 machine code to branch to different addresses depending on which architecture is decoding the bytes.

推荐答案

最简单的方法是使用被改变用途作为一个字节的 INC 运算codeS REX prefixes在64位模式。一个REX preFIX对 江铜 无影响,所以你可以这样做:

The easiest way is by using the one-byte inc opcodes that are repurposed as REX prefixes in 64bit mode. A REX prefix has no effect on jcc, so you can do:

xor    eax,eax       ; clear ZF
db  0x40             ; 32bit: inc eax.   64bit: useless REX prefix
jz   .64bit_mode     ; REX jcc  works fine


下面是一个使用系统调用一个完整的Linux / NASM程序退出(1)如果运行的是64位,或 0x80的INT 退出(0)如果运行32位为


Here's a full Linux/NASM program that uses syscall to exit(1) if run as 64bit, or int 0x80 to exit(0) if run as 32bit.

使用BITS 32和BITS 64确保装配在同一台机器code两种方式。 (是的,我与 objdump的-d 检查显示原始机器code字节)

The use of BITS 32 and BITS 64 ensure that it assembles to the same machine code either way. (And yes, I checked with objdump -d to show the raw machine-code bytes)

但即便如此,我用 DB 0X40 而不是 INC EAX ,这样可以很清楚有什么特别的。

Even so, I used db 0x40 instead of inc eax, to make it clearer what's special.

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]
        ;; 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


;;;;; 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


$ 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

(修建从<一个命令href=\"http://stackoverflow.com/questions/36861903/assembling-32-bit-binaries-on-a-64-bit-system-gnu-toolchain/36901649#36901649\">Assembling在64位系统上的32位二进制文​​件(GNU工具链),从常见问题解答部分中的 86 标签的wiki)。

(build commands from Assembling 32-bit binaries on a 64-bit system (GNU toolchain), linked from the FAQ section in the x86 tag wiki).

这篇关于X86-32 / X86-64通晓多国语言机器code,它在运行时检测到64位模式片段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆