glizzykingdreko/botdeflector-deobfuscator
GitHub: glizzykingdreko/botdeflector-deobfuscator
基于 Babel AST 的 BotDeflector JavaScript 脚本反混淆工具,通过在沙箱中重建字符串解码器将混淆代码还原为可读源码。
Stars: 1 | Forks: 0
# botdeflector-deobfuscator
针对 **BotDeflector** 客户端脚本 `pow.js` 和 `api.js` 的 Babel AST 反混淆工具。它在 sandbox 中重建字符串数组解码器,将每个解码器调用还原为其返回的字面量,随后删除这些脚手架代码,让你得到的是可读的代码,而不是五千次重复的 `a0_0x3b8e(0x1f3)`。
[](https://takionapi.tech/bypass/botdeflector)
BotDeflector 也是 **Queue-it** 的 proof-of-work 和 icon challenge 背后的引擎,因此该工具同样适用于处理来自 `challenge.queue-it.net` 的 bundle。
请务必[阅读相关文章](https://takionapi.tech/blog/understanding-and-bypassing-botdeflector)
## 目录
## 反混淆了哪些内容
BotDeflector 通过带有 string-array 编码的 [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator) 发布其脚本。这意味着在你和源码之间隔着三样东西:
- 一个 **string array**,保存了 bundle 中的所有字面量
- 一个 **hex accessor**,通过 offset 从中读取数据,例如 `a0_0x3b8e(0x1f3)`
- 一个 **rotator IIFE**,在加载时打乱数组,因此静态读取会得到错误的字符串
这是一种毫无意义的混淆,逆向起来非常简单,但在进行其他操作之前,你仍然必须先将其还原。一旦字符串还原完毕,`pow.js` 读起来就像普通代码一样,它所实现的 Cuckoo Cycle 也就清晰地展现在你面前。
## 核心逻辑简述
### 1. 通过形状定位脚手架,而非名称
标识符在每次构建时都会改变,因此匹配 `a0_0x42b6` 毫无意义。请匹配形状:
- **array function**,一个 0 参数的 `FunctionDeclaration`,其主体声明了一个由字符串字面量组成的大数组
- **accessor**,一个 2 参数的顶层 `FunctionDeclaration`,它引用了 array function
- **rotator**,一个 `CallExpression`,其被调用者是一个接收 array function 并执行经典的由 `parseInt` 驱动的 `push(shift())` 洗牌操作的函数
### 2. 仅提取 rotator
这是让简单的反混淆工具栽跟头的地方,因此值得为它单独列出一个步骤。rotator 经常被作为 **顶层 `SequenceExpression` 的第一个元素出现,而该表达式的另一个元素是整个应用程序**。如果你抓取整个序列并运行它,你也会运行应用程序,这会再次旋转或改变数组,导致之后你解码的每个字符串都是垃圾数据。
因此,请匹配树中任意位置的 `CallExpression` 本身,而不是其父节点:
```
traverse(ast, {
CallExpression(path) {
const usesArray = path.node.arguments.some(a => t.isIdentifier(a) && a.name === arrayFnName);
const calleeIsFn = t.isFunctionExpression(path.node.callee) || t.isArrowFunctionExpression(path.node.callee);
if (usesArray && calleeIsFn) {
const code = generate(path.node.callee).code;
if (/parseInt/.test(code) && /push|shift/.test(code)) { rotatorCall = path.node; path.stop(); }
}
},
});
```
### 3. 在 sandbox 中重建解码器
将 array function、accessor 和 rotator 放入一个 `vm` 上下文中,只运行这三个部分而不运行其他任何内容,然后暴露出 accessor:
```
vm.runInContext(setupCode + `\nthis.__decode = ${accessorFnName};`, sandbox, { timeout: 5000 });
// [+] decoder ready. sample: a0_0x3b8e(0x1f3) = "exponentialRampToValueAtTime"
```
真正的解码器会执行核心工作,这意味着无论构建时使用了何种 offset 和 key 处理方式,你都能将其完整继承。
### 4. 收集所有别名,直到 fixpoint
Bundle 会针对每个作用域重新绑定解码器,如 `const _0xlocal = a0_0x3b8e;`,有时甚至会对别名进行别名化。一次遍历是不够的,因此需要不断迭代,直到没有新内容出现为止。
### 5. 折叠调用
每个带有字面量参数的调用都会变为其返回的字符串。带有非字面量参数的调用,如 `C(someVar)`,则保持原样,因为它们无法进行静态解析。
### 6. 删除脚手架并进行清理
一旦字符串被内联,array function、accessor、aliases 和 rotator 都变成了无用负载。接下来是两项听起来微不足道但实际上很重要的清理工作:`'a' + 'b'` 折叠为 `'ab'`,以及 `obj['prop']` 转换为 `obj.prop`。
## 安装
```
git clone https://github.com/glizzykingdreko/botdeflector-deobfuscator
cd botdeflector-deobfuscator
npm install
```
运行验证器以确认一切正常:
```
npm test
# 10/10 通过
```
测试会构建一个合成的混淆 bundle(包含 rotation trap),并断言字符串已还原、脚手架已删除且应用程序代码完好无损。本仓库中未引入任何 BotDeflector 的代码。
## 作为 node 模块使用
```
const { deobfuscate } = require('botdeflector-deobfuscator');
const fs = require('fs');
const { code, stats, decoder } = deobfuscate(fs.readFileSync('pow.js', 'utf8'), {
onLog: (m) => console.error('[+]', m),
});
fs.writeFileSync('pow.deob.js', code);
console.log(stats);
// { original: 142313, deobfuscated: 98204, replaced: 1847, unresolved: 3, aliases: 12 }
```
## CLI 用法
```
# direct
node bin/cli.js input/pow.js output/pow.deob.js
# 附带一份结构化报告
node bin/cli.js --input input/pow.js --output output/pow.deob.js --report output/report.json
```
| flag | 含义 |
| --- | --- |
| `--input ` | 位置参数输入的替代方案 |
| `--output ` | 位置参数输出的替代方案,默认为 `.deob.js` |
| `--report ` | 将统计信息和解码器元数据写入为 JSON |
| `--log-level ` | `DEBUG \| INFO \| NONE`,默认为 `INFO` |
| `--no-tidy` | 跳过字符串折叠和括号到点号的重写 |
| `-h`, `--help` | 使用说明 |
| exit code | 含义 |
| --- | --- |
| 0 | 正常运行,所有内容均已解析 |
| 1 | 致命错误:错误的输入、缺失脚手架、解析失败 |
| 2 | 已完成,但部分解码器调用无法进行静态解析 |
## 相关工作
- [botdeflector-pow](https://github.com/glizzykingdreko/botdeflector-pow):此反混淆工具揭示的 Cuckoo Cycle proof of work,已用 Node、Python 和 Go 实现,并为每种语言提供了验证器。
- [new-datadome-deobfuscator](https://github.com/glizzykingdreko/new-datadome-deobfuscator):针对 DataDome 的相同思路实现,工作量要大得多。
- [AWS-WAF-Deobfuscator](https://github.com/glizzykingdreko/AWS-WAF-Deobfuscator)、[Incapsula-utmvc-Deobfuscator](https://github.com/glizzykingdreko/Incapsula-utmvc-Deobfuscator)、[PerimeterX-Deobfuscator](https://github.com/glizzykingdreko/PerimeterX-Deobfuscator):我发布的其他 AST 反混淆工具。
## 与我联系
如果你觉得这个工具有用,可以在 GitHub 和 Medium 上关注我,以便在我发布文章或开源项目时收到通知。
- [GitHub](https://github.com/glizzykingdreko)
- [Twitter](https://mobile.twitter.com/glizzykingdreko)
- [Medium](https://medium.com/@glizzykingdreko)
- [Email](mailto:glizzykingdreko@protonmail.com)
- [TakionAPI](https://takionapi.tech)
- [请我喝杯咖啡 ❤️](https://www.buymeacoffee.com/glizzykingdreko)
## 许可证
MIT,详见 [LICENSE](./LICENSE)。
标签:Babel AST, CMS安全, JavaScript, MITM代理, 云资产清单, 反混淆, 域环境探测, 数据可视化, 网络调试, 自动化, 自定义脚本, 逆向工程, 验证码绕过