egodeath
该项目并未实现不可区分性混淆。您不应使用此产品来保护秘密。它的存在是为了阻止逆向工程,而非防止逆向工程。

一个 JavaScript 混淆器,旨在使代码对人类和大型语言模型(LLM)都极难阅读和分析。使用 TypeScript 编写。实现了来自同行评审的密码学混淆研究中的技术。
安装
npm install
npm run build
CLI 使用
# 基本使用
node dist/index.js input.js > output.js
# 指定目标 token 预算(默认:2,000,000)
node dist/index.js --target-tokens 500000 input.js > output.js
# 最小混淆(小输出)
node dist/index.js --target-tokens 10000 input.js > output.js
# 最大膨胀(10M tokens)
node dist/index.js --target-tokens 10000000 input.js > output.js
# 使用环境变量
INPUT_FILE=input.js node dist/index.js > output.js
# 帮助
node dist/index.js --help
选项
| 选项 | 默认 | 描述 |
|---|
--target-tokens <n> | 2000000 | 目标输出大小(以 token 计)。小输入会膨胀至该上限。大输入会减少膨胀以保持预算。 |
--help, -h | | 显示帮助信息 |
npm 脚本
npm run build # 编译 TypeScript 到 dist/
npm run start # 运行混淆器(读取 input.js)
npm run test # 运行测试套件
npm run obfuscate-package # 对 npm 包运行兼容性测试
编程接口
const { obfuscate } = require('./dist/obfuscator');
const code = 'function add(a, b) { return a + b; }';
const obfuscated = obfuscate(code);
// 带选项
const obfuscated = obfuscate(code, { targetTokens: 500000 });
变换管道
混淆器在四个阶段中应用 20 个变换。每个阶段建立在前一个阶段之上。
阶段 1:安全与反分析预处理变换
阶段 2:结构预处理变换
阶段 3:标识符传递
阶段 4:后处理变换
死代码注入
死代码在多个点注入,使用两种生成策略:
| 策略 | 来源 | 描述 |
|---|
| 基于模板 | transforms/deadCodeInjection.ts | 9 种模板类型:循环累加、数组构建、对象操作、字符串拼接、嵌套条件、try/catch、while 倒计时、switch 计算、位运算链。模板引用真实作用域变量。 |
死代码注入点:
- CFF 死 switch case(每个函数大约增加 30%,根据预算缩放)
- 不透明谓词 else 分支
- 非 CFF 函数中的独立死代码块(预算控制)
研究论文参考文献
多个变换受同行评审的密码学混淆研究启发:
验证工具
两个验证工具测量混淆质量,位于 src/verification/:
空电路测试(verification/nullCircuitTest.ts)
混淆一个真实函数和一个“空”函数(相同形状,执行无操作),然后比较 14 个结构指标以评分它们的可区分程度。相似度越高 = 混淆越好。
import { runNullCircuitTest } from './verification/nullCircuitTest';
const result = runNullCircuitTest(realCode, paramCount, stmtCount, threshold, targetTokens);
console.log('相似度:', result.similarity); // 0.0-1.0
不可混淆函数测试(verification/unobfuscatableTests.ts)
来自论文 1 不可能证明的 7 个测试用例,试图从混淆代码中提取秘密:
import { runAllTests, printSummary } from './verification/unobfuscatableTests';
console.log(printSummary(runAllTests(10000)));
测试:点函数(密码)、魔法数字、金丝雀字符串、嵌入密钥、URL、正则表达式模式、控制流签名。
输出大小预算
--target-tokens 选项通过膨胀预算控制输出大小,该预算缩放死代码注入(主要体积杠杆)。预算门控变换:
| 预算比率 | 启用的变换 |
|---|
| > 3 | 反调试、触发器、CFF、不透明谓词、逗号合并 |
| > 5 | 代理函数、属性键编码、噪声注入、自完整性 |
| > 8 | 上下文窗口耗尽 |
| > 10 | 全局变量编码 |
死代码乘数从 1x(比率 30)到 150x(比率 1500+),控制死 switch case 和不透明谓词分支的数量和大小。
项目结构
src/
index.ts CLI 入口点
obfuscator.ts 主管道编排器(20 个变换)
options.ts 预算系统和选项
types.ts AST 类型定义
random.ts 随机 Unicode 名称生成(6-16 字符,16 个脚本范围)
ast.ts AST 节点工厂函数
keywords.ts 动态关键字发现(globalThis + window 包)
globals.ts 全局状态管理(空原型映射)
substitute.ts 标识符替换工具
declarations.d.ts 模块类型声明
passes/
firstPass.ts 标识符编目
secondPass.ts 标识符替换 + 字符串编码
thirdPass.ts 虚拟参数注入
transforms/
antiDebug.ts eval("debugger") 陷阱 + setInterval 循环
tripwires.ts 穿刺程序秘密输入检查 [论文 4]
noiseInjection.ts LPN 启发算术噪声 [论文 7]
controlFlowFlattening.ts while/switch + 模算术调度 [论文 3]
opaquePredicates.ts 15 个始终为 true/false 的数学谓词
proxyFunctions.ts 调用图平坦化分发器
contextExhaustion.ts 用于 LLM 上下文填充的三目/void 噪声
commaExpressions.ts 通过逗号运算符合并语句
globalVariableEncoding.ts 使用 eval+replace 处理全局变量
propertyKeyEncoding.ts 带每作用域注册表的计算属性访问
numberEncoding.ts 11 种位/算术编码策略
selfIntegrity.ts 反篡改运行时检查 [论文 10]
stringArrayExtraction.ts 链式 XOR + 稀疏位置错误 [论文 2, 9]
deadCodeInjection.ts 基于模板 + 变异的死代码 [论文 3]
verification/
nullCircuitTest.ts 死代码质量评分 [论文 10]
unobfuscatableTests.ts 秘密提取测试用例 [论文 1]
__tests__/ 超过 300 个单元测试,分布在 21 个套件中
tools/
obfuscate-package.ts 基于 webpack 的 npm 包兼容性测试
tests/
input*.js 原始测试输入文件
测试
# 运行所有测试
npm test
# 运行特定测试套件
npx jest controlFlowFlattening
npx jest tripwires
npx jest noiseInjection
# 针对 npm 包测试(克隆仓库,webpack 打包,混淆,运行测试)
npm run obfuscate-package # 所有 10 个包
npm run obfuscate-package -- minimist semver # 指定包
兼容性测试工具
tools/obfuscate-package.ts 工具针对真实的 npm 包测试混淆器:
- 克隆包的 git 仓库
- 安装所有依赖(包括用于测试的 devDependencies)
- 如果包有构建脚本,则构建包
- 使用 webpack 将库的主入口点打包成一个 CommonJS 文件
- 对打包后的文件运行混淆器
- 将库的主入口替换为混淆后的包
- 针对混淆后的版本运行库自身的测试套件
输出位置
| 路径 | 内容 |
|---|
dist/obfuscated/<package>/bundle.js | 每个包的混淆后 webpack 包 |
dist/obfuscated/report.json | 完整的 JSON 报告,包含包大小、混淆状态、测试输出 |
许可证
MIT - 版权所有 2026 Nicholas Starke