任务很简单:编写一个程序,仅使用机器代码中的可打印可见ASCII字符0x21 ... 0x7e(不允许使用空格和del)在x86(32位)和x86-64(64位)中分支不同。
- 不允许有条件的汇编。
- 不允许使用API调用。
- 不允许使用内核模式(0环)代码。
- 在Linux或某些其他保护模式的OS中,代码必须在不引起IA-32和x86-64异常的情况下运行。
- 功能不得依赖于命令行参数。
- 所有指令必须仅使用0x21 ... 0x7e(十进制33 ... 126)范围内的ASCII字符以机器代码编码。因此,例如。
cpuid
超出限制(是0f a2
),除非您使用自我修改的代码。 - 相同的二进制代码必须在x86和x86-64中运行,但是由于文件头(ELF / ELF64 / etc。)可能不同,因此您可能需要重新组装并链接它。但是,二进制代码不得更改。
- 解决方案应该可以在i386 ... Core i7之间的所有处理器上工作,但是我也对更有限的解决方案感兴趣。
- 该代码必须在32位x86中分支,但不能在x86-64中分支,反之亦然,但不是必须使用条件跳转(也可以接受间接跳转或调用)。分支目标地址必须有一定的空间,可以容纳一些代码,至少2个字节的空间可插入短跳转(
jmp rel8
)。
胜出的答案是在机器代码中使用最少字节的答案。文件头中的字节(例如ELF / ELF64)不计算在内,分支(出于测试目的等)之后的任何代码字节也不计算在内。
请以ASCII,十六进制字节和注释代码的形式显示您的答案。
我的解决方案,39个字节:
ASCII: fhotfhatfhitfhutfhotfhatfhitfhut_H3<$t!
十六进制:66 68 6F 74 66 68 61 74 66 68 69 74 66 68 75 74 66 68 6F 74 66 68 61 74 66 68 69 74 66 68 75 74 5F 48 33 3C 24 74 21
。
码:
; can be compiled eg. with yasm.
; yasm & ld:
; yasm -f elf64 -m amd64 -g dwarf2 x86_x86_64_branch.asm -o x86_x86_64_branch.o; ld x86_x86_64_branch.o -o x86_x86_64_branch
; yasm & gcc:
; yasm -f elf64 -m amd64 -g dwarf2 x86_x86_64_branch.asm -o x86_x86_64_branch.o; gcc -o x86_x86_64_branch x86_x86_64_branch.o
section .text
global main
extern printf
main:
push word 0x746f ; 66 68 6f 74 (x86, x86-64)
push word 0x7461 ; 66 68 61 74 (x86, x86-64)
push word 0x7469 ; 66 68 69 74 (x86, x86-64)
push word 0x7475 ; 66 68 75 74 (x86, x86-64)
push word 0x746f ; 66 68 6f 74 (x86, x86-64)
push word 0x7461 ; 66 68 61 74 (x86, x86-64)
push word 0x7469 ; 66 68 69 74 (x86, x86-64)
push word 0x7475 ; 66 68 75 74 (x86, x86-64)
db 0x5f ; x86: pop edi
; x86-64: pop rdi
db 0x48, 0x33, 0x3c, 0x24
; x86:
; 48 dec eax
; 33 3c 24 xor edi,[esp]
; x86-64:
; 48 33 3c 24 xor rdi,[rsp]
jz @bits_64 ; 0x74 0x21
; branch only if running in 64-bit mode.
; the code golf part ends here, 39 bytes so far.
; the rest is for testing only, and does not affect the answer.
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
jmp @bits_32
@bits_64:
db 0x55 ; push rbp
db 0x48, 0x89, 0xe5 ; mov rbp,rsp
db 0x48, 0x8d, 0x3c, 0x25 ; lea rdi,
dd printf_msg ; [printf_msg]
xor eax,eax
mov esi,64
call printf
db 0x5d ; pop rbp
NR_exit equ 60
xor edi,edi
mov eax,NR_exit ; number of syscall (60)
syscall
@bits_32:
lea edi,[printf_msg]
mov esi,32
call printf
mov eax,NR_exit
int 0x80
section .data
printf_msg: db "running in %d-bit system", 0x0a, 0