UPX: what the executable packer actually does to your binaries
UPX - the Ultimate Packer for eXecutables
At a glance
- What is it?
- UPX compresses Windows and Linux executables so they stay self-contained and run as before. This review covers the command line, the build from source, the security caveat the README states plainly, and when packing a binary is the wrong move.
- Who is it for?
- Adopt UPX if you ship large Linux or Windows executables and DLLs and can verify the packed result on your target systems; the README states packing requires the same security considerations as executing the file, so run it only on files you trust. Do not adopt it as a protection or obfuscation layer, because the project states it will not add protection or encryption, and do not treat ARM64 for Windows as available since the README lists it as help wanted.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem UPX solves, and who actually has it
UPX is an executable file compressor. The README states that it will typically reduce the file size of programs and DLLs by around 50%-70%, which lowers disk usage, network load, download times and distribution costs. That is the whole pitch, and it is a distribution problem rather than a development one.
The people who feel it are the ones paying for bytes in motion: anyone shipping a large static Linux binary to many machines, anyone bundling a Windows application or DLL where the download size shows up in install time, and anyone whose container images are dominated by one fat executable. If your artifact is already small, or if it is served once from a CDN to a handful of clients, the return is thin.
What UPX is not is a protector. The README is explicit that it will not add any sort of protection or encryption, on the grounds that this gives people a false feeling of security because all protectors can be broken by definition. Read that as a design boundary rather than a missing feature. If your reason for packing is to hide strings or slow down reverse engineering, UPX is the wrong tool and the project says so itself.
How the packer works and what it changes in the file
UPX rewrites the executable. It compresses the code and data sections into a packed form and attaches a small decompressor stub plus the metadata needed to reconstruct the original layout at load time. According to the README, programs and libraries compressed by UPX are completely self-contained and run exactly as before, with no runtime or memory penalty for most of the supported formats. The decompression happens as the loader brings the image in, so the operating system still sees a normal executable.
The supported formats are the practical constraint. The README names Windows programs and DLLs and Linux executables, and describes the project as supporting a number of different executable formats rather than every one. The repository layout reflects this: the src/ tree holds the per-format handling, and the format list is what determines whether your particular artifact is even a candidate.
One consequence follows from the design and is easy to miss. Because the original sections are compressed and the stub restores them, the file on disk no longer resembles the file the compiler emitted. Signatures computed over the packed bytes will not match signatures computed over the original, and tooling that inspects sections statically will see the stub instead of your code. UPX ships a decompressor for exactly this reason, and the documentation treats packing and unpacking as reversible operations on the same file.
Installing UPX and packing your first binary
Most people should not build UPX from source. The project publishes releases, and the current line is v5.2.1 from 2026-08-27, following v5.2.0 and v5.1.1. The README points to https://upx.github.io as the home page, and prebuilt binaries for common platforms are what the release artifacts are for. Grab the archive for your platform from there rather than compiling.
If you do need to build it, the top-level Makefile is a convenience wrapper around CMake and states that it needs GNU make and CMake >= 3.13. The default goal is build/release, so a plain make in the repository root configures and builds a release tree. The Makefile comment notes that on an older CMake 3.x you can invoke it by hand.
mkdir -p build/release
cd build/release
cmake ../..
make -j4That sequence produces the upx binary under build/release. The Makefile also defines debug, release and all targets, and passes --parallel to the build step, so make release is the shorter path once you are in the root.
Packing a file is a single command. The README gives this example directly:
upx program.exeFor better ratios the README suggests upx --best program.exe or upx --brute program.exe. Expect the second to take noticeably longer; the flag name is a fair warning. After the run, the tool reports the compression result and the file is smaller on disk. To get the original back, use the decompression mode, and to see what UPX would do without writing anything, use the test and list modes. The README notes that upx --help lists the available options, and that doc/upx-doc.txt holds the full documentation.
The security note in the README deserves to be read twice
UPX inherits the security context of any files it handles. That sentence is in the README under its own heading, and the explanation that follows is blunt: packing, unpacking, or even testing or listing a file requires the same security considerations as actually executing the file, so use UPX on trusted files only.
This is not boilerplate. Parsing an executable format means walking attacker-controlled offsets and lengths, and UPX does that for every supported format. The same reasoning applies to the test and list modes, which is the part people skip. If you were planning to point UPX at a directory of downloaded samples to see which ones it recognises, the README tells you that listing them carries the same risk as running them.
The practical shape of this in a pipeline is a build step that only ever sees artifacts your own toolchain produced. Feeding it untrusted input, whether from a user upload or a third-party download, moves the risk from the packer's parser to your build machine.
Where UPX stops being the right answer
The clearest limitation is the one the project states about itself: no protection and no encryption. Packing reduces size. It does not make a binary hard to analyse, and the README argues that claiming otherwise would be dishonest. Anyone adopting UPX for obfuscation should stop here.
Platform coverage is the second boundary. The README lists ARM64 for Windows as an open item with help wanted, so that combination is not something to plan around. The supported set is what the project says it supports, and the format list is the thing to check against your build matrix before you commit to a release process that assumes packing.
There is also a verification cost that does not appear in the compression ratio. A packed binary is a different artifact from the one your tests ran against, so the packed form needs its own smoke test on the oldest kernel or Windows version you support. Reversibility helps: the decompressor gives you a way to check that the packed file round-trips, and that check belongs in the pipeline rather than in a one-off manual step. Finally, if the size problem you are trying to solve is really a dependency problem, removing a large unused library will beat compression every time.
How UPX compares with ordinary compression tools
The obvious alternative is a general-purpose archiver such as gzip, xz or zstd. The difference in approach is where decompression happens. An archiver produces an archive that a user or an installer unpacks to disk before anything runs; the executable on disk is the original one. UPX produces an executable that decompresses itself in memory as it loads, which is why the README can describe packed programs as self-contained and running exactly as before.
That distinction decides the use case. If you are shipping a tarball that gets extracted once during installation, an archiver is simpler, has no per-format support matrix, and does not touch the executable's structure. If you need the deployed file itself to be smaller, with no separate unpack step and no installer change, self-decompression is the only one of the two that gets you there.
A second alternative is to skip compression and attack the artifact directly: strip symbols, build with size optimisation, drop unused dependencies, or split the binary. Those changes reduce size without altering the executable format, so signing, static analysis and packaging all keep working unchanged. UPX is worth reaching for when those have already been done and the file is still too large.
Licence, maintenance and what a UPX upgrade costs you
UPX is distributed under the GNU General Public License v2+. The README describes the licensing as a choice: you can take it under the pure GPLv2+ as set out in the file COPYING, or, at your option, under GPLv2+ with special exceptions and restrictions that grant free usage for all binaries including commercial programs, as set out in the file LICENSE. The README states that UPX may be distributed and used freely, even with commercial applications, and points to the UPX License Agreements for details. That is a summary of what the project says, not legal advice; if the exception matters to your distribution model, read LICENSE and COPYING in the repository.
The repository is not archived. The last push was on 2026-09-21, and releases have been arriving through 2026, with v5.2.1 on 2026-08-27. The README's own roadmap is short: stay up to date with ongoing OS and executable format changes, add ARM64 for Windows (help wanted), and fix remaining bugs, with issues reported at https://github.com/upx/upx/issues.
Upgrade cost is dominated by that first roadmap item rather than by the packer's own release cadence. Executable formats and OS loaders change, and UPX has to track them, so a new OS release is the event that can force a UPX upgrade. The cheap way to absorb that is to keep the round-trip check in your pipeline: pack a representative binary, decompress it, and compare against the original. When a format change breaks something, that check tells you before your users do.
Editorial conclusion
Adopt UPX if you ship large Linux or Windows executables and DLLs and can verify the packed result on your target systems; the README states packing requires the same security considerations as executing the file, so run it only on files you trust. Do not adopt it as a protection or obfuscation layer, because the project states it will not add protection or encryption, and do not treat ARM64 for Windows as available since the README lists it as help wanted. Before rolling it out, pack one representative binary with upx --best, run it on the oldest kernel or Windows version you support, and confirm that upx -d restores a byte-identical file.
Frequently asked questions
What does UPX mean?
The README states that UPX is a shorthand for the Ultimate Packer for eXecutables, and notes the term holds no connection with potential owners of registered trademarks or other rights.
Is UPX safe?
The README states that UPX inherits the security context of any files it handles, so packing, unpacking, or even testing or listing a file requires the same security considerations as executing it. It advises using UPX on trusted files only.
Is UPX a VPN?
No. UPX is an executable file compressor for formats such as Windows programs and DLLs and Linux executables, according to the README. Nothing in the repository describes network tunnelling or a VPN service.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/upx-upx)