UNPKG

@banana020/ast-plugin-system

Version:

AST插件系统 - 支持JavaScript/TypeScript代码转换,包含十六进制转换、代码清理等功能

1,067 lines (1,066 loc) 34.4 kB
import { p as parseCode, g as generateCode } from "./index-Cq5607iS.js"; import traverseModule from "@babel/traverse"; import { d as delExtra } from "./del-extra-DOJZIMAt.js"; import { d as removeVarComma, f as formatMember, i as renameVar, t as transCondition, c as conditionToIf, a as andToIf, b as conditionVarToIf, r as removeComma, e as clearBinaryIfDeadCode, g as calcBinary, h as addCatchLog } from "./rename-var-BF8V_HJx.js"; import t from "@babel/types"; import generatorModule from "@babel/generator"; function isUnusedFunction(path, functionName) { const binding = path.scope.getBinding(functionName); if (!binding) { return false; } if (binding.constantViolations.length > 0) { return false; } return binding.referencePaths.length === 0; } const clearNotUseFunction = (path) => { if (!t.isFunctionDeclaration(path.node)) { return; } const functionNode = path.node; if (!functionNode.id || !functionNode.id.name) { return; } const functionName = functionNode.id.name; if (isUnusedFunction(path, functionName)) { console.log(`🗑️ 移除未使用的函数: ${functionName}`); path.remove(); } }; const clearNotUseVar = (path) => { if (!t.isVariableDeclaration(path.node)) { return; } if (!path.getFunctionParent()) { return; } const variableDeclaration = path.node; const usedDeclarations = []; for (const declarator of variableDeclaration.declarations) { if (t.isIdentifier(declarator.id)) { const variableName = declarator.id.name; if (isVariableUsed(path, variableName)) { usedDeclarations.push(declarator); } } else { usedDeclarations.push(declarator); } } if (usedDeclarations.length > 0) { variableDeclaration.declarations = usedDeclarations; } else { path.remove(); } }; function isVariableUsed(path, variableName) { const binding = path.scope.getBinding(variableName); if (!binding) { return true; } if (binding.constantViolations.length > 0) { return true; } return binding.referencePaths.length > 0; } const traverse$4 = traverseModule.default || traverseModule; const generator$1 = generatorModule.default || generatorModule; function executeInSandbox$1(code, targetVarName) { try { const func = new Function(` ${code} return typeof ${targetVarName} !== 'undefined' ? ${targetVarName} : null; `); const result = func(); return { success: true, result }; } catch (error) { console.error("代码执行错误:", error); return { success: false, error }; } } const getDecodeFn$1 = (ast) => { let decodeFnName = null; const initNodes = []; traverse$4(ast, { FunctionDeclaration(path) { const { id, params, body } = path.node; if (id && params.length === 0 && body.body.length === 0) { decodeFnName = id.name; console.log(`找到载体函数: ${decodeFnName}`); path.stop(); } } }); if (!decodeFnName) { throw new Error("未能动态找到载体函数!"); } traverse$4(ast, { AssignmentExpression(path) { const { left } = path.node; if (t.isMemberExpression(left) && t.isIdentifier(left.object, { name: decodeFnName })) { initNodes.push(path.parentPath.node); } } }); console.log(`找到 ${initNodes.length} 个相关的初始化/代理节点`); let decodeFnObject = null; try { let initScript = `function ${decodeFnName}() {} `; initScript += initNodes.map((node) => generator$1(node).code).join("\n"); const executionResult = executeInSandbox$1(initScript, decodeFnName); if (!executionResult.success) { throw executionResult.error; } decodeFnObject = executionResult.result; console.log("沙箱执行成功, 载体对象已初始化。"); } catch (e) { console.error("沙箱执行失败:", e); throw new Error(`沙箱执行失败: ${e}`); } if (!decodeFnObject) { throw new Error("沙箱执行失败, 载体对象未初始化。"); } return { decodeFnName, decodeFnObject }; }; const removeAndReplace$1 = (path, options) => { if (!(options == null ? void 0 : options.decodeFnName) || !(options == null ? void 0 : options.decodeFnObject)) { return; } const { decodeFnName, decodeFnObject } = options; if (!t.isFunction(path.node)) { return; } const aliasMap = /* @__PURE__ */ new Map(); const functionName = getFunctionName$1(path.node); try { buildAliasMapping$1(path, decodeFnName, aliasMap); removeShiftStatements$1(path, aliasMap); replaceDecryptedCalls$1(path, aliasMap, decodeFnObject); } catch (error) { console.warn(`处理函数 "${functionName}" 时发生错误:`, error); } }; function getFunctionName$1(node) { if (t.isFunctionDeclaration(node) && node.id) { return node.id.name; } if (t.isFunctionExpression(node) && node.id) { return node.id.name; } return "anonymous"; } function buildAliasMapping$1(functionPath, decodeFnName, aliasMap) { if (!t.isFunction(functionPath.node) || !functionPath.node.body) { return; } const bodyPath = functionPath.get("body"); if (!bodyPath || Array.isArray(bodyPath)) { return; } bodyPath.traverse({ VariableDeclarator(declPath) { if (!t.isIdentifier(declPath.node.id) || !declPath.node.init) { return; } const varName = declPath.node.id.name; const init = declPath.get("init"); if (!init || Array.isArray(init)) { return; } if (handleDirectAssignment$1(init, decodeFnName, varName, aliasMap, declPath)) { return; } if (handleAliasTransfer$1(init, varName, aliasMap)) { declPath.remove(); return; } if (handleConcatPattern$1(init, varName, aliasMap, declPath)) { return; } if (handleArrayAccess$1(init, varName, aliasMap, declPath)) { return; } } }); } function handleDirectAssignment$1(init, decodeFnName, varName, aliasMap, declPath) { if (!init.isMemberExpression()) { return false; } const objectPath = init.get("object"); if (!objectPath.isIdentifier({ name: decodeFnName })) { return false; } const targetName = generatorModule(init.node).code; const parts = targetName.split("."); if (parts.length === 2) { aliasMap.set(varName, { targetName, propertyName: parts[1] }); declPath.remove(); return true; } return false; } function handleAliasTransfer$1(init, varName, aliasMap) { if (!init.isIdentifier()) { return false; } const sourceAlias = aliasMap.get(init.node.name); if (sourceAlias) { aliasMap.set(varName, sourceAlias); return true; } return false; } function handleConcatPattern$1(init, varName, aliasMap, declPath) { if (!init.isCallExpression()) { return false; } const callee = init.get("callee"); if (!callee.isMemberExpression()) { return false; } const property = callee.get("property"); if (!property.isIdentifier({ name: "concat" })) { return false; } const args = init.get("arguments"); if (args.length !== 1 || !args[0].isIdentifier()) { return false; } const aliasSource = args[0].node.name; const sourceAlias = aliasMap.get(aliasSource); if (sourceAlias) { const arrayKey = `${varName}[1]`; aliasMap.set(arrayKey, sourceAlias); declPath.remove(); return true; } return false; } function handleArrayAccess$1(init, varName, aliasMap, declPath) { if (!init.isMemberExpression()) { return false; } const objectPath = init.get("object"); const propertyPath = init.get("property"); if (!objectPath.isIdentifier() || !propertyPath.isNumericLiteral()) { return false; } const arrayName = objectPath.node.name; const index = propertyPath.node.value; const arrayKey = `${arrayName}[${index}]`; const sourceAlias = aliasMap.get(arrayKey); if (sourceAlias) { aliasMap.set(varName, sourceAlias); declPath.remove(); return true; } return false; } function removeShiftStatements$1(functionPath, aliasMap) { if (!t.isFunction(functionPath.node) || !functionPath.node.body) { return; } const bodyPath = functionPath.get("body"); if (!bodyPath || Array.isArray(bodyPath)) { return; } const statementsToRemove = []; bodyPath.traverse({ ExpressionStatement(stmtPath) { const expression = stmtPath.get("expression"); if (!expression.isCallExpression()) { return; } const callee = expression.get("callee"); if (!callee.isMemberExpression()) { return; } const calleeObject = callee.get("object"); const calleeProperty = callee.get("property"); if (!calleeObject.isIdentifier() || !calleeProperty.isIdentifier({ name: "shift" })) { return; } const calleeName = calleeObject.node.name; const arrayKey = `${calleeName}[1]`; if (aliasMap.has(calleeName) || aliasMap.has(arrayKey)) { statementsToRemove.push(stmtPath); } } }); for (const stmt of statementsToRemove) { stmt.remove(); } } function replaceDecryptedCalls$1(functionPath, aliasMap, decodeFnObject) { if (!t.isFunction(functionPath.node) || !functionPath.node.body) { return; } const bodyPath = functionPath.get("body"); if (!bodyPath || Array.isArray(bodyPath)) { return; } bodyPath.traverse({ CallExpression(callPath) { const callee = callPath.get("callee"); if (!callee.isIdentifier()) { return; } const calleeName = callee.node.name; const aliasInfo = aliasMap.get(calleeName); if (!(aliasInfo == null ? void 0 : aliasInfo.propertyName)) { return; } const args = callPath.get("arguments"); if (args.length !== 1 || !args[0].isNumericLiteral()) { return; } const argValue = args[0].node.value; try { const decodeFn = decodeFnObject[aliasInfo.propertyName]; if (typeof decodeFn === "function") { const realValue = decodeFn(argValue); if (typeof realValue === "string") { callPath.replaceWith(t.stringLiteral(realValue)); } } } catch (error) { console.warn(`解密调用 ${calleeName}(${argValue}) 失败:`, error); } } }); } const removeFor$1 = (path, options) => { if (!options) { return; } const { decodeFnObject, decodeFnName } = options; if (!t.isForStatement(path.node)) { return; } const forStatement = path.node; const prevSiblingPath = path.getPrevSibling(); const variableDeclaration = validateAndGetVariableDeclaration$1(prevSiblingPath, decodeFnName, decodeFnObject); if (!variableDeclaration) { return; } const forStatementInfo = validateForStatement$1(forStatement); if (!forStatementInfo) { return; } const { switchStatement, forTest } = forStatementInfo; const initialValue = calculateMemberExpressionValue$1(variableDeclaration.init, decodeFnName, decodeFnObject); const breakValue = calculateMemberExpressionValue$1(forTest.right, decodeFnName, decodeFnObject); if (initialValue === null || breakValue === null) { return; } const resultBody = processSwitchCases$1( switchStatement.cases, initialValue, breakValue, decodeFnName, decodeFnObject ); path.replaceWithMultiple(resultBody); prevSiblingPath.remove(); }; function validateAndGetVariableDeclaration$1(prevSiblingPath, decodeFnName, decodeFnObject) { if (!Array.isArray(prevSiblingPath.container)) { return null; } const firstStatement = prevSiblingPath.container[0]; if (!t.isVariableDeclaration(firstStatement)) { return null; } const declaration = firstStatement.declarations[0]; if (!declaration || !declaration.init) { return null; } if (!isValidDecodeMemberExpression$1(declaration.init)) { return null; } const memberExpr = declaration.init; const callExpr = memberExpr.object.object; const callee = callExpr.callee; if (!t.isIdentifier(callee.object) || callee.object.name !== decodeFnName) { return null; } if (!t.isIdentifier(callee.property) || !decodeFnObject[callee.property.name]) { return null; } const originDecodeFn = decodeFnObject[callee.property.name]; const decodeFn = (first, second) => originDecodeFn()[first][second]; return { init: declaration.init, decodeFn }; } function validateForStatement$1(forStatement) { if (!t.isBlockStatement(forStatement.body)) { return null; } const body = forStatement.body.body; if (body.length === 0 || !t.isSwitchStatement(body[0])) { return null; } const switchStatement = body[0]; if (!t.isIdentifier(switchStatement.discriminant)) { return null; } if (!t.isBinaryExpression(forStatement.test)) { return null; } const forTest = forStatement.test; if (!isValidDecodeMemberExpression$1(forTest.right)) { return null; } return { switchStatement, forTest }; } function calculateMemberExpressionValue$1(node, decodeFnName, decodeFnObject) { if (!isValidDecodeMemberExpression$1(node)) { return null; } try { const memberExpr = node; const firstIndex = memberExpr.object.property.value; const secondIndex = memberExpr.property.value; const callExpr = memberExpr.object.object; const callee = callExpr.callee; if (!t.isIdentifier(callee.object) || callee.object.name !== decodeFnName) { return null; } if (!t.isIdentifier(callee.property) || !decodeFnObject[callee.property.name]) { return null; } const originDecodeFn = decodeFnObject[callee.property.name]; const decodeFn = (first, second) => originDecodeFn()[first][second]; return decodeFn(firstIndex, secondIndex); } catch { return null; } } function processSwitchCases$1(cases, initialValue, breakValue, decodeFnName, decodeFnObject) { const resultBody = []; let currentValue = initialValue; while (currentValue !== breakValue) { let foundCase = false; for (const switchCase of cases) { if (!switchCase.test || !t.isMemberExpression(switchCase.test)) { continue; } const caseValue = calculateMemberExpressionValue$1(switchCase.test, decodeFnName, decodeFnObject); if (caseValue === currentValue) { foundCase = true; const caseBody = [...switchCase.consequent]; if (caseBody.length > 0 && t.isBreakStatement(caseBody[caseBody.length - 1])) { caseBody.pop(); } const nextValue = processStateUpdate$1(caseBody, decodeFnName, decodeFnObject); if (nextValue !== null) { currentValue = nextValue; } else { resultBody.push(...caseBody); return resultBody; } resultBody.push(...caseBody); break; } } if (!foundCase) { break; } } return resultBody; } function processStateUpdate$1(caseBody, decodeFnName, decodeFnObject) { if (caseBody.length < 1) { return null; } const lastStatement = caseBody[caseBody.length - 1]; if (t.isExpressionStatement(lastStatement)) { const expr = lastStatement.expression; if (t.isAssignmentExpression(expr) && isValidDecodeMemberExpression$1(expr.right)) { caseBody.pop(); return calculateMemberExpressionValue$1(expr.right, decodeFnName, decodeFnObject); } } return null; } function isValidDecodeMemberExpression$1(node) { if (!t.isMemberExpression(node)) return false; if (!t.isMemberExpression(node.object)) return false; if (!t.isCallExpression(node.object.object)) return false; if (!t.isMemberExpression(node.object.object.callee)) return false; if (!t.isNumericLiteral(node.object.property)) return false; if (!t.isNumericLiteral(node.property)) return false; return true; } const traverse$3 = traverseModule.default || traverseModule; function geetest3Defusion(jscode) { let ast = parseCode(jscode); const code = multiProcessDefusion(jscode, { clearNotUse: true }); ast = parseCode(code); traverse$3(ast, { VariableDeclarator: removeVarComma }); const { decodeFnName, decodeFnObject } = getDecodeFn$1(ast); traverse$3(ast, { Function: (path) => removeAndReplace$1(path, { decodeFnName, decodeFnObject }) }); traverse$3(ast, { ForStatement: (path) => removeFor$1(path, { decodeFnObject, decodeFnName }) }); traverse$3(ast, { MemberExpression: formatMember }); return generateCode(ast); } function getTsfq(jscode) { const code = geetest3Defusion(jscode); let ast = parseCode(code); let tsfq = ""; traverse$3(ast, { StringLiteral(path) { if (path.node.value.includes("tsfq")) { tsfq = path.node.value.split('"tsfq":')[1].split('"')[1]; } } }); if (!tsfq) throw new Error("tsfq not found"); return tsfq; } const traverse$2 = traverseModule.default || traverseModule; const generator = generatorModule.default || generatorModule; function executeInSandbox(code, targetVarName) { try { const func = new Function(` ${code} return typeof ${targetVarName} !== 'undefined' ? ${targetVarName} : null; `); const result = func(); return { success: true, result }; } catch (error) { console.error("代码执行错误:", error); return { success: false, error }; } } const getDecodeFn = (ast) => { let decodeFnName = null; const initNodes = []; traverse$2(ast, { FunctionDeclaration(path) { const { id, params, body } = path.node; if (id && params.length === 0 && body.body.length === 0) { decodeFnName = id.name; console.log(`找到载体函数: ${decodeFnName}`); path.stop(); } } }); if (!decodeFnName) { throw new Error("未能动态找到载体函数!"); } traverse$2(ast, { AssignmentExpression(path) { const { left } = path.node; if (t.isMemberExpression(left) && t.isIdentifier(left.object, { name: decodeFnName })) { initNodes.push(path.parentPath.node); } } }); console.log(`找到 ${initNodes.length} 个相关的初始化/代理节点`); let decodeFnObject = null; try { let initScript = `function ${decodeFnName}() {} `; initScript += initNodes.map((node) => generator(node).code).join("\n"); const executionResult = executeInSandbox(initScript, decodeFnName); if (!executionResult.success) { throw executionResult.error; } decodeFnObject = executionResult.result; console.log("沙箱执行成功, 载体对象已初始化。"); } catch (e) { console.error("沙箱执行失败:", e); throw new Error(`沙箱执行失败: ${e}`); } if (!decodeFnObject) { throw new Error("沙箱执行失败, 载体对象未初始化。"); } return { decodeFnName, decodeFnObject }; }; const removeAndReplace = (path, options) => { if (!(options == null ? void 0 : options.decodeFnName) || !(options == null ? void 0 : options.decodeFnObject)) { return; } const { decodeFnName, decodeFnObject } = options; if (!t.isFunction(path.node)) { return; } const aliasMap = /* @__PURE__ */ new Map(); const functionName = getFunctionName(path.node); try { buildAliasMapping(path, decodeFnName, aliasMap); removeShiftStatements(path, aliasMap); replaceDecryptedCalls(path, aliasMap, decodeFnObject); } catch (error) { console.warn(`处理函数 "${functionName}" 时发生错误:`, error); } }; function getFunctionName(node) { if (t.isFunctionDeclaration(node) && node.id) { return node.id.name; } if (t.isFunctionExpression(node) && node.id) { return node.id.name; } return "anonymous"; } function buildAliasMapping(functionPath, decodeFnName, aliasMap) { if (!t.isFunction(functionPath.node) || !functionPath.node.body) { return; } const bodyPath = functionPath.get("body"); if (!bodyPath || Array.isArray(bodyPath)) { return; } bodyPath.traverse({ VariableDeclarator(declPath) { if (!t.isIdentifier(declPath.node.id) || !declPath.node.init) { return; } const varName = declPath.node.id.name; const init = declPath.get("init"); if (!init || Array.isArray(init)) { return; } if (handleDirectAssignment(init, decodeFnName, varName, aliasMap, declPath)) { return; } if (handleAliasTransfer(init, varName, aliasMap)) { declPath.remove(); return; } if (handleConcatPattern(init, varName, aliasMap, declPath)) { return; } if (handleArrayAccess(init, varName, aliasMap, declPath)) { return; } } }); } function handleDirectAssignment(init, decodeFnName, varName, aliasMap, declPath) { if (!init.isMemberExpression()) { return false; } const objectPath = init.get("object"); if (!objectPath.isIdentifier({ name: decodeFnName })) { return false; } const targetName = generatorModule(init.node).code; const parts = targetName.split("."); if (parts.length === 2) { aliasMap.set(varName, { targetName, propertyName: parts[1] }); declPath.remove(); return true; } return false; } function handleAliasTransfer(init, varName, aliasMap) { if (!init.isIdentifier()) { return false; } const sourceAlias = aliasMap.get(init.node.name); if (sourceAlias) { aliasMap.set(varName, sourceAlias); return true; } return false; } function handleConcatPattern(init, varName, aliasMap, declPath) { if (!init.isCallExpression()) { return false; } const callee = init.get("callee"); if (!callee.isMemberExpression()) { return false; } const property = callee.get("property"); if (!property.isIdentifier({ name: "concat" })) { return false; } const args = init.get("arguments"); if (args.length !== 1 || !args[0].isIdentifier()) { return false; } const aliasSource = args[0].node.name; const sourceAlias = aliasMap.get(aliasSource); if (sourceAlias) { const arrayKey = `${varName}[1]`; aliasMap.set(arrayKey, sourceAlias); declPath.remove(); return true; } return false; } function handleArrayAccess(init, varName, aliasMap, declPath) { if (!init.isMemberExpression()) { return false; } const objectPath = init.get("object"); const propertyPath = init.get("property"); if (!objectPath.isIdentifier() || !propertyPath.isNumericLiteral()) { return false; } const arrayName = objectPath.node.name; const index = propertyPath.node.value; const arrayKey = `${arrayName}[${index}]`; const sourceAlias = aliasMap.get(arrayKey); if (sourceAlias) { aliasMap.set(varName, sourceAlias); declPath.remove(); return true; } return false; } function removeShiftStatements(functionPath, aliasMap) { if (!t.isFunction(functionPath.node) || !functionPath.node.body) { return; } const bodyPath = functionPath.get("body"); if (!bodyPath || Array.isArray(bodyPath)) { return; } const statementsToRemove = []; bodyPath.traverse({ ExpressionStatement(stmtPath) { const expression = stmtPath.get("expression"); if (!expression.isCallExpression()) { return; } const callee = expression.get("callee"); if (!callee.isMemberExpression()) { return; } const calleeObject = callee.get("object"); const calleeProperty = callee.get("property"); if (!calleeObject.isIdentifier() || !calleeProperty.isIdentifier({ name: "shift" })) { return; } const calleeName = calleeObject.node.name; const arrayKey = `${calleeName}[1]`; if (aliasMap.has(calleeName) || aliasMap.has(arrayKey)) { statementsToRemove.push(stmtPath); } } }); for (const stmt of statementsToRemove) { stmt.remove(); } } function replaceDecryptedCalls(functionPath, aliasMap, decodeFnObject) { if (!t.isFunction(functionPath.node) || !functionPath.node.body) { return; } const bodyPath = functionPath.get("body"); if (!bodyPath || Array.isArray(bodyPath)) { return; } bodyPath.traverse({ CallExpression(callPath) { const callee = callPath.get("callee"); if (!callee.isIdentifier()) { return; } const calleeName = callee.node.name; const aliasInfo = aliasMap.get(calleeName); if (!(aliasInfo == null ? void 0 : aliasInfo.propertyName)) { return; } const args = callPath.get("arguments"); if (args.length !== 1 || !args[0].isNumericLiteral()) { return; } const argValue = args[0].node.value; try { const decodeFn = decodeFnObject[aliasInfo.propertyName]; if (typeof decodeFn === "function") { const realValue = decodeFn(argValue); if (typeof realValue === "string") { callPath.replaceWith(t.stringLiteral(realValue)); } } } catch (error) { console.warn(`解密调用 ${calleeName}(${argValue}) 失败:`, error); } } }); } const removeFor = (path, options) => { if (!options) { return; } const { decodeFnObject, decodeFnName } = options; if (!t.isForStatement(path.node)) { return; } const forStatement = path.node; const prevSiblingPath = path.getPrevSibling(); const variableDeclaration = validateAndGetVariableDeclaration(prevSiblingPath, decodeFnName, decodeFnObject); if (!variableDeclaration) { return; } const forStatementInfo = validateForStatement(forStatement); if (!forStatementInfo) { return; } const { switchStatement, forTest } = forStatementInfo; const initialValue = calculateMemberExpressionValue(variableDeclaration.init, decodeFnName, decodeFnObject); const breakValue = calculateMemberExpressionValue(forTest.right, decodeFnName, decodeFnObject); if (initialValue === null || breakValue === null) { return; } const resultBody = processSwitchCases( switchStatement.cases, initialValue, breakValue, decodeFnName, decodeFnObject ); path.replaceWithMultiple(resultBody); prevSiblingPath.remove(); }; function validateAndGetVariableDeclaration(prevSiblingPath, decodeFnName, decodeFnObject) { if (!Array.isArray(prevSiblingPath.container)) { return null; } const firstStatement = prevSiblingPath.container[0]; if (!t.isVariableDeclaration(firstStatement)) { return null; } const declaration = firstStatement.declarations[0]; if (!declaration || !declaration.init) { return null; } if (!isValidDecodeMemberExpression(declaration.init)) { return null; } const memberExpr = declaration.init; const callExpr = memberExpr.object.object; const callee = callExpr.callee; if (!t.isIdentifier(callee.object) || callee.object.name !== decodeFnName) { return null; } if (!t.isIdentifier(callee.property) || !decodeFnObject[callee.property.name]) { return null; } const originDecodeFn = decodeFnObject[callee.property.name]; const decodeFn = (first, second) => originDecodeFn()[first][second]; return { init: declaration.init, decodeFn }; } function validateForStatement(forStatement) { if (!t.isBlockStatement(forStatement.body)) { return null; } const body = forStatement.body.body; if (body.length === 0 || !t.isSwitchStatement(body[0])) { return null; } const switchStatement = body[0]; if (!t.isIdentifier(switchStatement.discriminant)) { return null; } if (!t.isBinaryExpression(forStatement.test)) { return null; } const forTest = forStatement.test; if (!isValidDecodeMemberExpression(forTest.right)) { return null; } return { switchStatement, forTest }; } function calculateMemberExpressionValue(node, decodeFnName, decodeFnObject) { if (!isValidDecodeMemberExpression(node)) { return null; } try { const memberExpr = node; const firstIndex = memberExpr.object.property.value; const secondIndex = memberExpr.property.value; const callExpr = memberExpr.object.object; const callee = callExpr.callee; if (!t.isIdentifier(callee.object) || callee.object.name !== decodeFnName) { return null; } if (!t.isIdentifier(callee.property) || !decodeFnObject[callee.property.name]) { return null; } const originDecodeFn = decodeFnObject[callee.property.name]; const decodeFn = (first, second) => originDecodeFn()[first][second]; return decodeFn(firstIndex, secondIndex); } catch { return null; } } function processSwitchCases(cases, initialValue, breakValue, decodeFnName, decodeFnObject) { const resultBody = []; let currentValue = initialValue; while (currentValue !== breakValue) { let foundCase = false; for (const switchCase of cases) { if (!switchCase.test || !t.isMemberExpression(switchCase.test)) { continue; } const caseValue = calculateMemberExpressionValue(switchCase.test, decodeFnName, decodeFnObject); if (caseValue === currentValue) { foundCase = true; const caseBody = [...switchCase.consequent]; if (caseBody.length > 0 && t.isBreakStatement(caseBody[caseBody.length - 1])) { caseBody.pop(); } const nextValue = processStateUpdate(caseBody, decodeFnName, decodeFnObject); if (nextValue !== null) { currentValue = nextValue; } else { resultBody.push(...caseBody); return resultBody; } resultBody.push(...caseBody); break; } } if (!foundCase) { break; } } return resultBody; } function processStateUpdate(caseBody, decodeFnName, decodeFnObject) { if (caseBody.length < 1) { return null; } const lastStatement = caseBody[caseBody.length - 1]; if (t.isExpressionStatement(lastStatement)) { const expr = lastStatement.expression; if (t.isAssignmentExpression(expr) && isValidDecodeMemberExpression(expr.right)) { caseBody.pop(); return calculateMemberExpressionValue(expr.right, decodeFnName, decodeFnObject); } } return null; } function isValidDecodeMemberExpression(node) { if (!t.isMemberExpression(node)) return false; if (!t.isMemberExpression(node.object)) return false; if (!t.isCallExpression(node.object.object)) return false; if (!t.isMemberExpression(node.object.object.callee)) return false; if (!t.isNumericLiteral(node.object.property)) return false; if (!t.isNumericLiteral(node.property)) return false; return true; } const traverse$1 = traverseModule.default || traverseModule; function geetest4Defusion(jscode) { let ast = parseCode(jscode); const code = multiProcessDefusion(jscode, { clearNotUse: true }); ast = parseCode(code); traverse$1(ast, { VariableDeclarator: removeVarComma }); traverse$1(ast, { Scope: renameVar }); const { decodeFnName, decodeFnObject } = getDecodeFn(ast); traverse$1(ast, { Function: (path) => removeAndReplace(path, { decodeFnName, decodeFnObject }) }); traverse$1(ast, { ForStatement: (path) => removeFor(path, { decodeFnObject, decodeFnName }) }); traverse$1(ast, { MemberExpression: formatMember }); return generateCode(ast); } function getLibAndAbo(jscode) { const code = geetest4Defusion(jscode); let ast = parseCode(code); let lib = null; let _abo = null; traverse$1(ast, { AssignmentExpression(path) { const node = path.node; if (!t.isMemberExpression(node.left)) return; if (!t.isIdentifier(node.left.property)) return; if (node.left.property.name !== "_lib") return; if (!t.isObjectExpression(node.right)) return; if (node.right.properties.length !== 1) { console.log("lib 有不止一个key value值"); return; } if (!t.isObjectProperty(node.right.properties[0])) return; const property = node.right.properties[0]; if (!t.isIdentifier(property.key)) return; if (!t.isStringLiteral(property.value)) return; lib = { [property.key.name]: property.value.value }; } }); traverse$1(ast, { AssignmentExpression(path) { const node = path.node; if (!t.isMemberExpression(node.left)) return; if (!t.isIdentifier(node.left.property)) return; if (node.left.property.name !== "_abo") return; if (!t.isObjectExpression(node.right)) return; if (node.right.properties.length !== 1) { console.log("_abo 有不止一个key value值"); return; } if (!t.isObjectProperty(node.right.properties[0])) return; const property = node.right.properties[0]; if (!t.isStringLiteral(property.key)) return; if (!t.isStringLiteral(property.value)) return; _abo = { [property.key.value]: property.value.value }; } }); return { lib, _abo }; } const traverse = traverseModule.default || traverseModule; function multiProcessDefusion(jscode, config = {}) { let ast = parseCode(jscode); traverse(ast, { StringLiteral: delExtra }); traverse(ast, { NumericLiteral: delExtra }); traverse(ast, { ConditionalExpression: transCondition }); traverse(ast, { ExpressionStatement: conditionToIf }); traverse(ast, { ExpressionStatement: andToIf }); traverse(ast, { VariableDeclaration: conditionVarToIf }); traverse(ast, { ExpressionStatement: removeComma }); traverse(ast, { VariableDeclaration: removeVarComma }); traverse(ast, { MemberExpression: formatMember }); traverse(ast, { IfStatement: clearBinaryIfDeadCode }); traverse(ast, { BinaryExpression: { exit: calcBinary } }); traverse(ast, { CatchClause: addCatchLog }); if (config.clearNotUse) { ast = parseCode(generateCode(ast)); traverse(ast, { FunctionDeclaration: clearNotUseFunction }); traverse(ast, { VariableDeclaration: clearNotUseVar }); traverse(ast, { StringLiteral: delExtra }); traverse(ast, { NumericLiteral: delExtra }); } return generateCode(ast); } const transformFunctions = { multiProcessDefusion, geetest3Defusion, geetest4Defusion }; const defusion = { /** 多阶段解混淆函数 - 通用解混淆处理 */ multiProcess: multiProcessDefusion, /** 极验3专用解混淆函数 */ geetest3: geetest3Defusion, getTsfq, /** 极验4专用解混淆函数 */ geetest4: geetest4Defusion, /** 极验4专用获取 lib 和 _abo 的函数, 用户创建临时参数 */ getLibAndAbo }; export { defusion, geetest3Defusion, geetest4Defusion, getLibAndAbo, getTsfq, multiProcessDefusion, transformFunctions };