jbirby/binary-format-reverser
GitHub: jbirby/binary-format-reverser
专注于反编译未记录固定记录二进制文件,自动生成 Python 解析器与格式规范的逆向工具。
Stars: 0 | Forks: 0
# binary-format-reverser
一个用于反编译未记录固定记录二进制文件格式的工具包。从任何示例文件(可参考已解码数据的导出文件)生成可运行的 Python 解析器和 README 风格的格式规范。
基于以下观察构建:大多数设备日志格式(GPS 追踪器、传感器记录器、遥测转储、游戏存档、行车记录仪元数据)具有相同的形状:一系列大小相同的记录,可选地带有一个小型头部。给定这种形状,一组暴力技巧可以在几分钟而不是几天内识别出大部分字段。
## 适用场景
**适合使用的情况**
- 来自设备的专有 `.bin`、`.dat`、`.log`、`.gpl` 等文件,其 PC 软件提供了 CSV、GPX、JSON 或 KML 格式的导出文件作为参考。
- 上述情况但没有参考导出文件——黑盒模式也适用,只是速度较慢。
- 任何看起来像“均匀的小记录流”的格式:健身追踪器、潜水计算机、OBD/CAN 日志记录器、气象站、无人机飞行日志、实验室仪器、老式游戏存档等。
**不适合使用的情况**
- 容器格式(PNG、ZIP、WAV、ELF 可执行文件)——这些格式包含嵌套的报头和块,本工具不建模此类结构。
- 可变长度记录(Protobuf、长度前缀定界)。
- 压缩或加密的有效载荷——熵探测会标记它们,但本工具无法解码。
- 文本密集型格式(JSON、伪造成二进制的 XML)。
## 安装
```
git clone https://github.com//binary-format-reverser.git
cd binary-format-reverser
```
除 Python 3 标准库外无依赖。每个脚本均支持 `--help`。
## 四阶段工作流程
1. **侦察**(Reconnaissance)——记录大小和整体形状是什么?
2. **假设**(Hypothesis)——每个字节可能代表什么?
3. **确认**(Confirmation)——假设是否在所有记录中成立?
4. **编码**(Codification)——编写小型字段映射 JSON 并生成解析器与规范。
阶段对应脚本;阶段 1-3 是迭代过程,阶段 4 是一次性操作。
## 使用参考 CSV 的快速路径
快速路径。你拥有 `mystery.bin` 以及一份它应解码成的 CSV 参考文件。
```
# 1. Figure out the record size
python scripts/structure_probe.py mystery.bin
# 2. Brute-force find the fields
python scripts/csv_correlate.py mystery.bin --record-size 28 --csv reference.csv
# 3. Write a fieldmap.json describing the layout
# (see references/dg388_fieldmap.json for a complete example)
# 4. Generate the parser and spec document
python scripts/gen_parser.py fieldmap.json -o parser.py
python scripts/gen_docs.py fieldmap.json -o FORMAT.md
# 5. Run the parser
python parser.py mystery.bin decoded.csv
```
`csv_correlate` 为每个识别出的字段输出一行,例如:
```
--- Latitude ---
100.0% offset=0x08 (8) i32 LE scale=1/10000000
```
说明:字节 8-11 为小端有符号 32 位整数,除以 10,000,000 后与参考文件中的 `Latitude` 列在 100% 记录中匹配。将这四个事实带入字段映射并继续下一步。
标注为 `transform=ddmm` 的匹配表示二进制以 NMEA 风格的 `DDMM.MMMM` 格式存储坐标,而非十进制度——生成解析器时会自动处理转换。标注为 `unordered (values match but row order differs)` 的匹配表示两个文件中的值相同但顺序不同——当参考工具将航点排在轨迹点之前而二进制文件交错存储时常见。
## 无参考(黑盒)的快速开始
```
python scripts/structure_probe.py mystery.bin
python scripts/field_probe.py mystery.bin --record-size 28 --scan
```
扫描会输出每个偏移量及其通过合理性检查的字段类型解释:`YYYYMMDD`、`HHMMSS`、`unix_ts`、`coord/1e7`、`coord_deg (float)`、`coord_ddmm (float NMEA)`、`altitude_m`、`speed_kmh`、`heading_deg`、`monotonic↑`、`enum(N)`。每个标签均为提示而非确认。
对有希望的偏移量进行有针对性的后续扫描:
```
python scripts/field_probe.py mystery.bin --record-size 28 --offset 8 --type i32 --endian LE
```
你将获得每个记录的最小值、最大值、均值与标准差,以及相同的启发式标签,以便你肉眼判断分布是否符合预期(例如海拔 0–9000 米、速度 0–300 公里/小时、航向 0–360°)。
## 脚本说明
| 脚本 | 用途 |
| --- | --- |
| `scripts/structure_probe.py` | 按列熵对候选记录大小进行排名;提取 ASCII/UTF-16 字符串;报告字节频率峰值(填充模式、已擦除闪存、压缩区域)。 |
| `scripts/multi_file_diff.py` | 比较多份同类样本文件;查找魔数、常量标志与可变字段。 |
| `scripts/csv_correlate.py` | 在(偏移量 × 类型 × 字节序 × 缩放因子 × 变换)空间中对参考 CSV 进行暴力搜索。包含 NMEA `DDMM` 变换以及针对顺序错开参考的排序值回退。 |
| `scripts/field_probe.py` | 黑盒假设测试器。靶向模式(单个偏移量与单个类型)或扫描模式(所有偏移量与所有类型)。 |
| `scripts/gen_parser.py` | 从字段映射 JSON 生成仅依赖标准库的 Python 解析器。处理缩放因子、`YYYYMMDD`、`HHMMSS`、`unix_seconds`、`ddmm` 以及跳过空白规则。 |
| `scripts/gen_docs.py` | 从同一字段映射 JSON 生成 README 风格的格式规范。 |
## 字段映射模式
请参阅 `references/fieldmap_schema.md` 获取完整模式,`references/dg388_fieldmap.json` 为实际示例。简言之:
```
{
"format_name": "My Device GPS Log",
"endianness": "little",
"record_size": 28,
"file_header_size": 0,
"fields": [
{"name": "latitude", "offset": 8, "size": 4, "type": "i32",
"encoding": "degrees", "scale": 10000000, "unit": "°"}
]
}
```
支持的字段类型:`u8`、`i8`、`u16`、`i16`、`u32`、`i32`、`u64`、`i64`、`f32`、`f64`、`bytes`、`utf8`、`pad`。
支持的编码:`YYYYMMDD`、`HHMMSS`、`unix_seconds`、`ddmm`、`degrees`、`meters`、`kmh`、`enum`,以及用于文档的自由形式标签。
## 实际示例
`references/dg388_fieldmap.json` 是 GlobalSat DG-388 GPS 数据记录器的完整字段映射——一种 28 字节固定记录格式,携带日期、时间、坐标(i32 × 1e-7 度)、海拔、速度、航向和记录类型标志。阅读该字段映射并结合 `references/fieldmap_schema.md` 是理解本工具期望输出的最快方式。
## 常见陷阱
- **选取真实记录大小的倍数**。`structure_probe` 按列熵对候选大小进行排名,真实记录大小的倍数得分同样高。优先选择得分高且尺寸最小的候选。
- **信任常量列的 100% 匹配**。任意字节解释都可能匹配 `[34.400, 34.400, 34.400, ...]`。务必结合具有真实方差的列进行验证。
- **预分配空白记录**。许多设备会预先格式化 N 条记录并在记录时逐步填充。可使用 `--skip-zero-records` 或在字段映射中添加 `skip_blank` 规则。
- **参考数据被重排序或过滤**。PC 工具常按时间戳排序或丢弃无效记录。`unordered` 回退可自动处理排序情况;过滤情况需要手动对齐。
- **宽字段内的压缩字段**。一个解码后无意义的大 `uint32` 可能是两个背靠背的 `uint16`。`field_probe --scan` 会分别标记这些窄解释。
## 范围与限制
本工具处理固定记录二进制格式。它不支持可变长度记录、容器/块格式(PNG、WAV、ZIP、ELF)、压缩或加密有效载荷、混合文本格式或位级字段。`structure_probe` 中的熵探测会正确标记看起来被压缩或加密的区域;解码这些区域不在本工具范围内。
它也无法识别校验和或 CRC——它们看起来像随机字节,会被报告为未知。
## 贡献
可拓展本工具适用范围的扩展包括:
- 支持可变长度记录(长度前缀或定界符分帧)。
- 子字节字段提取。
- 容器格式检测(LEN-TYPE-DATA 块遍历)。
- 更多编码变换(六十进制坐标、非十进制比例的固定点数)。
- Python 以外的语言解析器生成器。
## 许可证
根据 MIT 许可证授权。详见 [`LICENSE`](LICENSE)。
标签:GPS追踪, GPX导出, JSON导出, KML导出, OBD/CAN记录, Python, README规格说明, 二进制文件逆向, 云资产清单, 传感器日志, 健身追踪器, 固定记录格式, 字段推断, 字段映射, 实验室仪器, 嵌入式日志, 工具集, 快速逆向, 批量解析, 探针分析, 数据解码, 文件格式规范, 文件格式解析, 无人机飞行日志, 无依赖, 无后门, 旧游戏存档, 格式规范生成, 气象站, 游戏存档, 潜水计算机, 熵检测, 网络连接监控, 记录结构分析, 设备固件, 设备日志, 逆向工具, 逆向工程, 遥测数据, 黑盒分析