【AST 混淆】四、代码块的混淆 [ 编程杂谈 ]
大数据男孩 文章 正文
明妃
{{nature("2022-08-14 17:23:20")}}更新特别说明:本文 生成节点时,函数的使用对于 Js 来说是错误的(不能指定参数给值),这样写是方便 看节点属性
二项式 转 函数花指令
花指令用来更好的隐藏 源代码的真实意图,还能增加代码量,增加分析难度
类型一
// 源代码
var num = a + b;
// 变成
function xxx(c, d){
return c + d;
}
var num = xxx(a, b)
类型二
// 源代码
var num = add(a);
// 变成
function xxx(c, v){
return c(v);
}
var num = xxx(add, v)
类型一 思路
获取
二项式
的符号
和左右部分
,然后 生成函数节点
,把函数节点
添加到当前代码块
的最前面
,然后把原始
的二项式
替换为调用表达式
// 二项式转花指令
traverse(ast, {
BinaryExpression(path) {
let operator = path.node.operator;
let left_ = path.node.left; // 加个下滑线 防止 冲突
let right_ = path.node.right;
// 构造函数节点
let funName = path.scope.generateUidIdentifier('xxx');
let a = type.identifier(name = 'a');
let b = type.identifier(name = 'b');
let func = type.functionDeclaration(
id = funName,
params = [a, b],
body = type.blockStatement(
body = [type.returnStatement(
argument = type.binaryExpression(
operator = operator,
left=a,
right = b
)
)]
)
)
// 把生成的函数节点添加到当前代码的最前面
let blockStatement = path.findParent(function (p) {
return p.isBlockStatement()
})
blockStatement.node.body.unshift(func);
// 替换原节点 为 调用表达式
path.replaceWith(type.callExpression(
callee = funName, _arguments = [left_, oright_]
))
}
})
[]()
类型二 思路
获取
调用表达式
的函数
和参数
,然后 生成函数节点
,把函数节点
添加到当前代码块
的最前面
,然后把原始
的调用表达式
替换为新的调用表达式
,只处理 一层的fun('aa')
不处理fun.fun('aa')
例子
function add(a, b) {
return a + b;
}
console.log(add(2, 3))
代码
// 调用表达式 转 花指令
traverse(ast, {
CallExpression(path) {
let callee_ = path.node.callee;
let arguments_ = path.node.arguments;
if(!type.isIdentifier(callee_)){ // 只处理 一层的 `fun('aa')` 不处理 `fun.fun('aa')`
return
}
// 构造函数节点
let funName = path.scope.generateUidIdentifier('fff');
let f = type.identifier(name = 'f') // 第一个参数,是 函数
let params_ = []; // 参数列表
for (let arg in arguments_) {
params_.push(name = path.scope.generateUidIdentifier('arg'))
}
let func = type.functionDeclaration(
id = funName,
params = [f].concat(params_),
body = type.blockStatement(
body = [type.returnStatement(
type.callExpression(
callee = f, _arguments = params_
)
)]
)
)
// 把生成的函数节点添加到当前代码的最前面
let blockStatement = path.findParent(function (p) {
return p.isBlockStatement() || p.isProgram() // 兼容处理 如何函数需要添加到 最外面层
})
blockStatement.node.body.unshift(func);
// 替换原节点 为 调用表达式
arguments_.unshift(callee_)
path.replaceWith(type.callExpression(
callee = funName, _arguments = arguments_
))
path.skip()
}
})
[]()
{{nature('2020-01-02 16:47:07')}} {{format('12641')}}人已阅读
{{nature('2019-12-11 20:43:10')}} {{format('9527')}}人已阅读
{{nature('2019-12-26 17:20:52')}} {{format('7573')}}人已阅读
{{nature('2019-12-26 16:03:55')}} {{format('5017')}}人已阅读
目录
标签云
一言
评论 0
{{userInfo.data?.nickname}}
{{userInfo.data?.email}}