AST 技巧:自动添加 catch 日志输出

大家好,今天分享一个使用 AST 自动为代码 catch 块添加日志打印的功能。

catch

在扣完代码进行调试时,有的时候会发现明明没有报错,但是结果不对,就像这篇文章:JS逆向实战:扣代码时如何快速定位结果不对的问题?

文章中给出了两个方法,一种是通过代理,获取代码检测了哪些环境,补上对应的环境,从而绕过检测。还有一种就是将所有的 catch 语句添加日志打印逻辑,因为可能有的代码正常来说应该是不走 catch 分支,但是因为环境问题报错导致走了 catch 分支,从而让某些变量的值发生了变化。

image-20250416203131492

就像是这里,正常来说这段代码在浏览器中不会报错,但是在 nodejs 环境中会报错,导致 _0x42fb36 变量被错误的初始化为 1,进而会导致后续的计算结果都会出现错误,或者走到了错误的分支去。

添加日志打印语句后的结果应该是这样的:

image-20250416203434185

AST 自动添加日志语句

现在问题说完了,来说说解决方案。因为这个 JS 文件的 catch 语句有点多,手动一个个添加肯定是不现实的,所以我们选择使用 AST 的方式来添加。

下面来讲讲思路:

  1. 遍历所有的 catch 语句
  2. 获取 catch 中的变量名,便于在后面打印出来
  3. 获取 catch 中的所有语句,在头部添加日志打印语句
  4. 通过 template 来快捷构建一个打印语句

AST 实现

那使用 AST 应该如何实现呢?

老样子,先打开 AST 解析网站,每次写 AST 代码的时候都要准备好,肯定要用上的。

image-20250416203847837

找到 CatchClause,对应的就是 catch 语句。将鼠标放到上面左侧会自动高亮对应的语句,catch 以及它里面所有的代码都高亮了,说明找对地方了。

接下来要构造打印语句,为了简化构造流程,使用 template 的方式来构造。正常来说要使用 types.xxx 来一步一步的构造,但是这样太繁琐了,尤其是像是一个打印语句 console.log(xxx); 要使用多个函数嵌套起来,比较复杂。

使用 template 就比较简单了,直接一句 let t = template('console.log(A);') 就完事,在使用的时候直接将 A 替换成实际的变量名就可以了。

构造好打印语句后,将打印语句添加到 catch 语句的 body 数组中即可。

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
let add_catch_log = {
CatchClause: {
exit(path) {
let {node} = path;
let t = template('console.log(A);')
if (types.isIdentifier(node.param)) {
let name = node.param.name;
node.body.body.unshift(t({'A': name}))
}
}
}
}
traverse(ast, add_catch_log);

总结

以上就是使用 AST 给 catch 语句添加日志的方法了,整体来说比较简单,适合 AST 入门的小伙伴练手使用。

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

本文作者:LLLibra146

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

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

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