/elfdude

a small & primitive elf32 packer.

Primary LanguageAssembly

 ██████████ █████       ███████████     █████                █████          |
░░███░░░░░█░░███       ░░███░░░░░░█    ░░███                ░░███           |
 ░███  █ ░  ░███        ░███   █ ░   ███████  █████ ████  ███████   ██████  |
 ░██████    ░███        ░███████    ███░░███ ░░███ ░███  ███░░███  ███░░███ |
 ░███░░█    ░███        ░███░░░█   ░███ ░███  ░███ ░███ ░███ ░███ ░███████  |
 ░███ ░   █ ░███      █ ░███  ░    ░███ ░███  ░███ ░███ ░███ ░███ ░███░░░   |
 ██████████ ███████████ █████      ░░████████ ░░████████░░████████░░██████  |
░░░░░░░░░░ ░░░░░░░░░░░ ░░░░░        ░░░░░░░░   ░░░░░░░░  ░░░░░░░░  ░░░░░░   |
____________________________________________________________________________+
                                                                       v0.005
a small ELF32 packer                                                        
                                                    (c) 2024 kamila szewczyk,
                         prototyped on a sunny sunday afternoon of 23-06-2024

===> table of contents

1. introduction
2. basic usage
3. rpn calculator
4. how it works
5. limitations
6. acknowledgements, copyright & license
7. changelog

===> 1. introduction

elfdude is a versatile executable packer. it's capable of generating tiny ELF
files that run on 32-bit x86 Linux systems (i386 or later). it fills the
niche of a small, simple and easy-to-use packer that generates ELF32 files.

comparison with other ELF processors:
- upx: elfdude is much simpler and smaller, supports and more advanced
  compression algorithms. upx is generally more serious (it supports many
  other platforms besides i386 Linux) but offers worse compression ratio on
  very small files (demos) and on very large files (UCL does not scale).
  elfdude is also generally slower than upx. currently, it also does not
  implement some UPX features.
- ezuri, midgetpack: elfdude is merely a packer and not an encryption tool,
  not intended to be used for malware. ezuri/midgetpack do not support
  compression. elfdude does not provide the same level of security as
  either.
- gzexe: elfdude is generally competitive with gzexe in terms of compression
  ratio. gzexe generates shell scripts, not ELF files. further, it depends
  on the system's gzip implementation, which may not be available.
- papaw: similar to elfdude. elfdude is generally a bit more advanced and
  efficient.

===> 2. basic usage

refer to `elfdude -h'. generally, `-m X' sets the compression mode. the
number does not really correspond to compression quality, so make sure to
test a bunch. 

`--bss_size' and `--bss_base' set the base address and the size of the bss
section in the packed image. it's a zeroed section meant for static data.

`--image_base' sets the base address of the image (the entry point). it's
usually within the first 16M of the address space, but you can set it to
more or less whatever.

`--image_pad' specifies the size of zero-padding after the image in the
packed file. it's useful for self-modifying code assuming `--wx' is not set.

`--wx' makes the pages containing the entry point read-only. this is useful
for compatibility with some systems like selinux that implement data
execution prevention.

invocation example:

>>>
% cat > hello.asm <<EOF
; hello.asm: binary format, 32bit, origin 0x1000000
use32
org 0x1000000
mov eax, 4
mov ebx, 1
mov ecx, message
mov edx, 51
int 0x80
mov eax, 1
xor ebx, ebx
int 0x80
message: db 'HelloHelloHelloHelloHelloHelloHelloHelloHelloHello', 0x0a
EOF

% fasm hello.asm hello.bin     # assembles the source

% elfdude -m 1                 # sets the method to LZSS
        --image_base=0x1000000 # sets the image base address
        --image_pad=32         # adds extra padding at the end
        --bss_base=0x2000000   # sets the bss base address
        --bss_size=32          # sets the bss size
        hello.bin hello.elf
<<<

===> 3. rpn calculator

rpn.asm is a toy rpn calculator. build it without bss and wx.

===> 4. how it works

elfdude uses a bunch of stubs written using fasm syntax; the packer modifies
the addresses, offsets and sizes in the stubs to match the packed image. the
stub is a simple ELF32 executable that allocates pages with `mmap' for the
resulting machine code and the bss section. then, the data appended to the
stub is decompressed and copied to the allocated memory. the entry point (the
first instruction at the base address) is then executed. register state is
preserved on stub startup and restored before the jump to the entry point.

methods:
- lzmw: Lempel-Ziv-Miller-Wegman, variant of LZW that adapts quicker.
- lzss: Lempel-Ziv-Storer-Szymanski, a simple dictionary-based algorithm
        it uses a byte-wise encoding similar to this of LZ4.
- store: no compression, just stores the data.
- lzssopt: a variant of LZSS that takes more time to find good matches.
- ppmii (low order): a variant of D. Shkarin's PPMDvJ with max order of 4
- ppmii (mid order): a variant of D. Shkarin's PPMDvJ with max order of 6
- ppmii (high order): a variant of D. Shkarin's PPMDvJ with max order of 8

===> 5. limitations

Current list of improvements yet to be made:

- support for (dynamically linked) ELFs.
- tool that turns ELFs into flat images.
- support for more algorithms.
- support FreeBSD/OpenBSD/NetBSD
- golf down the stubs.
- support shell script stubs like gzexe.

===> 6. acknowledgements, copyright & license

elfdude was written by kamila szewczyk in 2024. it can be freely distributed
as freeware. the author is not responsible for any damage caused by the use
of this software. the software is provided as-is and comes with no warranty.

thanks to:
- andy kelley for zig-cc
- tomek grysztar for fasm
- rich felker for musl
- mark oberhumer for upx
- igor pavlov for lzma
- dymitry shkarin for ppmd
- many more. feel like you should be on the list? let me know.

https://palaiologos.rocks - kspalaiologos@gmail.com

===> 7. changelog

v0.004: golf down stubs, implement --wx for selinux compatibility.
        improved error checking. verbose output mode. lzssopt compression
        mode that uses near-optimal parsing, cli tool preserves permissions
        owner and time now.
v0.005: added PPM support, made all stubs --wx by default (no RWX sections),
        added low/mid/high order PPMII modes, verbose mode now displays blake2b
        sums. fixed some internal bugs.