How to fuck JSFuck
字数 1307 2025-09-23 19:27:38
JSFuck 混淆原理与逆向还原技术解析
一、JSFuck 概述
JSFuck 是一种基于 JavaScript 隐式类型转换特性的代码混淆技术,它仅使用六个字符 [, ], (, ), !, + 就能表示任何有效的 JavaScript 代码。
1.1 基本示例
- 混淆前:
alert(1);console.log(1); - 混淆后:由
[,],(,),!,+组成的复杂表达式
二、技术原理分析
2.1 隐式类型转换基础
JavaScript 的隐式类型转换机制是 JSFuck 的核心基础:
// 基础示例
'1' + '1' // "11"
'1' + 1 // "11"
[] + "" // "" (空数组转为空字符串)
2.2 数字构造原理
利用一元运算符和布尔转换:
+[] // 0 (空数组转为数字0)
+
!![] // true (空数组转为布尔值true)
+!![] // 1 (true转为数字1)
2.3 字符构造原理
2.3.1 基础字符构造
([+[]] // "f" (从"false"中取第一个字符)
([+!![]] // "a" (从"false"中取第二个字符)
(!![]+[])[+!![]] // "r" (从"true"中取第二个字符)
2.3.2 复杂字符构造
通过组合多种转换技术,可以构造出所有需要的字母:
// 构造 "constructor"
([]+[])[+!![]+!![]+!![]+!![]+!![]+!![]] +
([]+[])[+!![]+!![]+!![]+!![]+!![]+!![]+!![]] +
// ... 更多组合
2.4 函数调用机制
2.4.1 索引调用替代属性访问
// 两种等价调用方式
object.property
object["property"]
// 实际应用
[]["at"] // 获取数组的at方法
2.4.2 关键函数获取
// 获取constructor函数
[]["at"]["constructor"]
// 创建Function实例
[]["at"]["constructor"]("return eval")()
// 获取eval函数
[]["at"]["constructor"]("return eval")()["eval"]
三、逆向还原技术
3.1 AST(抽象语法树)分析方法
使用AST技术对混淆代码进行逆向还原的核心思路是常量折叠和表达式求值。
3.2 常量判断算法
function is_constant(node, depth=0) {
if (depth >= MAX_DEPTH) return false;
// 二元表达式判断
if (isBinaryExpression(node)) {
return is_constant(node.left, depth+1) &&
is_constant(node.right, depth+1);
}
// 一元表达式判断
if (isUnaryExpression(node)) {
return is_constant(node.argument, depth+1);
}
// 成员表达式判断
if (isMemberExpression(node)) {
return is_constant(node.object, depth+1) &&
(node.computed ? is_constant(node.property, depth+1) :
isIdentifier(node.property));
}
// 数组表达式判断
if (isArrayExpression(node)) {
return node.elements.every(e => is_constant(e, depth+1));
}
// 调用表达式判断
if (isCallExpression(node) && isMemberExpression(node.callee)) {
return is_constant(node.callee.object, depth+1) &&
isIdentifier(node.callee.property) &&
node.arguments.every(arg => is_constant(arg, depth+1));
}
// 标识符判断(处理NaN等特殊值)
if (isIdentifier(node)) {
return node.name === 'NaN';
}
// 字面量判断
if (isNumericLiteral(node) ||
isStringLiteral(node) ||
isBooleanLiteral(node)) {
return depth !== 0; // 避免对原始字面量进行处理
}
return false;
}
3.3 表达式求值策略
3.3.1 安全求值方法
function evaluate_constant(node) {
if (isBinaryExpression(node)) {
const left = evaluate_constant(node.left);
const right = evaluate_constant(node.right);
switch (node.operator) {
case '+': return left + right;
// 处理其他运算符...
}
}
// 处理其他节点类型...
}
3.3.2 快速求值方法(不安全但高效)
function unsafe_evaluate(node) {
const code = generate_code(node); // 将AST节点转为代码
return eval(code); // 直接执行求值
}
3.4 还原流程
- 常量折叠:识别并计算所有可求值的常量表达式
- 属性简化:将形如
object["property"]的表达式简化为object.property - 函数调用简化:简化常量函数调用
- 字符串拼接:合并相邻的字符串字面量
- 最终优化:生成简洁易读的代码
四、实战案例分析
4.1 典型JSFuck代码分解
// 原始混淆代码
([+!+[]+!+[]+!+[]]+([]+[])[!+[]+!+[]]+([][[]]+[])[+[]]+...
// 分解步骤
1. [1] → "a"
// ... 继续分解
4.2 完整还原过程
通过AST解析器逐步处理:
- 识别并求值所有常量表达式
- 替换所有可简化的成员表达式
- 执行函数调用求值
- 生成清晰的可读代码
五、工具与应用
5.1 推荐工具
- ClarityJS:专用于JS混淆代码还原的AST工具
- Babel:JavaScript编译器,可用于AST操作
- AST Explorer:在线AST分析工具
5.2 应用场景
- 恶意代码分析
- 代码审计与安全研究
- 学术研究(编程语言特性分析)
- 代码混淆与反混淆技术研究
六、防御与应对
6.1 检测方法
- 特征匹配:识别JSFuck特有的字符模式
- 静态分析:通过AST分析识别可疑模式
- 动态检测:监控异常eval行为
6.2 防护策略
- 内容安全策略(CSP)限制
- 输入验证与过滤
- 定期安全审计
七、总结
JSFuck利用了JavaScript语言设计中的隐式类型转换特性,通过极有限的字符集实现完整代码表达能力。对其的逆向还原需要深入理解AST处理技术和JavaScript运行时特性。AST技术不仅可用于反混淆,在代码分析、漏洞挖掘和安全检测等领域都有重要应用价值。
通过系统性的常量折叠、表达式求值和结构简化,可以有效还原JSFuck混淆代码,揭示其真实逻辑。这一过程体现了静态代码分析的强大能力和对语言特性的深入理解。
本文基于对JSFuck技术的深入分析和AST逆向工程实践,提供了从原理到实践的完整解析。工具实现详见ClarityJS项目。