owengregson/Ruam

GitHub: owengregson/Ruam

基于虚拟机技术的JavaScript混淆器,将源代码编译为自定义字节码以防止逆向工程。

Stars: 2 | Forks: 0


:::::::..    ...    :::  :::.     .        :

;;;;``;;;;   ;;     ;;;  ;;`;;    ;;,.    ;;;

 [[[,/[[['  [['     [[[ ,[[ '[[,  [[[[, ,[[[[,

 $$$$$$c    $$      $$$c$$$cc$$$c $$$$$$$$"$$$

 888b "88bo,88    .d888 888   888,888 Y88" 888o

 MMMM   "W"  "YmmMMMM"" YMM   ""` MMM  M'  "MMM
基于虚拟化的 JavaScript 混淆器

将 JavaScript 函数编译为由内嵌虚拟机执行的自定义字节码。
目前不存在针对 RuamVM 字节码的反混淆器。

Node.js >= 18 LGPL-2.1 TypeScript Strict Tests Passing Avg Size Ratio VM Overhead

快速链接

安装 ·  快速开始 ·  工作原理 ·  预设 ·  API

为什么选择 Ruam?

大多数 JavaScript 混淆器仅应用表面的转换 — 重命名变量、编码字符串、插入死代码。坚定的攻击者可以使用现成的工具、逻辑分析或通过在运行时修补函数来撤销这些更改。

Ruam 采取了一种根本不同的方法。 它将你的 JavaScript 编译 为自定义字节码指令集,并将原始源代码替换为一个紧凑的虚拟机,该虚拟机执行难以理解的指令流。原始代码被销毁 — 它在输出中任何地方都不存在。

传统混淆器

源 JS → 转换后的 JS (仍是 JS)

  • 相同的语言,相同的语义
  • AST 可逆的转换
  • 存在自动化的反混淆工具

Ruam

源 JS → 自定义字节码 + 内嵌 VM

  • 原始源代码被销毁
  • 必须对 VM 本身进行逆向工程
  • 不存在反混淆器

300+ 操作码开源 ISA 覆盖 26 个类别的全覆盖指令集 — 栈、算术、位运算、比较、控制流、属性访问、作用域、调用、类、迭代器、解构、async/await、生成器等。
每次构建多态 每次构建都会产生结构独特的输出。没有两个构建共享相同的编码、标识符名称或内部结构 — 即使来自相同的源代码。
多层加密 字节码使用多个独立层进行加密。密钥隐式地从输出自身的结构中派生 — 没有密钥材料以明文形式出现。
防篡改绑定 VM 的解密逻辑与其自身的源代码纠缠在一起。修改解释器以添加日志或断点会破坏所有解密 — 字节码变得无法恢复。
运行时变形 指令集在执行期间发生变异。相同的操作码字节在程序的不同点映射到不同的操作。静态反汇编会产生错误的结果。
优化编译器 多层优化管道最大限度地减少了虚拟化的性能成本。融合指令、寄存器提升和内联操作使 JS-in-JS 解释器的开销保持在具有竞争力的水平。
数千个测试 全面的测试套件,涵盖核心 JS 语义、压力/边缘情况、安全属性和集成场景 — 包括随机模糊测试。

安装

NPM 即将推出

npm install ruam

快速开始

CLI

# 原地混淆文件

ruam app.js



# 混淆到新文件

ruam app.js -o app.obf.js



# 使用 medium 预设混淆目录

ruam dist/ --preset medium



# 最大保护

ruam dist/ --preset max



# 交互式向导 (或直接运行不带参数的 `ruam`)

编程 API

import { obfuscateCode, obfuscateFile, runVmObfuscation } from "ruam";



// 同步 — 混淆代码字符串

const result = obfuscateCode('function hello() { return "world"; }');



// 异步 — 混淆文件

await obfuscateFile("src/app.js", "dist/app.js");



// 异步 — 使用选项混淆目录

await runVmObfuscation("dist/", {

  include: ["**/*.js"],

  exclude: ["**/node_modules/**"],

  options: { preset: "max" },

选择性混淆

并非每个函数都需要虚拟化。使用 comment 模式仅保护重要的内容:

/* ruam:vm */

function sensitiveLogic() {

  // → 编译为字节码

}



function publicHelper() {

  // → 未触及,无开销

ruam app.js -m comment

工作原理

Ruam 应用多层独立的保护层,这些保护层增加了逆向工程的难度。每一层都迫使攻击者在进入下一层之前解决一个独特的问题。

描述
虚拟化 原始 JS 被编译为自定义字节码 ISA。源代码被销毁 — 攻击者必须对整个 VM 进行逆向工程才能恢复任何逻辑。
多态编码 指令编码、标识符和内部结构在每次构建时都是随机的。逆向一个构建不能提供关于任何其他构建的可重用知识。
指令加密 每条指令都是单独加密的。密钥是从输出本身的属性派生的 — 没有密钥材料以明文存储。需要顺序解密;你不能跳到字节码流的中间。
完整性绑定 解密过程与 VM 解释器自身的源代码纠缠在一起。以任何方式修改 VM(添加日志、设置断点、修补行为)都会静默地破坏所有解密。
VM 屏蔽 每个函数都可以接收自己独立的微型解释器,具有独特的编码、加密密钥和内部结构。逆向一个函数的解释器对任何其他函数没有帮助。
字符串编码 字节码中的所有字符串常量都是独立加密的。编译后没有明文字符串存留 — 无论是变量名、属性键还是字面量值。
反调试 多层运行时检测,响应逐步升级。没有 eval()new Function()debugger 语句或 console 调用 — 完全兼容严格的 CSP 环境,包括 Chrome 扩展。
算术混淆 解释器内的算术和位运算被替换为数学上等效但不透明的复合表达式,使解释器逻辑更难跟踪。
字符串原子化 解释器中的所有字符串字面量 — 属性名、方法名、内部标签 — 都被替换为编码的表查找。输出中没有硬编码字符串存留。
块置换 字节码基本块在每个编译函数内随机重新排序。控制流通过显式跳转保留。字节码流不再反映原始程序结构。
密钥分散 加密密钥材料被分割成片段,分布在输出的多个闭包作用域中。恢复任何单个密钥都需要跟踪整个作用域链。

其他加固选项包括死字节码注入、栈值加密、诱饵操作码处理器、处理器分片、运行时操作码变异和多态字符串解码 — 均可独立配置或通过预设配置。


预设

三个内置预设提供递增的保护。显式选项始终覆盖预设值。

预设 启用内容 使用案例
low 仅 VM 编译 开发、调试、基本 IP 保护
medium + 标识符重命名、字节码加密、指令加密、诱饵和动态操作码、字符串原子化、密钥分散 生产环境 — 平衡保护和大小
max 一切 — 所有加密层、VM 屏蔽、调试保护、完整性绑定、算术混淆、死代码、栈编码、块置换、字符串原子化、密钥分散 高价值目标 — 最大保护
ruam dist/ --preset max
obfuscateCode(source, {

  preset: "medium",

  debugProtection: true,  // 覆盖:向 medium 添加调试保护


性能

虚拟化本质上会增加开销 — 这是表面转换无法提供的保护所付出的代价。Ruam 的多层优化管道最大限度地减少了这种成本。

典型开销:在计算密集型基准测试中为原生速度的 ~38–45x,对于纯 JS-in-JS 解释器来说具有竞争力。

使用选择性混淆-m comment)仅保护敏感函数,并让热路径作为原生 JS 运行。


CLI 参考

ruam <input> [options]



预设:

  --preset <name>           应用预设:low, medium, max



输出  -o, --output <path>       输出文件或目录(默认:覆盖输入)



编译:

  -m, --mode <mode>         目标模式:"root"(默认)或 "comment"

  -e, --encrypt             启用字节码加密

  -p, --preprocess          在编译前重命名所有标识符



安全:

  -d, --debug-protection    启用反调试器保护

  --no-debug-protection     禁用反调试器(覆盖预设)

  --rolling-cipher          启用指令加密

  --integrity-binding       将解密绑定到解释器完整性

  --vm-shielding            每函数独立微型解释器



加固:

  --dynamic-opcodes         从解释器中过滤未使用的操作码

  --decoy-opcodes           添加假操作码处理器

  --dead-code               注入死字节码序列

  --stack-encoding          加密 VM 栈上的值

  --mba                     算术混淆(混合布尔算术)

  --handler-fragmentation   将处理器逻辑拆分为交错的片段

  --string-atomization      用编码查找替换解释器字符串

  --polymorphic-decoder     每次构建随机化字符串解码链

  --scattered-keys          将密钥材料分片到闭包作用域中

  --block-permutation       打乱字节码基本块顺序

  --opcode-mutation         插入运行时处理器表变异



环境:

  --target <env>            目标环境:node, browser(默认), browser-extension



文件选择:

  --include <glob>          目录模式的文件 glob(默认:"**/*.js")

  --exclude <glob>          排除 glob(默认:"**/node_modules/**")



其他:

  --debug-logging           注入详细的 VM 跟踪日志

  -I, --interactive         启动交互式配置向导

  -h, --help                显示帮助


API 参考

obfuscateCode(source, options?)

同步混淆 JavaScript 源字符串。将混淆后的代码作为字符串返回。

import { obfuscateCode } from "ruam";



const output = obfuscateCode(source, {

  preset: "medium",

  targetMode: "root",

obfuscateFile(inputPath, outputPath, options?)

读取文件,对其进行混淆,并写入结果。返回 Promise<void>

import { obfuscateFile } from "ruam";



runVmObfuscation(directory, config?)

混淆目录中的所有匹配文件。返回 Promise<void>

import { runVmObfuscation } from "ruam";



await runVmObfuscation("dist/", {

  include: ["**/*.js"],

  exclude: ["**/node_modules/**"],

  options: { preset: "medium" },

选项

选项 类型 默认值 描述
preset "low" | "medium" | "max" 应用预设配置
targetMode "root" | "comment" "root" "root":所有顶层函数。"comment":仅带有 /* ruam:vm */ 注释的
threshold number 1.0 符合条件的函数被编译的概率(0–1)
target "node" | "browser" | "browser-extension" "browser" 目标执行环境
preprocessIdentifiers boolean false 在编译前重命名所有局部标识符
encryptBytecode boolean false 使用环境指纹密钥加密字节码
rollingCipher boolean false 每条指令加密,带有隐式密钥派生
integrityBinding boolean false 将解密绑定到解释器源完整性(自动启用 rollingCipher
vmShielding boolean false 每函数微型解释器,具有独特编码(自动启用 rollingCipher
debugProtection boolean false 多层反调试器,响应逐步升级
dynamicOpcodes boolean false 从解释器中过滤未使用的操作码
decoyOpcodes boolean false 向解释器添加假操作码处理器
deadCodeInjection boolean false 注入不可达的字节码序列
stackEncoding boolean false 在运行时加密 VM 栈上的值
mixedBooleanArithmetic boolean false 用不透明的 MBA 表达式替换算术/位运算
handlerFragmentation boolean false 将操作码处理器拆分为交错的片段
stringAtomization boolean false 用编码的表查找替换所有解释器字符串字面量(自动启用 polymorphicDecoder
polymorphicDecoder boolean false 每次构建随机化字节操作链用于字符串解码
scatteredKeys boolean false 将密钥材料分片并分散到闭包作用域中
blockPermutation boolean false 在编译函数内打乱字节码基本块顺序
opcodeMutation boolean false 插入运行时处理器表变异(自动启用 rollingCipher
debugLogging boolean false 向解释器注入详细的跟踪日志

支持的语法

Ruam 编译全方位的现代 JavaScript:

  • 函数(声明、表达式、箭头函数、生成器、async、async 生成器)
  • 类(继承、构造函数、方法、getter/setter、计算属性、静态成员、super
  • 控制流(ifforfor-infor-ofwhiledo-whileswitch、标签语句)
  • 异常处理(try/catch/finallythrow
  • 解构(数组和对象模式、默认值、rest 元素、嵌套)
  • Spread/rest(调用、数组和对象字面量中的 ...args
  • 闭包和词法作用域(带有正确 TDZ 的 let/const、每次迭代绑定)
  • Async/await、生成器(yieldyield*)、async 生成器
  • 模板字面量、带标签的模板、可选链、空值合并
  • 计算属性名、简写属性/方法、Symbol 键

目标环境

使用 --target 为你的部署环境优化输出:

目标 描述
browser <script> 标签。默认。
node Node.js(CJS 或 ESM 模块)。
browser-extension Chrome 扩展 MAIN 世界内容脚本。包装输出以避免 TrustedScript CSP 错误。
ruam content-script.js --target browser-extension --preset max

环境要求

  • Node.js >= 18
  • ESM"type": "module"

许可证

LGPL-2.1

标签:AST 抽象语法树, DNS 反向解析, DOM解析, GNU通用公共许可证, JavaScript 混淆器, MITM代理, Node.js, RuamVM, TypeScript, 代码保护, 代码安全, 代码混淆, 前端安全, 反调试, 反逆向工程, 字节码编译, 安全插件, 漏洞枚举, 自动化攻击, 虚拟化保护, 虚拟机 (VM), 解释器