From f3e84b0a0c2df8a359c104d7cb7121fcaea3d13e Mon Sep 17 00:00:00 2001 From: echo094 <20028238+echo094@users.noreply.github.com> Date: Tue, 3 Sep 2024 00:00:01 +0800 Subject: [PATCH] AntiTooling --- src/main.js | 3 ++ src/plugin/jsconfuser.js | 78 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/plugin/jsconfuser.js diff --git a/src/main.js b/src/main.js index 0c85154..b7f0d1c 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,7 @@ const fs = require('fs') const PluginCommon = require('./plugin/common.js') const PluginJjencode = require('./plugin/jjencode.js') +const PluginJsconfuser = require('./plugin/jsconfuser.js') const PluginSojson = require('./plugin/sojson.js') const PluginSojsonV7 = require('./plugin/sojsonv7.js') const PluginObfuscator = require('./plugin/obfuscator.js') @@ -40,6 +41,8 @@ if (type === 'sojson') { code = PluginAwsc(sourceCode) } else if (type === 'jjencode') { code = PluginJjencode(sourceCode) +} else if (type === 'jsconfuser') { + code = PluginJsconfuser(sourceCode) } else { code = PluginCommon(sourceCode) } diff --git a/src/plugin/jsconfuser.js b/src/plugin/jsconfuser.js new file mode 100644 index 0000000..2fcdb3c --- /dev/null +++ b/src/plugin/jsconfuser.js @@ -0,0 +1,78 @@ +const { parse } = require('@babel/parser') +const generator = require('@babel/generator').default +const traverse = require('@babel/traverse').default +const t = require('@babel/types') +const ivm = require('isolated-vm') + +const isolate = new ivm.Isolate() +const globalContext = isolate.createContextSync() +function virtualGlobalEval(jsStr) { + return globalContext.evalSync(String(jsStr)) +} + +function deAntiToolingCheckFunc(path) { + if (path.node.params.length) { + return false + } + const body = path.node.body + if (!t.isBlockStatement(body)) { + return false + } + if (body.body.length) { + return false + } + return true +} + +function deAntiToolingExtract(path, func_name) { + let binding = path.scope.getBinding(func_name) + for (let ref of binding.referencePaths) { + if (!ref.parentPath.isCallExpression() || !ref.key === 'callee') { + continue + } + const call = ref.parentPath + if (!call.listKey === 'body') { + continue + } + for (let node of call.node.arguments) { + call.insertBefore(node) + } + call.remove() + } + binding.scope.crawl() + binding = path.scope.getBinding(func_name) + if (binding.references === 0) { + path.remove() + } +} + +const deAntiTooling = { + FunctionDeclaration(path) { + const func_name = path.node.id?.name + if (!func_name) { + return + } + if (!deAntiToolingCheckFunc(path)) { + return + } + console.log(`AntiTooling Func Name: ${func_name}`) + deAntiToolingExtract(path, func_name) + }, +} + +module.exports = function (code) { + let ast + try { + ast = parse(code, { errorRecovery: true }) + } catch (e) { + console.error(`Cannot parse code: ${e.reasonCode}`) + return null + } + // AntiTooling + traverse(ast, deAntiTooling) + code = generator(ast, { + comments: false, + jsescOption: { minimal: true }, + }).code + return code +}