Source linked

Réduction d'un ELF Linux à 81 octets par le piratage de p_paddr

En superposant les en-têtes et en exploitant un champ non spécifié dans l'en-tête du programme, un développeur a créé une exécutable ELF entièrement conforme aux spécifications de seulement 81 octets.

linuxelfmuppetlabsassemblysystems engineeringbinary optimization

A fully ELF-spec-compliant Linux executable can be squeezed into just 81 bytes by overlapping data structures and repurposing the p_paddr field for program code.

Why 45 Bytes Snapped the ELF Spec

The original Teensy Executable hit 45 bytes by treating the kernel's tolerance as a specification. Purists rightly pointed out that file didn't conform to the ELF standard. The author, Brian Raiter, acknowledges the criticism but couldn't resist pushing further. So he went back to the last conforming version: 91 bytes.

That 91-byte baseline uses the standard ELF header and program header table without any creative liberties. From there, the goal was to shrink without violating published requirements.

Overlapping Headers Saves Eight Bytes

The ELF spec explicitly allows different data structures within the file to overlap. Raiter exploits this by merging the end of the ELF header (e_phnum, e_shentsize, e_shnum, e_shstrndx) with the beginning of the program header (p_type, p_offset). This shaves off eight bytes, bringing the size to 83 bytes.

No fields are actually missing - they just share file space. The kernel reads the correct values because it interprets each structure at its declared offset.

p_paddr: The Four-Byte Loophole

Stuck at 83 bytes, Raiter returns to the ELF spec. Most header fields must be zero if unused, but p_paddr is explicitly described as having "unspecified contents." That means you can put arbitrary data there - like executable code.

He fits the two-byte xor eax, eax instruction into p_paddr, then uses a jmp short to jump to the rest of the program. That reclaims two bytes from the payload area, landing at 81 bytes.

The resulting file still sets p_paddr to the code bytes, which is perfectly legal because the spec says the field is undefined for executable segments on Intel architecture.

Relocating the Load Address for Two More Bytes

Could we go lower? The next idea is to use the p_paddr field for more than two bytes by adjusting the load address (p_vaddr). Normally, the load address is 0x08048000. By changing it to 0x2AB30000, we can encode a two-byte instruction (mov bl, 42) into the top two bytes, giving us an extra instruction slot.

Combined with careful rearrangement, this could theoretically drop below 81 bytes. But Raiter stops at 81 bytes as the current practical minimum for a fully conforming executable.

For anyone pushing the boundaries of binary size, this exercise shows the ELF spec still has hidden pockets of flexibility worth mining.


Source: The Teensy Executable Revisited
Domain: muppetlabs.com

Read original source ->

External source stays available while the OJO article and comment thread stay local.

Comments load interactively on the live page.