AST技巧:模版(template)的高级用法

admin 2026-04-16 04:04:00 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细介绍了AST语法树中template模板的高级用法,重点讲解标识符占位和语法占位(%%)两种方法在代码反混淆中的应用。通过具体代码示例展示了模板如何简化节点构造过程,并提醒注意Babel版本兼容性问题。文章还介绍了template.ast、template.statement等扩展用法,为JavaScript代码分析和安全研究提供实用技术参考。 综合评分: 85 文章分类: 代码审计,WEB安全,安全工具,安全开发,逆向分析


cover_image

AST 技巧:模版(template)的高级用法

原创

LLLibra146 LLLibra146

LLLibra146

2025年5月26日 08:03 北京

在小说阅读器读本章

去阅读

大家好,今天分享一下 AST 语法树中模版(template)的高级用法。

模版的作用

模版,就是 template,一般用来快速构造节点。例如要反混淆逻辑表达式,看一个简单的示例:

const template = require("@babel/template").default;
const generator = require("@babel/generator").default;
const types = require("@babel/types");
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;

ast = parser.parse('a + b && (c = d) ;');

const buildRequire = template(`
  if(A){B;};
  console.log(111)
`);

traverse(ast, {
    LogicalExpression(path) {
        let {node} = path;
        path.replaceWithMultiple(buildRequire({'A': node.left, 'B': node.right}));
    }
})

console.log(generator(ast).code);

运行结果:

image-20250525211058953

如果要自己构造节点的话,图中的 IfStatement 节点以及它的多个属性都要正确的构造,不仅繁琐而且很容易出错,代码可读性也很差,使用模版就很方便了。

image-20250525211332408

模版的使用

标识符占位

模版的使用有两种方法,一般情况下使用上文中的方法就足够了,使用一个标识符来占位,例如文中的 A 和 B,标识符会在构造节点的时候被替换成具体的代码。

例如:

const buildRequire = template(`
  var IMPORT_NAME = require(SOURCE);
`);

const ast = buildRequire({
  IMPORT_NAME: t.identifier("myModule"),
  SOURCE: t.stringLiteral("my-module"),
});
//const myModule = require("my-module");

但是最近在做猿人学 2024 新春题目的时候,发现如果使用标识符占位的话,有的时候需要打印某个大写的变量,模版也会尝试替换这个变量,这样的话会报错,这个时候可以使用模版的另一种不太常见的方法。

报错例子:

ast = parser.parse('a + b && (c = d) ;');

let ddd='ddd';
const buildRequire = template(`
  console.log(new URL(),A)
`);

traverse(ast, {
    LogicalExpression(path) {
        let {node} = path;
        path.replaceWithMultiple(buildRequire({'A': node.left, 'B': node.right}));
    }
})

console.log(generator(ast).code);

image-20250525230100256

语法占位

语法占位符就是使用 %% 将需要占位的字符标识出来,可以防止与其他的大写字符冲突,可以在标识符可能出现问题的地方使用。

举个例子:

const buildRequire = template(`
  var %%importName%% = require(%%source%%+new URL());
`);

const ast = buildRequire({
    importName: t.identifier("myModule"),
    source: t.stringLiteral("my-module"),
});

console.log(generator(ast).code);
//var myModule = require("my-module" + new URL());

可以看到即使有大写字符,但是还是可以正常解析并且完成相应的功能。上面的代码仅作为示例,实际可能无法运行。

注:请注意,语法占位符是在 Babel 7.4.0 中引入的,如果使用低于此版本的 babel 可能会导致错误。

其他用法

模版还可以将组装好的代码直接解析为 AST 语法树,方便在反混淆的时候进行替换或者覆盖操作。

const name = "my-module";
const mod = "myModule";

const ast = template.ast`
  var ${mod} = require("${name}");
`;
console.log(ast)
// {
//     type: 'VariableDeclaration',
//         kind: 'var',
//     declarations: [
//     {
//         type: 'VariableDeclarator',
//         id: [Object],
//         init: [Object],
//         loc: undefined
//     }
// ],
//     loc: undefined
// }

注:在使用 template 的时候别忘了 template 的返回值是一个函数,在进行节点替换的时候要执行函数传入可选参数才可以正常使用。

const source = "my-module";

const fn = template`
  var IMPORT_NAME = require('${source}');
`;

console.log(fn)
console.log(typeof fn)
//[Function (anonymous)]
//function

template

默认情况下,根据解析的结果返回单个语句或语句数组。

template.statement

返回单个节点,如果传入的参数不是单个节点,则抛出异常。

template.statements

返回节点数组。

template.expression

返回表达式节点。

template.program

返回 Program 节点。

更多用法大家可以参考 babel 官网[1]。

总结

模版在 AST 反混淆中用的还算是比较多的,一般在可能遇到报错的地方使用语法占位符解决即可,但是切记两种方法不能混合使用,在使用的时候要注意自己使用的 babel 的版本,防止语法占位符不被支持。

参考资料

[1]

官网: https://babeljs.io/docs/babel-template

最近一直有小伙伴问我有没有交流群,为了能让大家更好的交流,我组建了一个逆向交流群,想要进群的小伙伴可以在后台点击“联系我”菜单或者扫码,添加微信并且备注“交流群”,我会拉你进群。

推荐阅读:

如何在浏览器中使用 AST 实时反混淆?(附AST模版可直接使用)

AST 使用技巧:如何快速分析混淆代码结构

在 JS逆向时如何 hook 属性?

如何 “正确” hook JS方法

无需登录,满血版DeepSeek R1,很强!

一日一技:反爬虫的极致手段,几行代码直接炸了爬虫服务器

JS调试技巧:如何让时间和随机数“听你指挥”?

【Windows版】tcpdump + wireshark 联动 frida,实现APP无感抓取HTTPS数据包

AST 技巧:还在手动扣代码?AST技术帮你自动扣代码

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


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:LLLibra146 LLLibra146 LLLibra146《AST 技巧:模版(template)的高级用法》

评论:0   参与:  0