abrignoni/batch-leapp

GitHub: abrignoni/batch-leapp

一款用于批量运行 LEAPP 系列数字取证工具的自动化脚本,能够递归处理提取文件并生成带哈希清单的主题化报告索引。

Stars: 3 | Forks: 1

# batch_leapp.py [![最新发布](https://img.shields.io/github/v/release/abrignoni/batch-leapp)](https://github.com/abrignoni/batch-leapp/releases/latest) [![下载量](https://img.shields.io/github/downloads/abrignoni/batch-leapp/total)](https://github.com/abrignoni/batch-leapp/releases) ![平台](https://img.shields.io/badge/platform-macOS%20%7C%20Windows-lightgrey) Batch LEAPP icon 递归查找目录中的每个 `.zip` 文件,并对每个文件运行 **LEAPP** 工具 —— [iLEAPP](https://github.com/abrignoni/iLEAPP)、[ALEAPP](https://github.com/abrignoni/ALEAPP)、[RLEAPP](https://github.com/abrignoni/RLEAPP) 或 [VLEAPP](https://github.com/abrignoni/VLEAPP) —— 生成一个装满随时可审查报告目录的文件夹,以及一个链接所有报告的主 `index.html` 文件。 将它指向一个提取文件目录,然后离开,回来时就能得到一组随时可审查的 LEAPP 报告。

Batch LEAPP GUI running a batch

## 下载 预构建的应用程序 —— 无需 Python: | 平台 | GUI | CLI | |---|---|---| | 🍎 macOS (Apple Silicon) | [Batch LEAPP.app](https://github.com/abrignoni/batch-leapp/releases/latest/download/Batch-LEAPP-macos-arm64.zip) | [batch-leapp](https://github.com/abrignoni/batch-leapp/releases/latest/download/batch-leapp-macos-arm64.tar.gz) | | 🪟 Windows (x64) | [Batch LEAPP.exe + CLI](https://github.com/abrignoni/batch-leapp/releases/latest/download/Batch-LEAPP-windows-x64.zip) | — | 首次启动未签名 —— 请参阅[首次运行说明](#signing--first-run-warnings)。想从源码运行或自行构建?请参阅[用法](#usage)和[构建独立二进制文件](#building-standalone-binaries)。 ## 功能说明 - **递归**查找输入目录下的每个*提取*存档(`.zip`、`.tar`、`.tar.gz`/`.tgz`、gzip 压缩的 tar `.gz`),并根据文件扩展名自动选择匹配的 `-t` 类型。它会刻意**忽略先前的 LEAPP 报告文件夹**(`*LEAPP_Reports_*`)和单独的非 tar `.gz` 文件(浏览器缓存块、单个日志),以免将报告产物误认为提取文件。 - 在每个存档上运行您选择的 LEAPP 工具,并输出到**其专属的输出文件夹**,这样报告就永远不会相互覆盖。 - **对每个输入文件进行散列**(SHA-256),并编写一份**清单**(`manifest.csv` + `manifest.json`)记录已处理的内容 —— 为您的案件卷宗提供证据保管链。 - **预先检查每个存档**,并将损坏或标记错误的存档标记为 `invalid`,而不是让 LEAPP 运行崩溃。 - 在输出目录的根目录下生成一个**主 `index.html`**,每个提取文件对应一行,链接到报告文件夹、LEAPP 的 `index.html` 以及 `_lava_data.lava` 文件 —— 此外还包含输入文件的 SHA-256。 - 添加一个**Source dir**列,显示每个存档所在的顶级目录(方便按案件分组)。 - **遇到失败继续执行** —— 一个损坏的存档不会中断批处理 —— 并在最后打印 ok/failed/invalid/skipped 的汇总摘要。 - 可选地**并行运行多个 LEAPP 进程**,并可以将**额外参数**直接传递给该工具。 iLEAPP、ALEAPP、RLEAPP 和 VLEAPP 都共享相同的命令行 —— `python leapp.py -t zip -i -o ` —— 因此同一个脚本可以驱动它们中的任何一个。该工具会根据您传递给 `--leapp` 的脚本文件名自动检测,并用于标签、每个任务的日志文件名以及索引标题。 ## 环境要求 - Python 3.8+(仅限标准库 —— 无需 `pip install` 任何内容)。 - 一个可用的 LEAPP 工具。您可以将 `--leapp` 指向**以下任一项**: - 一个脚本 —— `ileapp.py`、`aleapp.py`、`rleapp.py`、`vleapp.py`,或者 - 一个来自 LEAPP 发行版的**已编译 CLI 二进制文件** / macOS **`.app`**(`ileapp`、`iLEAPP.exe`、`iLEAPP.app` 等)。 - (请使用命令行版本,而不是交互式 GUI 版本 —— GUI 不接受批处理参数。如果名称看起来像 GUI,batch-leapp 会发出警告。) - 如果 `.py` 工具位于其专属的虚拟环境中,请将 `--python` 指向该环境的解释器(对于二进制文件会被忽略)。 - 可选的 GUI 使用 **Tkinter**(大多数 Python 安装都自带;在某些 Linux 发行版上需要:`sudo apt install python3-tk`)。 ## 用法 ### GUI ``` python batch_leapp_gui.py ``` 选择输入目录、输出目录和 LEAPP 工具,设置并行任务数,然后点击 **Run** —— 窗口中会实时显示流式日志,并配有 **Stop**、**Open report index** 和 **Open output folder** 按钮。它会尝试自动检测已安装的 LEAPP 工具以预填该字段。 **记住您的路径。**每个字段都有一个 **Recent ▾** 按钮,列出您以前使用过的输入目录、输出目录和 LEAPP 工具,并且 GUI 会在启动时将这三个字段预填为您上次使用的值。历史记录按用户保存(macOS `~/Library/Application Support/BatchLEAPP/`,Windows `%APPDATA%\BatchLEAPP\`,Linux `~/.config/BatchLEAPP/`);每个菜单都有一个 **Clear recent** 选项。 想要无需终端的双击应用程序?请参阅下面的**[构建独立二进制文件](#building-standalone-binaries)**。 ### 命令行 ``` python batch_leapp.py INPUT_DIR OUTPUT_DIR --leapp /path/to/leapp.py ``` - `INPUT_DIR` —— 递归搜索 `.zip` 文件的目录。 - `OUTPUT_DIR` —— 写入每个 zip 的报告文件夹和主 `index.html` 的位置(如果不存在则创建)。 ### 示例 iLEAPP: ``` python batch_leapp.py /Volumes/Cases/ios /Volumes/Cases/ios_reports \ --leapp ~/tools/iLEAPP/ileapp.py ``` ALEAPP: ``` python batch_leapp.py /Volumes/Cases/android /Volumes/Cases/android_reports \ --leapp ~/tools/ALEAPP/aleapp.py ``` 已编译二进制文件 / macOS `.app`(工具本身不需要 Python): ``` python batch_leapp.py /Volumes/Cases/ios /Volumes/Cases/ios_reports \ --leapp /Applications/iLEAPP.app ``` 打开结果: ``` open /Volumes/Cases/ios_reports/index.html ``` ## 选项 | 选项 | 默认值 | 描述 | |---|---|---| | `--leapp PATH` | `ileapp.py` | LEAPP **脚本**(`ileapp.py` …)**或已编译二进制文件 / macOS `.app`** 的路径。`--ileapp` 可作为别名接受。 | | `--python PATH` | 当前解释器 | 用于运行 `.py` 工具的 Python(如果工具有自己的 venv,请指向该 venv)。对于二进制文件会被忽略。 | | `-t`, `--type TYPE` | `auto` | `auto` 根据扩展名为每个文件选择 `-t` 值(`zip`/`tar`/`gz`)。任何其他值都会强制每个存档使用该类型。 | | `-j`, `--jobs N` | `1` | 并行执行的 LEAPP 运行数量。 | | `--heartbeat SECONDS` | `30` | 在并行模式下,每 N 秒打印一次“仍在运行”的行,这样长时间运行的任务就不会看起来像卡住了(`0` 禁用)。 | | `--timeout SECONDS` | 无 | 每个 zip 的超时时间;超过该时间的运行将被标记为失败,批处理将继续执行。 | | `--no-hash` | 关闭 | 跳过计算每个输入存档的 SHA-256(默认开启散列)。 | | `--skip-existing` | 关闭 | 跳过输出文件夹已存在且非空的 zip(用于恢复部分运行的批处理)。 | | `--dry-run` | 关闭 | 打印确切的命令而不运行工具。 | | `-- ` | — | 字面量 `--` 之后的所有内容都将原封不动地附加到每次 LEAPP 运行中(例如 `-- -p fast` 用于指定 iLEAPP 配置文件)。 | ## 构建独立二进制文件 您可以使用 [PyInstaller](https://pyinstaller.org/) 将 batch-leapp 打包成不需要安装 Python 的原生二进制文件 —— 一个可双击的 **GUI 应用程序**和一个单文件的 **CLI 二进制文件**。内含构建脚本和图标。 每台机器上的一次性设置: ``` python3 -m pip install pyinstaller ``` ### macOS ``` ./build_macos.sh # both: dist/Batch LEAPP.app + dist/batch-leapp ./build_macos.sh gui # just the .app ./build_macos.sh cli # just the CLI binary ``` 将 `Batch LEAPP.app` 拖到 `/Applications` 中。要分享它,请使用 `ditto` 进行 zip 压缩(保留 bundle 结构): ``` ditto -c -k --sequesterRsrc --keepParent "dist/Batch LEAPP.app" Batch-LEAPP-macos.zip ``` ### Windows ``` build_windows.bat :: both: dist\Batch LEAPP.exe + dist\batch-leapp.exe build_windows.bat gui :: just the GUI .exe build_windows.bat cli :: just the CLI .exe ``` ### 签名与首次运行警告 二进制文件是**未签名**的(公证/签名需要付费的 Apple Developer ID 或 Windows 代码签名证书)。它们在构建它们的机器上运行良好;但在分享给他人时: - **macOS** —— Gatekeeper 会提示“Apple 无法检查其是否包含恶意软件”。右键点击 → **打开** 一次,或者运行 `xattr -dr com.apple.quarantine "Batch LEAPP.app"`。 - **Windows** —— SmartScreen 显示“Windows 已保护你的电脑”。点击 **更多信息 → 仍要运行**。 如果您有签名证书,请将 `codesign`/`signtool` 步骤添加到构建脚本中,我可以将其接入。 ### 自动化构建 (GitHub Actions) [`.github/workflows/build.yml`](.github/workflows/build.yml) 在云端构建所有内容 —— **macOS (Apple Silicon)** 和 **Windows**,包含 GUI 和 CLI —— 因此您不需要 Windows 机器。有两种运行方式: - **按需运行:** GitHub → **Actions** 标签页 → **Build binaries** → **Run workflow**。二进制文件将在运行页面上显示为可下载的**构件**。 - **在发布版本时:** 推送一个版本标签,二进制文件将自动附加到 GitHub 的 **Release** 中: git tag v1.0.0 && git push origin v1.0.0 生成的构件:`Batch-LEAPP-macos-arm64.zip`(包含 `.app`)、`batch-leapp-macos-arm64.tar.gz`(CLI)和 `Batch-LEAPP-windows-x64.zip`(GUI + CLI `.exe`)。它们仍然是未签名的 —— 适用相同的首次运行步骤。Apple Silicon 涵盖了自 2020 年以来的所有 Mac;Intel macOS 构建已被弃用。 ## 推荐的首次运行 在处理大量案件之前,请务必先检查 zip 列表和命令是否合理: ``` python batch_leapp.py INPUT_DIR OUTPUT_DIR --leapp /path/to/leapp.py --dry-run ``` ## 并行运行 ``` python batch_leapp.py INPUT_DIR OUTPUT_DIR --leapp /path/to/leapp.py -j 4 ``` - 输出目录在任何运行开始**之前**就已分配,因此名称绝不会发生冲突。 - 在并行模式下,每次运行的输出都会被捕获到该提取文件文件夹内的 `_run.log`(例如 `aleapp_run.log`)中,这样并发运行就不会使终端显示混乱;屏幕上只会随着任务完成显示每个 zip 的 `OK` / `FAILED` / `TIMEOUT`。 - 使用 `-j 1`(默认值)时,工具的输出将像往常一样实时显示。 ### 为什么并行运行需要隔离 LEAPP 工具会保留一个**共享的**历史记录/设置文件(例如 macOS 上的 `~/Library/Application Support/LEAPP/history.json`),并使用固定的临时文件名通过读取-修改-写入的方式更新它。两个同时运行的工具会在这个文件上发生竞争 —— 一个成功重命名,另一个则因 `history.tmp -> history.json: No such file` 而终止,随后的读取还会看到只写了一半的文件(`JSONDecodeError: Extra data`)。 为了避免这种情况,**并行运行(`-j > 1`)会在 `//.leapp_home/` 处获得一个私有的配置目录**,并通过 `HOME` / `APPDATA` / `XDG_CONFIG_HOME` 进行设置。结果是: - 并发运行绝不会触碰同一个历史记录文件,因此不会发生损坏。 - 您真实的用户级 LEAPP 历史记录将保持原样,并且并行运行**不会**记录在其中(空的私有配置目录意味着这些运行的历史记录功能仅是被关闭了)。 - 顺序运行(`-j 1`)使用您正常的配置目录,并像往常一样记录历史记录。 ## 控制台输出 每次运行都会打印一个横幅(检测到的工具、zip 数量、输出目录、**开始时间**)以及一个实时的 **`[done/total]` 进度计数器**,让您随时了解批处理的进度。 顺序运行(`-j 1`)—— 工具自身的输出会实时流式传输,并由计数器行作为框架: ``` [1/4] running: caseA/a.zip ... live iLEAPP/ALEAPP output ... [1/4] OK caseA/a.zip (37s) [2/4] running: caseB/b.zip ``` 并行运行(`-j > 1`)—— 详细输出将进入每个任务的日志中,因此屏幕上会在每个工作进程接收一个 zip 时显示 `START` 行,定期显示仍在运行的任务的**心跳**(这样长时间运行的任务看起来就不会像卡住了),并在每个任务完成时显示计数器行(计数器按完成顺序从 `1 → total` 增): ``` Running 4 job(s) with 2 worker(s)... START caseA/a.zip START caseB/b.zip ... 2 running [0/4 done]: caseA/a.zip (30s), caseB/b.zip (30s) [1/4] OK caseA/a.zip (37s) START caseC/c.zip ... 2 running [1/4 done]: caseB/b.zip (60s), caseC/c.zip (23s) [2/4] OK caseB/b.zip (66s) ... ``` 心跳间隔为 `--heartbeat SECONDS`(默认为 30;`0` 禁用)。它最多列出四个正在处理中的 zip 及其已经过的时间,如果还有更多任务在运行,则加上 `+N more`。 它以主索引路径和一个汇总块结束 —— 包含数量以及**开始、结束和耗时**(以及任何失败的列表): ``` Done. 12 ok, 1 failed, 0 skipped. Started: 2026-06-27 09:14:02 Finished: 2026-06-27 11:48:37 Elapsed: 2h 34m 35s ``` 相同的开始/结束/耗时时间也会出现在主索引的页眉中。 ## 输入布局 batch-leapp 递归搜索 `INPUT_DIR`,因此您可以根据案件的需要随意排列。最简洁的布局是**每个案件或设备一个文件夹**,只包含该提取文件的存档: ``` Cases/ ← point INPUT_DIR here ├── 2024-001_iPhone15/ │ └── extraction.zip ├── 2024-002_Pixel8/ │ └── fullfs.tar.gz └── 2024-003_iPadAir/ └── backup.zip ``` 顶级文件夹名称(例如 `2024-001_iPhone15`)将成为报告索引和清单中的 **Source dir** 列,因此您可以按照自己希望的方式来命名,以便对运行进行分组和识别。 几条指导原则: - **将输出目录保留在输入树之外。** 将 `OUTPUT_DIR` 指向其他独立的位置(或同级目录),这样报告就永远不会落回您正在扫描的内容中。 - **不要将以前的 LEAPP 报告混入输入中。** batch-leapp 已经忽略了 `*LEAPP_Reports_*` 文件夹、输出目录和单独的非 tar `.gz` 文件,但是输入目录*仅包含提取文件*是最安全的设置,并且使 `--dry-run` 预览易于检查。 - 扁平的存档文件夹也可以工作 —— 它们都将共享 `INPUT_DIR` 的名称作为其 Source dir。 ## 输出布局 ``` OUTPUT_DIR/ ├── index.html ← master index (open this) ├── manifest.csv ← run manifest: hash, status, paths, times ├── manifest.json ← same, machine-readable, + run metadata ├── caseA_phone/ ← one folder per archive │ ├── ileapp_run.log ← captured tool output (parallel mode) │ ├── .leapp_home/ ← private config dir (parallel mode only) │ └── iLEAPP_Reports_/ │ ├── index.html ← the LEAPP report │ └── _lava_data.lava ← the LAVA file ├── caseB_tablet/ │ └── ... └── ... ``` (报告子文件夹由工具命名 —— `iLEAPP_Reports_*`、`ALEAPP_Reports_*` 等 —— 日志文件以检测到的工具命名。) 每个 zip 的文件夹名称来自每个 zip **相对于** `INPUT_DIR` 的路径(例如 `caseA/sub/phone.zip` → `caseA_sub_phone`),因此不同子文件夹中两个同名的 zip 绝不会发生冲突。如果名称仍然冲突,则会附加 `_N` 后缀。 ### 主索引

Master HTML report index — one row per extraction with report, LAVA, status, and SHA-256

`index.html` 是一个包含以下列的表格: | 列 | 含义 | |---|---| | **Source dir** | 存档所在的顶级目录(例如 `caseA`)。对于直接位于 `INPUT_DIR` 中的存档,将退回显示 `INPUT_DIR` 的名称。 | | **Zip** | 存档相对于 `INPUT_DIR` 的路径。 | | **Report folder** | 链接到该提取文件的输出目录。 | | **Report** | 直接链接到 LEAPP 的 `index.html`。在新标签页中打开。 | | **LAVA** | 打开 `_lava_data.lava` 项目。映射 LEAPP GUI 的行为(见下文)。 | | **Status** | `ok` / `failed` / `invalid` / `skipped` / `dry-run`,颜色编码。 | | **SHA-256** | 输入存档散列值的前 16 个字符;鼠标悬停可查看完整摘要。 | ### 取证文档(散列值与清单) 每次运行都会在 `OUTPUT_DIR` 的根目录下写入两个清单: - **`manifest.csv`** —— 每个提取文件对应一行:Source dir、存档路径、**SHA-256**、状态、`-t` 类型、耗时(秒)、输出文件夹,以及报告和 `.lava` 的相对路径。 - **`manifest.json`** —— 相同的行以及运行元数据(工具、输入/输出目录、开始/结束、耗时、计数、散列算法)。 散列默认开启(采用流式读取,因此它可以处理庞大的全文件系统提取,而不会耗尽 RAM)。如果您只想要报告,可以使用 `--no-hash` 将其禁用。 该页面的样式与 **[leapps.org](https://leapps.org)** 相匹配 —— 深色黑底金字主题、Barlow 字体、LEAPPs 徽标,以及标题上每个工具的特定强调色(iLEAPP 红色、ALEAPP 绿色、RLEAPP 蓝色、VLEAPP 紫色)。页眉中包含 ok/failed/skipped 计数的摘要。徽标和图标**嵌入**在 HTML 中(base64),因此页面不需要外部图像文件;网络字体在线时会从 Google Fonts 加载,离线时则回退到系统字体。 链接在新标签页中打开,以便索引页面保持原状供下次点击。 ### LAVA 按钮 这映射了 LEAPP GUI 的行为(`leapp_functions/lava_launcher.py`)。生成索引时,batch-leapp 会使用与 iLEAPP 相同的检测方式(macOS 上使用 `open -Ra LAVA`;Windows 和 Linux 上使用 LAVA 可执行文件 / 已知的安装路径),检查计算机上是否安装了 **LAVA 桌面应用程序**: - **已安装 LAVA** → 按钮 (**LAVA**) 会打开一个页面内的小对话框,其中包含一键 **Open in LAVA** 按钮,可触发 `lava://open?path=…` 处理程序,此外还有项目的**完整文件系统路径**和一个 **Copy** 按钮作为备选方案(粘贴到 LAVA 的 *File ▸ Open* 中,在文件管理器中双击 `.lava`,或者在 macOS/Linux 上使用 `open ""`)。 - **未安装 LAVA** → 按钮变为 **Get LAVA**;对话框显示项目路径和指向下载页面的链接 `https://www.leapps.org/#lava`。

The Open-in-LAVA dialog showing the project path and how to open it

所有链接都是**相对路径**,因此整个 `OUTPUT_DIR` 都是可移植的 —— 压缩它、移动它或将其放在共享网络盘中,链接仍然可以正常解析。报告和 LAVA 文件是通过扫描每个输出文件夹来定位的,因此无论工具将它们写入何处,都能被找到。如果工具没有生成 `.lava` 文件,该单元格只会显示 `—`。 ## 行为说明 - 如果有任何存档失败或无效,**退出代码**为 `1`,否则为 `0` —— 这对于脚本编写非常方便。 - **停止 / 关闭 GUI 会终止正在运行的任务。** LEAPP 子进程的启动方式使得它们可以被终止 —— 点击 **Stop** 或关闭窗口(系统会要求您确认),会终止正在处理中的 LEAPP 进程,而不是让它们作为孤儿进程继续运行。 - **Ctrl-C** 会停止启动新任务,并仍会为已完成的内容生成主索引和清单。 - **失败**、**无效**或**跳过**的提取文件的行仍会出现在索引和清单中;报告/LAVA 链接仅在那些文件实际存在时才会显示。 - **损坏或标记错误的存档会被标记,而不是致命错误。** 在 LEAPP 运行之前,会对每个存档进行完整性检查(zip 中央目录 / tar 标头);坏文件会被标记为 `invalid`,批处理将继续进行。 - **macOS AppleDouble 文件将被忽略。** 在非 HFS 卷(exFAT、NTFS、SMB 共享)上,macOS 会在每个真实文件旁边生成一个 `._name.zip` 伴随文件。这些不是存档,因此它们会被跳过 —— 否则 LEAPP 工具会因为某个文件而卡住并报错 `BadZipFile: File is not a zip file`。 - **先前的 LEAPP 报告和孤立的 `.gz` 文件不会被重新处理。** 扫描绝不会进入 `*LEAPP_Reports_*` 文件夹,会跳过输出目录,并且仅当裸 `.gz` 文件实际上是 gzip 压缩的 tar 时,才将其视为提取文件 —— 这样,现有报告中数以千计的微小浏览器缓存 `.gz` 文件就不会被当作“提取文件”捡拾起来。 - 该脚本是独立的 —— 可以将其复制到任何地方;它不依赖于本代码仓库。
标签:Python, 批处理工具, 数字取证, 数字取证, 无后门, 漏洞挖掘, 自动化脚本, 自动化脚本, 跨平台GUI, 逆向工具