AST反混淆实战篇二十二|实参为字面量的eval函数还原

之前一直找不到完美的办法来替换eval里面的字符串,想了很多招,但效果不尽人意。

初次使用的是类似这样的代码:

path.replaceWith(t.Identifier(value));

我们知道,eval的实参为字符串,而上面的代码中是生成的确是 Identifier,因此没办法继续遍历eval出来后的代码,除非从新生成代码后再解析遍历,代码不够优雅,并且字符串类型本来就不应该转换成 Identifier 类型。

后来,看到了源码中的 replaceWithSourceString 方法,试用后,效果也不尽人意,部分代码如下:

const types         = require("@babel/types");
const replaceEval = {
  CallExpression: {
    exit(path) {
      let {callee, arguments} = path.node;
      if (arguments.length != 1 || !types.isLiteral(arguments[0]))
          return;
      if (!types.isIdentifier(callee, {name: "eval"}))
      {
        return;
      }
      let funcPath = path.getFunctionParent();
      let sourceCode = funcPath.toString();
      let value = arguments[0].value;
      sourceCode = sourceCode.replace(path.toString(), value);
      path.replaceWithSourceString(sourceCode);
      }
    }
  },
}

使用上面的插件,在某些情况下是个错的,效果还是不行。

就当我手足无措的时候,偶尔使用搜索引擎,竟然达到了完美的答案。

因为是 replaceWithSourceString 这个方面,因此搜索这个试试:

这个著名的 stackoverflow 网站,应该有大神遇到过类似的问题,点进去看看:

虽然只有一个答案,但足够让我眼前一亮,依葫芦画瓢,很快就写出了代码,但是,报错了:

throw new Error("Found multiple statements but wanted one");

看到了 multiple statements,瞬间就明白了。答案给的是单个语句的处理方法,而我处理的eval函数,包含多个语句,因此,稍微改改就可以了。

    if (types.isIdentifier(callee, {name: "eval"})) 
    {
       const evalNode = template.statements.ast(arguments[0].value);
      path.replaceWithMultiple(evalNode);
    }

这里 把 template.statement 改成 template.statements 即可,注意后面的replaceWith也要跟着改变为 replaceWithMultiple。

这就完美的解决了实参为字面量的eval函数还原。完整源代码,星友们可以看这里:

https://t.zsxq.com/6u3ByFq

感谢阅读,欢迎关注本人微信公众号,学习更多AST相关知识。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值