【AST 混淆】七、实现流程平坦化 [ 编程杂谈 ]
大数据男孩 文章 正文
明妃
{{nature("2022-08-14 17:23:20")}}更新特别说明:本文 生成节点时,函数的使用对于 Js 来说是错误的(不能指定参数给值),这样写是方便 看节点属性
思路
流程平坦化有好几种形式,结果都是 打乱代码执行 流程,原理都一样,while-switch、 for-switch
当然 阿里 极验 的平坦流混淆,更复杂,这里只是最简单的,分发器还能看见
while (!![]){ // 一个死循环
switch (...){ // 每次循环 改变 switch 的判断,而走不同的分支
case "0":
...
case "1":
...
}
}
实现
获取代码块,映射
代码块的 执行循序{index:i, value: 代码块节点}
,然后 打乱 执行顺序
,构造 分发器
,构建 死循环
,再构建 switch
分支,替换
原来的代码块
// 流程平坦流 混淆
traverse(ast, {
FunctionExpression(path) {
let blockStatement = path.node.body;
// 映射 语句执行顺序
let statement = blockStatement.body.map((v, i) => {
return {index: i, value: v}
})
// 流程打乱语句
for (let i = 1; i < statement.length; i++) {
const j = Math.floor(Math.random() * (i + 1));
[statement[i], statement[j]] = [statement[j], statement[i]];
}
// 构建分发器,创建 swichCase 数组
let dispenserArr = []; // 流程分发数组
let cases = []; // 构建 cases 节点
statement.map((v, i) => {
dispenserArr[v.index] = i;
let switchCase = type.switchCase(
test = type.numericLiteral(value = i),
consequent = [v.value, type.continueStatement()]
)
cases.push(switchCase);
})
// 生成 _array 和 _index 标识符,利用 BableAPI 保证不重名
let array = path.scope.generateUidIdentifier('array')
let index = path.scope.generateUidIdentifier('index')
// 生成 var _array = '0|2|2'.spiit('|'), index=0; 节点
let dispenserStr = dispenserArr.join('|');
let dispenser = type.variableDeclaration(
kind = 'var',
declarations = [type.variableDeclarator(
id = array,
init = type.callExpression(
callee = type.memberExpression(
object = type.stringLiteral(value = dispenserStr),
property = type.identifier(name = 'split')
),
_arguments = [type.stringLiteral(value = '|')]
),
), type.variableDeclarator(
id = index,
init = type.numericLiteral(value = 0))
]
)
// 生成 while-swiich 节点
let whileSta = type.whileStatement(
test = type.unaryExpression( // while 循环条件节点
operator = '!',
argument = type.unaryExpression(
operator = '!',
argument = type.arrayExpression(
elements = []
))),
body = type.blockStatement( // swiich 节点
body = [type.switchStatement(
discriminant = type.unaryExpression( // 构建 switch 判断部分 switch(+array[index++])
operator = '+',
argument = type.memberExpression(
object = array,
property = type.updateExpression(
operator = '++',
argument = index),
computed = true),
),
cases = cases) // case 节点
]
)
)
// 用分发器 和 while 循环 来替换原有的节点
path.get('body').replaceWith(type.blockStatement(
body = [dispenser, whileSta]))
}
})
[]()
{{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}}