JavaScript反混淆插件八:还原简单的CallExpression 类型

今天来学习下怎么将简单的CallExpression 类型进行处理。

昨天写了这篇文章 JavaScript 代码混淆实战(二):将 BinaryExpression 类型转换为 CallExpression 类型,今天来看看它的逆过程。

如何将下面的代码:


   
  1. var Xor = function (p,q)
  2. {
  3. return p ^ q;
  4. }
  5. let a = Xor(111,222);

转变成下面的:


   
  1. var Xor = function (p,q)
  2. {
  3. return p ^ q;
  4. }
  5. let a = 111 ^ 222;

01

分析及思路

分析:上面的转变其实就是将  Xor(111,222) 变成 111 ^ 222

  1. Xor 函数以 var 的方式定义,因此这里最好遍历 VariableDeclarator 类型,可以同时获取函数名和函数体。

  2. 这个函数体很简单,只有一个 return 语句。

  3. 功能只是对两个参数进行异或运算。

思路:

  1. 遍历 VariableDeclarator 路径,对参数、函数体之间的关系进行判断。

  2. 遍历 函数 所在的作用域,函数名相同替换即可。

02


实战

一.插件编写,遍历 VariableDeclarator, 判断其 init 节点:


二.功能编写:


   
  1. function call2express(path)
  2. {
  3. }
  1. 函数名获取:

    
         
    1. const {init,id} = path.node;
    2. const name = id.name;
  2. 获取参数,并判断长度:

    
         
    1. const params = init.params;
    2. if (params.length !== 2return;
    3. let first_arg  = params[0].name;
    4. let second_arg = params[1].name; 
  3. 判断函数体长度是否为1:

    
         
    1. const body = init.body;
    2. if (!body.body || body.body.length !== 1return;
  4. 判断 ReturnStatement 及其 参数类型

    
         
    1. const t  = require("@babel/types");
    2. let return_body = body.body[0];
    3. let argument = return_body.argument;
    4. if (!t.isReturnStatement(return_body) ||
    5.     !t.isBinaryExpression(argument))
    6. {
    7.      return;
    8. }
  5. 判断函数的参数与 return语句的参数是否一致:

    
         
    1. let {left,right,operator} = argument;
    2. if (!t.isIdentifier(left, {name:first_arg}) ||
    3.     !t.isIdentifier(right,{name:second_arg}))
    4.    {
    5. return;
    6.    }
  6. 函数声明所在的作用域:

    let scope = path.scope;
    
        
  7. 遍历作用域块节点,找出所有 CallExpression 判断成功后替换:

    
         
    1. traverse(scope.block,{
    2. CallExpression:function(_path) {
    3. let _node = _path.node;
    4.         let args = _path.node.arguments;
    5.         if (args.length === 2 && t.isIdentifier(_node.callee,{name:name}))
    6. {
    7.             _path.replaceWith(t.BinaryExpression(operator, args[0], args[1]))
    8. }
    9. },
    10. })

完整代码:


本文旨在告诉小白如何去编写简单的插件,在分析的过程中可以对照在线解析网站,总之,熟能生巧吧。

文章来源: blog.csdn.net,作者:悦来客栈的老板,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq523176585/article/details/111771998

(完)