MENU

UPX 的使用

September 2, 2023 • Read: 1361 • Linux,编码,算法,Go

UPX 是什么

UPX 全称是 "Ultimate Packer for eXecutables",是一个免费、开源、编写、可扩展、高性能的可执行程序打包程序。换句话说一个可执行文件的压缩工具。主要的功能是将可执行的二进制程序、动态链接库和其他的二进制文件压缩为更小的体积,UPX 通常可以将文件大小减少 50% - 70%。从而减少磁盘空间占用、降低网络传输所需带宽、以及分发成本(UPX 创建于 1996年,那时大家都在使用软盘,所以存储空间十分宝贵,也凸显了可执行程序压缩的必要性)。

同时 UPX 还有以下优势:

  • 可靠性: UPX 内部维护了一套校验逻辑,对压缩前和解压后的文件进行校验,以保证程序的完整性。
  • 安全性: 由于UPX 多年来一直是开源项目,因此任何开发者、防病毒软件厂商都能看到 UPX 压缩程序内部逻辑并验证安全性。
  • 解压速度: 在任何现代机器上,解压速度都超过 500 MB/秒。
  • 无内存开销: 解压运行压缩后的程序无需额外的内存开销。
  • 出色的压缩比: UPX 通常比传统的 Zip 压缩算法压缩效果更好。使用 UPX 可以减小分发文件的大小,从而在网络传输和存储方面节省资源。
  • 通用性: 可以打包多种可执行格式,包括 Windows 应用程序和 DLL、macOS 应用程序和 Linux 可执行文件。
  • 可扩展: UPX 良好的代码设计,很容易添加新的可执行文件格式支持和新的压缩算法。

UPX 的争议

UPX 的除了上面提到的压缩功能之外,还有另一个主要作用就是加壳。既字面意思,将可执行程序的外部再包一层外壳程序,并在运行时使用外壳程序将实际的程序来解压运行。

通过 UPX 加壳有以下优势:

  • 安全性:加壳可以提高可执行文件的安全性,因为攻击者很难直接分析或修改外壳程序中的代码。这样可以防止恶意修改和病毒注入。
  • 反调试和反分析:一些外壳程序可以包含反调试和反分析的技术,使得分析者难以逆向工程和分析程序的逻辑。
  • 授权保护:加壳可以用于保护软件的授权,使其只能在经过授权的环境中运行,从而防止盗版。
  • 代码混淆:加壳可以将原始可执行文件的代码混淆到外壳程序中,增加分析的复杂性,从而提高了对抗逆向工程的能力。

在过去的一段时间里,一些黑客或者恶意软件作者使用 UPX 等加壳工具来隐藏恶意软件和病毒,以逃避杀毒软件和分析者的检测。主要有以下几个要点:

  • 病毒和恶意软件的加壳:黑客和恶意软件作者使用UPX等加壳工具来包装他们的恶意代码。这使得分析者和杀毒软件难以识别和分析这些恶意软件,因为它们需要解压缩才能揭示其真实的目的和功能。
  • 病毒分发:加壳也可用于将恶意软件嵌入到合法的可执行文件中,然后通过社会工程或其他手段欺骗用户执行。用户可能认为他们正在运行一个合法的程序,但实际上却是运行了一个加壳的恶意软件。
  • 反病毒工具的适应性:随着黑客使用加壳技术来隐藏其活动,安全软件公司也不得不不断提高其产品的适应性,以识别和处理加壳的可执行文件。这导致了反病毒工具的不断演进,以更好地应对这种挑战。
  • 法律和道德问题:加壳技术的滥用引发了一系列法律和道德问题。黑客使用加壳来隐藏其犯罪活动,这导致了对加壳工具的合法性和使用的争议。

正因为上面提到的一些争议,导致大部分情况下,杀毒软件会对加壳的可执行文件产生警报或误报病毒。这是因为加壳技术会改变可执行文件的结构和行为,使杀毒软件难以确定文件的真实性质。不过随着杀毒软件公司对检测引擎的改进,这些误报也在逐渐减少。

为什么使用 UPX

我使用 UPX 的目的是因为自己在公司内部做了一个运维工具,这个运维工具对部署的便捷程度要求比较高。运维工具使用 Go 语言开发,在项目编译的同时将依赖的资源文件,借助 Go 语言的 embed 功能打包到二进制文件内部,使其运行只依赖主程序一个文件。

编译的 Linux 可执行文件有 22 MB 左右,为了进一步方便运维同时部署此工具,决定使用 UPX 进一步压缩体积。

UPX 下载

访问官方下载地址:https://github.com/upx/upx/releases/latest

根据开发环境选择不同的 upx 版本,我的开发环境是 Windows,所以选择的也是 Windows 版本,需要注意的是,upx 可以跨平台压缩,也就是说可以在Windows 的开发平台上压缩 Linux 平台的可执行程序。

下载完成后可以选择直接解压 upx 主程序使用,或者配置环境变量来使用。

使用

UPX 的基本使用格式为:upx [选项] 待压缩的文件

压缩级别参数

  • 默认级别: 通常是一个压缩比和消耗时间的中间选项,如果不指定压缩级别参数,UPX 会使用此级别。
  • -1 ~ -9: UPX 提供了 -1-9 的压缩级别参数。其中 -1 表示最低级别的压缩,而 -9 表示最高级别的压缩,通常级别越高,压缩比越高(压缩后体积越小),但压缩所需时间也会更长。
  • --brute: 高级别的压缩选项,类似于 -9,但压缩的过程中会使用更多的压缩技巧,可能会导致更长的压缩时间。
  • --ultra-brute: UPX 中最高级别的压缩,使用最激进的压缩算法,尽可能的减小文件大小。需要更长的压缩时间,并且运行时所需的解压时间也会增加。
  • --best: 使用最佳压缩结果的选项,通常效果等于 -9 或者 --ultra-brute
  • --fast: 使用最快压缩速度的选项,通常效果等于 -1 或者 -2
  • --lzma: 使用 LZMA 算法进行压缩,可以获得比较高的压缩比,但不会有 --ultra-brute 那么激进,且通常比 -9 更快。
  • --overlay: 选项将压缩文件附加到可执行文件的末尾,而不是创建新文件。这可以用于一些特殊用途。
  • --force: 用于强制压缩,即使 UPX 认为此文件不适合压缩。
  • --all-filters: 尝试所有可用的压缩算法,以尝试找到最佳的压缩组合(个人感觉和默认差不多)。

其他参数

  • -o: 指定压缩后文件输出的名称,如果不指定则默认覆盖原始文件。
  • --list: 列出压缩过的文件信息,例如压缩比例、文件大小等。
  • --quiet:-q 选项,使用安静模式,减少输出信息,在批处理或自动化的过程中使用。
  • --verbose:-v 选项,启用详细输出,嫌疑有关压缩进程的详细信息。
  • --test: 用于测试压缩程序是否能正常的解压缩或运行,不会进行实际的压缩操作。
  • --keep: 保留原始文件,默认情况下如果不指定输出文件名,则会在压缩结束后删掉原始文件。
  • --threads: 指定用于压缩的线程数,默认情况下与 CPU 核心数量相等。
  • --decompress: 用于解压还原已经被 UPX 压缩的文件。

压缩效果展示

我这里使用一个体积为 23007232 字节(21.9MB),使用 Go 语言编译后的二进制程序进行压缩测试,演示在不同压缩机别下的压缩比、耗时、压缩后的体积等信息,提供压缩算法的选择参考。

压缩级别/算法压缩率体积(字节)体积(MB)所需耗时
-149.43 %1137270410.81 秒
-346.84 %1077664010.22 秒
-538.34 %88201128.415 秒
-736.13 %83127767.9211 秒
-935.23 %81045207.7218 秒
默认级别36.13 %83127767.9210 秒
--brute29.87 %68713446.55107 秒
--ultra-brute29.74 %68433006.52128 秒
--lzma29.97 %68960806.5711 秒
--best35.21 %81002327.7210 秒
--fast49.43 %1137270410.81 秒

Snipaste_2023-09-02_02-04-04.png

参考来源: https://upx.github.io