飞道的博客

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

448人阅读  评论(0)

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

放眼望去,尽是两个正(负)数的异或,明明可以直接得出结果,为啥要弄成这种形式呢?这么做也许是为了吓退新手们吧。如果你会操作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 这样的节点

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

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

    path.replaceWith(node);
    

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


   
  1. const NumericToBinary = {
  2. NumericLiteral(path)
  3. {
  4. let value = path.node.value;
  5. let left = 0- Math.floor( Math.random() * 10000000 + 10000000);
  6. let right = value ^ left;
  7. let node = types. BinaryExpression( "^",types.valueToNode( left),types.valueToNode( right));
  8. path.replaceWith(node);
  9. },
  10. }

运行后发现内存溢出了:

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

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

path.stop()

插件源代码

所以再次修改后的代码:


   
  1. const types = require( "@babel/types");
  2. const NumericToBinary = {
  3. NumericLiteral(path)
  4. {
  5. let value = path.node.value;
  6. let left = 0- Math.floor( Math.random() * 10000000 + 10000000);
  7. let right = value ^ left;
  8. let node = types. BinaryExpression( "^",types.valueToNode( left),types.valueToNode( right));
  9. path.replaceWith(node);
  10. path.stop();
  11. },
  12. }

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

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

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


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

本文完。

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


转载:https://blog.csdn.net/qq523176585/article/details/112792764
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场