upx
一、 UPX 壳基础原理
UPX 是一种开源的可执行文件压缩工具,其主要目的是减小文件体积,而非提供强力的反调试或代码混淆保护。
-
区段结构变化:
加壳后,原本的 PE(Portable Executable)或 ELF 文件区段会被重构。典型的 UPX 壳包含以下特征区段:
-
UPX0:在文件中占用大小通常为 0,但在内存中分配了较大的虚拟空间(Virtual Size)。这里用于存放解压后的原始代码和数据。
-
UPX1:包含压缩后的原始程序数据以及 UPX 的解压存根(Stub)代码。程序启动时,首先执行此处的存根代码。
-
UPX2(可选):通常用于存放资源文件(Resource)或导入表(Import Table)等信息。
-
-
执行流程:
带壳程序的执行流如下:
入口点 (EntryPoint) -> 执行 UPX 解压存根 -> 将 UPX1 中的数据解压至 UPX0 -> 恢复导入表 (IAT) -> 跳转至原始入口点 (OEP, Original Entry Point) -> 执行原程序
二、 UPX 壳的识别与特征
在分析未知二进制文件时,可通过以下特征快速判断是否加了 UPX 壳:
-
查壳工具检测:
使用 Detect It Easy (DIE)、Exeinfo PE 或 PEiD 等静态分析工具,通常能直接识别出 "UPX"。
-
字符串与区段名:
-
区段表(Section Table)中存在名为
.UPX0、.UPX1的区段。 -
文件内部存在明显的
UPX!魔数字符串标志。
-
-
内存与体积特征:
文件实际大小(Raw Size)远小于其在内存中展开的大小(Virtual Size)。
三、 标准 UPX 的自动化脱壳
对于未经任何修改的标准 UPX 壳,最简单且首选的方法是使用官方工具进行静态脱壳。
-
脱壳命令:
例如:
upx -d task.exe -o task_unpacked.exe -
适用场景:文件头、区段名及内部特征标志未被破坏的常规题目。
四、 动态/手动脱壳技术(寻找 OEP)
当官方工具失效,或需要进行底层行为分析时,需采用动态调试器(如 x64dbg, OllyDbg)进行手动脱壳。手动脱壳的核心目标是找到 OEP(原始入口点)并转储(Dump)内存文件,最后修复导入表。
1. ESP 定律法
ESP 定律基于栈平衡原理。UPX 在执行解压代码前,会保存当前寄存器状态;在解压完成即将跳转到 OEP 时,会恢复这些状态。
-
操作步骤:
-
程序载入调试器,停在入口点。
-
单步步过(F8)第一条指令(通常是
pushad或push eax等),此时观察 ESP 寄存器的值发生变化。 -
在内存窗口中跳转到该 ESP 地址,设置硬件访问断点(Hardware Breakpoint on Access/Dword)。
-
运行程序(F9)。程序将在即将完成解压、恢复寄存器状态(
popad)之后断下。 -
断下后,向下单步执行(F8),遇到大跨度的跳转指令(通常为
jmp),该跳转的目的地址即为 OEP。
-
2. 单步跟踪法
-
操作步骤:
-
载入程序,使用单步步过(F8)向下执行。
-
核心原则:遇到向上的跳转(如循环)则在下一条指令处设断点并运行(F4),跳过循环;遇到向下的跳转则跟随。
-
最终会来到一个
popad指令,随后跟随一个jmp指令跳转至 OEP。
-
3. 内存转储与 IAT 修复
到达 OEP 后,内存中的代码已解压完毕,但此时的文件无法直接保存运行,需要进行转储和修复:
-
Dump 内存:使用调试器插件(如 OllyDumpEx)将当前内存镜像保存为 PE 文件。
-
修复 IAT:由于加壳程序破坏了原始的导入地址表(Import Address Table),需使用 Scylla 或 ImportREC 等工具:
-
附加当前调试进程。
-
填入刚刚找到的 OEP 相对虚拟地址(RVA)。
-
点击 "IAT Autosearch" 和 "Get Imports"。
-
点击 "Fix Dump",选择刚才 Dump 出的文件,生成修复后的最终程序。
-
五、 CTF 常见“魔改” UPX 及其修复策略
在 CTF 比赛中,出题人经常会对 UPX 壳进行轻微修改,导致 upx -d 命令报错(如提示 NotPackedException)。
-
抹除或篡改特征标志:
-
现象:文件内部的
UPX!魔数被替换成了其他字符(例如CTF!、VMP!等)。 -
修复方案:使用十六进制编辑器(如 010 Editor、Hex Workshop)打开文件,搜索被篡改的特征字符串,将其全面替换回标准的
UPX!。
-
-
修改区段名称:
-
现象:
.UPX0和.UPX1区段名被修改为随机乱码或.text、.data以伪装成无壳文件。 -
修复方案:利用 PE 查看工具(如 CFF Explorer),在区段头部(Section Headers)将区段名手动修改回
UPX0和UPX1。
-
-
修复后处理:
完成上述特征复原后,保存文件,再次尝试使用
upx -d进行自动化脱壳,成功率会大幅提升。如果依然失败,则必须退回使用“手动脱壳(ESP 定律)”进行处理。