P1rate5ec/byte-bouncer

GitHub: P1rate5ec/byte-bouncer

通过读取文件头 magic number 而非扩展名来识别文件真实类型,专门用于检测扩展名与实际内容不符的伪装文件并输出可解释的分拣判定。

Stars: 0 | Forks: 0

# 🛂 Byte Bouncer ### 在门口检查每个文件的身份证 —— 看重 magic number 而非文件名。 ![python](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white) ![license](https://img.shields.io/badge/license-MIT-blueviolet) ![tests](https://img.shields.io/badge/tests-26%20passing-brightgreen) ![interface](https://img.shields.io/badge/interface-CLI%20%2B%20Web-22c55e) ![transmits](https://img.shields.io/badge/transmits-nothing%20by%20default-success) *每个文件都声称自己是某种东西。Byte Bouncer 会检查它的 ID。*
扩展名只是用户(或攻击者)输入的一个标签。而 magic number 则是 固化在文件头部的字节级证据。Byte Bouncer 会读取文件头, 识别文件*实际上*是什么,并标记任何扩展名与 内容不符的文件 —— 重点关注典型的恶意软件投递手法: **披着文档外衣的可执行文件**(例如实际上是 Windows PE 的 `invoice.pdf`,实际上是 ELF 二进制文件的 `photo.jpg`,或者是直接被重命名为 `report.docx` 的普通 ZIP)。 它是专为 Kali Linux / Parrot OS 的分类处理、IT 支持台的问题排查以及 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` | 递归时跟随符号链接(默认关闭) | | `--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 门控:如果有任何内容被伪装,则使 pipeline 失败 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:上传一个文件,即可获得渲染为网页报告的相同判定结果。 | 方法 | 路径 | 用途 | | --- | --- | --- | | `GET` | `/` | 上传表单 | | `POST` | `/scan` | 分析上传的文件并渲染报告 | ## 安全与授权 Byte Bouncer 是一款**防御性**工具,用于处理您拥有所有权或被 授权检查的系统上的文件。它绝不会执行、打开或渲染其分析的文件 —— 它仅读取字节。 - **默认仅本地回环。** `serve` 绑定到 `127.0.0.1`。将其暴露在可路由的 地址上相当于在您的网络上开放了一个上传端点;仅在您 获得授权运行它的主机/网络上执行此操作,并置于您自己的身份验证之后。如果 `--host` 不是回环地址,Byte Bouncer 会发出强烈的警告。 - **对抗性输入处理。** 不受信任的 ZIP 被视为敌对载荷:仅列出其 中央目录,并且最多只读取一个极小(`<4 KB`)的 `mimetype` 成员 —— 压缩包内容**绝不**被解压,因此 ZIP/解压炸弹在这里根本不可能发生。 - **安全的文件遍历。** 默认情况下在递归过程中会跳过符号链接(因为链接可能 指向您打算扫描的目录树之外,或者导致无限循环)。可以使用 `--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 ``` 测试套件运行速度快且依赖少(不需要网络,也没有 sleep),涵盖了 签名检测、具备容器感知能力的 ZIP 检查、严重性分类、 伪装/双扩展名路径、跳过符号链接、错误韧性,以及 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 应用分开:您可以 在不改动 CLI 或 Web 应用的前提下扩展 `signatures.py`。 ## 🏷️ 为什么叫“Byte Bouncer”? 门卫不在乎你衬衫上印着什么 —— 他会核对你的身份证和你的脸是否一致。这个工具处理文件前 512 个字节的方式也是如此。扩展名是文件**声称**自己是什么。Magic number 才是它**真正**是什么。当这两者不一致时,就有人在说谎,而真正有趣的问题不是他们*有没有*说谎 —— 而是你应该有多在意这个谎言。一个披着图片扩展名外衣的可执行文件,随时会毁掉你一个下午的好心情。而一个被错误标记为 JPEG 的 PDF,可能只是某人的导出按钮抽风了而已。 ## 🔬 这个工具是如何构建的 **目的。** 一个在门口检查每个文件身份证的文件门卫 —— 看重 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 / 发现不匹配 / 可能的伪装)而变化的摘要面板,以及一个 `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` 标记之前会被转义(封堵了一个崩溃 / 标记注入的漏洞);遍历时默认跳过符号链接和非常规文件;具备针对单个文件的错误韧性,这样一个被锁定的文件就不会导致整个扫描中止。 **示例。** ``` 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)。
防御性工具。无漏洞利用,无有效载荷,无凭据收集器。
标签:CLI, DAST, DNS 解析, GET 请求, Python, WiFi技术, 库, 应急响应, 恶意软件分析, 搜索语句(dork), 数字取证, 文件识别, 文档结构分析, 无后门, 自动化脚本, 逆向工具