(c) 2026, Roberto A. Foglietta roberto.foglietta@gmail.com, text published under CC BY-NC-ND 4.0
A 512-byte polymorphic stub/payload (uzpexec) written in Assembler that converts ELF and scripts into executable gzip packages (UZP). It runs in RAM also when started by the STDIN pipe, ssh or wget, and the carryload is trivial to extract by dd skip=1.
- Pre-compiled
ELF32(for all x86 arch) available in releases. - Development happens in devel branch, testing on devsrc tag.
Note
Only the stub, which executes the compressed binary or script, runs as ELF32 and it makes perfect sense since its role is to deal with few system calls and runs everywhere (x86 all arches, because the Assembler is a machine specific language). Obviously the ELF32 nature of the launcher doesn't affect in any manner what is executed which runs by its own kind (cfr. examples).
Warning
Since the release v0.93 packages contain uzpexec.arm source file for ARM64 versioned as v0.33. That source compiles but it is still experimental and reasonably affected by bugs because for a full validation it is a required a complete aarch64 system. However, testing with qemu-aarch64-static 10.2.3 in its original and customised form helped a lot to improve the x86 version.
- Release ‒ Usage ‒ License
- Presentation ‒ Deploying ‒ Compile ‒ Python ‒ BusyBox
- Examples ‒ Customisation ‒ Trivials ‒ TeenyELF ‒ gzcmd.sh
Current release is v0.98.1 on the master branch.
-
Since v0.96, it aims to keep the
uzpexecuncustomised as much as possible and, instead, relies on system standards likebinfmt_script, zutilszcatand busyboxzcatwith seamless decompression, and offeringuzcatas a lightweight alternatives for system customisation. -
This release v0.98, moves forward integrating the
zstdsupport and being self-sufficient in executing fromSTDINplain inputs, and it is freed fromzcat -fpotentially insecure option. In v0.98.1, thegzip/pigzformat returns as default because it is universally available. -
35903e0 - 2026-07-29 - uzpack.sh: regression fix about re-converting from old versions
The use of uzpexec extends every GitHub action from executing whatever is installable by their internal repository to whatever is available by an URL access. Despite this potential, running uzpexec directly isn't probably your goal as end-user, but uzpack to create compressed self-extracting in RAM executables:
Usage: uzpack [-h|--help] [-v|--version]
uzpack origin [destination[.uzp]]
uzpack [-x: debug | -1/-19: pigz]
export UZCMD=[zstd | (any other ztool)]This tool comes with its man page uzpack.1 which can be read by GitHub via uzpack.md. However, the help from the script is pretty clear, and its development is simplicity-oriented.
sh ./uzpack.sh uzpack.sh uzpack
./uzpack -vMoreover, the shell script uzpack.sh is able to convert itself into a standalone executable converter by incorporating itself via base64 binary-to-text conversion. Via shebang and Linux kernel binfmt_script standard registration, script support is extended to any interpreter installed on the system, in particular python.
-
/bin/sh,/bin/zcat(gunzip),/procmounted, Linux kernel 3.19 or later. -
/bin/zstdfor creation, and/bin/zstdcatfor 1GB/s in memory extraction. -
/bin/base64for stand-alone conversion andpythonin PATH for.pyscripts.
In short: MIT the source and MIT the binary, because compiling the source we get the executable, and by disassembling the binary we get the source (var names apart) due its extreme nature and Assembler coding. Hence, the MIT terms apply to both.
; (C) 2026, Roberto A. Foglietta <roberto.foglietta@gmail.com>, MIT+1 license
;
; MIT+1: due to the extreme nature of this software, an extra clause is
; added to the standard MIT license, which forbids everyone to
; remove or change the authorship string also from the binary.
; The clause rationale is rooted in security fingerprinting and
; due to the strong -- nearly 1:1 -- match between the Assembler
; source code and the x86 32-bit executable code (human-machine).
;
; The MIT+1 licensing terms apply to all the previous, current and future
; versions, unless the author provides a public legal charter allowing a
; designated entity to be exempted from this extra clause. Comply or delete.
;
; Note: coded with the help of Kimi and Gemini for the size reduction,
; this aspect deepens the link between the human and the machine.
;
; In this specific case, MIT+1 is not a derivative of the MIT license but
; due to the peculiar and extreme nature of this source code, the license
; acts as a direct extension to the binary code generated by it (1sc:1bc).After all, scripts are the sources and the "running code" at the same time.
The uzpexec is an utility for executing a compressed ELF binary or a script from STDIN or alternatively from a carryload appended to it, and the two are independent and complementary ways of working.
- it extracts and executes
- it adds a just 512-bytes stub
- trivial to inflate by
dd skip=1 - it runs binary via
sshorwget - it runs in RAM only, no disk write
- it converts ELF and shell scripts, both
- it works with
dash,bash, and busyboxash - it executes from
STDINby internalread/write - qemu-friendly
execveat()bug fallback toexecve() - reserved
providerfield for customisations
Using uzpexec to convert uzpack.sh generates a tool that can convert executables.
Soon after uzpack.sh incorporates uzpexec as payload, it can work in standalone mode.
In a standalone mode, it can convert itself in uzpack and it becomes self-hosted, also.
stub + script --> script w/ payload --> self-hosted ELF32 executable converter tool
It supports natively the gzip (legacy) and zstd (fastest) carryload formats extraction.
-
Support extentions: from
dash-only to every shell in v0.92, python scripts since v0.95,zutils+binfmt_scriptsince v0.97,zstdcatinternal support since v0.98. -
In v0.98 the
sedcustomisation returns fully available for running auzpexecself-extracting binary on a system / container with/usr/localfrom amake installinstallation. -
RAM-only, without writing on the remote / local systems storage because
memfd_create(). Obviously when RAM-only is a benefit otherwise gzcmd.sh writes on disk / tmpfs.
-
Customisations are allowed strictly within the licensing terms and the dedicated 8-char field for the provider identifier / nickname.
-
Providers who will disclose their changes with the author will (on their request) be listed here with their chosen identifier / nickname.
- defender notes: already in README.md
- signed sha256sum releases: by GitHub
- reproducible builds: by design / ASM
- custom distribution: provider field
- Unless a binary pre-compiled package is needed, download the source
.ziparchive from githubmasterbranch.
-
Those who are planning to deploy / distribute self-extracting binaries, may consider to recompile
uzpexecas loader withmake JE_STDIN=_NO_STDINto avoid users extract it withdd count=1for lazy / unsafe pipeline executions. -
Instead, embedded system architects / engineers are going to appreciate this feature in
uzpexecas command-line tool because they have a stricter control about users / accesses, thus over the pipeline executions.
-
Since the project didn't reach yet the v1.0, it is suggest to consult the documentation, the man page, the design choices in the Assembly source code and the comments, the coverage of tests.sh by
make testsin Makefile. -
Last but not least the licensing terms, which allows everyone to change the code (also at running time) but not to remove the authorship note, not even from the binary executable form. A powerful tool requires awareness about how to use it.
- Suggested file extension:
.uzp
Compiling .asm files requires nasm, otherwise sudo apt install nasm if missing:
make testsTest by yourself and then decide how to deploy.
{ cat uzpexec; zstd -19c $elf; } > $elf.uzpcp uzpexec $elf.uzp; gzip -c $elf >> $elf.uzpwget $url/$elf[.gz] -O- | uzpexec [args]uzpexec <&-||echo# for the version + github
It works as a single block 512-bytes self-inflating executable payload replacing also gzcmd.sh with the sole requirement of /bin/zcat available.
Using sed to change the interpreter from /bin/sh to every other available interpreter, the uzpexec can inflate and execute also non-shell scripts. Packaging a .pyz is a trivial procedure:
rm -f uzpexec; make uzpexec
export WORLD="Wonderful"; bin="hello.py"; cp -f uzpexec ${bin}z
pigz -11c $bin >> ${bin}z && chmod +x ${bin}z && ./${bin}z Nice
Hello Nice World!
lsfd: 0 1 2 3 9
args: 'Nice'
HOME: '/home/roberto'
WORLD: 'Wonderful'
du -b hello.py*
1370 hello.py
1235 hello.pyz <-- the output is smaller than original !!!In v0.95 or before, supporting phython scripts was possible only by properly customising uzpexec. After, by system changes like configuring the /bin/sh or Linux binfmt to properly routing shebang-ed scripts to their own interpreter. Which is the standard configuration in desktop and servers and some less-than-minimal embedded systems.
Warning
Currently BusyBox uzcat alias zcat with seamless decompression fully supports only few of the available algorithms, and in particular it has not zstdcat.
Integrating #37ab6ac38 (0.1Kb) to busybox uchaosys edition, /bin/uzcat is created as an applet and its link signals that it can by magic-number auto-detection decompress any supported format by busybox. This allows uzpexec as stub to work "seamlessly" with any compression format (gz, bz2, xz, lzma) without further customisation, while the uncompressing algorithms are already included in BusyBox.
Moreover, by the integration of the /bin/uxsh applet (0.4Kb) in BusyBox, the uzpexec should no longer care about carrying the proper interpreter full path when it stubs as a launcher script. Calling directly /bin/uxsh the shebang line will be used to call the defined interpreter. This applet isn't strictly necessary because binfmt_script might be missing in some embedded or lightweight system (or secured systems that do not allow chmod +x on /proc/self/*).
An example of use is related to this project about QEMU footprint reduction which uses uzpexec to deliver the executable binary in UZP format which can be downloaded from here
Note
The qemu-system-x86_64, provided in UZP self-inflate executable, appears to be an x86 ELF 32-bit LSB executable. That type file refers to the extractor. While qemu is expanded in RAM and execute in its original ELF 64-bit format.
The shell script uzpack.sh converts a binary or a script into a self-extracting self-running in memory only. The most natural test is using the script to convert itself. Which is what happens during make and the result can be found as uzpack (2.7Kb circa).
Obviously, it is possible to convert an already converted binary. Which fails to run when it carries a shell script, but it is acceptable because it is totally useless to convert anything twice, especially in this case.
Note
Performance report: uzpexec in "fork loop" mode, is capable of sucking 2 core power from my i5-8365. Two! And this number can correctly taken as an index of its performance: no any lags but pure execution.
Quick customisation by coreutil sed, or any other stings-based editor (or commands line combination like xxd or base64 with busybox sed or awk) which can deal with binary data containing '\0', is straightforward supported:
rm -f uzpexec hello; make distclean uzpexec hello; elf=hello
sed -e 's/zstdcat.\{7\}U238/xzcat\x00_2_4_6_8x238/' uzpexec > $elf.uxp
xz -9c $elf >>$elf.uxp && chmod +x $elf.uxp && strace -f ./$elf.uxp 2>&-It is worth to note the relevant role of the U238 as string length sentinel:
U238 --> x238to inform the running code about the customisation- between
zcat_catandeof_testsdata size can change,U238tags it
Alternatives to /bin/zstdcat are every equivalent executable for which its full pathname would fit into a 22 chars string plus the trailing \0, and it can contain /usr/local/bin/zstdcat, for example.
When compiled with _HAS_PROVIDER and _NO_INFOSIX boolean declarations, the full pathname length remains unchanged. Depending on the compilation, the length can vary between 16 and 28 chars plus the ending \0.
; ==============================================================================
; COMPACT DATA SECTION (appended to code)
; ==============================================================================
; LN | XE
copy_vers: db "(c) github/robang74/uzpexec v0.98" ; 33 | 33
%ifdef _HAS_PROVIDER
provider : db 0x20, "12345678", 0x0a ; 10 | -
%else
micro_ver: db 0x20, 0x20, 0x20, 0x0a ; - | 4
%endif
; following fields are conditionally overwritable, do unions
zcat_path: db "/bin/z"
zcat_cmd : db "std"
zcat_cat : db "cat", 0 ; 13 | 23 (29)
%ifndef _HAS_PROVIDER
times 6 db 0 ; - | -
%endif
%ifdef _NO_INFOSIX
times 6 db 0 ; - | -
%endif
eof_tests: db "U238" ; for tests : 4 | -
; This introduces the need of having the /proc mounted,granted after the /init
; The shorter alernative is /dev/fd/9, but it is NOT grated on embedded systems
commd_exe: db "/proc/self/exe", 0,0 ; 16 | 16
; ----------
; 76 tot.
; ==============================================================================
; PADDING: Aligned exactly to 512 bytes (dd skip=1)
; ==============================================================================
file_end: ; Physical end of the binary file!
times (512 - ($ - $$)) db 0 ; Padding to 512 bytes for skip=1Since /path/name can point to a shell script, it can be changed to pair the input with the proper decompressing tool. While a tiny xcat binary in ASM would be much faster in properly pairing the matches.
Warning
The following script is provided untested AS-IS, just for the concept:
#!/bin/sh
HEADER=$(dd bs=1 count=4 2>/dev/null)
HEX=$(printf '%s' "$HEADER" | od -An -tx1 | tr -d ' \n')
case "$HEX" in
1f8b*) # GZIP
(printf '%s' "$HEADER"; cat) | gzip -d -c "$@"
;;
fd377a58) # XZ (\xfd7zX)
(printf '%s' "$HEADER"; cat) | xz -d -c "$@"
;;
425a68*) # BZIP2 (BZh)
(printf '%s' "$HEADER"; cat) | bzip2 -d -c "$@"
;;
28b52ffd) # ZSTD
(printf '%s' "$HEADER"; cat) | zstd -d -c "$@"
;;
*) # to support -f / --force
(printf '%s' "$HEADER"; cat)
;;
esacFrom the desktop user perspective the GNU coreutils sed command, or a specific shell script, can properly deal with elf and different script interpreters like python. Installing the zutils the alternative zcat is able to autodetect the compression format and act accordingly.
From the system integration perspective, the approach explained in the busybox support section would deal with different decompressing formats and selecting the proper script interpreter on the fly, bypassing the binfmt_script settings and replacing zutils zcat with a tiny footprint.
Hence, the customisation can scale up to completely different usage and deploying paradigms while still relying on the same basic tools and uzpexec strings embedded in the .data section.
The execution by pipe allows a basic running system, then an app is piped into uzpexec and executed accordingly with its nature and compression format. And this is a great feature for a lightweight supervisor OS that can create separated virtual execution spaces for each app granting that there is no absolute way one can sniff or read data from the others (unless system vulnerabilities, obviously, but not for the design of the uzpexec).
As a standalone utility uzpexec doesn't need to subdue the strict dd skip=1 constraint, being just an utility on a system. And this explains why the full version for AMR64 is totally fine being 1Kb or whatever minimal size, while the stub (two different for elf and scripts) are designed for the same constraint of the x86 counterpart. Knowing that x86 is for data-centers and arm64 for mobile devices.
Just to have an idea of the compacting everything in a 1-dd-block challenge, this following schema shows the sections within the 512-byte binary file in which the effective code area is necessarily compressed between the headers and the static data stored in the bottom part: 320 bytes are two 160 chars GSM-era SMS with 8 bit/char text encoding, just to have an idea of the size.
RAM ADDRESS Stub/Payload 512 bytes, v0.95 DISK SIZE
0x08048000 -- +---------------------------------+ -- 0x0000
| ELF Header | 52 B |
0x08048034 -- +---------------------------------+ -- 0x0034
| Program Header | 32 B |
0x08048054 -- +---------------------------------+ -- 0x0054
| Machine Code | 320 B |
| (start -> exit) | |
0x08048194 -- +---------------------------------+ -- 0x0194
| Embedded Data: | 105 B |
| version, provider, | |
| paths, args, etc. | |
0x080481FD -- +---------------------------------+ -- 0x01FD
| Padding (zeros) | 3 B |
0x08048200 -- +---------------------------------+ -- 0x0200
| .bss (RAM only) | not in |
| buf[516] | file |
+---------------------------------+
Customising this little guy is easy because the data is stored in plain text
which can easily be changed by a sed command line but altering the byte code
to change its running behaviour or logic, is completely another story.
The uzarm64.arm for aarch64 is a 512-byte stub/payload function-tuned created by refactoring down from the full 1024-bytes uzpexec.arm version, introduces some limitations to cut down its size:
- it uses
argv[0]as filename - just gzipped elf by
execve() qemu-aarch64's bug friendly- still has the provider field
Potentially separating the ELF binary from script support, it is reasonable to have two stubs both dd single-block size that a script like zpack.sh can embed as payload and deploy each of them selectively.
$ make testb
$ export WORLD=Wonderful
$ { cat uzarm64; gzip -9c hello; } > hiwld && chmod +x hiwld
$ ~/bin/qemu-aarch64-static -d strace ./hiwld nice 1147131 prctl(38,1,0,0,0,0) = 0
1147131 prctl(4,0,0,0,0,0) = 0
1147131 openat(AT_FDCWD,"/proc/self/exe",O_RDONLY|O_CLOEXEC) = 4
1147131 memfd_create(124085102814410,3,524288,0,0,0) = 5
1147131 read(4,0x400200,512) = 512
1147131 clone(0x11,child_stack=0x0000000000000000,
parent_tidptr=0x0000000000000000,tls=0x0000000000000000,
child_tidptr=0x0000000000000000) = 1147134
1147131 wait4(-1,0,0,0) = 0
1147134 dup3(4,0,0) = 0
1147134 dup3(5,1,0) = 1
1147134 execve("/bin/zcat",{"/bin/zcat",NULL}) =
1147131 fcntl(5,F_ADD_SEALS,0x000000000000000f) = 0
1147131 execve("/proc/self/fd/5",{"./hiwld","nice",NULL})
Hello nice World!
ARGV0: './hiwld'
ARGC: '2'
HOME: '/home/roberto'
WORLD: 'Wonderful'
The above reported console commands and output provide a reference about the running of a simple ARM64 compressed elf, the system call involved, the args/envp management and last but not the simplicity of assembling it.
The use of uzpexec extends every GitHub action from executing whatever is installable by their internal repository to whatever is available by an URL access.
PRE v0.98 RELEASE QUICK TESTS
38.8MB w/ 1st degree dynamic libraries
time qemu-system-x86_64 -m4 >/dev/null 2>&1
real 0m0.021s
user 0m0.008s
sys 0m0.013s
7.5MB musl-static, 2.5MB zstd compressed
time ./qemu-system-x86_64 -m4 >/dev/null 2>&1
real 0m0.046s
user 0m0.028s
sys 0m0.022s
uzpexec executes a binary which has already uzpexec as loader
time cat ./qemu-system-x86_64 | ./uzpexec -m4 >/dev/null 2>&1
real 0m0.073s
user 0m0.029s
sys 0m0.061s
uzpexec executes by STDIN pipe a binary which is zstd compressed
time dd skip=1 if=qemu-system-x86_64 2>&- | ./uzpexec -m4 >/dev/null 2>&1
real 0m0.046s
user 0m0.031s
sys 0m0.029s
Quick tests aim to set a raw reference in differential launch latency
By a raw estimation a 1GBit/s network call is nearly equivalent to a local call, because the 1Gbit/s network transfer time (25 ms) is zeroed by decompression on stream.
-
Security is a matter of perception, mainly. Currently, more a bureaucratics market rather than a serious R&D field. Hence, it is destabilising seeing an independent developer combining and surfacing 10-20yo techniques that relates to: TeenyELF (2005, darkweb),
memfd_create()andexecveat()(2014 and 2015, Linux) in glibc (2018). -
A 64 bit ELF would be much bigger, 2x potentially, and adding no value because this ELF32 doesn't process anything, not even the read() / write() hot loops (since the zero pipes implementation) but just a few system calls.
-
The
uzpexechas been developed to compensate for the gzcmd.sh shortcomings and to add useful capability in dealing with STDIN pipe. So, thegzcmd.shis this project's MVP to reach the production grade withuzpexec. -
Every sane compressing algorithm is also self-validating in terms of output conformity with the original while executing from a url in pipe is popular but a dangerous action because man-in-the-middle attack.
-
Is
uzpexeca stub or a payload or a pipexec? All of them, depending on the role it plays. When it gets embedded inuzpack.shit is a payload, whenuzpack.shconverts itself, it is a stub. When it is used vanilla is a pipexec. -
Moreover, all these three roles are complementary and necessary. Without pipexec it would not be able to run compressed scripts, hence it would not be able to convert itself. But it does, hence it is also a stub and a payload.
-
This triade of roles, and related capabilities, underlines why
uzpexecisn't limited by the unzip-and-run goal, which is theuzpackmain pourpose. It is different by design, by audience, by roles.
Separating executable code (X) from writing memory (W) costs too many bytes of code in stubs when a proper design can prevent any practical exploitation of that memory by an unprivileged enough attacker (aka before privileges escalation happens, aka for uzpexec not being the primary vector because this W+X memory design).
dd 7 ; p_flags (R+W+X - Read, Write, and Execute)
dd 0x1000 ; p_align (Standard page alignment)
; Security-by-Design VS Security-by-Subtraction
; Because uzpexec contains no input parsing logic that could be corrupted and
; its fixed 512-byte read loop cannot be overflowed, the writeable-executable
; segment offers no exploitable attack vector.
; Since the loader immediately forfeits control through atomic fork() / exec()
; or execveat() transitions that never return, an attacker cannot redirect
; execution to modified code before the process image is replaced.
; An adversary who can already write to the process memory holds sufficient
; privileges to inject code via ptrace or mprotect on any standard binary,
; which means the R+W+X flag introduces zero additional risk.
; WRX is the least of your troubles, but uzpexec as obscenely-powerful tool.Sealing in RO the anonymous file descriptor before execve() strongly supports security and integrity of the code/script set to run by uzpexec.
; ----------------------------------------------------------------------------
; HARDENING: F_ADD_SEALS TO MEMFD
;
; Apply F_ADD_SEALS (F_SEAL_WRITE, etc.) to the memfd exclusively
; within the ELF execution path before invoking execveat().
;
; - ELF hardening: prevents any runtime exploits from tampering with
; or rewriting the binary payload resident in RAM via /proc/self/fd/.
;
; - Script compatibility: this security measure is omitted for the
; shell interpreter branch because /bin/sh and its sub-utilities
; often require standard read/write descriptors or create temporary
; files, meaning write-restricted seals could break compatibility.
; ----------------------------------------------------------------------------A couple more of constraints strengthen the overall security policy:
; ----------------------------------------------------------------------------
; HARDENING: NO_NEW_PRIVS & ANTI-CORE-DUMP
;
; Using umask() is omitted because memfd ignores filesystem permissions.
; Additional hardening:
; - prctl(NO_NEW_PRIVS) prevents SUID escalation,
; - prctl(PR_SET_DUMPABLE, 0) prevents core dumps,
; - F_SEAL_SEAL locks the memfd seals permanently,
; - MFD_CLOEXEC and F_SEAL_WRITE are already set.
; ----------------------------------------------------------------------------- every script is supported when provided by its own shebang
- the related interpreter is registered with
binfmt_scripts
#!/bin/sh
# ------------------------------------------------------------------------------
# ############################################### #
# ####### put your shell script code here ####### #
# ############################################### #
# ------------------------------------------------------------------------------
exit $retSince /bin/dash is far faster than /bin/bash is usually the default shell on most
Linux desktop installations and almost always available.
By contrast, gzcmd.sh is designed to create self-extracting executable scripts. Therefore, when the script is complex, implements bashisms, or performs peculiar activity with/by the console, or requires to be self-finding or self-editing as standard file by its executable path then gzcmd.sh is a solid way to go.
A shell script that converts any ELF in a self-extracting executable for standard Unix/POSIX systems
- Initially written and committed in this repository Bare Minimal Linux Kernel & RootFS (2026-02-17)
The gzcmd.sh was the predecessor of uzpexec in terms of project planning and evolution. Once the gzcmd.sh shrunk in its payload version below 512 bytes (1 dd standard block), it sets the limit for developing a version in Assembler, the only other universal language that would have a chance to fit an ELF into 512 bytes.
Alternatively it can be used by activating the execution bit by chmod +x gzcmd.sh or calling it by the shell sh gzcmd.sh, the only parameter that matters is the ELF patch to convert and the converted file will be written in the current directory.
$ UZCMD=pigz ZCMPLVL=11 sh gzcmd.sh gzcmd.sh
FILE: 'gzcmd.gz.sh', HEAD: 506 (512), GZIP: 6635 (6 Kb, 37 %), GZSH: v0.3.3
An ELF binary compressed with gzcmd.sh can be installed permanently providing a directory which resides on a writable and executable disk space:
TMPDIR=~/bin ./$filename.gz.sh # to install in ~/binTo use the converted file, launch it directly or by a shell because from the PoV of the Linux kernel is a shell script.
Previous versions than v0.1.8 had the payload size variable, which was an optimization in terms of overhead but confusing in doing an independent extraction.
Therefore the payload size had been set fixed to 1024 (two 512 blocks) because such a default value allows a trivial extraction of the gzipped appended file:
dd skip=1 if=${filename.gz.sh} | zcat - >${filename}Starting from the v0.3.1 the payload size has reduced below the 512 (1 block) size. Hence skip=1 instead of skip=2. Moreover the SZE internal value, now it refers to the maximum memory pages (4kB) that the extracted ELF binary will take.
#!/bin/sh
# (C) 2026 robang74 l.MIT v0.3.1 git.new/ttRvFBu
BFN=hello:d713d0d05c;SZE=4
: ${PATH:=/bin:/usr/bin:/usr/local/bin}
exec 2>&-
T=".gzc-$BFN-${USER:-$(id -u)}"
for d in "${TMPDIR:-/tmp}" /run /dev/shm "${HOME:-.}/.cache"
do
F="$d/$T"
(umask 077;echo>"$F"&&chmod 700 "$F"&&"$F")&&break
rm -f "$F"
F=
done
dd if=$0 skip=1|$(command -v pigz gzip gunzip zcat|head -n1) -dc>"$F"&&{
grep -qe "tmpfs.*$d" /proc/mounts&&trap 'rm -f "$F"_' EXIT INT TERM
mv -f "$F" "$F"_&&(F=;exec "$d/$T"_ "$@")
}
exit
#1_345678The padding line(s) provide(s) enough bytes to reach the fixed payload size, shortening more the payload, requires adding more padding lines, unless the size drops below 512 bytes and in that case bs skip=1 would be enough.
In order to run the paylod, a few minimum requirements are need:
- a Unix/POSIX shell: even minimal, with basic file descriptor management.
- shell internals:
echo,exec,for,command,exitand possiblytrap - utilities:
dd,rm,mv,head, and possiblygrep,id - alternatives:
zcator every equivalent,umaskorchmod - environment:
PATH, and optionalHOME,USER,TMPDIR
All of the requirements are almost always granted in every Unix/POSIX.