最小的可执行程序(x86-64)

问题描述 投票:0回答:2

我最近看到这篇文章描述了最小的可能的ELF可执行文件,但是这篇文章是为32位编写的,我无法获得在我的机器上编译的最终版本。这让我想到一个问题:可以编写且运行无错误的最小 x86-64 ELF 可执行文件是什么?

assembly x86-64 elf
2个回答
17
投票

从我的一个关于 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 位的基本布局和相关修改,因此您只需尝试更大胆的重叠


0
投票
我有一个 129 字节的 x64“Hello World!”。

步骤1。使用

nasm -f bin hw.asm

 编译以下 asm 代码

; hello_world.asm BITS 64 org 0x400000 ehdr: ; Elf64_Ehdr db 0x7f, "ELF", 2, 1, 1, 0 ; e_ident times 8 db 0 dw 2 ; e_type dw 0x3e ; 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 dd 1 ; e_phnum ; p_type ; e_shentsize dd 5 ; e_shnum ; p_flags ; 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 _start: ; write "Hello World!" to stdout pop rax mov dl, 60 mov esi, hello syscall syscall hello: db "Hello World!", 10 ; 10 is the ASCII code for newline filesize equ $ - $$
步骤2。使用以下Python脚本修改它

from pwn import * context.log_level='debug' context.arch='amd64' context.terminal = ['tmux', 'splitw', '-h', '-F' '#{pane_pid}', '-P'] with open('./hw','rb') as f: pro = f.read() print(len(pro)) pro = list(pro) cut = 0x68 pro[0x18] = cut pro[0x74] = 0x7c-(0x70-cut) pro = pro[:cut]+pro[0x70:] print(pro) x = b'' for _ in pro: x+=_.to_bytes(1,'little') with open("X",'wb') as f: f.write(x)
您应该是 129 字节的“Hello World”。

[18:19:02] n132 :: xps ➜ /tmp » strace ./X execve("./X", ["./X"], 0x7fffba3db670 /* 72 vars */) = 0 write(0, "Hello World!\n\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 60Hello World! ) = 60 exit(0) = ? +++ exited with 0 +++ [18:19:04] n132 :: xps ➜ /tmp » ./X Hello World! [18:19:11] n132 :: xps ➜ /tmp » ls -la ./X -rwxrwxr-x 1 n132 n132 129 Jan 29 18:18 ./X
    
© www.soinside.com 2019 - 2024. All rights reserved.