vicnaum/bun-demincer

GitHub: vicnaum/bun-demincer

针对 Bun 编译的独立 JavaScript 二进制文件的反编译与反混淆工具,可提取源码、恢复标识符并重建可读的项目结构。

Stars: 0 | Forks: 0

# bun-demincer 用于 [Bun](https://bun.sh) 编译的独立 JavaScript 二进制文件的反编译器、还原器和反混淆器。 从 Bun 的二进制格式中提取嵌入的 JavaScript 源代码,将其拆分为单个模块,识别 vendor (npm) 包,恢复原始标识符,并将所有内容组织成可读、结构化的代码库 —— 所有操作均基于单个编译后的二进制文件。 ## 功能介绍 ``` Bun binary (opaque executable) → extract embedded JS + assets → split into individual modules (1 file per module) → classify vendor vs app modules (fingerprint DB + flood-fill) → deobfuscate (structural transforms + name recovery + formatting) → reconstruct ES import/export statements → cluster modules by dependency graph (Louvain community detection) → organize into semantic directories → readable, organized source code ``` ## 快速开始 ``` npm install ``` ### 完整流程(冷启动 —— 对二进制文件无先验知识) ``` # 1. 从 Bun 二进制文件中提取 JS node src/extract.mjs /path/to/bun-binary extracted/ # 2. 拆分为独立模块 node src/resplit.mjs extracted/bundle.js resplit/ # 3. 通过指纹库识别 Vendor 包 node src/match-vendors.mjs resplit/ --db data/vendor-fingerprints-1000.json --classify # 4. 反混淆(结构变换 + 自动提取重命名 + 格式化) cp -r resplit/ decoded/ node src/deobfuscate.mjs --dir decoded/ # 5. 重建 ES imports/exports node src/reconstruct-imports.mjs decoded/ # 6. 构建 Dependency graph node src/extract-deps.mjs decoded/manifest.json --out deps-graph.json # 7. 聚合模块(扫描解析结果,选择最佳项) node src/cluster-graph.mjs deps-graph.json --sweep node src/cluster-graph.mjs deps-graph.json --pick 1.5 --png # → clusters-core.json(聚合成员) # → clusters.png(可视化) # 8. 标记聚合(创建包含目录名称的 cluster-labels.json) # 使用 PNG 及每个聚合的热门函数进行命名。 # 请参阅下方的“Organizing modules”了解格式。 # 9. 整理为语义化目录 node src/organize.mjs decoded/ # → decoded-organized/(包含命名目录) + INDEX.md ``` 步骤 1-5 是全自动化的。步骤 6-9 将输出组织到目录中 —— 步骤 8 需要手动标记(或使用 LLM)。 ### 配合 AI 辅助重命名(可选,提高可读性) 在步骤 5 之后,组织之前: ``` # 批量重命名:将每个模块发送给 LLM,一次性获取所有重命名 node src/ai-rename.mjs --dir decoded/ --out renames-ai.json node src/deobfuscate.mjs --dir decoded/ --batch renames-ai.json --only rename # Scoped 重命名:基于 AST 上下文的逐标识符操作(质量更高,API 调用更多) node src/ai-rename-scoped.mjs --dir decoded/ --out renames-scoped.json node src/deobfuscate.mjs --dir decoded/ --batch renames-scoped.json --only rename ``` ### 增量流程(更新到新版本) 如果您已经有一个解码版本并希望更新到更新的二进制文件: ``` # 通过基于内容的匹配迁移所有构建产物(重命名、Vendor 标记、布局) node src/transfer-artifacts.mjs new-version/ --reference old-version/ # 或直接应用旧版本的文件布局 node src/apply-reference-layout.mjs new-decoded/ --reference old-decoded-organized/ ``` ## 前置条件 - **Node.js** (v18+) - **Bun**(可选 —— 仅在*运行*提取的代码时需要,而非反编译) ## 工作原理 ### 二进制格式 Bun 独立可执行文件将所有 JavaScript 嵌入在 `__BUN` Mach-O section(macOS)、附加的 ELF 数据或 `.bun` PE section(Windows)中。该 section 包含一个 `StandaloneModuleGraph`: ``` [8-byte size header (u64 LE)] [data buffer: source code, bytecode, native addons, wasm modules...] [module table: array of CompiledModuleGraphFile structs (52 bytes each)] [Offsets struct (32 bytes)] [\n---- Bun! ----\n] ``` 即使使用 `--bytecode` 编译,完整的 JavaScript 源代码也总是存储在字节码旁边(JSC 需要它)。`--bytecode` 标志是一种启动优化,而非混淆。 有关全面的 Bun 打包器内部机制,请参阅 [docs/BUN.md](docs/BUN.md)。 ### 模块拆分 `resplit.mjs` 检测 Bun 的模块包装器模式: - **`y((exports, module) => { ... })`** — CJS 模块 (`__commonJS`) - **`h(() => { ... })`** — ESM 懒加载初始化器 (`__esm`) 输出每个模块一个扁平文件,附带依赖图和导出映射。 ### Vendor 分类 `match-vendors.mjs --classify` 使用属性名称和字符串字面量的指纹数据库(这些在压缩后依然存在)来识别 npm 包。然后通过反向调用者漫灌算法传播:如果某个模块的所有调用者都已经是 vendor,则该模块也是 vendor。 指纹数据库(`data/vendor-fingerprints-1000.json`,26MB)覆盖了来自 1,668 个 npm 包的 23,746 个文件。可以使用 `--rebuild-db --npm-dir /path/to/node_modules` 进行扩展。 ### 反混淆流程 1. **wakaru** — 结构转换:`!0`→`true`,`void 0`→`undefined`,逗号拆分,`var`→`const/let` 2. **lebab** — ES5→ES6+ 现代化 3. **extract** — 从 `MR()` 导出映射 + `this.name`/`displayName` 模式自动生成重命名映射 4. **rename** — 通过 Babel 进行基于 AST 的标识符重命名(批量 JSON 文件) 5. **prettier** — 统一格式化 ### 名称恢复 Bun 的 `__export()` 模式 —— `MR(target, { exportName: () => minifiedVar })` —— 将原始导出名称保留为字符串键。这是名称恢复的最大来源。其他模式包括:类构造函数中的 `this.name = "X"`,`displayName = "X"` 赋值,以及 20 多个映射的 Bun runtime 辅助函数。 对于其余标识符,AI 辅助重命名(`ai-rename.mjs`,`ai-rename-scoped.mjs`)使用 LLM 从上下文推断语义名称。 ### 组织模块 反混淆后,模块是扁平的编号文件。组织流程将它们转换为有意义的目录结构: 1. **`extract-deps.mjs`** 构建函数级依赖图(哪个模块调用哪个模块) 2. **`cluster-graph.mjs --sweep`** 以 14 种分辨率运行 Louvain 社区检测并显示对比表 —— 模块度分数、集群数量、大小分布 3. **`cluster-graph.mjs --pick `** 选择一个分辨率并输出 `clusters-core.json`(成员资格)+ PNG 可视化 4. **您创建 `cluster-labels.json`** — 根据顶级函数命名每个集群: { "clusters": { "0": { "directory": "ui", "label": "UI rendering" }, "1": { "directory": "api", "label": "API client" } } } 5. **`organize.mjs`** 使用 4 层算法将模块分配到目录: - **第 1 层:** 直接集群成员资格 - **第 2 层:** 函数级亲和力(来自跨模块调用者/被调用者的多数表决) - **第 3 层:** 清单级亲和力(来自导入/导出依赖关系的多数表决) - **第 4 层:** 其余模块放入 `uncategorized/` ### 跨版本支持 `diff-versions.mjs` 和 `transfer-artifacts.mjs` 使用基于内容的指纹识别(字符串 + 属性 + 导出 —— 绝不使用变量名)来跨版本匹配模块,并传递重命名构件、vendor 分类和文件布局。 ## 工具 ### 核心流程 | 脚本 | 描述 | |--------|-------------| | `src/extract.mjs` | 解析 Bun 二进制格式,提取所有嵌入的模块 | | `src/resplit.mjs` | 将包拆分为单模块单文件。`--reassemble` 用于重组 | | `src/match-vendors.mjs` | Vendor 分类:指纹数据库 + 漫灌算法。`--classify`,`--no-move` | | `src/deobfuscate.mjs` | 完整流程:wakaru → lebab → extract → rename → prettier | | `src/reconstruct-imports.mjs` | 转换内部标记 → ES import/export 语句 | ### 名称恢复 | 脚本 | 描述 | |--------|-------------| | `src/rename.mjs` | AST 感知标识符重命名。单个、批量 JSON,`--dry-run` | | `src/extract-exports.mjs` | 自动提取 `MR()` 导出映射 → 重命名 JSON | | `src/extract-names.mjs` | 从 `this.name="X"` + `displayName="X"` 模式提取重命名 | | `src/extract-tools.mjs` | 从 `userFacingName()` 模式提取名称 | | `src/extract-errors.mjs` | 从工厂模式提取错误类名 | | `src/ai-rename.mjs` | AI 语义重命名。可恢复,并发 | | `src/ai-rename-scoped.mjs` | 作用域排序的逐标识符 AI 重命名(humanify 风格) | ### 组织 | 脚本 | 描述 | |--------|-------------| | `src/extract-deps.mjs` | 函数级依赖图。`--query`,`--stats`,`--dot` | | `src/cluster-graph.mjs` | Louvain 聚类 + PNG 可视化。`--sweep`,`--pick`,`--png` | | `src/organize.mjs` | 通过集群成员资格 + 亲和力投票将模块分配到目录 | ### 跨版本 | 脚本 | 描述 | |--------|-------------| | `src/diff-versions.mjs` | 跨版本差异对比:指纹识别 → 匹配 → 规范化 → 差异 | | `src/transfer-artifacts.mjs` | 通过基于内容的模块匹配将构件传输到新版本 | | `src/apply-reference-layout.mjs` | 应用参考版本的文件布局(目录、文件名、vendor 标志) | ## 平台说明 - **macOS**: `__BUN`/`__bun` Mach-O segment。尾部有代码签名(~1.7MB 填充)。 - **Linux**: 数据附加到 ELF 二进制文件。尾部位于最末端。 - **Windows**: `.bun` PE section。无 8 字节大小头。 - 原生 `.node` 插件是平台特定的。JS 和 WASM 是可移植的。 ## 项目结构 ``` src/ 18 pipeline scripts (all standalone, no cross-imports) data/ vendor-fingerprints-1000.json Vendor fingerprint DB (26MB, 1,668 packages) docs/ BUN.md Bun bundler internals & deobfuscation strategies ``` ## 许可证 MIT
标签:AST 抽象语法树, Bun, CMS安全, DNS枚举, JavaScript, MITM代理, WebSocket, 二进制分析, 云安全监控, 云安全运维, 云资产清单, 代码反混淆, 依赖分析, 反编译器, 反迷你化, 可执行文件分析, 模块化重构, 源码恢复, 社区发现算法, 网络安全工具, 自定义脚本, 自定义脚本, 软件开发, 逆向工程, 静态分析