AST 技巧:打印控制流混淆执行路径

大家好,今天分享一个可以打印控制流执行顺序的 AST 技巧。

控制流

有的时候遇到那种比较复杂的控制流,将多个函数拆散后共用一个控制流,使用索引来进入到不同的函数中,这个时候还原控制流就比较复杂,可能扣代码是一个更好的选择。

image-20250429213441897

image-20250429213516029

类似上面这种控制流,它有多个入口,每个入口对应不同的逻辑,要想使用单一的入口还原整个控制流就比较难,根据浏览器的执行结果来扣代码可能会遇到环境检测导致代码的执行路径发生变化。

打印执行路径

这个时候可以使用日志来打印控制流的执行路径,在每个 case 语句的第一行添加日志打印,打印当前的 case 值即可。

image-20250429213922675

获取到 case 节点的 consequent 属性,并且添加日志即可,代码不复杂,大家可以自己试一试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//给 case 加 log
let caseLog = {
SwitchCase: {
exit(path) {
let {node,scope} = path;
if (!types.isNumericLiteral(node.test)) {
return
}
let t = template('console.log("A");')
let value = node.test.value;
node.consequent.unshift(t({'A': value.toString()}))
}
}
}
traverse(ast,caseLog)

记得使用 unshift 将日志添加到第一行,要不然遇到了 break 会不生效的。

image-20250429214346823

来看 AST 执行的结果,每一个 case 的第一行都添加了日志打印,自动打印当前的 case 值。

在浏览器执行的结果:

image-20250429214327958

在本地 nodejs 中再执行一次,对比数据 case 是否一致即可。

执行路径不一致

如果执行路径不一致,则需要找到不一致的地方,往前查找是在哪里的路径发生了变化。

image-20250429215204217

因为有的时候,代码会检测某些环境特征,然后使执行路径发生变化,如上图所示,在执行路径会判断变量的值然后判断是否要跳过一部分逻辑。

总结

今天的文章比较简单,大家在补环境或者扣代码的时候,可以使用日志的方案尝试和浏览器对比,可以更快的找到执行路径异常的位置,大大提升效率。

本文章首发于个人博客 LLLibra146’s blog

本文作者:LLLibra146

更多文章请关注公众号 (LLLibra146):LLLibra146

版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!

本文链接
https://blog.d77.xyz/archives/c6466fbc.html