关注它,不迷路。
本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!
需求
本文以一个简短的混淆js代码来讲解如何根据节点前后的变化来写代码。代码如下:
calc(p?33:34);
为什么要还原?
因为还原后,方便后续的处理,如果这里不还原,没办法 计算出 calc 这个函数的值,因为实参不是常量的调用表达式,是没办法在AST文件中计算它的值的。也就不能反混淆。
还原后的代码是怎样的?
根据js基础知识,它还原后的代码应该是这样的:
p?calc(33):calc(34);
还原前后的代码有什么异同?
就整个代码而言,都是 ExpressionStatement 类型的表达式,而它的 expression 子节点却发生了变化:
由 CallExpression 变成了 ConditionalExpression 表达式。
因此这里会有一个 生成 ConditionalExpression 表达的过程,还有一个替换节点的过程。
混淆代码有哪些特征,如何过滤?
首先,它是一个 CallExpression 类型,主要关心的是它的 arguments 节点。
1. 只有一个实参,即arguments 长度为1
2.实参是ConditionalExpression 表达式。
因此,过滤这两个特征即可。
AST插件源码
完整代码如下:
const changeCallToConditionalExpression =
{CallExpression(path) {let { callee, arguments } = path.node;if (arguments.length != 1 || !types.isConditionalExpression(arguments[0])) {return;}let { test, consequent, alternate } = arguments[0];let newConsequent = types.callExpression(callee, [consequent]);let newAlternate = types.callExpression(callee, [alternate]);let newConditionalNode = types.ConditionalExpression(test, newConsequent, newAlternate);path.replaceWith(newConditionalNode);}
}traverse(ast, changeCallToConditionalExpression);
今天的文章就分享到这里,后续分享更多的技巧,敬请期待。
欢迎加入知识星球,学习更多AST和爬虫技巧。