RE-Unpacker
用于逆向工程分流的递归式软件包 / 安装程序 / 归档 / 二进制提取器。
**当前发布版本:0.5.0** —— 此版本采用里程表式版本号,其中每个版本组件都是一个单数字,满位后向前进位;因此 0.4.9 之后的版本是 0.5.0。它合并了对所有 52 个模块的源码头部标准化,移除了代码和文档中的发布注释,并进行了仓库清理。提取行为没有变化。有关从 0.1.0 开始的完整历史记录,请参阅 [CHANGELOG.md](CHANGELOG.md)。清单 schema 为 **1.1.0**,并且在 Linux 和 Windows 上是字节兼容的。
给它一个文件或目录,它会递归地拆解它能识别的每一个软件包、安装程序、归档、文件系统镜像、压缩流和打包的二进制文件——直到触底——并生成一个结构化的目录树以及一个描述它发现的所有内容的清单。
专为 Linux 上修改过的 Kali Linux RE 工作流和 Windows 上由 winget 管理的 PowerShell 工作流而设计:零外部 Python 依赖,所有提取工作均通过知名的操作系统二进制程序执行。
| 概览 | 数量 |
|---|---|
| 支持的平台 | 2 (Linux, Windows) |
| 跟踪的外部工具 | 93 |
| 跟踪的外部工具 | 56 |
| 具有版本探测覆盖的工具 | 93 个 Linux / 56 个 Windows (两者均完全覆盖) |
| 受保护工具/软件包 | 2 / 2 |
| 已知不可用的软件包 | 1 (libfsfat-utils) |
| 已知不可用的软件包 | 14 (libyal 二进制文件、signtool 等) |
| FileKind 枚举条目 | 78 |
| 可提取的类型 | 70 (双平台对等) |
| 可分发的主要类型 | 70 |
| 已注册的提取器类 (主要 + 次要) | 69 (66 个主要 + 3 个次要) |
| 需要 Root/管理员权限的提取器 | 11 (仅限 Linux FUSE) |
| 终端分类类型 (加密,无递归) | 3 |
| 验证器 | 9 (gpgv, debsigs, dpkg-sig, debsums, rpm-K, apksigner, osslsigncode, powershell-authenticode, signtool) |
| 分类器 | 4 (entropy, fuzzy_hash, exif, yara) |
| 跟踪的 Python 绑定 | 3 (tlsh, yara, ssdeep) |
| 包管理器后端 | 2 (apt, winget) |
| 内置包装器 | 3 (bash, PowerShell, cmd) |
| 硬性大小上限 (分类器处理) | 256 MiB (验证器豁免) |
| 默认单次充实超时 | 30 秒 |
| YARA 默认规则目录 | 3 (分平台:Linux 路径或 Windows %PROGRAMDATA% / %APPDATA% 路径) |
| 退出码 | 0--6 |
| CLI 模式 | 7 |
| CLI 标志 (argparse actions) | 37 |
| FileEntry 字段 | 25 |
| RunStats 计数器 | 20 |
| 清单 schema 版本 | 1.1.0 (Linux / Windows 清单字节级完全一致) |
**HTML 附属文档:** 格式丰富的 README 和使用指南位于 `docs/` 中:
- `docs/ReUnpacker-README.html` —— 以带样式且可导航的布局镜像此 README。
- `docs/ReUnpacker-Usage-Guide.html` —— 面向步骤、以实用指南为主的手册,涵盖了所有 CLI 模式、工作流和故障排除手册。建议与 README 配套阅读。
两者均为自包含的 (无外部 CSS / JS / 字体),可在任何浏览器中渲染。在 Linux 上使用 `xdg-open docs/ReUnpacker-README.html` 打开,或者直接在浏览器中指向该文件。
## 目录
1. [支持的格式](#supported-formats)
2. [安装说明](#install)
3. [用法](#usage)
- [模式](#modes) -- `--install`, `--uninstall`, `--repair`, `--dry-run-install`
4. [输出布局](#output-layout)
5. [清单 schema](#manifest-schema)
6. [安全模型](#safety-model)
7. [退出码](#exit-codes)
8. [程序化使用](#programmatic-use)
9. [设计概述](#design-overview)
10. [文档](#documentation)
11. [贡献指南](#contributing)
12. [许可证](#license)
13. [更新日志](#changelog)
## 支持的格式
| 类别 | 格式 | 主要工具 | 备选工具 |
|----------|---------|--------------|-------------|
| Linux 软件包 | `.deb` `.udeb` | `dpkg-deb` | `ar` + `tar` |
| | `.rpm` | `rpm2cpio` \| `cpio` | `rpm2archive` + `tar` |
| Windows 安装程序 | `.msi` `.msp` | `msiextract` | `7z` |
| | `.cab` | `cabextract` | `7z` |
| | NSIS 安装程序 | `7z` | `binwalk` |
| | InnoSetup | `innoextract` | `7z` |
| | InstallShield (`setup.exe` + `data*.cab`) | `unshield` | `7z` |
| | WiX Burn / 通用 PE 安装程序 | `7z` | `binwalk` |
| 文件系统镜像 | `.iso` / UDF | `7z` | `bsdtar` |
| | `.dmg` (未加密的 UDIF) | `7z` | -- |
| | `.xar` / `.pkg` (macOS) | `7z` | -- |
| | SquashFS | `unsquashfs` | -- |
| | `.snap` (SquashFS) | `unsquashfs` | -- |
| | AppImage | `unsquashfs` at offset | `--appimage-extract` |
| 传统归档 | `.tar` / `.tar.{gz,bz2,xz,zst,lzma}` | `tar` | -- |
| | `.zip` / `.jar` / `.apk` / `.whl` / `.docx` / … | `unzip` | `7z` |
| | `.7z` | `7z` | -- |
| | `.rar` | `unrar` | `7z` |
| | `.ar` / `.a` | `ar` | -- |
| | `.cpio` | `cpio` | -- |
| 单流压缩 | `.gz` / `.bz2` / `.xz` / `.zst` / `.lzma` / `.lz4` / `.lzo` | 对应的 CLI | -- |
| 二进制文件 | UPX 压缩的 ELF / PE / Mach-O | `upx -d` on copy | -- |
| | PE 资源 (图标、清单、嵌入的二进制文件) | `wrestool` (**次要**) | -- |
| | ELF 节区 (`.text`, `.rodata`, `.data`, `.note.*` …) | `objcopy` + `readelf` (**次要**) | -- |
| 最后手段 | 带有嵌入签名的未知二进制文件 | `binwalk -Me` | -- |
| | | | |
| **扩展与旧版归档** | `.arj` | `arj` | -- |
| | `.lha` / `.lzh` | `lha` (lhasa) | `unar` |
| | `.lz` (lzip 单流) | `lzip -d -c` | -- |
| | `.tar.lz` / `.tlz` | `lzip -d \| tar -xf -` (pipeline) | -- |
| | `.lrz` (lrzip) | `lrzip -d` on copy | -- |
| | `.zpaq` | `zpaq x` | -- |
| | `.arc` / `.ark` (ARC/ARK MS-DOS) | `nomarch` | -- |
| | `.tnef` / `winmail.dat` | `tnef -C` | -- |
| | `.shar` (POSIX shell 归档) | `unshar -d` | -- |
| | `.uu` / `.uue` (uuencoded) | `uudecode` | -- |
| | `.sit` / `.sitx` (StuffIt) | `unar` | -- |
| | `.alz` (Korean ALZ) | `unar` | -- |
| | `.ace` | `unar` | -- |
| | | | |
| **文档、磁盘镜像与文件系统** | PDF (带附件) | `pdfdetach -saveall` | -- |
| | PDF (结构 / 流) | `qpdf --qdf` | -- |
| | `.apk` (Android 软件包,已解码) | `apktool d` | `unzip` (raw fallback at priority 80) |
| | `.vmdk` (VMware) | `vmdkmount` (FUSE, root) | `qemu-img convert` (no root) |
| | `.qcow2` / `.qcow` (QEMU) | `qcowmount` (FUSE, root) | `qemu-img convert` |
| | `.vhd` / `.vhdx` (Microsoft) | `vhdimount` (FUSE, root) | `qemu-img convert` |
| | NTFS (在磁盘镜像中) | `fsntfsmount` (FUSE, root) | -- |
| | ext{2,3,4} (在磁盘镜像中) | `fsextmount` (FUSE, root) | -- |
| | XFS (在磁盘镜像中) | `fsxfsmount` (FUSE, root) | -- |
| | APFS (在磁盘镜像中) | `fsapfsmount` (FUSE, root) | -- |
| | HFS+ (在磁盘镜像中) | `fshfsmount` (FUSE, root) | -- |
| | FAT (在磁盘镜像中) | `fsfatmount` (FUSE, root) | `mtools` |
| | VSS 卷影副本 | `vshadowmount` (FUSE, root) | -- |
| | LVM2 | `vslvmmount` (FUSE, root) | -- |
| | JFFS2 / UBI / MTD (固件) | `binwalk -e` (priority 80) | -- |
| | `.kwaj` / `.szdd` (MS DOS 时代) | `msexpand` | -- |
| | macOS 二进制 plist (BPLIST) | `plistutil -i -o -f xml` (secondary) | (terminal kind, no primary) |
| | | | |
| **终端分类 (无递归)** | LUKS 加密卷 | (none -- classify only, kind=LUKS_ENCRYPTED) | -- |
| | 加密的 RAR/7z/DMG | (none -- classify only, kind=ENCRYPTED_GENERIC) | -- |
“次要”提取器在主要提取之外(而非代替)运行,它们的输出会存放在解包目录内的同级 `_secondary_
/` 目录中。
## 安装说明
### 前置条件
- Python 3.10+
- 带有相关提取工具的 Kali Linux / Debian / Ubuntu。请参阅 `re-unpacker --tools-check` 在首次运行时打印的安装提示——它会准确告诉你需要添加哪些 `apt` 软件包。
在全新的 Kali / Debian / Ubuntu 机器上,完整的工具集如下:
```
sudo apt-get update
sudo apt-get install -y \
arj binutils binwalk bzip2 cabextract cpio dpkg file gzip icoutils \
innoextract lhasa libarchive-tools lrzip lz4 lzip lzop msitools \
nomarch p7zip-full pixz plzip rpm rpm2cpio sharutils squashfs-tools \
tar tnef unar unrar unshield unzip upx-ucl xz-utils zpaq zstd \
apktool fuse libfsapfs-utils libfsext-utils libfshfs-utils \
libfsntfs-utils libfsxfs-utils libluksde-utils libplist-utils \
libqcow-utils libsmraw-utils libvhdi-utils libvmdk-utils \
libvshadow-utils libvslvm-utils mscompress mtd-utils mtools \
poppler-utils qemu-utils qpdf
```
在完整的 Kali 安装中,libyal 的 `lib*-utils` 软件包提供了取证文件系统提取器所需的 FUSE `*mount` 二进制程序。在 Ubuntu 和最小化的 Debian 安装中,仅提供 `*info` 配套包;基于 FUSE 挂载的提取器将被静默过滤为不可用(运行 `re-unpacker --tools-check` 查看差距)。
或者更简单的方法——让 RE-Unpacker 为你安装所有内容(参见下文[模式](/re-unpacker.git
cd re-unpacker
chmod +x re-unpacker
./re-unpacker --version
```
`re-unpacker` 包装器会将 `src/` 添加到 `PYTHONPATH` 中,并调用 `python3 -m re_unpacker`。如果你希望将其加入你的 `PATH`,可以在 `~/.local/bin/` 中放置一个软链接。
### 在 Windows 上安装
同样的源码树,不同的包管理器。有两种调用方式:
```
# PowerShell wrapper(首选):
.\re-unpacker.ps1 --version
# Cmd.exe shim(用于受限执行策略环境):
re-unpacker.cmd --version
```
**Windows 上的前置条件:**
- PATH 中包含 Python 3.10 或更高版本 (`winget install Python.Python.3.12` 或任何等效的安装方式)
- Windows Package Manager (`winget`) -- 作为 App Installer 系统组件的一部分,内置于 Windows 10 1809+ 和 Windows 11 中
- 用于运行 `re-unpacker.ps1` 的 PowerShell 5.1 (内置于 Windows 10+),或者仅需用于运行 `re-unpacker.cmd` 的 cmd.exe
**Windows 上的工具安装。** 同样的 `--install` 模式会调用 winget 而不是 apt:
```
.\re-unpacker.ps1 --install --yes
```
这将安装每一个由 winget 管理的工具:`7zip.7zip`, `OliverBetz.ExifTool`, `VirusTotal.YARA`, `GnuPG.GnuPG`, `QPDF.QPDF`, `Microsoft.Sysinternals.Sigcheck`, `Microsoft.PowerShell` (PowerShell 7+)。内置工具 (`expand.exe`, `msiexec.exe`, `tar.exe`, Windows PowerShell 5.1) 无需安装。
**Windows 上的手动安装工具。** 有些工具没有 winget 软件包(libyal Windows 二进制文件、来自 Windows SDK 的 `signtool`、来自 Android SDK 的 `apksigner`、通过 pip 安装的 `binwalk` 等)。`re-unpacker --tools-check` 会将这些标记为 MISSING,并且编排器的可用提取器过滤器允许在没有它们的情况下继续运行。每个缺失工具的行都会打印来自 `KNOWN_UNAVAILABLE_PACKAGES_WIN` 的手动安装提示。有关完整的各工具安装路径,请参阅使用指南中的“在 Windows 上运行”一章。
**工具清单对等性。** Windows 工具集(56 个工具)比 Linux 的(93 个)要小,因为 Windows 上的 7-Zip 处理了许多在 Linux 上需要独立工具的格式:deb(不需要 `dpkg-deb`)、rpm(不需要 `rpm2cpio`)、cab(不需要 `cabextract`)、KWAJ/SZDD(不需要 `mscompress`)、cpio + ar(不需要独立工具)、VMDK / QCOW2 / VHD / VHDX(不需要 FUSE 挂载)。这满足了输出层的对等性要求:在 Linux 上可提取的每一种类型在 Windows 上同样可提取,且具有完全相同的 FileEntry 结构和清单 schema。
## 用法
### 基础用法
```
# 解包单个文件(输出至 ./.re-unpacker/)
./re-unpacker sample.deb
# 显式输出根目录
./re-unpacker sample.deb -o ./out
# 递归遍历目录下的每个文件
./re-unpacker ./samples -o ./out
# 使用 4 个工作线程
./re-unpacker ./samples -o ./out -j 4
# 增加递归深度(默认为 10)
./re-unpacker firmware.bin -o ./out -d 20
```
### 预检和试运行
```
# 安装了哪些工具?缺少哪些?
./re-unpacker --tools-check
# 在不提取的情况下扫描并分类目录下的每个文件
./re-unpacker --dry-run ./samples -o ./dryrun
cat ./dryrun/manifest.json | jq '.files[].kind' | sort | uniq -c
```
### 功能开关
每个 feature-flag 默认都处于合理的开启(ON)状态。使用 `--no-*` 形式可将其关闭。
| 标志 | 默认值 | 效果 |
|------|---------|--------|
| `--binwalk` / `--no-binwalk` | 开启 | 在未知的二进制文件上回退到 `binwalk -Me` |
| `--resources` / `--no-resources` | 开启 | 转储 PE 资源和 ELF 节区 |
| `--hash` / `--no-hash` | 开启 | 为每个文件计算 SHA-256 + MD5 |
| `--dedup` / `--no-dedup` | 开启 | 跳过重新处理之前已发现过相同 SHA-256 的文件 |
### 过滤
```
# 仅处理特定的文件名模式(适用于初始 seed walk)
./re-unpacker ./samples --include '*.deb' --include '*.rpm'
# 跳过您不关心的文件
./re-unpacker ./samples --exclude '*.txt' --exclude '*.log'
```
### 模式
RE-Unpacker 有六种顶层模式,且均为互斥关系:
| 模式 | 功能描述 | 需要 Root 权限 |
|------|-------------|---------------|
| (默认) | 解包输入的文件或目录 | 否 |
| `--dry-run` | 检测文件类型但不进行提取 | 否 |
| `--tools-check` | 探测外部工具,打印状态表并退出 | 否 |
| `--dry-run-install` | 打印用于安装 / 卸载 / 修复的精确 apt 命令但不执行 | 否 |
| `--install` (别名 `--install-missing`) | 安装当前所有缺失的已知解包工具 | **是** (否则以状态码 5 退出) |
| `--uninstall` | 从系统中移除每一个当前存在的解包工具 | **是** (否则以状态码 5 退出) |
| `--repair` | 重新安装每一个当前存在的解包工具(从损坏 / 半安装状态中恢复) | **是** (否则以状态码 5 退出) |
`--install` / `--uninstall` / `--repair` 模式默认会提示确认。使用 `-y` / `--yes` 可跳过提示:
```
# 安装所有缺失的内容
sudo re-unpacker --install --yes
# 预览 install/uninstall/repair 将执行的操作,不实际执行
re-unpacker --dry-run-install
# 重新安装当前工具集(例如在 dpkg 部分失败后)
sudo re-unpacker --repair --yes
# 在重复运行时跳过 apt-get update 步骤
sudo re-unpacker --install --yes --no-refresh-index
```
**包管理模式下的安全护栏:**
- `apt` 和 `dpkg` 受注册表跟踪(因此 `--tools-check` 会显示它们的状态),但它们**绝不**是安装 / 卸载 / 修复的目标。`constants.py` 中的双层 `PROTECTED_TOOLS`(按工具名)和 `PROTECTED_PACKAGES`(按包名)集合强制执行了这一点。
- `--uninstall` 会跳过被 dpkg 标记为 `Essential: yes` 的软件包(`tar`, `gzip`, `dpkg` 等)。它们在输出中被列为“已排除”,以便让你知道什么没有被触及以及原因。apt 无论如何都会拒绝;我们在自己的层面进行过滤,以便用户看到清晰的摘要,而不是非零的 apt 错误。
- `--repair` 不会跳过必需包——损坏的 `tar` 正是修复功能旨在修复的那种情况,而且 apt 允许重新安装(只是不允许移除)必需包。
### 资源 / 安全限制
```
# 每个 extractor 的超时时间(秒)
--timeout 1800
# 硬字节上限
--max-extracted-size 50000000000 # 50 GiB per single archive
--max-total-size 500000000000 # 500 GiB across the whole run
--max-files 1000000 # files per archive
```
触发其中任何一项都会以 `SafetyLimitExceeded` 中止进一步的提取并返回退出码 2,但到目前为止写入的清单和日志都会被保留。
### 充实
提取完成后,编排器会运行针对单个文件的充实阶段:签名/完整性验证器 (Subsystem B) 以及分类器处理 (Subsystem C)。验证器会不分大小地对每个文件运行;分类器则遵循 256 MiB 的硬性上限(超过上限的文件会记录 `enrichment_skipped="size_exceeds_cap"` 并跳过所有分类器处理)。
```
# 禁用单个 classifier pass(verifiers 始终运行,无法 opt-out)
--no-yara # Skip YARA rule matching pass
--no-fuzzy-hash # Skip ssdeep + TLSH fuzzy hash computation
--no-exif # Skip exiftool metadata extraction
--no-entropy # Skip Shannon entropy computation (also disables
# The encryption heuristic that depends on it)
# YARA 规则加载
--yara-rules PATH # Single file or directory; bypasses default
# Auto-discovery (UNION of /etc/yara/,
# ~/.config/re-unpacker/yara/, YARA Forge default)
# 每个 pass 每个文件的超时时间(verifiers 和 classifiers)
--enrich-timeout SEC # Default: 30 seconds
```
**默认 YARA 规则自动发现(未指定 `--yara-rules` 时):** 取所有三个默认目录的并集,每个规则文件的源目录都会提供一个命名空间前缀 (`etc:` / `user:` / `forge:`),从而能够干净利落地解决不同目录间重复的规则名称。
**验证器分发:** 编排器会询问每个验证器 `applies_to(file_entry) -> bool`。验证器在 `src/re_unpacker/verifiers/` 中注册并使用 `Verifier` ABC;它们是尽力而为的,绝不会在失败时中止运行。结果会落在清单的 `file_entry.verification` 中。
| 验证器 | 工具 | 适用的文件类型 |
|---|---|---|
| `gpgv` | gpgv | 任何带有同级 `.sig` / `.asc` 的文件 |
| `debsigs` | debsigs | DEB |
| `dpkg-sig` | dpkg-sig | DEB |
| `debsums` | debsums | DEB (DISABLED -- debsums operates on installed packages, not .deb files at rest. Tracked for tooling but never invoked.) |
| `rpm-K` | rpm | RPM |
| `apksigner` | apksigner | APK |
| `osslsigncode` | osslsigncode | PE_EXECUTABLE / PE_NSIS / PE_INNOSETUP / PE_INSTALLSHIELD / PE_WIXBURN / MSI / CAB |
**分类器分发:** 所有 4 个分类器都会对每个文件运行(受 256 MiB 上限和任何 `--no-*` 禁用标志的约束)。Pipeline 顺序:`entropy` -> `fuzzy_hash` -> `exif` -> `yara`(最便宜的先运行;YARA 最后运行,因为它主导了大型规则集上针对单文件的充实成本)。
| 分类器 | 工具 | 填充的字段 |
|---|---|---|
| `entropy` | `ent` (with pure-Python fallback) | `entropy`, `encrypted`, `encryption_scheme` |
| `fuzzy_hash` | `python3-tlsh` + `python3-ssdeep` (preferred) or `ssdeep` CLI | `ssdeep`, `tlsh` |
| `exif` | `exiftool` | `exif_metadata` (per-value 4096-char cap) |
| `yara` | `python3-yara` | `yara_matches` (list of rule_name / namespace / tags / meta dicts) |
### 日志
```
# Console 日志级别(文件日志始终记录 DEBUG)
--log-level {DEBUG|INFO|WARNING|ERROR|CRITICAL}
# 便捷的详细程度快捷方式
-v, --verbose # = --log-level INFO (default)
-vv # = --log-level DEBUG
-q, --quiet # = --log-level WARNING (suppress INFO)
# (-v 和 -q 互斥;--log-level 会覆盖两者并发出警告)
# 文件日志路径(extract 模式会将其添加在