AST 技巧:模版(template)的高级用法
大家好,今天分享一下 AST 语法树中模版(template
)的高级用法。
模版的作用
模版,就是 template
,一般用来快速构造节点。例如要反混淆逻辑表达式,看一个简单的示例:
1 | const template = require("@babel/template").default; |
运行结果:
如果要自己构造节点的话,图中的 IfStatement
节点以及它的多个属性都要正确的构造,不仅繁琐而且很容易出错,代码可读性也很差,使用模版就很方便了。
模版的使用
标识符占位
模版的使用有两种方法,一般情况下使用上文中的方法就足够了,使用一个标识符来占位,例如文中的 A
和 B
,标识符会在构造节点的时候被替换成具体的代码。
例如:
1 | const buildRequire = template(` |
但是最近在做猿人学 2024 新春题目的时候,发现如果使用标识符占位的话,有的时候需要打印某个大写的变量,模版也会尝试替换这个变量,这样的话会报错,这个时候可以使用模版的另一种不太常见的方法。
报错例子:
1 | ast = parser.parse('a + b && (c = d) ;'); |
语法占位
语法占位符就是使用 %%
将需要占位的字符标识出来,可以防止与其他的大写字符冲突,可以在标识符可能出现问题的地方使用。
举个例子:
1 | const buildRequire = template(` |
可以看到即使有大写字符,但是还是可以正常解析并且完成相应的功能。上面的代码仅作为示例,实际可能无法运行。
注:请注意,语法占位符是在 Babel 7.4.0 中引入的,如果使用低于此版本的 babel 可能会导致错误。
其他用法
模版还可以将组装好的代码直接解析为 AST 语法树,方便在反混淆的时候进行替换或者覆盖操作。
1 | const name = "my-module"; |
注:在使用 template
的时候别忘了 template
的返回值是一个函数,在进行节点替换的时候要执行函数传入可选参数才可以正常使用。
1 | const source = "my-module"; |
template
默认情况下,根据解析的结果返回单个语句或语句数组。
template.statement
返回单个节点,如果传入的参数不是单个节点,则抛出异常。
template.statements
返回节点数组。
template.expression
返回表达式节点。
template.program
返回 Program 节点。
更多用法大家可以参考 babel 官网。
总结
模版在 AST 反混淆中用的还算是比较多的,一般在可能遇到报错的地方使用语法占位符解决即可,但是切记两种方法不能混合使用,在使用的时候要注意自己使用的 babel 的版本,防止语法占位符不被支持。
本文章首发于个人博客 LLLibra146’s blog
本文作者:LLLibra146
更多文章请关注公众号 (LLLibra146):
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!