kareemheshaam/jsunveil
GitHub: kareemheshaam/jsunveil
一款基于模式识别的 JavaScript 反混淆工具,通过沙箱执行解码器并利用 AST 变换恢复 obfuscator.io 风格字符串数组混淆中的原始字符串。
Stars: 0 | Forks: 0
# jsunveil
一个小巧的、基于模式的反混淆工具,专为受**字符串数组(字符串表)混淆**保护的 JavaScript 设计——这类混淆由 `obfuscator.io` 等工具及基于相同理念构建的众多引擎生成(旋转的字符串数组、通过单一解码器路由所有字面量、诱饵/死代码,以及每次构建时随机生成的标识符)。
它**不**针对任何特定的网站或样本。它攻击的是*技术*本身,因此当受保护的脚本使用全新的名称、新的字母表和不同的旋转偏移量重新生成时,同一工具依然有效。
## 功能介绍
给定一个混淆过的 `.js` 文件,`jsunveil` 将:
1. **定位字符串数组及其解码器**(每个字面量都会经过的 `f(idx)`),以及在加载时应用的旋转步骤。
2. **重建明文字符串映射表**,只需在密封的沙箱中运行数组和解码器即可——绝不运行完整程序。
3. **在 AST 层面内联所有解码器调用**(`_d(0x1f) → "deviceMemory"`),使用 Babel 实现。
4. **剥离常见的诱饵**——逗号操作符无操作、死 `if (false)` 分支以及自保护包装器——并重新输出易读、格式化的 JS。
它适用于构建生成的任何解码器,因为它是在沙箱中实时运行该解码器,而不是手动重新实现各种字符串方案(base91、自定义 base-N、rotate/XOR 等)。
## 为什么是“基于模式,而非基于样本”
字符串数组混淆器在每次构建时都会随机化其*表层结构*——标识符名称、字母表、旋转偏移量、诱饵位置——但其*结构*是稳定的:总是有一个字符串数组,总是有一个单一解码器,总是有一个旋转。`jsunveil` 依赖于这种结构(形态和调用模式),因此它能在重新生成后继续工作,而不会在下一次下载时就失效。
## 安装
```
git clone https://github.com/kareemheshaam/jsunveil
cd jsunveil
npm install
```
需要 Node 18+。
## 用法
```
# 反混淆文件
node src/cli.js examples/obfuscated.sample.js -o clean.js
# 仅 dump 恢复的 string map(非常适合 triage)
node src/cli.js examples/obfuscated.sample.js --strings
```
编程方式调用:
```
const { deobfuscate } = require('./src');
const clean = deobfuscate(fs.readFileSync('input.js', 'utf8'));
```
## 工作原理(简述)
这类混淆的难点在于解码器本身就*在*文件中,但与其它所有内容纠缠在一起。诀窍在于提取并**仅**在隔离环境中运行解码器,这样你就可以在不执行 payload 的情况下,获取每一个索引对应的值:
```
// Pull the string array + decoder out, run them in a sandbox, map every index.
const vm = require('vm');
const sandbox = {};
vm.createContext(sandbox);
vm.runInContext(arrayAndDecoderSource, sandbox, { timeout: 1000 });
const map = {};
for (let i = 0; i < sandbox.__arr.length; i++) map[i] = sandbox.__decode(i);
```
接下来就是普通的 Babel 处理流程:用映射表替换 `decoder(idx)` 字面量,丢弃诱饵,然后输出。
请参阅[详细文章](https://medium.com/@kareem.hesham/i-spent-a-week-inside-a-top-tier-web-anti-bot-stack-heres-what-i-found-4d8b67166f07)了解完整内幕,包括无头执行方面的内容(在 Node 中伪装足够多的浏览器环境以运行指纹挑战)。
## 适用范围与局限性
- 针对的是**字符串数组 / 字符串表**混淆。它*不是*通用的 VM-devirtualizer(虚拟机去虚拟化工具);控制流平坦化的 VM 需要不同的方法。
- 输出结果旨在供**阅读**,不一定能重新运行——内联字符串和剥离自保护代码会改变运行时的行为,这是设计使然。
- 仓库中内置的 `examples/obfuscated.sample.js` 是由一个使用公共混淆器处理的一次性代码片段生成的——本仓库中没有任何特定于供应商的内容。
## 许可证
MIT — 查看 [LICENSE](LICENSE)。
标签:Babel, CMS安全, JavaScript, MITM代理, 代码分析, 代码反混淆, 凭证管理, 数据可视化, 自定义脚本