araray/binfiddle

GitHub: araray/binfiddle

一款模块化的 Rust 二进制文件操作工具包,提供检查、修补、差异分析和统计分析等功能。

Stars: 2 | Forks: 0

# Binfiddle **面向开发者和黑客的二进制实用工具** [![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg)](LICENSE) [![Rust](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://www.rust-lang.org/) *版本 0.18.0 | 跨平台 (Windows/Linux/macOS) | 支持 x86_64/Arm64* Binfiddle 是一个**专注于开发者的二进制操作工具包**,旨在提供灵活性、模块化和清晰度。它支持跨多种格式检查、修补、差异分析、统计分析以及对二进制数据的自定义探索。 无论您是在对固件进行逆向工程、调试二进制协议、分析恶意软件样本,还是构建用于二进制文件的自定义工作流,Binfiddle 都能提供 essential 工具而不会显得臃肿。 ## 🌐 概述 - [功能](#features) - [安装](#installation) - [快速开始](#quick-start) - [命令参考](#command-reference) - [示例](#examples) - [架构](#architecture) - [贡献](#contributing) - [许可证](#license) ## 功能 ### 核心能力 | 功能 | 描述 | |---------|-------------| | **Read** | 提取并以多种格式显示字节范围 | | **Write** | 覆盖指定位置的字节 | | **Edit** | 插入、删除或替换字节序列 | | **Search** | 使用精确匹配、regex 或通配符查找模式 | | **Analyze** | 统计分析:entropy、histograms、Index of Coincidence | | **Diff** | 比较二进制文件,支持多种输出格式 | | **Patch** | 应用二进制补丁(与 diff --format patch 输出兼容) | | **Convert** | 文本编码转换和行尾规范化 | | **Chain** | 将多个 binfiddle 命令连接在一起,无需 shell 转义 | | **Process Memory** | 通过 `/proc//mem` 读取任何相同用户进程的内存并列出映射区域 (Linux,实验性) | | **Struct** | 使用 YAML 模板解析二进制数据以进行结构定义 | ### 主要区别 | 功能 | Binfiddle | 传统工具 | |---------|-----------|-------------------| | **Pipeline 集成** | 一流的 stdin/stdout 支持 | 通常仅限交互式 | | **统一操作** | 单一工具内集成 Read/Write/Edit/Search/Analyze/Diff | 每个操作需要独立的工具 | | **可配置分块** | 1-64 位粒度 | 固定 8 位(字节)块 | | **多格式 I/O** | hex/dec/oct/bin/ascii/raw | 通常仅支持 hex | | **脚本友好** | 确定性、非交互式 | 通常需要用户交互 | | **内置分析** | Entropy、histograms、IC 分析 | 需要外部工具 | ### 设计原则 - **Unix 哲学**:可组合、支持 pipeline、以文本流作为接口 - **默认安全**:无静默数据丢失,需要显式修改标志 - **确定性**:相同的输入产生字节完全相同的输出 - **内存安全**:使用 Rust 构建,无 buffer 溢出或数据竞争 ## 安装 ### 从源码构建(推荐) ``` # 安装 Rust toolchain(如果尚未安装) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # 克隆并构建 git clone https://github.com/araray/binfiddle.git cd binfiddle cargo build --release # Binary 位于 target/release/binfiddle sudo cp target/release/binfiddle /usr/local/bin/ ``` ### 从 Releases 下载 从 [Releases](https://github.com/araray/binfiddle/releases) 页面下载预构建的二进制文件。 可用目标: - `x86_64-unknown-linux-gnu` (Linux x64) - `x86_64-unknown-linux-musl` (Linux x64,静态) - `x86_64-pc-windows-gnu` (Windows x64) - `x86_64-apple-darwin` (macOS Intel) - `aarch64-apple-darwin` (macOS Apple Silicon) ### 为其他平台构建 ``` # 使用 build script ./build_releases.sh --native # Current platform only ./build_releases.sh --help # See all options # 或者手动使用 cargo rustup target add x86_64-pc-windows-gnu cargo build --release --target x86_64-pc-windows-gnu ``` ## 快速开始 ``` # 将前 16 个字节读取为 hex binfiddle -i file.bin read 0..16 # 将整个文件读取为 ASCII binfiddle -i file.bin read .. --format ascii # 在 offset 0x100 处写入字节 binfiddle -i file.bin write 0x100 DEADBEEF -o modified.bin # 搜索 pattern binfiddle -i file.bin search "7F 45 4C 46" --all # 在位置处插入字节 binfiddle -i file.bin edit insert 0x200 CAFEBABE -o modified.bin # 分析 entropy(查找加密/压缩区段) binfiddle -i firmware.bin analyze entropy --block-size 4096 # 比较两个 binary 文件 binfiddle diff original.bin modified.bin --diff-format unified # Pipeline 用法 cat data.bin | binfiddle read 0..32 | grep "7f 45" # 带地址和 ASCII 侧边栏的 xxd 风格输出 binfiddle -i firmware.bin read 0..256 --show-ascii # Raw binary 输出(适合 pipe,无格式化) binfiddle -i archive.bin read 0..4 --format raw | file - ``` ## 命令参考 ### 全局选项 | 选项 | 缩写 | 描述 | 默认值 | |--------|-------|-------------|---------| | `--input ` | `-i` | 输入文件(使用 `-` 表示 stdin) | stdin | | `--output ` | `-o` | 输出文件(使用 `-` 表示 stdout) | — | | `--in-file` | — | 原地修改输入文件 | false | | `--format ` | `-f` | 输出格式:hex, dec, oct, bin, ascii, raw | hex | | `--input-format ` | — | 输入值格式 | hex | | `--chunk-size ` | `-c` | 每个显示块的位数 (1-64) | 8 | | `--width ` | — | 每行的块数(0=不换行) | 16 | | `--show-offset` | — | 在每行显示 hex 地址前缀 | false | | `--show-ascii` | — | 显示 ASCII 侧边栏(隐含偏移量显示) | false | | `--silent` | — | 抑制更改差异输出 | false | ### 命令 #### `read ` — 从二进制数据读取字节 ``` binfiddle -i file.bin read 0..64 # Bytes 0-63 binfiddle -i file.bin read 0x100..0x200 # Hex offsets binfiddle -i file.bin read 10.. # Byte 10 to end binfiddle -i file.bin read ..100 # First 100 bytes binfiddle -i file.bin read .. # Entire file binfiddle -i file.bin read 42 # Single byte at index 42 binfiddle -i file.bin read 0..256 --show-offset # xxd-style with address prefixes binfiddle -i file.bin read 0..256 --show-ascii # xxd-style with ASCII sidebar binfiddle -i file.bin read 0..64 --format raw | file - # Raw binary output for piping ``` #### `write ` — 向二进制数据写入字节 ``` binfiddle -i file.bin write 0x100 DEADBEEF -o out.bin binfiddle -i file.bin write 0 "127 69 76 70" --input-format dec -o out.bin binfiddle -i file.bin --in-file write 16 FF # In-place modification ``` #### `edit [DATA]` — 结构性修改 **Insert** — 在指定位置添加字节(数据右移): ``` binfiddle -i file.bin edit insert 0x100 DEADBEEF -o out.bin ``` **Remove** — 删除字节范围(数据左移): ``` binfiddle -i file.bin edit remove 0x500..0x600 -o out.bin ``` **Replace** — 删除范围并插入新数据: ``` binfiddle -i file.bin edit replace 0..4 7F454C46 -o out.bin ``` #### `search ` — 在二进制数据中查找模式 ``` # 精确的 hex pattern binfiddle -i file.bin search "DE AD BE EF" --all # ASCII 字符串 binfiddle -i file.bin search "PASSWORD" --input-format ascii --all # Regex pattern binfiddle -i file.bin search "[A-Z]{4}" --input-format regex --all # Wildcard mask(? = 任意字节) binfiddle -i file.bin search "DE ?? BE EF" --input-format mask --all # 仅统计匹配项 binfiddle -i file.bin search "00 00" --all --count # 显示匹配项周围的上下文 binfiddle -i file.bin search "CAFE" --all --context 8 # 防止重叠匹配 binfiddle -i file.bin search "AA AA" --all --no-overlap ``` #### `analyze ` — 二进制数据的统计分析 分析二进制数据的 entropy、字节分布和密码分析指标。 ``` # Entropy 分析(查找加密/压缩区段) binfiddle -i firmware.bin analyze entropy --block-size 4096 # 字节频率直方图 binfiddle -i file.bin analyze histogram # Index of Coincidence(cryptanalysis) binfiddle -i file.bin analyze ic --block-size 0 # 输出为 CSV 以便绘图 binfiddle -i file.bin analyze entropy --output-format csv > entropy.csv # 输出为 JSON binfiddle -i file.bin analyze histogram --output-format json ``` **分析类型:** | 类型 | 描述 | 用例 | |------|-------------|----------| | `entropy` | Shannon entropy (0-8 bits/byte) | 查找加密/压缩区域 | | `histogram` | 字节频率分布 | 识别文件类型、编码 | | `ic` | Index of Coincidence | 密码分析,检测加密 | **Entropy 解释:** | 范围 | 含义 | |-------|---------| | 0.0 - 1.0 | 高度重复(null bytes,单值) | | 1.0 - 4.0 | 文本、代码、结构化数据 | | 4.0 - 6.0 | 混合内容 | | 6.0 - 7.5 | 压缩数据 | | 7.5 - 8.0 | 加密或随机数据 | #### `diff ` — 比较两个二进制文件 逐字节比较二进制文件,并以多种格式显示差异。 ``` # 简单格式(每个差异一行) binfiddle diff original.bin modified.bin # Unified 格式(类似文本 diff,带上下文) binfiddle diff original.bin modified.bin --diff-format unified --context 3 # 并排比较 binfiddle diff original.bin modified.bin --diff-format side-by-side # 生成 patch 文件(用于 binfiddle patch) binfiddle diff original.bin modified.bin --diff-format patch > changes.patch # 忽略特定范围(例如 timestamps) binfiddle diff v1.bin v2.bin --ignore-offsets "0x0..0x10,0x100..0x110" # 带 color 输出 binfiddle diff file1.bin file2.bin --color always # 显示摘要统计信息 binfiddle diff file1.bin file2.bin --summary ``` **Diff 输出格式:** | 格式 | 描述 | |--------|-------------| | `simple` | 每个差异一行:`Offset: 0xXX != 0xYY` | | `unified` | 带有上下文行和 hex 转储的 unified diff | | `side-by-side` | 双列并行比较 | | `patch` | 用于 `binfiddle patch` 的机器可读格式 | #### `convert` — 文本编码和行尾转换 转换文本编码并规范化嵌入文本数据的行尾。 ``` # 将 UTF-8 转换为 UTF-16LE binfiddle -i document.txt convert --to utf-16le -o document_utf16.txt # 将 UTF-16LE 转换为 UTF-8 binfiddle -i windows_file.txt convert --from utf-16le --to utf-8 -o unix_file.txt # 将 Windows 换行符 (CRLF) 转换为 Unix (LF) binfiddle -i script.bat convert --newlines unix -o script.sh # 添加 UTF-8 BOM binfiddle -i file.txt convert --bom add -o file_with_bom.txt # 从文件中移除 BOM binfiddle -i file_with_bom.txt convert --bom remove -o file_no_bom.txt # 完全转换:UTF-16LE → UTF-8、Unix 换行符、无 BOM binfiddle -i windows_doc.txt convert \ --from utf-16le --to utf-8 --newlines unix --bom remove \ -o unix_doc.txt ``` **Convert 选项:** | 选项 | 值 | 默认值 | 描述 | |--------|--------|---------|-------------| | `--from` | utf-8, utf-16le, utf-16be, latin-1, windows-1252 | utf-8 | 源编码 | | `--to` | utf-8, utf-16le, utf-16be, latin-1, windows-1252 | utf-8 | 目标编码 | | `--newlines` | unix, windows, mac, keep | keep | 换行符转换 | | `--bom` | add, remove, keep | keep | BOM 处理 | | `--on-error` | strict, replace, ignore | replace | 错误处理模式 | #### `patch ` — 应用二进制补丁 应用由 `binfiddle diff --format patch` 生成或手动创建的补丁。 ``` # 应用 patch 文件以创建新输出 binfiddle --output patched.bin patch original.bin changes.patch # 预览更改而不修改(dry run) binfiddle patch original.bin changes.patch --dry-run # 通过 backup 原地修改文件 binfiddle --in-file -i target.bin patch target.bin changes.patch --backup .bak # Revert 一个 patch(撤销更改) binfiddle --output reverted.bin patch patched.bin changes.patch --revert ``` **完整的 Diff-Patch 工作流:** ``` # 1. 从两个文件创建一个 patch binfiddle diff original.bin modified.bin --diff-format patch > changes.patch # 2. 将 patch 应用于 original 以重建 modified binfiddle --output reconstructed.bin patch original.bin changes.patch # 3. 验证结果是否匹配 diff modified.bin reconstructed.bin && echo "Perfect match!" ``` **Patch 选项:** | 选项 | 描述 | |--------|-------------| | `--backup ` | 修改前创建备份(例如,`.bak`) | | `--dry-run` | 显示将要执行的操作而不进行实际更改 | | `--revert` | 反向应用补丁(撤销更改) | **Patch 文件格式:** ``` # binfiddle patch 文件 # source: original.bin # target: modified.bin # format: OFFSET:OLD_HEX:NEW_HEX # differences: N # 0x00000000:de:ff 0x00000002:be:ca ``` #### `chain --step ` — 顺序执行多个命令 按顺序运行多个 binfiddle 命令,将每个步骤的字节输出作为下一步的输入。这避免了 shell pipe 转义,并使多步骤转换变得明确。 中间步骤必须产生字节输出(例如 `write`、`edit`、`replace`、`convert`)。最后一步可以产生文本输出。 ``` # 替换 header 然后 patch 一个字节 binfiddle -i firmware.bin -o patched.bin chain \ --step "edit replace 0..4 44415431" \ --step "write 8 00" # 从 stdin 链式读取并读取结果 printf '\x00\x11\x22\x33' | binfiddle chain \ --step "edit replace 0..2 4142" \ --step "read 0..4" # 静默运行,以便中间的诊断信息不会污染 stderr binfiddle --silent -i data.bin -o out.bin chain \ --step "edit replace 0..8 1234567890abcdef" \ --step "write 0 ff" ``` **Chain 选项:** | 选项 | 描述 | |--------|-------------| | `--step ` | 要执行的一个步骤(可重复,必填)。遵循 shell 引号规则。 | #### Process memory — Linux 实验性 通过 `/proc//mem` 从当前进程或任何相同用户的进程读取内存,列出映射的内存区域,并在明确选择加入的情况下写回当前进程。 ``` # 列出当前进程的内存区域 binfiddle --process-self --list-regions # 列出另一个进程的区域 binfiddle --pid 1234 --list-regions # 从已知地址的当前进程中读取 16 个字节 binfiddle --process-self --address 0x7ffd12345678 --size 16 read 0..16 # 从另一个进程读取 binfiddle --pid 1234 --address 0x7f8a1b2c3000 --size 16 read 0..16 # 在进程内存中搜索 pattern binfiddle --process-self --address 0x400000 --size 0x1000 search 474343 # 覆盖当前进程中的 4 个字节(需要 --allow-write) binfiddle --process-self --address 0x7ffd12345678 --size 4 \ --allow-write write 0 DEADBEEF # 覆盖另一个进程可写内存中的字节 binfiddle --pid 1234 --address 0x7f8a1b2c3000 --size 4 \ --allow-write write 0 CAFEBABE # 强制写入当前进程中的只读区域(危险) binfiddle --process-self --address 0x7ffd12345678 --size 4 \ --allow-write --force-writable write 0 DEADBEEF # 强制写入另一个进程中的只读区域(Linux x86_64,危险) binfiddle --pid 1234 --address 0x7f8a1b2c3000 --size 4 \ --allow-write --force-writable write 0 CAFEBABE ``` **Process Memory 选项:** | 选项 | 描述 | |--------|-------------| | `--process-self` | 定位当前进程。 | | `--pid ` | 定位另一个进程。 | | `--list-regions` | 打印来自 `/proc//maps` 的内存区域。 | | `--address` | 要读取或写入的基地址(hex 或十进制)。 | | `--size` | 要读取或写入的字节数(hex 或十进制)。 | | `--allow-write` | 任何进程内存写入都需要明确选择加入。 | | `--force-writable` | 在写入之前临时将只读页面设为可写。 | #### `struct