我最近遇到this post,它描述了可能的最小ELF可执行文件,但是该帖子是用32位编写的,因此我无法在计算机上获得最终版本进行编译。这使我想到一个问题:可以编写出无错误运行的最小x86-64 ELF可执行文件是什么?
答案 0 :(得分:3)
从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个字节,覆盖填充字节(确定)和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位的相关修改,因此您只需要尝试更大胆的重叠