从from an answer of mine 开始,关于 Linux 上 ELF 可执行文件的“真实”入口点和“原始”系统调用,我们可以将其剥离为
bits 64
global _start
_start:
mov di,42 ; only the low byte of the exit code is kept,
; so we can use di instead of the full edi/rdi
xor eax,eax
mov al,60 ; shorter than mov eax,60
syscall ; perform the syscall
我不认为你可以在不超出规格的情况下让它变得更小 - 特别是,psABI 不能保证eax 的状态。这被组装成精确的 10 个字节(而不是 32 位有效负载的 7 个字节):
66 bf 2a 00 31 c0 b0 3c 0f 05
直接的方式(用nasm 组装,用ld 链接)生成一个352 字节的可执行文件。
他所做的第一个“真正”转变是“手工”构建 ELF;这样做(有一些修改,因为 x86_64 的 ELF 标头有点大)
bits 64
org 0x08048000
ehdr: ; Elf64_Ehdr
db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident
times 8 db 0
dw 2 ; e_type
dw 62 ; e_machine
dd 1 ; e_version
dq _start ; e_entry
dq phdr - $$ ; e_phoff
dq 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
dw 1 ; e_phnum
dw 0 ; e_shentsize
dw 0 ; e_shnum
dw 0 ; e_shstrndx
ehdrsize equ $ - ehdr
phdr: ; Elf64_Phdr
dd 1 ; p_type
dd 5 ; p_flags
dq 0 ; p_offset
dq $$ ; p_vaddr
dq $$ ; p_paddr
dq filesize ; p_filesz
dq filesize ; p_memsz
dq 0x1000 ; p_align
phdrsize equ $ - phdr
_start:
mov di,42 ; only the low byte of the exit code is kept,
; so we can use di instead of the full edi/rdi
xor eax,eax
mov al,60 ; shorter than mov eax,60
syscall ; perform the syscall
filesize equ $ - $$
我们减少到 130 个字节。这比 91 字节的可执行文件大一点,但它来自于几个字段变成 64 位而不是 32 位的事实。
然后我们可以应用一些类似于他的技巧; phdr 和 ehdr 的部分重叠可以做到,尽管phdr 中的字段顺序不同,我们必须将p_flags 与e_shnum 重叠(但是由于e_shentsize 应该忽略它为 0)。
在标头内移动代码稍微困难一些,因为它大了 3 个字节,但标头的那部分与 32 位的情况一样大。我们通过提前 2 个字节开始,覆盖填充字节(ok)和 ABI 版本字段(不好,但仍然有效)来克服这个问题。
所以,我们到达:
bits 64
org 0x08048000
ehdr: ; Elf64_Ehdr
db 0x7F, "ELF", 2, 1, ; e_ident
_start:
mov di,42 ; only the low byte of the exit code is kept,
; so we can use di instead of the full edi/rdi
xor eax,eax
mov al,60 ; shorter than mov eax,60
syscall ; perform the syscall
dw 2 ; e_type
dw 62 ; e_machine
dd 1 ; e_version
dq _start ; e_entry
dq phdr - $$ ; e_phoff
dq 0 ; e_shoff
dd 0 ; e_flags
dw ehdrsize ; e_ehsize
dw phdrsize ; e_phentsize
phdr: ; Elf64_Phdr
dw 1 ; e_phnum p_type
dw 0 ; e_shentsize
dw 5 ; e_shnum p_flags
dw 0 ; e_shstrndx
ehdrsize equ $ - ehdr
dq 0 ; p_offset
dq $$ ; p_vaddr
dq $$ ; p_paddr
dq filesize ; p_filesz
dq filesize ; p_memsz
dq 0x1000 ; p_align
phdrsize equ $ - phdr
filesize equ $ - $$
112 字节长。
我暂时停在这里,因为我现在没有太多时间。您现在已经有了 64 位相关修改的基本布局,因此您只需要尝试更大胆的重叠