DreadpiratePickles/byte-bouncer
GitHub: DreadpiratePickles/byte-bouncer
Byte Bouncer 通过 magic number 文件头签名检测文件真实类型,标记扩展名与内容不匹配的可疑文件,帮助防御性安全团队在恶意文件被执行前完成快速分拣。
Stars: 0 | Forks: 0
# 🛂 Byte Bouncer
### 在门口检查每个文件的 ID —— 依赖 magic number 而非文件名。
    
*每个文件都声称自己是什么。Byte Bouncer 要求出示 ID。*
扩展名只是用户(或攻击者)输入的标签。magic number 则是
内嵌在文件头的字节级证据。Byte Bouncer 读取文件头,
识别文件*实际*是什么,并标记出任何扩展名与内容不一致的文件
—— 特别关注经典的恶意软件传递手段:
**披着文档外衣的可执行文件**(实际是 Windows PE 的 `invoice.pdf`,
实际是 ELF 二进制文件的 `photo.jpg`,或是被重命名为
`report.docx` 的普通 ZIP)。
它专为 Kali Linux / Parrot OS 甄别、服务台接收和 DLP
调查而构建,在这些场景下,重命名的可执行文件或伪造的图像应该
*在*某人双击导致糟糕的下午*之前*就被注意到。
## 为什么开发它
| 威胁 | 文件名显示 | 字节显示 | Byte Bouncer 判定 |
| --- | --- | --- | --- |
| 恶意软件传递 | `cat.jpg` | Windows PE 可执行文件 | **CRITICAL** |
| 恶意软件传递 | `notes.txt` | ELF / PE 可执行文件 | **CRITICAL** |
| 数据窃取 / 逃避检测 | `quarterly.jpg` | PDF 文档 | WARNING |
| 容器欺诈 | `report.docx` | 普通 ZIP (无 Word 结构) | WARNING |
| 损坏 / 截断 | `logo.png` | 文件头太短无法匹配 | WARNING |
| 一切正常 | `memo.docx` | 验证为 Word (OOXML) | OK |
判定结果是**可解释的** —— 每个发现都包含检测到的类型、
预期类型、置信度、SHA-256,以及一行你可以直接粘贴到工单
或交给审计员的理由,无需额外的解释性舞蹈。
## 工作原理
```
┌─────────────┐
file ───────▶ │ read header │ first 512 bytes only
└──────┬──────┘
▼
┌─────────────────┐
│ match signatures│ longest/strongest magic wins
└──────┬──────────┘
▼
is it a ZIP (PK\x03\x04)?
│ yes
▼
┌───────────────────────┐
│ peek inside (zipfile) │ central directory only — no bulk
│ docx? xlsx? jar? apk? │ extraction, one tiny member read
│ epub? odt? │
└──────┬────────────────┘
▼
┌──────────────────────────┐
│ compare vs. extension │ + lure/masquerade + double-ext
└──────┬───────────────────┘
▼
verdict: ok · warning · critical · error (+ SHA-256, size, reason)
```
1. **读取文件头。** 仅读取前 512 字节用于识别,因此
扫描包含数 GB 文件的目录成本很低。
2. **匹配签名。** Byte Bouncer 维护着一个手工整理的包含约 50 个
magic number 的数据库(`signatures.py`)。当多个签名匹配时,
具有最多独特字节的那个胜出。签名长度还会影响**置信度**:8 字节的
PNG magic 为 `high`;2 字节的 `MZ`/`BM` 为 `medium`。
3. **细化 ZIP 容器。** `docx`、`xlsx`、`pptx`、`jar`、`apk`、`epub` 和
OpenDocument 文件全都是 ZIP。Byte Bouncer 通过读取 ZIP 的*中央目录*
(不对不受信任的数据进行解压)来区分真正的 Word
文档和仅仅被重命名的普通归档文件。
4. **判断不匹配及其严重程度。**
- 在受信任且看似无害的扩展名(`.jpg`、`.pdf`、`.txt`、`.docx`…)下的可执行文件 / 脚本内容
→ **CRITICAL**(伪装)。
- 任何其他的扩展名/文件头不匹配 → **WARNING**。
- 带有伪造内部扩展名的正确命名可执行文件
(`invoice.pdf.exe`) → **WARNING**(双扩展名诱饵)。
- 一致,或未知但无害的文件 → **OK**。
5. **哈希作为证据。** 每个文件都会记录流式 SHA-256(使用 `--no-hash` 跳过
以进行更快的大量初筛)。
### 数据模型
单个结果对象是 `FileAnalysis`:
| 字段 | 含义 |
| --- | --- |
| `path`, `extension`, `size_bytes`, `sha256` | 文件身份 |
| `detected_type`, `detected_mime`, `category` | 字节说明的内容 |
| `expected_types` | 扩展名暗示的内容 |
| `mismatch` (bool) | 它们是否一致? |
| `severity` | `ok` · `warning` · `critical` · `error` |
| `confidence` | `high` · `medium` · `low` |
| `reason` | 纯文本解释 |
| `error` | 当文件无法读取时设置 |
## 安装
```
cd byte-bouncer
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt # flask, rich, pytest
pip install -e . # optional: exposes the `byte-bouncer` command
cp .env.example .env # optional: for the web dashboard
```
从源码运行不需要可编辑安装 —— 设置 `PYTHONPATH=src` 即可:
```
PYTHONPATH=src python -m byte_bouncer.cli scan README.md
```
## CLI 用法
每个命令都会打印一个紧凑的品牌标头,并支持 `--plain` / `--no-color`
/ `NO_COLOR` 环境变量。当输出不是 TTY(通过管道或重定向)时,它会
自动降级为纯文本,不带任何样式。`--json` **始终**是
纯 JSON,没有任何修饰,可以安全地通过管道传递给 `jq`。
### `scan` —— 检查文件或目录
```
byte-bouncer scan suspicious.jpg
byte-bouncer scan ~/Downloads --recursive
byte-bouncer scan ./intake --recursive --only-mismatches
byte-bouncer scan ./bulk --recursive --no-hash # faster: skip SHA-256
byte-bouncer scan ~/Downloads --recursive --json > report.json
```
| 标志 | 效果 |
| --- | --- |
| `-r`, `--recursive` | 递归遍历子目录 |
| `--json` | 输出纯 JSON 到 stdout |
| `--no-hash` | 跳过 SHA-256 哈希(更快) |
| `--only-mismatches` | 仅显示未通过检查的文件 |
| `--follow-symlinks` | 递归时跟随 symlink(默认关闭) |
| `--plain` / `--no-color` | 输出纯文本,不带样式 |
示例输出:
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ 🛂 byte-bouncer │
└───────── checks every file's ID at the door — magic numbers over filenames ─┘
┌─────────┬──────────────────────┬──────┬─────────────────────────┬──────────────────────┬────────┐
│ Verdict │ File │ Ext │ Detected │ Expected │ Conf │
├─────────┼──────────────────────┼──────┼─────────────────────────┼──────────────────────┼────────┤
│ OK │ badge.png │ png │ PNG image image │ PNG image │ high │
│ CRITICAL│ cat.jpg │ jpg │ Windows PE executable │ JPEG image │ medium │
│ OK │ memo.docx │ docx │ Word document (OOXML) │ Word document (OOXML)│ high │
│ CRITICAL│ notes.txt │ txt │ Windows PE executable │ — │ medium │
│ WARNING │ quarterly_selfie.jpg │ jpg │ PDF document document │ JPEG image │ high │
│ WARNING │ report.docx │ docx │ ZIP archive archive │ Word document (OOXML)│ high │
└─────────┴──────────────────────┴──────┴─────────────────────────┴──────────────────────┴────────┘
┌───────────── Possible masquerade — inspect the critical files ──────────────┐
│ 3 ok 2 warning 2 critical 0 error │
└───────────────────────────── 7 files inspected ─────────────────────────────┘
```
**退出码**(不变的契约,对脚本友好):
- `0` —— 扫描完成,一切匹配
- `1` —— 操作错误(路径错误)或文件无法读取
- `2` —— 发现至少一个扩展名/文件头不匹配
```
# CI/pre-ingest 门控:如果存在任何伪装内容则使流水线失败
byte-bouncer scan ./upload_staging --recursive --json > out.json || echo "flagged!"
```
### `signatures` —— 列出 Byte Bouncer 能识别的内容
```
byte-bouncer signatures # pretty table grouped by category
byte-bouncer signatures --json # the whole database as JSON
```
### `serve` —— 本地上传仪表板
```
byte-bouncer serve # http://127.0.0.1:5061 (loopback only)
byte-bouncer serve --port 8080
```
一个小型的 Flask UI:上传一个文件,即可获得呈现为 Web 报告的相同判定。
| 方法 | 路径 | 用途 |
| --- | --- | --- |
| `GET` | `/` | 上传表单 |
| `POST` | `/scan` | 分析上传的文件并生成报告 |
## 安全与授权
Byte Bouncer 是一款用于检查你拥有或
授权检查的系统上文件的**防御性**工具。它从不执行、打开或渲染它分析的
文件 —— 它只读取字节。
- **默认使用环回地址。** `serve` 绑定到 `127.0.0.1`。将其暴露在可路由的
地址上相当于在你的网络上开放了一个上传端点;仅在你
授权运行它的主机/网络上这样做,并在你自己的身份验证之后。如果 `--host` 不是环回地址,Byte Bouncer 会
发出强烈警告。
- **恶意输入处理。** 不受信任的 ZIP 被视为敌意:仅列出中央目录,且最多读取一个微小(`<4 KB`)的 `mimetype` 成员 —— 归档内容**绝不**会被解压,因此 ZIP/解压炸弹在这里是不可能发生的。
- **安全的文件遍历。** 递归过程中默认会跳过 symlink(因为链接可能指向你打算扫描的目录之外,或者导致无限循环)。可以使用
`--follow-symlinks` 开启。非常规文件(设备、FIFO、套接字)会被跳过。
- **弹性扫描。** 一个被锁定或消失的文件会报告为 `error` 行,
而不是中止整个运行。
- **上传限制。** 仪表板会限制上传大小
(`BYTE_BOUNCER_MAX_UPLOAD_MB`,默认 16 MB),对文件名进行清理,并且仅在
一个在之后立即删除的临时目录中检查上传内容。
- **输出中无秘密。** Byte Bouncer 仅输出文件元数据和哈希;它
从不记录凭据或环境变量值。
- `serve` 上的 `--debug` 会启用 Werkzeug 的交互式调试器(设计上允许任意代码
执行) —— 仅在受信任的本地机器上使用。默认关闭。
## 测试
```
cd byte-bouncer
PYTHONPATH=src python -m pytest -q
```
测试套件快速且依赖极少(无网络,无休眠),涵盖了
签名检测、感知容器的 ZIP 检查、严重性分类、
伪装/双扩展名路径、跳过 symlink、错误弹性,以及
CLI 的 JSON 纯度和退出码契约。
## 项目结构
```
byte-bouncer/
src/byte_bouncer/
signatures.py # magic-number database + categories
analyzer.py # header reading, ZIP refinement, mismatch & severity logic, hashing
ui.py # shared rich Theme + Console + banner (suite look)
cli.py # argparse CLI: scan / signatures / serve
app.py # Flask upload dashboard
templates/ # HTML UI
tests/ # pytest coverage
```
签名数据库特意与 CLI 和 Web 应用分离:你可以
扩展 `signatures.py` 而无需触动它们。
## 🏷️ 为什么叫 "Byte Bouncer"?
保安不在乎你衣服上印着什么 —— 他会根据你的脸检查 ID。这个工具对文件的前 512 字节做同样的事情。扩展名是文件**声称**自己是什么。magic number 才是它**实际**是什么。当这两者不一致时,就有人的在撒谎,而真正有趣的问题不是他们撒谎了*这件事* —— 而是你应该有多在意。一个披着照片扩展名的可执行文件注定会带来一个糟糕的下午。而一个被错误标记为 JPEG 的 PDF 可能只是某人的导出按钮出了点问题。
## 🔬 这个工具是如何构建的
**目的。** 一个在门口检查每个文件 ID 的文件保安 —— 依赖 magic number
而非文件名 —— 并且不仅告诉你文件*在*其身份上撒了谎,还告诉你
*这个谎言有多值得担忧*。披着照片扩展名的可执行文件是
CRITICAL;被错误标记为 JPEG 的 PDF 是 WARNING。
**工作原理。** 它仅读取前 512 字节以匹配精心策划的
magic number 数据库,通过读取 ZIP 中央目录(Word/Excel/PowerPoint OOXML、JAR、APK、EPUB、OpenDocument)来细化基于 ZIP 的容器,而无需
提取任何内容,然后将检测到的类型与扩展名进行比较,并
按严重程度对不匹配进行分类。流式 SHA-256 被记录为证据。
**出色的 CLI。** 带有颜色编码的结果表(OK=绿色,WARNING=黄色,
CRITICAL=红色,ERROR=灰色),显示的路径相对于扫描的根目录,
多文件扫描期间的瞬时进度条,一个标题随
最严重程度(Clean / Mismatches found / Possible masquerade)而变化的摘要面板,以及一个
`signatures` 子命令,用于呈现按类别分组的整个检测数据库。
**关键改进。** *功能性:* 感知容器的 ZIP 细化标记了重命名为 `.docx` 的普通归档或具有 `.xlsx` 名称的 Word 文件;具有标记为 CRITICAL 的可执行文件/脚本伪装的严重性模型 (ok/warning/critical);精心策划的 `LURE_EXTENSIONS` 检查弥补了一个实际的缺陷 —— 重命名为无签名扩展名的可执行文件 (`malware.exe` → `notes.txt`) 过去常常会静默通过;双扩展名诱饵检测 (`invoice.pdf.exe`);签名数据库从 21 个条目扩展到 54 个。*安全性:* 不受信任的 ZIP 被视为具有敌意(仅限中央目录,最多读取一个经过大小检查的 `<4 KB` `mimetype` 成员 —— 解压炸弹是不可能发生的);攻击者控制的文件名在进入 `rich` 标记之前被转义(修复了崩溃 / 标记注入向量);在遍历期间默认跳过 symlink 和非常规文件;单文件错误弹性,这样一个被锁定的文件就不会中止扫描。
**示例。**
```
PYTHONPATH=src python -m byte_bouncer.cli scan ./intake --recursive
```
## ⚖️ 授权使用与安全章程
**这些是用于你拥有或被明确授权评估的系统、文件、网络和人员的防御性工具。**
在运行任何内容之前阅读此内容:
- **授权不是可选项。** 网络钓鱼模拟、网络扫描、IP
信誉查询和 Web 应用探测都会触及他人的系统或
数据。请先获得书面授权。几个工具*拒绝行动*,直到你
声明这一点(`--yes`、`--authorized-training`、`--i-have-authorization`、
`--i-am-authorized` 等)。
- **默认安全。** 每个 Web UI 都绑定到 `127.0.0.1`(环回地址)。出站流量、
实时发送和主动扫描都在明确的标志控制之下 —— 演练、
被动模式,或拒绝并警告始终是默认设置。
- **没有意外的自伤行为。** Flask `--debug`(Werkzeug 交互式调试器在任何回溯上都是代码执行)会被强烈警告,
并在环回地址之外完全拒绝。不受信任的输入受到大小限制、验证,
并无害化渲染,因此恶意的文件或日志行不会崩溃 —— 或接管 —— 你的终端。
- **输出中无秘密。** API key 保留在请求标头中,密码来自
环境变量,并且不会记录或打印任何敏感信息。
这些不是攻击性工具。它们不包含任何漏洞利用程序、凭据收集器
和有效载荷。如果某个工具*可能*被滥用,那么它在构造上就是
为了抵御那种滥用而构建的。
## 🧪 开发
```
python -m venv .venv && source .venv/bin/activate
pip install -e .
pytest -q # 26 tests, no network, no sleeps
byte-bouncer --help
```
## 📄 许可证
基于 **MIT License** 发布。详见 [LICENSE](LICENSE)。
防御性工具。无漏洞利用,无有效载荷,无凭据收集器。
标签:AMSI绕过, DAST, DNS 解析, Python, Web界面, 威胁检测, 恶意软件分析, 搜索语句(dork), 文件类型识别, 文档结构分析, 无后门, 逆向工具