Hubbry Logo
UPXUPXMain
Open search
UPX
Community hub
UPX
logo
8 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
UPX
UPX
from Wikipedia
UPX
Initial releaseMay 26, 1998; 27 years ago (1998-05-26)
Stable release
5.0.2 / July 20, 2025; 6 months ago (2025-07-20)
Repository
Written inC++, Assembly
Operating systemMicrosoft Windows, Linux, macOS, DOS, Atari TOS
Platformi386, MIPS, AMD64, ARM, PowerPC, m68k
Available inEnglish
TypeExecutable compression
LicenseGPL with exception for compressed executables,[1] proprietary for compression algorithm in binary distributions[2]
Websiteupx.github.io

UPX (Ultimate Packer for eXecutables) is a free and open source executable packer supporting a number of file formats from different operating systems.[3][4]

Compression

[edit]

UPX uses a data compression algorithm called UCL,[5] which is an open-source implementation of portions of the proprietary NRV (Not Really Vanished)[6] algorithm.[2]

UCL has been designed to be simple enough that a decompressor can be implemented in just a few hundred bytes of code. UCL requires no additional memory to be allocated for decompression, a considerable advantage that means that a UPX packed executable usually requires no additional memory.

UPX (since 2.90 beta) can use LZMA on most platforms; however, this is disabled by default for 16-bit due to slow decompression speed on older computers (use --lzma to force it on).

Starting with version 3.91, UPX also supports 64-Bit (x64) PE files on the Windows platform.[7] This feature is currently declared as experimental.

Decompression

[edit]

UPX supports two mechanisms for decompression: an in-place technique and extraction to temporary file.

The in-place technique, which decompresses the executable into memory, is not possible on all supported platforms. It has the advantage of being more efficient in terms of memory, and that the environment set up by the OS remains correct.

The rest uses extraction to temporary file. This procedure involves additional overhead and other disadvantages; however, it allows any executable file format to be packed. The extraction to temporary file method has several disadvantages:

  • Special permissions are ignored, such as suid.
  • argv[0] will not be meaningful.
  • Multiple running instances of the executable are unable to share common segments.

Unmodified UPX packing is often detected and unpacked by antivirus software scanners. UPX also has a built-in feature for unpacking unmodified executables packed with itself.

Supported formats

[edit]

UPX supports the following formats:[8]

UPX does not currently support PE files containing CIL code intended to run on the .NET Framework.

Notes

[edit]

References

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
UPX (Ultimate Packer for eXecutables) is a free, open-source, portable, and high-performance packer designed to compress files, libraries, and other binary formats while preserving their functionality. It achieves compression ratios typically ranging from 50% to 70%, outperforming tools like ZIP or in many cases, and supports in-place decompression with no additional runtime memory overhead. Developed primarily in portable C++, UPX is extendable, allowing for the addition of new formats or compression algorithms, and includes safety features such as verification for testing and unpacking packed files. Originally created by Markus F.X.J. Oberhumer and László Molnár, with later contributions from John F. Reiser and Jens Medoch, UPX's development began in the mid-1990s, with its first production-quality release occurring around 1996 and the project becoming fully open-source under the GNU General Public License version 2 (with exceptions) starting from version 0.99. The tool supports a wide array of executable formats across multiple operating systems and architectures, including Windows PE (32-bit and 64-bit), ELF (i386, AMD64, PowerPC), macOS , DOS EXE/COM/SYS, and others such as , PlayStation EXE, and Watcom LE. As of 2025, the latest stable version is 5.0.2 (released July 2024), with ongoing maintenance ensuring compatibility and security updates. UPX is widely used for reducing distribution sizes in , embedded systems, and bootloaders, though it has also been noted in contexts for potentially obscuring due to its packing mechanism, which can be easily unpacked using the tool's built-in decompressor. Its decompression speed exceeds 500 MB/s on modern hardware, making it suitable for performance-sensitive applications, and it operates via a with options for compression levels, format-specific tweaks, and overlay handling. The project's and binaries are hosted on , fostering community contributions while maintaining for older packed files.

Introduction

Overview

UPX, the Ultimate Packer for eXecutables, is a free and open-source tool designed to compress executable files, reducing their size while preserving full functionality and enabling self-decompression at runtime. It achieves this by packing programs, dynamic libraries, and other binaries into compact forms suitable for distribution, thereby minimizing disk space usage, network bandwidth, and loading times without imposing runtime penalties in most cases. UPX is licensed under the GNU General Public License version 2 or later, with a special exception that permits the redistribution of compressed executables—including for commercial purposes—without requiring the disclosure of the original , provided the UPX version remains unmodified and the decompression stub is used solely for unpacking at startup. This licensing model ensures broad while protecting users from potential modifications that could embed malicious code. The project was initially released on May 26, 1998, with the latest stable version, 5.0.2, issued on July 20, 2024. Key benefits of UPX include typical compression ratios of 50% to 70%—superior to general-purpose archivers like ZIP or for executables—along with high portability across multiple operating systems and architectures. It supports various executable formats from platforms such as Windows, , and macOS, making it a versatile option for developers and system administrators. The official website is upx.github.io, and the source repository is hosted at /upx/upx.

History and Development

UPX originated as a hobby project initiated in 1996 by developers Markus F.X.J. Oberhumer and László Molnár, who sought to create an efficient compressor building on prior tools like DJP and LZOP. The duo's collaboration laid the foundation for what would become a widely used open-source utility, with John F. Reiser later joining as a key contributor. The first public beta release, version 0.05, arrived on May 26, 1998, marking UPX's debut as a portable packer for multiple formats. Early development emphasized stability and licensing clarity, culminating in the release of the full source code under the GNU General Public License with version 0.99 on February 25, 2000. This was swiftly followed by the stable version 1.00 on March 26, 2000, which included documentation enhancements and bug fixes to solidify its reliability. A significant advancement came with version 2.90 on October 8, 2006, introducing LZMA compression support for improved ratios across 32-bit and 64-bit formats via the new --lzma option. Further expansion occurred in version 3.91, released on September 30, 2013, which added experimental support for 64-bit Windows PE files based on contributions from Stefan Widmann. The project transitioned to GitHub hosting with version 3.92 on December 11, 2016, facilitating broader community involvement. In more recent years, UPX adopted semantic versioning starting with 4.0.0 on October 28, 2022, to better manage updates and compatibility. Version 5.0, released on February 20, 2024, brought enhancements including refined ARM64 support for Linux (aarch64) and other modern architectures, alongside optimizations like LZMA for 64-bit PowerPC contributed by Thierry Fauck. The latest release, 5.0.2 on July 20, 2024, primarily addresses bug fixes and compatibility issues for contemporary systems, ensuring ongoing viability. As an active open-source endeavor on GitHub, UPX continues to receive community contributions and is implemented mainly in C++ with assembly for performance-critical sections.

Core Functionality

Compression Process

The compression process in UPX begins with the input file to understand its format-specific structure, including identification of compressible sections such as and data, entry points, and relocation tables. These sections are then analyzed for to determine suitability for compression, with non-compressible elements like certain headers preserved or minimally modified. UPX primarily employs algorithms from the NRV (Not Really Vanished) family, re-implemented as the open-source UCL library, which are LZ77-based dictionary compressors designed for high decompression speed and reasonable ratios. Variants such as nrv2b and nrv2d are commonly used, where nrv2b offers a good balance of size reduction and speed, while nrv2d prioritizes slightly better ratios at minor speed costs; these algorithms process data in blocks, replacing repeated sequences with references to achieve lossless compression. For higher compression ratios, UPX supports LZMA (Lempel–Ziv–Markov chain algorithm), introduced in version 2.90, which uses a more advanced range encoder and adaptive dictionary for superior entropy coding but results in slower decompression times. The core steps involve compressing eligible sections individually using the chosen and compression level—ranging from 1 (fastest, lowest ratio) to 9 (slowest, highest ratio), with --best or --ultra-brute modes applying aggressive optimizations like multiple passes or brute-force parameter tuning for maximum reduction. Relocation tables are adjusted to account for offset changes due to compression, ensuring correct runtime addressing, while original headers are embedded to maintain format compatibility. Factors influencing the include the input file's code and , typically yielding 50-70% size reduction for programs and DLLs, though results vary by algorithm and options. The output is a self-extracting that incorporates a small decompression stub—often under 3 KB—prepended or appended to the compressed data, allowing the file to run transparently by unpacking sections in place or to at runtime without additional overhead for most supported formats. This stub is platform-specific and optimized in assembly for minimal size and fast execution.

Decompression Process

When a UPX-packed is launched, a small, uncompressed stub—typically ranging from 1 to 5 KB in size and written in assembly—executes first to handle the unpacking process. This stub is embedded at the beginning of the packed file and relies on minimal system calls without dependencies on libraries like libc, ensuring portability across supported platforms. For instance, on ELF executables, the stub is approximately 1700 bytes and performs all necessary operations independently. The runtime decompression proceeds in-place within memory for most formats, avoiding the creation of temporary files and minimizing overhead. The stub maps the packed file into memory, then applies the inverse of the compression algorithm—such as the NRV (Not Really Vanished) decompression routine from the UCL library—to expand compressed sections directly over their packed counterparts. It subsequently restores the original entry point, handles any necessary relocations, wipes the stack if required, and transfers control to the unpacked code, simulating kernel mappings as needed (e.g., setting brk() on Linux/ELF). This self-modifying approach ensures the original program executes seamlessly, with decompression speeds exceeding 500 MB/sec on modern hardware and no additional memory footprint post-unpacking. To maintain integrity, the stub includes built-in checks for file corruption or modifications, aborting execution with an exit code of 127 if issues are detected during decompression. Non-executable overlay data—such as resources or appended files—is preserved if the --overlay option was specified during compression, by copying it after the decompressed image without alteration. The stub's lightweight design adds negligible startup overhead, typically under a second, and supports compatibility across diverse architectures by tailoring operations to the target format, such as decompressing to /tmp and re-executing via execve() for certain variants.

Supported Platforms and Formats

Executable Formats

UPX primarily supports the (PE) format for Windows systems, encompassing both 32-bit and 64-bit executables as well as dynamic link libraries (.exe and .dll files). This format enables compression of native Windows applications while preserving their functionality upon decompression. The (ELF) is another core supported format, targeting 32-bit and 64-bit binaries on and operating systems. Additional formats include for macOS and applications, supporting both 32-bit and 64-bit binaries, with ARM64 support added in version 4.0. Other legacy formats covered are the Linear Executable (LE) for DOS and 16-bit Windows environments; a.out for older Unix systems; and for Atari ST platforms. These extend UPX's compatibility to historical systems while maintaining focus on native . UPX does not support managed formats such as .NET assemblies or , restricting its use to native binaries that can be directly executed or linked. During processing, UPX automatically detects the input file's format by inspecting its header signatures or magic bytes, ensuring seamless handling without manual specification.

Operating Systems and Architectures

UPX runs on a wide range of host operating systems, including all versions of Windows, various distributions, macOS, , DOS, and . Pre-built binaries are provided for major platforms such as (across architectures like amd64, arm64, ), Windows (x86 and x64), and macOS, facilitating easy deployment without compilation. Cross-compilation is fully supported, allowing users to generate packed executables for diverse targets from a single host environment, such as creating Windows PE files on a system or macOS binaries from Windows. The tool targets numerous CPU architectures, encompassing x86 (i386 in both 32-bit and 64-bit configurations), AMD64, (32-bit and 64-bit variants, including instruction set), PowerPC (32-bit and 64-bit), MIPS (supporting both big-endian and little-endian byte orders), and the family (m68k). These architectures enable UPX to compress executables in formats like ELF for , PE for Windows, for macOS, and legacy formats such as LE for or TOS for Atari. Support for these platforms ensures compatibility with both modern and embedded systems, though decompression stubs are optimized per architecture for efficient runtime performance. Notable enhancements include the addition of ARM64 (aarch64) support for ELF executables in version 3.94 (2017), with further refinements in subsequent releases up to version 4.0 (2022) for broader stability across PE and formats. As of version 5.0.0 (February 2025), enhancements include improved handling of ELF sections such as PT_MIPS_ABIFLAGS, maintaining . Building UPX from source requires a standards-compliant C++ (such as GCC or ) and the NASM assembler for generating architecture-specific stubs. The build process uses for configuration, supporting cross-compilation toolchains to produce binaries for non-native hosts; official documentation recommends verifying toolchain compatibility for less common architectures like MIPS or m68k. Pre-built binaries mitigate these requirements for standard use cases on supported hosts.

Usage

Command-Line Interface

UPX operates primarily through a command-line interface, functioning as a console application without a graphical user interface, which makes it suitable for scripting and batch processing of multiple files. To use UPX, users must first install it by downloading pre-built binaries from the official GitHub releases page at https://github.com/upx/upx/releases, which provides executables for Windows (32-bit and 64-bit) and various Linux architectures (such as amd64 and arm64, often statically linked for portability). As of November 2025, the latest version is 5.0.2. For macOS, pre-built binaries are not directly provided in releases; instead, UPX can be installed via package managers like Homebrew (brew install upx) or MacPorts (sudo port install upx), ensuring compatibility with Apple Silicon and Intel architectures; users can also build from source. After installation, verify the setup by running upx -V in the terminal, which displays the UPX version and build information to confirm proper functionality. The basic syntax for invoking UPX is upx [options] file1 [file2 ...], allowing the processing of one or more input files in a single command; by default, it compresses the files and outputs packed versions with a .upx extension to avoid overwriting originals, though the --overwrite option can be used to replace the input files directly. Core commands include upx file.exe for default compression of an executable, upx -d file.exe to decompress or unpack a previously packed file back to its original form (supports multiple files for batch operations), and upx -l file.exe to list detailed packing information such as compression ratios and supported formats without modifying the file. These operations require no additional prerequisites beyond a standard command-line environment, and UPX supports batch processing by specifying multiple filenames or using wildcards in scripts for automation. UPX returns exit codes to indicate operation status: 0 for , 1 for fatal errors (e.g., unsupported or validation failure), and 2 for warnings (non-fatal issues); consult the for version-specific details to implement appropriate error handling in scripts. This design ensures reliable integration into build scripts or pipelines.

Common Options and Examples

UPX provides several command-line options to control compression levels, decompression, output handling, and file , allowing users to tailor the packing to specific needs. The --best option enables the highest compression ratio by exhaustively trying multiple methods and levels, though it is computationally intensive and slower than default settings, making it suitable for final releases of executables. The -9 flag sets the maximum compression level for the default algorithm, prioritizing size reduction over speed, but is generally less thorough than --best, which tests multiple algorithms. For alternative algorithms, --lzma invokes the LZMA compression method, which can achieve better ratios but results in slower decompression times, particularly for larger files. The --brute option further enhances optimization by testing all available compression algorithms exhaustively to find the best fit. Decompression is handled via the -d or --decompress flags, which unpack one or more UPX-compressed files in place, restoring them to their original state without altering functionality. Output can be directed to a custom file using -o followed by the desired filename, preventing overwrites of originals during testing. Additionally, --overlay=strip removes non-essential overlay data from files, potentially improving compression ratios but risking crashes if the program depends on that data. Practical examples illustrate common usage patterns. To achieve maximum compression on a single executable, the command upx --best program.exe applies exhaustive optimization, reducing file size significantly while preserving executability. For decompression with a specified output, upx -d -o original.exe packed.upx unpacks the file to a new location named original.exe. Batch compression of multiple executables is straightforward with upx --best *.exe, which processes all .exe files in the current directory using optimal settings. To inspect packed files, the -l or --list option displays compression statistics, such as original and packed sizes along with the ratio achieved. Integrity verification uses -t or --test, which checks the file's compressed and uncompressed data without modifying it, ensuring no corruption occurred during packing. For scripting or automated environments, --no-progress suppresses verbose output, keeping logs clean. Best practices emphasize verifying results after operations: always run -t on packed files to confirm , and test the unpacked to ensure it functions correctly, as compression can occasionally interact poorly with certain code patterns. Using --no-progress is recommended in batch scripts to avoid cluttering output, and specifying -o helps maintain safe backups during experimentation.

Advanced Topics

Customization and Building from Source

UPX can be built from source to enable customization and for specific development needs, such as targeting niche architectures or integrating modified compression behaviors. The source code is hosted on , where developers clone the repository using git clone https://github.com/upx/upx.git. Building requires a C++ that supports , such as GCC 8 or later, Clang 5 or later, or MSVC 2019 (version 16.11 or later), along with version 3.8 or higher (3.10 recommended) and an assembler like NASM or YASM for x86/x64 targets, or GAS for other architectures. The build process typically involves configuring with and compiling the executable. For systems, including and macOS, run cmake -S . -B build followed by cmake --build build from the ; alternatively, traditional Makefiles are available in the src/ directory for make -C src. On Windows, use projects or with cmake to generate appropriate build files, such as cmake -G "MinGW Makefiles" .. and then mingw32-make. Cross-compilation is supported via target-specific toolchains, for example, setting CROSS=arm-linux- in Makefiles or using 's cross-compilation presets for embedded targets like or , allowing tailoring to architectures beyond the standard supported platforms. Dependencies are minimal and mostly bundled: the UCL compression library and zlib are included as static libraries for core functionality, with optional support for or Zstandard if enabled during configuration. For DOS-specific stubs, PMODE/W is optionally required to handle extender support in legacy builds. No external runtime libraries are needed beyond the build tools, ensuring portability across platforms. Customization allows developers to modify core components for specialized use cases. Decompression stubs, which handle runtime unpacking, can be edited in the src/stub/ directory, where architecture-specific assembly files (e.g., i386-linux.elf.S) define the stub behavior; after changes, rebuild the stubs using provided tools in contrib/stubtools/. To implement new compression algorithms, alter files like compress_lzma.cpp or compress_zlib.cpp in the src/ directory, integrating them into the packer framework. Adding support for new executable formats involves creating or extending packer classes, such as deriving from base classes in p_com.cpp or p_elf.cpp, and registering them in the format detection logic. These modifications require recompiling UPX to incorporate the changes. Binary releases distributed via GitHub include pre-built decompression stubs for common architectures, simplifying end-user deployment without source compilation. In contrast, building from source permits precise tailoring, such as enabling experimental features or optimizing for specific hardware constraints not covered in standard binaries. Version control is managed through Git, with the official repository at https://github.com/upx/upx; developers track changes locally and contribute improvements via pull requests, following the project's guidelines for code reviews and testing.

Integration with Development Tools

UPX can be integrated into build systems to automate the compression of executables as a post-linking step, enhancing distribution efficiency without altering the core build process. In Makefiles, developers commonly append UPX invocation after the linking target, such as upx $(TARGET) to compress the resulting binary directly. supports this through the FindSelfPackers module, which detects and configures UPX for use in custom commands or install rules, allowing seamless incorporation into cross-platform projects. For Visual Studio environments, MSBuild tasks can invoke UPX via custom build steps in project files, typically targeting release configurations to minimize executable size before deployment. In and (CI/CD) pipelines, UPX is frequently employed to compress release artifacts, reducing bandwidth and storage needs. GitHub Actions workflows often include dedicated steps using actions like ghaction-upx or upx-action, where commands such as upx --best release/*.exe are executed after compilation to pack binaries before publishing. Similarly, Jenkins pipelines can incorporate UPX in shell scripts during deployment stages, ensuring compressed outputs for automated releases while maintaining pipeline reproducibility. UPX integrates with various development tools, particularly in workflows and scenarios. It is compatible with and compilers, where packed executables generated from these tools retain full functionality, as UPX supports the PE and ELF formats they produce. For , tools like GDB require unpacking the binary first with upx -d to access original symbols and code, avoiding issues with the compression stub. IDA Pro users can analyze UPX-packed files by leveraging its built-in unpacking capabilities or manual techniques to locate the original post-decompression. In contexts, UPX's -d option facilitates straightforward unpacking for static analysis, enabling tools like Detect It Easy (DIE) to identify and extract UPX-packed or PE files through integrated scripts. This approach is standard for , where decompression reveals the unpacked payload without needing specialized plugins. UPX is utilized in software packaging processes, including distribution builds. includes UPX as the upx-ucl package, allowing packagers to compress binaries during Debian package creation to optimize repository space. For mobile applications, its support enables packing of native libraries within Android APK files, reducing app bundle sizes without impacting runtime performance. Best practices for UPX integration emphasize reliability and targeted application. Scripts should pin specific UPX versions to ensure consistent compression behavior across builds, mitigating risks from updates that might alter packing algorithms. Packing should be conditional, applied only to release builds to preserve debuggability in development versions, and always followed by verification of the unpacked to confirm integrity.

Limitations and Considerations

Performance Impacts

UPX typically achieves a reduction of 50% to 70% for programs and DLLs, making it particularly effective for decreasing disk space and network transfer requirements. This is determined by comparing the original to the packed size, as reported by the upx -l command, and is more substantial for executables dominated by sections rather than embedded data. At runtime, UPX introduces a modest overhead in startup time owing to the execution of its decompression stub, which can slow initial loading by a few milliseconds to hundreds of milliseconds depending on the binary size and hardware; however, this effect is negligible for applications that run for extended periods. Post-decompression, there is no ongoing penalty, as the unpacked behaves identically to its original form. In terms of memory usage, UPX employs in-place decompression, which avoids persistent overhead after startup but involves a temporary allocation during unpacking equivalent to the size of the decompressed data. This process can lead to higher peak memory consumption compared to non-packed executables, especially in scenarios where multiple instances run concurrently without mapping. The time required for compression varies by selected options; default levels (around -7 or -8) complete quickly, often in seconds for files under 1 MB, while the --best mode prioritizes ratio over speed and can take considerably longer for only marginal additional gains. selection influences these trade-offs, with options like LZMA providing superior compression ratios at the expense of increased packing duration, though decompression remains rapid at over 500 MB/s on modern systems.

Security Aspects

UPX is a free, open-source executable packer that operates without inherent backdoors or malicious components, as its source code has been publicly available and scrutinized for over two decades. However, files compressed with UPX can sometimes bypass basic signature-based antivirus detection by altering the executable's structure and entropy, making them appear less suspicious to simplistic scanners. Despite its benign design, UPX has been frequently misused by authors to obfuscate viruses and trojans, particularly in threats from the and 2000s, where packing helped evade early detection tools by compressing and encrypting malicious payloads. In contemporary environments, however, most advanced antivirus solutions automatically unpack UPX-compressed files during scanning to analyze the underlying code, reducing the effectiveness of this evasion technique. UPX-packed executables are commonly flagged by security scanners as potentially suspicious; for instance, frequently identifies them via heuristics labeling files as "UPX-packed," even if benign, leading to false positives in automated analysis. Users can employ UPX's --all-methods option to apply multiple compression algorithms, which may complicate straightforward identification but does not guarantee evasion against modern unpackers. Vulnerabilities in UPX are rare but have been documented, such as CVE-2021-20285, a in the canPack function of p_lx_elf.cpp affecting version 3.96, which could lead to denial-of-service via segmentation faults or overflows, and was addressed in subsequent releases. More recently, CVE-2025-2849 exposed a heap-based in the PackLinuxElf64::un_DT_INIT function in src/p_lx_elf.cpp for versions up to 5.0.0, potentially allowing local denial-of-service; this was mitigated in later patches, with users advised to employ the current stable release, version 5.0.2. To mitigate security risks, best practices include digitally signing UPX-packed executables to verify and origin, avoiding its use for highly sensitive applications where could raise compliance concerns, and routinely unpacking files with the UPX -d command for security auditing and verification. Additionally, UPX inherits the security context of processed files, so operations should occur in isolated environments to prevent unintended . Legally, while UPX is licensed under General Public License version 2 or later, it includes a special exception permitting the distribution of packed proprietary executables without requiring them to adopt the GPL, though unmodified UPX must remain under GPL terms. Packing with UPX can impede by concealing original code structures, complicating static analysis for security researchers or attackers alike; nonetheless, the original is readily restorable using the UPX -d option, which decompresses files without loss, enabling thorough inspection.

References

Add your contribution
Related Hubs
User Avatar
No comments yet.