AST反混淆插件|如何对多个节点使用同一插件

关注它,不迷路。       

本文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,否则后果自负,如有侵权,请联系作者立即删除!

1. 需求分析

如题,如何对多个节点使用同一插件?例如我有下面一行代码:

var a = 1+2,b = ![];

如果使用常规的方法,你需要这样写插件:

const visitor = {
    "BinaryExpression"(path)
    {
        const {confident,value} = path.evaluate();
        confident && path.replaceWith(types.valueToNode(value));
    },
    "UnaryExpression"(path)
    {
        const {confident,value} = path.evaluate();
        confident && path.replaceWith(types.valueToNode(value));
    },


}

可以看到,这两个代码是一模一样的,那能不能将其合并起来?

2. 混淆代码

还原前:

var a = 1+2,b = ![];

还原后:

var a = 3,b = false;

条件 : 写一个插件,需要同时兼顾这两种不同类型的节点

3. 思路

还是得从源码入手,定位到 traverse 函数:

function traverse(parent, opts = {}, scope, state, parentPath) {
  if (!parent) return;


  if (!opts.noScope && !scope) {
    if (parent.type !== "Program" && parent.type !== "File") {
      throw new Error("You must pass a scope and parentPath unless traversing a Program/File. " + `Instead of that you tried to traverse a ${parent.type} node without ` + "passing scope and parentPath.");
    }
  }


  if (!VISITOR_KEYS[parent.type]) {
    return;
  }


  visitors.explode(opts);
  (0, _traverseNode.traverseNode)(parent, opts, scope, state, parentPath);
}

看到 这行代码:

visitors.explode(opts);

跟进去:

function explode(visitor) {
  if (visitor._exploded) return visitor;
  visitor._exploded = true;


  for (const nodeType of Object.keys(visitor)) {
    if (shouldIgnoreKey(nodeType)) continue;
    const parts = nodeType.split("|");
    if (parts.length === 1) continue;
    const fns = visitor[nodeType];
    delete visitor[nodeType];


    for (const part of parts) {
      visitor[part] = fns;
    }
   }
   ......
  }

定位到for循环,可以看到这行代码:

const parts = nodeType.split("|");

这里是将 nodeType 进行了分割,而  nodeType  来自于 Object.keys(visitor),因此可以尝试在插件中key 用 "|" 隔开试试。

4. 插件源码

const visitor = {
    "BinaryExpression|UnaryExpression"(path)
    {
        const {confident,value} = path.evaluate();
        confident && path.replaceInline(t.valueToNode(value));
    },

这里需要注意的是,key一定要是字符串形式,否则会报错。

今天的文章就分享到这里,后续分享更多的技巧,敬请期待。

616c5274bdce319a84121a76aaba6957.jpeg

欢迎加入知识星球,学习更多AST和爬虫技巧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值