UNPKG

js-confuser

Version:

JavaScript Obfuscation Tool.

100 lines (81 loc) 3.05 kB
import { PluginArg, PluginObject } from "./plugin"; import * as t from "@babel/types"; import { Order } from "../order"; import { ok } from "assert"; import { NameGen } from "../utils/NameGen"; import { prependProgram } from "../utils/ast-utils"; export default ({ Plugin }: PluginArg): PluginObject => { const me = Plugin(Order.Calculator, { changeData: { expressions: 0, }, }); const nameGen = new NameGen(me.options.identifierGenerator); return { visitor: { Program: { exit(programPath) { const allowedBinaryOperators = new Set(["+", "-", "*", "/"]); var operatorsMap = new Map<string, string>(); var calculatorFnName = me.getPlaceholder() + "_calc"; programPath.traverse({ BinaryExpression: { exit(path) { const { operator } = path.node; if (t.isPrivate(path.node.left)) return; // TODO: Improve precedence handling or remove this transformation entirely if (!t.isNumericLiteral(path.node.right)) return; if (!t.isNumericLiteral(path.node.left)) return; if (!allowedBinaryOperators.has(operator)) return; const mapKey = "binaryExpression_" + operator; let operatorKey = operatorsMap.get(mapKey); // Add binary operator to the map if it doesn't exist if (typeof operatorKey === "undefined") { operatorKey = nameGen.generate(); operatorsMap.set(mapKey, operatorKey); } ok(operatorKey); me.changeData.expressions++; path.replaceWith( t.callExpression(t.identifier(calculatorFnName), [ t.stringLiteral(operatorKey), path.node.left, path.node.right, ]) ); }, }, }); // No operators created if (operatorsMap.size < 1) { return; } // Create the calculator function and insert into program path var switchCases: t.SwitchCase[] = Array.from( operatorsMap.entries() ).map(([mapKey, key]) => { const [type, operator] = mapKey.split("_"); let expression = t.binaryExpression( operator as any, t.identifier("a"), t.identifier("b") ); return t.switchCase(t.stringLiteral(key), [ t.returnStatement(expression), ]); }); prependProgram( programPath, t.functionDeclaration( t.identifier(calculatorFnName), [t.identifier("operator"), t.identifier("a"), t.identifier("b")], t.blockStatement([ t.switchStatement(t.identifier("operator"), switchCases), ]) ) ); }, }, }, }; };