1 个不稳定版本
0.1.0 | 2019年6月17日 |
---|
#573 in 编程语言
89KB
1.5K SLoC
Rusty-JSYC
Rusty-JSYC(JavaScript字节码编译器)是一个用Rust编写的JavaScript到字节码的编译器。该字节码旨在与提供的虚拟机一起使用,该虚拟机是用JavaScript编写的。组合它们形成了虚拟化混淆的组件。
如何使用本工具
您必须首先编译给定的JavaScript代码。之后,您可以使用提供的虚拟机执行它。
编译您的JavaScript代码
您可以使用提供的命令行工具
cargo run </path/to/javascript.js> </path/to/vm-template.js> </output/dir> -d
或者将编译器作为库使用,并在自己的Rust代码中调用它
extern crate jsyc_compiler;
use jsyc_compiler::{JSSourceCode, BytecodeCompiler};
fn main() {
let js_code = JSSourceCode::new("console.log('Hello World');".into());
let mut compiler = BytecodeCompiler::new();
let bytecode = compiler.compile(&js_code).expect("Failed to compile code");
println!("Bytecode: {}", bytecode);
let depedencies = compiler.decl_dependencies();
println!("Depedencies: {:?}", depedencies);
let base64_bytecode = bytecode.encode_base64();
println!("Base64-encoded bytecode: {}", base64_bytecode);
}
在您的Cargo.Toml中
[dependencies]
jsyc_compiler = "~0.1"
运行虚拟机
// include vm.js
// ...
var vm = new VM();
vm.init(Base64EncodedBytecode);
requestIdleCallback(() => vm.run());
// ...
将Base64EncodedBytecode
替换为实际编码的字节码。
示例演示
一个演示编译器和虚拟机都能使用的示例可以在playground/snake
中找到。它包含一个小型的Snake游戏(snake.js)。您可以使用以下方式编译它:
cargo run "playground/snake/unobfuscated/snake.js" "vm/vm.js" "playground/snake/obfuscated" "playground/snake/unobfuscated/index.html"
编译后,在您的浏览器中打开index.html文件。
/path/to/rusty-jsyc/playground/snake/obfuscated/index.html
这已在Chrome 74和Firefox 67上进行了测试。然而,任何支持ES6的浏览器都应该是兼容的。
虚拟化混淆
虚拟化混淆是一种最先进的混淆方案。它通过将代码编译成字节码来混淆代码,然后由虚拟机(VM)执行。因此,VM与编译的字节码一起分发。然后,使用此字节码调用它并执行它,从而执行实际代码。
由于字节码是逐条指令执行的,原始代码在任何地方都没有被恢复。因此,任何潜在的攻击者必须首先逆向工程VM,这可能是高度混淆的。然后必须理解底层架构和指令集,然后才能分析实际的字节码。由于任何两种虚拟化混淆都可能不同,因此自动工具的使用受到限制。[1][2]
兼容性
虚拟和真实JavaScript上下文之间的交互
可以将虚拟JavaScript上下文中定义的函数提供给真实JavaScript上下文。
// Compiled JavaScript
function secret_function(a, b, c) { return a*b+c; }
window.secret_function = secret_function;
// Non-Compiled JavaScript
var secret_function = window.secret_function;
secret_function(10, 20, 1337);
它不需要是 window
,任何两个上下文都知晓的对象实例都适用。当调用 secret_function
时,虚拟机将开始执行相应的字节码块。因此,以这种方式调用函数并不会比在编译后的 JavaScript 中调用它透露更多关于实现的信息。
当前的不稳定属性
这些属性在字节码中不会像在真实 JavaScript 中那样反映。
- 外部非成员函数的 'this' 指针简单地是 'void 0'
- 赋值表达式不会返回值,因此它们实际上不是表达式
- 如果你声明了一个没有赋值的变量,它的值将是未知的。因此,它可能是或可能不是 undefined (void 0)。(它将是 undefined,但不是 JavaScript 的 undefined (void 0))
let
和const
声明被视为var
声明
不支持的 JavaScript 语法
当前,此编译器只支持 JavaScript 功能的子集。目前缺少的是
- 与对象相关的符号 ({}, new, this, super)
- for-of 和 for-in 循环
- try 和 throw 结构
- break, continue, with, await, class 和 switch 关键字
- 标签
- 函数表达式和箭头函数(允许常规函数)
- 函数表达式和箭头函数可以用以下方式实现
var func_expr = eval("0, function(x) {return x*x;}");
然而,它们不支持对编译后的 JavaScript 中定义的变量的引用。
- 标记模板表达式
- 展开、剩余和序列符号
如何运行测试
该项目中有几个测试集
- Cargo 测试:
cargo test
- Node (mocha) 测试:
npm install && npm test
1: Rolf Rolles. Unpacking virtualization obfuscators. USENIX Workshop on Offensive Technologies (WOOT), 2009。
2: Johannes Kinder. Towards static analysis of virtualization-obfuscated binaries. Reverse Engineering (WCRE), 2012 19th Working Conference。
依赖项
~7–17MB
~217K SLoC