Enuvid/bun-unpacker
GitHub: Enuvid/bun-unpacker
一款用于从 Bun 单文件可执行程序中提取内嵌 JS bundle、原生插件和资产文件的解包工具。
Stars: 1 | Forks: 0
# bun-unpacker
[](https://github.com/Enuvid/bun-unpacker/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/bun-unpacker)
读取通过 `bun build --compile` 构建的可执行文件,并将其内部打包的
文件写出来:JavaScript bundle、原生插件、sourcemap 以及任何其他
内嵌的资产。
该包仅包含源代码。它不包含任何第三方代码,也没有
提取出的产物,并且它不会下载任何内容:你只需将它指向
你机器上已有的二进制文件,它就会逐字节地将内容复制出来。没有任何
内容会被执行、反编译或反混淆;输出的文件与打包器
存储的完全一致。
## 快速开始
```
$ npx bun-unpacker ./my-app --list
my-app 58.4 MB (/home/you/build/my-app)
ELF · x86-64 · payload 41.2 MB at 0x2c41008 · 3 modules · 52-byte entries
path size kind bytecode
----------- -------- ----------------------------- --------
index.js 1.84 MB JS (bun cjs, bytecode-backed) 12.6 MB
sharp.node 1.40 MB ELF x86-64 -
schema.json 9.11 KB JSON -
total extracted: 3.25 MB
```
去掉 `--list` 即可将文件写入 `./out`:
```
npx bun-unpacker ./my-app # extract to ./out
bunx bun-unpacker ./my-app -o dump # explicit target
```
## 选项
| 标志 | 含义 |
| :------------------ | :--------------------------------------------------------------------------------------------- |
| `-o`, `--out ` | 输出目录,默认为 `./out`。通用二进制文件会为每个架构生成一个子目录。 |
| `-l`, `--list` | 打印模块表且不写入任何内容。 |
| `--bytecode` | 同时转储 JSC bytecode 缓存。它通常是源代码大小的几倍。 |
| `--json` | 在 stdout 上以 JSON 格式打印清单(manifest)。 |
| `-v`, `--version` | 此工具的版本。 |
| `-h`, `--help` | 用法。 |
## 输出
提取的文件会保留打包器记录的路径,因此 `/$bunfs/root/src/index.js`
会落地在 `out/src/index.js`。路径遍历片段会被丢弃,而两个如果
落地到同一路径的模块会添加数字后缀,而不是相互
覆盖。
```
out/
src/index.js one file per embedded module
manifest.json every module, with offsets and hashes
_bytecode/ only with --bytecode
src/index.js.jsc
```
通用二进制文件会为每个架构生成一个目录(`out/arm64/`,
`out/x86-64/`)。`manifest.json` 描述了每个模块:
```
{
"name": "/$bunfs/root/src/index.js",
"path": "src/index.js",
"kind": "JS (bun cjs, bytecode-backed)",
"size": 1929216,
"offsetInFile": 46859528,
"sha256": "8f1dded3...",
"bytecode": { "offset": 120, "length": 13221888, "offsetInFile": 6315136 }
}
```
清单(manifest)路径始终使用正斜杠,因此在 Windows 上写入的清单
与在任何其他地方写入的清单比较结果是一致的。
## 支持的容器
payload 是通过其 trailer magic 找到的,因此可执行文件格式仅
对报告和遍历通用二进制文件的切片有意义。
| 格式 | 平台 |
| :--------------- | :------------------------------------------------------ |
| ELF | Linux, x86-64 和 arm64 |
| Mach-O | macOS, arm64 和 x86-64 |
| Mach-O universal | macOS, 每个切片包含一个 payload,分别进行提取 |
| PE32+ | Windows, x86-64 和 arm64 |
这四种格式都经过了测试。ELF、Mach-O 和 PE 还在所有三个平台上
针对 Bun 1.4.0 生成的真实二进制文件进行了额外验证,方法是将提取的
字节与输入进行比较。
## 库
```
import { BinaryReader, inspectContainer, extractSlice } from 'bun-unpacker';
using reader = BinaryReader.open('/path/to/binary');
const container = inspectContainer(reader);
for (const slice of container.slices) {
const manifest = extractSlice(reader, container, slice, {
outputDir: 'extracted',
write: true,
includeBytecode: false,
});
console.log(manifest.modules.map((module) => module.path));
}
```
`unpackBinary` 和 `unpackTargets` 也被导出,供那些使用自己的方式
查找二进制文件来包装此 CLI 的工具使用。
[claude-code-unpacker](https://github.com/Enuvid/claude-code-unpacker) 就是这样
的一个包装器。
## 工作原理
Bun 将其 payload 追加到可执行镜像的末尾:
```
...native executable...
payload blob bytecode cache, file contents, sourcemaps,
NUL-terminated names
module table moduleCount * entrySize
offsets struct u64 blobSize, u32 tableOffset, u32 tableLength, ...
"\n---- Bun! ----\n"
...native metadata... ELF section headers, Mach-O code signature, ...
```
有两个细节会导致简单的读取器失败。原生元数据跟在 trailer 之后,
因此它并不位于文件的末尾。此外,Bun 自己的 runtime 将 magic 作为
字符串字面量携带,因此真实的二进制文件会包含多个副本,只有最后一个
才标志着 payload。
offsets 结构的大小和模块表的步长是探测出来的,而不是硬编码的。只有
当第一个表条目解析为打包器路径时(Linux 和 macOS 上为
`/$bunfs/root/...`,Windows 上为 `B:/~BUN/root/...`),候选项才会被
接受。这使得解析器能够在改变这些结构的 Bun 版本中继续正常工作。
## 范围和许可
该工具采用 MIT 许可,且不包含任何第三方代码。
它提取的内容则是另一回事。从二进制文件中提取出的任何内容仍受该
二进制文件自身许可证的约束,该工具既不捆绑也不重新分发
其中的任何内容。为了研究或调试而解包你已有的副本,正是此工具的
用途。
## 开发
需要 Node 22 或更高版本。
```
npm install
npm run build # tsc, output in dist/
npm test # compiles src and test, then runs node:test
npm run test:smoke # runs dist/cli.js against a synthetic binary
npm run lint # eslint with type-checked rules
npm run format:check # prettier
```
测试套件会逐字节构建合成的 Bun 可执行文件:payload blob、
模块表、offsets 结构、trailer,以及包含所有这些内容的通用包装器。
这涵盖了当前版本使用的结构大小和表步长之外的其他情况,而
没有任何真实的二进制文件会涉及这些情况。
## 许可证
MIT
标签:Bun, CMS安全, JavaScript, MITM代理, SOC Prime, 二进制解析, 云资产清单, 可执行文件提取, 开发工具, 自动化攻击, 逆向工程