evex-dev/expose-kit
GitHub: evex-dev/expose-kit
一款强调安全性与可验证性的 JavaScript 反混淆工具包,通过逐步 AST 转换帮助安全研究人员还原被混淆的代码逻辑。
Stars: 22 | Forks: 0
# Expose Kit

[](https://discord.gg/evex)
[](https://xn--zwqt06btym6jly7j.com)
## 这是什么?
JavaScript 反混淆工具随处可见。
但它们中的许多都**过于激进**,甚至会改写到代码崩溃。
Expose Kit 采用了一种**不同的方法**。
- 不使用暴力破解
- 逐步、可验证的转换
- 旨在 *不会* 默默破坏你的代码
每一次转换都旨在被**检查和验证**,因此你始终能知道问题 *何时* 出现。
除了反混淆,Expose Kit 还提供了一套实用的**实用工具**,用于处理混淆的 JavaScript。
## 安装
只需一步:
```
npm i -g expose-kit
# 或
bun i -g expose-kit
```
```
expose --help
expose parsable sample.js
```
## 使用说明
### 默认参数
- 第一个参数是输入文件
(也可以使用 `--file` / `--input`)
- 如果缺少必需的选项,Expose Kit 会**提示你**
- 默认启用超时以避免挂起
使用 `--unlimited` 进行长时间运行
## 推荐工作流
首先,一个重要的前提:
原因包括:
- 不可预测的执行(`eval`,动态代码)
- AST 操作中的错误或边缘情况
因此,你应该**在每一步都验证代码**。
### 1. 始终使用 `parsable` 验证
每次转换后,运行:
```
expose parsable file.js
```
这可确保语法仍然有效。
### 2. 首先使作用域安全
导致代码破坏的最常见原因之一是**变量名混淆**。
如果你尝试编写自己的反混淆逻辑(例如在 Python 中),你很快就会意识到正确跟踪作用域是多么痛苦。
这就是为什么你**应该始终从以下操作开始**:
```
expose safe-scope input.js
```
这会按作用域重命名绑定,生成如下代码:
```
Before: var x = 810;((x) => console.log(x))(114514);
After: var x = 810;((_x) => console.log(_x))(114514);
```
仅凭这一点:
- 代码变得更不容易被破坏
- 编写自定义反混淆逻辑变得更容易
- 你不再需要担心作用域冲突
### 3. 逐步应用转换
在 `safe-scope` 之后,结合常见技术,例如:
- `expand-array`、`expand-object` 等
在**每一步**之后,再次运行 `parsable` 和 `remove-unused`。
(即使不频繁,我们也可能会忽略某些被破坏的部分)
你做得越多,代码就越清晰。
Expose Kit 还会清楚地指出是否存在 **diff**,从而使检查变得容易。
重复此过程,原始代码将逐渐展现出来。
## 命令
### `expose parsable`
检查文件在语法上是否有效。
```
parsable: const x = 810;
not parsable: const ;x; == 810;
```
```
expose parsable path/to/file.js
```
参数:
- 仅默认参数
### `expose safe-scope`
按作用域重命名绑定,以便更安全地进行转换。
```
expose safe-scope path/to/file.js --output path/to/file.safe-scope.js
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/safe-scope/mocks)。
参数:
- `--o, --output `
输出文件路径
- 无扩展名 → `file.safe-scope.js`
- 有扩展名 → `file.safe-scope.`
### `expose pre-evaluate`
预计算 const 数字/字符串表达式。(安全计算)
```
const a = 1 + 2 * 3; // => 7
const c = "aaaa";
const b = "a" + c; // => "aaaaa"
```
```
expose pre-evaluate path/to/file.js --output path/to/file.pre-evaluate.js
```
参数:
- `--o, --output `
输出文件路径
- 无扩展名 → `file.pre-evaluate.js`
- 有扩展名 → `file.pre-evaluate.`
注意:
- 通过将返回安全数组字面量的零参数函数提升为 var 来内联它们。
### `expose expand-array`
展开对原始值访问的数组索引。
```
var a = [1, 1, 4, 5, 1, 4];
// before
console.log(a[0], a[2], a[3]);
// after
console.log(1, 4, 5);
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/expand-array/mocks)。
```
expose expand-array path/to/file.js --target arrayName --output path/to/file.expand-array.js
```
参数:
- `--target `
目标数组变量名
- `--o, --output `
输出文件路径
注意:
- 每次替换都通过重新解析进行验证;跳过不安全的替换。
(此数组预期是不可变的,因此需要谨慎处理)
### `expose expand-object`
展开对原始值访问的对象属性。
```
const obj = { a: 1, b: 2 };
// before
console.log(obj.a, obj["b"]);
// after
console.log(1, 2);
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/expand-object/mocks)。
```
expose expand-object path/to/file.js --target objectName --output path/to/file.expand-object.js
```
参数:
- `--target `
目标对象变量名
- `--o, --output `
输出文件路径
注意:
- 每次替换都通过重新解析进行验证;跳过不安全的替换。
(此对象预期是不可变的,因此需要谨慎处理)
### `expose object-packer`
将连续的对象属性赋值打包为字面量。
```
const obj = {};
// before
obj.a = 0;
obj["b"] = 1;
// after
const obj = { a: 0, b: 1 };
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/object-packer/mocks)。
```
expose object-packer path/to/file.js --output path/to/file.object-packer.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 仅打包空对象字面量之后的连续赋值。
- 当属性值引用对象本身时停止。
### `expose key-simplify`
将安全的字符串字面量属性访问(`obj["foo"]`)替换为点号访问方式(`obj.foo`)。
```
const obj = { foo: 1, bar_baz: 2 };
obj["foo"] = obj['bar'];
console.log(obj["foo"], obj["bar_baz"]);
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/key-simplify/mocks)。
```
expose key-simplify path/to/file.js --output path/to/file.key-simplify.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 仅重写为普通标识符的计算键。
- 保留无效的标识符键,以便输出保持可解析。
### `expose remove-updater`
用 += 或 -= 替换安全的更新表达式。
```
// before
a++;
--b;
// after
a += 1;
b -= 1;
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-updater/mocks)。
```
expose remove-updater path/to/file.js --output path/to/file.remove-updater.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 仅替换其值未被使用的更新表达式。
- 对表达式语句和 for 循环更新子句是安全的。
### `expose remove-reassign`
内联安全的别名赋值和包装器调用。
```
const a = 0;
const b = a;
const c = b;
console.log(c); // => console.log(a);
```
```
function a(arg) {
return b(arg);
}
function c(arg) {
return d[arg];
}
a(0); // => b(0)
c(0); // => d[0]
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-reassign/mocks)。
```
expose remove-reassign path/to/file.js --output path/to/file.remove-reassign.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 仅内联 const/不可变的别名链。
- 跳过对象简写替换和被遮蔽的绑定。
- 包装器内联仅限于单次 return 的直通操作。
### `expose remove-deadcode`
移除不可达的分支并简化条件表达式。
```
if (true) {
a();
} else {
b();
}
// after
a();
const x = cond ? true : false;
// after
const x = !!cond;
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-deadcode/mocks)。
```
expose remove-deadcode path/to/file.js --output path/to/file.remove-deadcode.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 仅移除带有字面量/数组/对象测试的分支。
- 当两个分支都是布尔值时简化三元表达式。
### `expose remove-anti-tamper`
丢弃由反篡改脚本生成的自我保护包装器、调试防护和 console 劫持。
```
var wrapper = (function () {
var guard = true;
return function (ctx, fn) {
var thunk = guard ? function () {
if (fn) {
fn.apply(ctx, arguments);
fn = null;
}
} : function () {};
guard = false;
return thunk;
};
})();
wrapper(this, function () {
console.log("tamper");
});
console.log("safe");
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-anti-tamper/mocks)。
```
expose remove-anti-tamper path/to/file.js --output path/to/file.remove-anti-tamper.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 针对返回受保护辅助函数的包装器,并移除其调用。
- 在移除包装器之前清理 debug/console 辅助函数。
### `expose control-flow-packer`
内联由基于字符串的状态机生成的控制流平坦化循环。
```
const _0x1 = "a|b|c".split("|");
let _0x2 = 0;
while (true) {
switch (_0x1[_0x2++]) {
case "a":
console.log("a");
continue;
case "b":
console.log("b");
continue;
case "c":
console.log("c");
return;
}
break;
}
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/control-flow-packer/mocks)。
```
expose control-flow-packer path/to/file.js --output path/to/file.control-flow-packer.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 仅平坦化其状态数组来自字面量 `split` 的循环。
- 当某个分支返回或缺少状态 token 时停止。
### `expose fn-inliner`
将代理函数调用内联到表达式中。
```
const add = (a, b) => a + b;
const sum = add(1, 2);
// after
const sum = 1 + 2;
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/fn-inliner/mocks)。
```
expose fn-inliner path/to/file.js --output path/to/file.fn-inliner.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 仅内联返回单个表达式的函数。
- 跳过带有赋值、函数、块或序列的 return 表达式。
### `expose sequence-split`
将序列表达式拆分为语句。
```
// before
a, b, c;
// after
a;
b;
c;
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/sequence-split/mocks)。
```
expose sequence-split path/to/file.js --output path/to/file.sequence-split.js
```
参数:
- `--o, --output `
输出文件路径
注意:
- 将安全的序列表达式拆分为独立的语句。
- 也会规范化单语句的控制流块。
### `expose remove-unused`
移除未使用的变量。
```
// before
var a = 0, b = 1;
console.log(a);
// after
var a = 0;
console.log(a);
```
示例在[这里](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-unused/mocks)。
```
expose remove-unused path/to/file.js --output path/to/file.remove-unused.js
```
参数:
- `--o, --output `
输出文件路径
## 社区与支持
- 缺少某个功能? → [创建一个 issue](https://github.com/EdamAme-x/expose-kit/issues)
- 不确定该使用哪个命令? → 加入我们的 [Discord](https://evex.land)
## 作者
- [EdamAme-x](https://github.com/EdamAme-x)
为研究而生,而非滥用。
想要更强大的混淆?那就构建一个这个工具无法逆向的东西。
标签:AST操作, AST解析, Bun, CMS安全, DAST, DNS 反向解析, GNU通用公共许可证, JavaScript, MITM代理, Node.js, npm包, 云安全监控, 云资产清单, 代码混淆, 代码转换, 代码还原, 反混淆, 威胁情报, 开发者工具, 恶意软件分析, 数据可视化, 暗色界面, 脚本分析, 自动化payload嵌入, 自动化攻击, 逆向工程, 静态分析