AST混淆与解混淆笔记:二项式转为花指令

本文主要是作者记笔记为主,温故而知新,记录混淆和解混淆的代码,后期可能会更新文章细节
以以下代码为例:

function test(a, b){
	const c = "123";
	a = a + 1 // a
	a = a + 2
	a = a * 1234
	a = a.toString()
	a = a.substring(0, 3)
	b = a + "00"
	return b;
}
test(2)
console.log(test(1))

首先导入库

const fs = require('fs');
const parser = require("@babel/parser");
const traverse = require("@babel/traverse").default;
const types = require("@babel/types");
const generator = require("@babel/generator").default;

const jscode = fs.readFileSync("./test2.js", {
    encoding: "utf-8"
});
let ast = parser.parse(jscode);

本次就是将一些二项式的计算提取出来,改成函数调用的形式来混淆代码过程,混淆代码如下:

// 混淆代码,将二项式转为花指令
const obexpfun ={
    BinaryExpression(path){
        if (types.isBinaryExpression(path.node)) {
            let operator = path.node.operator
            let result = path.node.left
            let right = path.node.right
            // 建立花指令
            let a = types.Identifier("a")
            let b = types.Identifier("b")
            let funcname = path.scope.generateUidIdentifier("func")
            let func = types.functionDeclaration(funcname, [a, b], types.blockStatement([types.returnStatement(types.binaryExpression(operator, a, b))]))
            // 将花指令插入到ast的最前面
            let block = path.findParent(p => p.isBlockStatement())
            // console.log(path.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.node)
            // block.node.body.unshift(func)
            // 找到该作用域最接近func定义的作用域,在其最前面插入花指令
            let funcscope = path.getFunctionParent()
            funcscope.node.body.body.unshift(func)

            // path.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.parentPath.node.body.unshift(func); //

            // 将二项式转为花指令
            path.replaceWith(types.callExpression(funcname, [result, right]))
        }
        //path.skip()
    }
}
traverse(ast, obexpfun)

混淆后代码如下:

function test(a, b) {
  function _func4(a, b) {
    return a + b;
  }
  function _func3(a, b) {
    return a * b;
  }
  function _func2(a, b) {
    return a + b;
  }
  function _func(a, b) {
    return a + b;
  }
  const c = "123";
  a = _func(a, 1); // a
  a = _func2(a, 2);
  a = _func3(a, 1234);
  a = a.toString();
  a = a.substring(0, 3);
  b = _func4(a, "00");
  return b;
}
test(2);
console.log(test(1));

还原混淆的代码如下:

// 获取所有混淆函数
let funarr = {}
let getfunarr = {
    FunctionDeclaration(path) {
        funname = path.node.id.name
        funarr[funname] = path.node
    }
}
traverse(ast, getfunarr)

// 混淆代码,将二项式转为花指令(解混淆)
let obexpfun = {
    CallExpression(path) {
        //花指令参数不足两个,不处理
        calleename = path.node.callee.name
        if (!(path.node.arguments.length == 2 && calleename && funarr[calleename])) {
            return
        }
        param1 = path.node.arguments[0]
        param2 = path.node.arguments[1]
        func = funarr[calleename]
        operator = func.body.body[0].argument.operator
        let binexpr = types.binaryExpression(operator, param1, param2)
        path.replaceWith(binexpr)

    }
}
traverse(ast, obexpfun)

// 遍历 AST,删除未被调用的函数
const calledFunctions = new Set();
traverse(ast, {
    CallExpression(path) {
        if (types.isIdentifier(path.node.callee)) {
            calledFunctions.add(path.node.callee.name);
        }
    },
});
traverse(ast, {
    FunctionDeclaration(path) {
        const functionName = path.node.id.name;
        if (!calledFunctions.has(functionName)) {
            path.remove();
            console.log(`Function ${functionName} is defined but not called.`);
        }
    },
});

你可能感兴趣的:(AST解混淆笔记,笔记,javascript,ast解混淆)