AST抽象语法树及如何转JS代码:

AST抽象语法树及如何转JS代码:

资料来源:

https://www.cnblogs.com/goloving/p/14078228.html

抽象语法树(Abstract Syntax Tree)也称为AST语法树,指的是源代码语法所对应的树状结构。也就是说,对于一种具体编程语言下的源代码,通过构建语法树的形式将源代码中的语句映射到树中的每一个节

点上。

在编译完成语法分析后生成。

作用是:

聊到AST的用途,其应用非常广泛,下面我简单罗列了一些:

  • IDE的错误提示、代码格式化、代码高亮、代码自动补全等
  • JSLintJSHint对代码错误或风格的检查等
  • webpackrollup进行代码打包等
  • CoffeeScriptTypeScriptJSX等转化为原生Javascript

其实它的用途,还不止这些,如果说你已经不满足于实现枯燥的业务功能,想写出类似reactvue这样的牛逼框架,或者想自己搞一套类似webpackrollup这样的前端自动化打包工具,那你就必须弄懂AST

抽象语法树的作用非常的多,比如编译器、IDE、压缩优化代码等。在JavaScript中,虽然我们并不会常常与AST直接打交道,但却也会经常的涉及到它。例如使用UglifyJS来压缩代码,实际这背后就是在对JavaScript的抽象语法树进行操作。 在一些实际开发过程中,我们也会用到抽象语法树,下面通过一个小例子来看看怎么进行JavaScript的语法解析以及对节点的遍历与操纵。

AST转JS代码:

需要安装@babel/generator

npm install @babel/generator
npm install @babel/generator estree-to-babel

这样只能在安装文件夹里生效

符合ESTree AST规范的:

const { default: generate } = require('@babel/generator');
const estreeToBabel = require('estree-to-babel');

// 加载 ESTree 格式的 AST
const estreeAST = require('./2.json'); // 替换为你的 JSON 路径

// 转换 ESTree AST → Babel AST
const babelAST = estreeToBabel(estreeAST);

// 生成 JavaScript 代码
const { code } = generate(babelAST, {
  quotes: 'single', // 统一使用单引号
  decoratorsBeforeExport: true // 适配 ES6+ 语法
});

console.log(code);

符合babel规范的

const generate = require('@babel/generator').default;

// 从 JSON 加载 AST
const astJson = require('./ast.json'); 

// 转换为代码(自动处理缩进、分号等格式)
const { code } = generate(astJson, {
  retainLines: false,
  compact: false,
  quotes: 'double'
});

console.log(code);

例题:

[SWPUCTF 2021 新生赛]astJS

{
  "type": "Program",
  "start": 0,
  "end": 233,
  "body": [
    {
      "type": "ExpressionStatement",
      "start": 0,
      "end": 233,
      "expression": {
        "type": "CallExpression",
        "start": 0,
        "end": 232,
        "callee": {
          "type": "FunctionExpression",
          "start": 1,
          "end": 229,
          "id": null,
          "expression": false,
          "generator": false,
          "async": false,
          "params": [],
          "body": {
            "type": "BlockStatement",
            "start": 13,
            "end": 229,
            "body": [
              {
                "type": "FunctionDeclaration",
                "start": 18,
                "end": 177,
                "id": {
                  "type": "Identifier",
                  "start": 27,
                  "end": 29,
                  "name": "bE"
                },
                "expression": false,
                "generator": false,
                "async": false,
                "params": [
                  {
                    "type": "Identifier",
                    "start": 30,
                    "end": 33,
                    "name": "str"
                  },
                  {
                    "type": "Identifier",
                    "start": 34,
                    "end": 37,
                    "name": "key"
                  }
                ],
                "body": {
                  "type": "BlockStatement",
                  "start": 38,
                  "end": 177,
                  "body": [
                    {
                      "type": "VariableDeclaration",
                      "start": 46,
                      "end": 70,
                      "declarations": [
                        {
                          "type": "VariableDeclarator",
                          "start": 50,
                          "end": 69,
                          "id": {
                            "type": "Identifier",
                            "start": 50,
                            "end": 53,
                            "name": "arr"
                          },
                          "init": {
                            "type": "CallExpression",
                            "start": 56,
                            "end": 69,
                            "callee": {
                              "type": "MemberExpression",
                              "start": 56,
                              "end": 65,
                              "object": {
                                "type": "Identifier",
                                "start": 56,
                                "end": 59,
                                "name": "str"
                              },
                              "property": {
                                "type": "Identifier",
                                "start": 60,
                                "end": 65,
                                "name": "split"
                              },
                              "computed": false,
                              "optional": false
                            },
                            "arguments": [
                              {
                                "type": "Literal",
                                "start": 66,
                                "end": 68,
                                "value": "",
                                "raw": "''"
                              }
                            ],
                            "optional": false
                          }
                        }
                      ],
                      "kind": "var"
                    },
                    {
                      "type": "ReturnStatement",
                      "start": 77,
                      "end": 171,
                      "argument": {
                        "type": "CallExpression",
                        "start": 84,
                        "end": 171,
                        "callee": {
                          "type": "MemberExpression",
                          "start": 84,
                          "end": 167,
                          "object": {
                            "type": "CallExpression",
                            "start": 84,
                            "end": 162,
                            "callee": {
                              "type": "MemberExpression",
                              "start": 84,
                              "end": 91,
                              "object": {
                                "type": "Identifier",
                                "start": 84,
                                "end": 87,
                                "name": "arr"
                              },
                              "property": {
                                "type": "Identifier",
                                "start": 88,
                                "end": 91,
                                "name": "map"
                              },
                              "computed": false,
                              "optional": false
                            },
                            "arguments": [
                              {
                                "type": "ArrowFunctionExpression",
                                "start": 92,
                                "end": 161,
                                "id": null,
                                "expression": false,
                                "generator": false,
                                "async": false,
                                "params": [
                                  {
                                    "type": "Identifier",
                                    "start": 93,
                                    "end": 94,
                                    "name": "i"
                                  }
                                ],
                                "body": {
                                  "type": "BlockStatement",
                                  "start": 97,
                                  "end": 161,
                                  "body": [
                                    {
                                      "type": "ReturnStatement",
                                      "start": 107,
                                      "end": 153,
                                      "argument": {
                                        "type": "CallExpression",
                                        "start": 114,
                                        "end": 153,
                                        "callee": {
                                          "type": "MemberExpression",
                                          "start": 114,
                                          "end": 133,
                                          "object": {
                                            "type": "Identifier",
                                            "start": 114,
                                            "end": 120,
                                            "name": "String"
                                          },
                                          "property": {
                                            "type": "Identifier",
                                            "start": 121,
                                            "end": 133,
                                            "name": "fromCharCode"
                                          },
                                          "computed": false,
                                          "optional": false
                                        },
                                        "arguments": [
                                          {
                                            "type": "BinaryExpression",
                                            "start": 134,
                                            "end": 152,
                                            "left": {
                                              "type": "CallExpression",
                                              "start": 134,
                                              "end": 148,
                                              "callee": {
                                                "type": "MemberExpression",
                                                "start": 134,
                                                "end": 146,
                                                "object": {
                                                  "type": "Identifier",
                                                  "start": 134,
                                                  "end": 135,
                                                  "name": "i"
                                                },
                                                "property": {
                                                  "type": "Identifier",
                                                  "start": 136,
                                                  "end": 146,
                                                  "name": "charCodeAt"
                                                },
                                                "computed": false,
                                                "optional": false
                                              },
                                              "arguments": [],
                                              "optional": false
                                            },
                                            "operator": "^",
                                            "right": {
                                              "type": "Identifier",
                                              "start": 149,
                                              "end": 152,
                                              "name": "key"
                                            }
                                          }
                                        ],
                                        "optional": false
                                      }
                                    }
                                  ]
                                }
                              }
                            ],
                            "optional": false
                          },
                          "property": {
                            "type": "Identifier",
                            "start": 163,
                            "end": 167,
                            "name": "join"
                          },
                          "computed": false,
                          "optional": false
                        },
                        "arguments": [
                          {
                            "type": "Literal",
                            "start": 168,
                            "end": 170,
                            "value": "",
                            "raw": "''"
                          }
                        ],
                        "optional": false
                      }
                    }
                  ]
                }
              },
              {
                "type": "ExpressionStatement",
                "start": 181,
                "end": 227,
                "expression": {
                  "type": "CallExpression",
                  "start": 181,
                  "end": 227,
                  "callee": {
                    "type": "MemberExpression",
                    "start": 181,
                    "end": 192,
                    "object": {
                      "type": "Identifier",
                      "start": 181,
                      "end": 188,
                      "name": "console"
                    },
                    "property": {
                      "type": "Identifier",
                      "start": 189,
                      "end": 192,
                      "name": "log"
                    },
                    "computed": false,
                    "optional": false
                  },
                  "arguments": [
                    {
                      "type": "CallExpression",
                      "start": 193,
                      "end": 226,
                      "callee": {
                        "type": "Identifier",
                        "start": 193,
                        "end": 195,
                        "name": "bE"
                      },
                      "arguments": [
                        {
                          "type": "Literal",
                          "start": 196,
                          "end": 222,
                          "value": "EXXH_MpjxBxYnjggrM~eerv",
                          "raw": "'EXXH_MpjxBxYnjggrM~eerv'"
                        },
                        {
                          "type": "Literal",
                          "start": 223,
                          "end": 225,
                          "value": 11,
                          "raw": "11"
                        }
                      ],
                      "optional": false
                    }
                  ],
                  "optional": false
                }
              }
            ]
          }
        },
        "arguments": [],
        "optional": false
      }
    }
  ],
  "sourceType": "module"
}

WP:

exp:

const { default: generate } = require('@babel/generator');
const estreeToBabel = require('estree-to-babel');

// 加载 ESTree 格式的 AST
const estreeAST = require('./2.json'); // 替换为你的 JSON 路径

// 转换 ESTree AST → Babel AST
const babelAST = estreeToBabel(estreeAST);

// 生成 JavaScript 代码
const { code } = generate(babelAST, {
  quotes: 'single', // 统一使用单引号
  decoratorsBeforeExport: true // 适配 ES6+ 语法
});

console.log(code);

输出:

(function () {
  function bE(str, key) {
    var arr = str.split("");
    return arr.map(i => {
      return String.fromCharCode(i.charCodeAt() ^ key);
    }).join("");
  }
  console.log(bE("EXXH_Mpjx\x7FBxYnjggrM~eerv", 11));
})();

直接运行即可得到flag:

NSSCTF{astIsReallyFunny}

posted @ 2025-03-21 10:58  漫宿骄盛  阅读(108)  评论(0)    收藏  举报