Small gzip/xz unpacker for modern Linux
Go to file
PoroCYon 036268783e add zstd support, add autovndh to repo 2021-04-05 16:40:38 +02:00
.gitignore filedump 2018-06-29 01:53:08 +02:00
LICENSE fix argv passing to execveat 2020-04-09 08:34:07 +02:00
Makefile fix argv passing to execveat 2020-04-09 08:34:07 +02:00 fix argv passing to execveat 2020-04-09 08:34:07 +02:00 add zstd support, add autovndh to repo 2021-04-05 16:40:38 +02:00
test.c filedump 2018-06-29 01:53:08 +02:00
vondehi.asm add zstd support, add autovndh to repo 2021-04-05 16:40:38 +02:00



An unpacker based on fishypack-trident (which is my fork of Fishypack), but even smaller. It doesn't have a 64-bit version, though.


mode etc. vondehi trident Fishypack sh-based unpacker
gzip, 32-bit 161 172 179? (198?) 48 to 72
xz, 32-bit 164 (168*) 179 186 48 to 72
gzip, 64-bit N/A 208 208? 48 to 72
xz, 64-bit N/A 217 217 48 to 72
Preserve arg & env Y/N N tries to can, but often not
Min. platform Linux 3.19 Linux 2.27 Linux 2.27 Most Unices
Touches filesystem N N N Y

*: with NO_UBUNTU_COMPAT disabled.

All values are with NO_CHEATING disabled. If this is enabled, add 5 bytes.

The exact size of a shell-based unpacker depends on the exact impmelentation, many variations exist. 'xz' means the usage of xzcat instead of zcat, the former supports both xz- and lzma-compressed data.

Fishypack and trident depend on Linux >=2.27 because of the use of the memfd_create syscall. vondehi requires execveat as well.

Note that a 32-bit unpacker can still run a 64-bit binary, as long as the kernel is 64-bit and supports the 32-bit emulation layer.


nasm -fbin -o$out vondehi.asm [-DUSE_GZIP] [-DTAG="j0!"] [-DNO_UBUNTU_COMPAT] \
cat $out $intro_compressed > $final

See also, a script that brute-forces all compression parameters to find the optimal binary.


  • USE_GZIP (default off): use gzip (/bin/zcat) instead of xz (/usr/bin/xzcat).
  • NO_UBUNTU_COMPAT (default off): assume /bin is the same as /usr/bin. Originally named like this because on my machine, /bin is linked to /usr/bin, but on the Revision compomachine (which runs Ubuntu), it isn't.
  • NO_FILE_MANAGER_COMPAT (default off): save two bytes by putting instructions in the EI_CLASS and EI_DATA fields of the ELF header. Causes executables packed with vondehi to not be recognized as executable in file managers.
  • USE_VFORK (default off): use vfork(2) instead of fork(2). I hope you know what you're doing when you enable this.
  • TAG (default empty): add a vanity tag right before the compressed data. Only use this when you have bytes to spare, of course.
  • NO_CHEATING (default off): don't assume file descriptor numbers and properly pass arguments and environment variable to the payload. You need this if you're running on Wayland. Costs 5 bytes.
  • WANT_ARGV (default off): properly pass argv to the payload binary if NO_CHEATING is enabled. Costs 3 or so bytes.

How to debug it if it doesn't work

  1. strace it
  2. See where errors start happening
  • This can be obscured because the code assumes eg. syscall return values to be between 0 and 255, so later syscalls might fail, or nonsense syscalls might be invoked.
  1. Fix it. Somehow.

Greets to

  • Blackle, for the original Fishypack, and for replacing the waitid(2) call with waitpid(2), fixing compatibility with some kernels and shaving off a few bytes at once!
  • Shiz, for other packing/unpacking and x86-related stuff
  • Faemiyah, yx, etc., for small sh-based unpackers (yx: nice trick with the script partially embedded in the gzip file!)

Extra thanks to:

  • blackle, greg, and others for contributions