JavaScript 代码混淆实战(四):NumericLiteral拆分为BinaryExpression

下面是某滑块的关键加密代码的部分截图:

放眼望去,尽是两个正(负)数的异或,明明可以直接得出结果,为啥要弄成这种形式呢?这么做也许是为了吓退新手们吧。如果你会操作AST,这种代码分分钟就给还原了。所谓知己知彼,百战不殆,我们下面来简单看看这样的代码是怎么生成的。

随便取两个数(符号相同)进行异或,例如:

-16892453 ^ -16892095 = ?

得到结果:

-16892453 ^ -16892095 = 666

所以,上面截图里的代码不过是将一个 NumericLiteral 类型的节点(666) 拆分为 一个 BinaryExpression 类型的节点(-16892453 ^ -16892095)。

目的

处理前节点:

var a = 666,b = 777;


处理后节点:

var a = -12270231 ^ -12269581,b = -14267009 ^ -14266762;

思路

  1. 首先要明确的是遍历 NumericLiteral 这样的节点

    const  NumericToBinary = {
      NumericLiteral(path)
      {
       // somecodes  
      },
    }
    
  2. 需要生成一个BinaryExpression节点:

    let node = types.BinaryExpression("^",left,right);
    
  3. 节点替换:

    path.replaceWith(node);
    

基本上都是这套路,很快,就写出了代码:

const  NumericToBinary = {
  NumericLiteral(path)
  {
    let value = path.node.value;
    let left = 0-Math.floor(Math.random() * 10000000 + 10000000);
    let right = value ^ left;
    
    let node = types.BinaryExpression("^",types.valueToNode(left),types.valueToNode(right));
    path.replaceWith(node);
  },
}

运行后发现内存溢出了:

一般出现这样的情况是因为替换的节点(node)包含了正在遍历的类型(例如NumericLiteral),因此程序会一直递归遍历下去,直到内存溢出。

想要解决这样的问题也很简单,加一行代码即可:

path.stop()

插件源代码

所以再次修改后的代码:

const types     = require("@babel/types");
const  NumericToBinary = {
  NumericLiteral(path)
  {
    let value = path.node.value;
    let left = 0-Math.floor(Math.random() * 10000000 + 10000000);
    let right = value ^ left;
    
    let node = types.BinaryExpression("^",types.valueToNode(left),types.valueToNode(right));
    path.replaceWith(node);
    path.stop();
  },
}

运行后不再报内存溢出的错误,结果也正常了。

思考:如果不用 path.stop(),还有其他的方法没?

有点,我们给出一个退出条件即可。例如,遍历前的节点NumericLiteral,就是一个NumericLiteral类型的节点,没有前缀 "-",而替换后的NumericLiteral 节点,有了前缀"-"之后变成了 UnaryExpression 节点。因此,根据这个特征,可以写出退出代码:

const  NumericToBinary = {
  NumericLiteral(path)
  {//添加退出条件
    if (path.parentPath.isUnaryExpression({operator:"-"})) return;
    let value = path.node.value;
    let left = 0-Math.floor(Math.random() * 10000000 + 10000000);
    let right = value ^ left;
    
    let node = types.BinaryExpression("^",types.valueToNode(left),types.valueToNode(right));
    path.replaceWith(node);
  },
}

本文完。

欢迎关注本人微信公众号,学习交流更多AST相关的知识。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值