mirror of
https://github.com/smallfawn/decode_action.git
synced 2026-11-05 23:36:44 +08:00
update
This commit is contained in:
1 parent
f76b8fb9bd
commit
1100a6d4f7
9 files changed
+151
-107
No files matched your search
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"name": "decode-js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"decode": "node src/main.js",
|
||||
"deob": "node src/main.js -t obfuscator",
|
||||
|
||||
+60
-33
@@ -1,46 +1,62 @@
|
||||
const fs = require('fs')
|
||||
const PluginCommon = require('./plugin/common.js')
|
||||
const PluginJjencode = require('./plugin/jjencode.js')
|
||||
const PluginSojson = require('./plugin/sojson.js')
|
||||
const PluginSojsonV7 = require('./plugin/sojsonv7.js')
|
||||
const PluginObfuscator = require('./plugin/obfuscator.js')
|
||||
const PluginAwsc = require('./plugin/awsc.js')
|
||||
import fs from 'fs';
|
||||
import { fileURLToPath } from 'url';
|
||||
import * as path from 'path';
|
||||
import process from 'process';
|
||||
|
||||
// Dynamically import ESM modules
|
||||
const commonModule = await import('./plugin/common.js');
|
||||
const jjencodeModule = await import('./plugin/jjencode.js');
|
||||
const sojsonModule = await import('./plugin/sojson.js');
|
||||
const sojsonv7Module = await import('./plugin/sojsonv7.js');
|
||||
const obfuscatorModule = await import('./plugin/obfuscator.js');
|
||||
const awscModule = await import('./plugin/awsc.js');
|
||||
|
||||
// Provide default exports if necessary
|
||||
const PluginCommon = commonModule.default || commonModule;
|
||||
const PluginJjencode = jjencodeModule.default || jjencodeModule;
|
||||
const PluginSojson = sojsonModule.default || sojsonModule;
|
||||
const PluginSojsonV7 = sojsonv7Module.default || sojsonv7Module;
|
||||
const PluginObfuscator = obfuscatorModule.default || obfuscatorModule;
|
||||
const PluginAwsc = awscModule.default || awscModule;
|
||||
|
||||
// Read command-line arguments
|
||||
let encodeFile = 'input.js';
|
||||
let decodeFile = 'output.js';
|
||||
|
||||
// 读取参数
|
||||
let encodeFile = 'input.js'
|
||||
let decodeFile = 'output.js'
|
||||
for (let i = 2; i < process.argv.length; i += 2) {
|
||||
if (process.argv[i] === '-i') {
|
||||
encodeFile = process.argv[i + 1]
|
||||
}
|
||||
if (process.argv[i] === '-o') {
|
||||
decodeFile = process.argv[i + 1]
|
||||
encodeFile = process.argv[i + 1];
|
||||
} else if (process.argv[i] === '-o') {
|
||||
decodeFile = process.argv[i + 1];
|
||||
}
|
||||
}
|
||||
console.log(`输入: ${encodeFile}`)
|
||||
console.log(`输出: ${decodeFile}`)
|
||||
|
||||
// 读取源代码
|
||||
const sourceCode = fs.readFileSync(encodeFile, { encoding: 'utf-8' })
|
||||
console.log(`输入: ${encodeFile}`);
|
||||
console.log(`输出: ${decodeFile}`);
|
||||
|
||||
// Read source code
|
||||
const sourceCode = fs.readFileSync(encodeFile, { encoding: 'utf-8' });
|
||||
|
||||
let processedCode = sourceCode;
|
||||
let pluginUsed = '';
|
||||
let time;
|
||||
|
||||
// 循环尝试不同的插件,直到源代码与处理后的代码不一致
|
||||
// Try plugins in sequence until the processed code differs from the original
|
||||
const plugins = [
|
||||
{ name: 'obfuscator', plugin: PluginObfuscator },
|
||||
{ name: 'sojsonv7', plugin: PluginSojsonV7 },
|
||||
{ name: 'sojson', plugin: PluginSojson },
|
||||
|
||||
{ name: 'awsc', plugin: PluginAwsc },
|
||||
{ name: 'jjencode', plugin: PluginJjencode },
|
||||
{ name: 'common', plugin: PluginCommon },// 最后一次使用通用插件
|
||||
{ name: 'common', plugin: PluginCommon }, // Use common plugin last
|
||||
];
|
||||
|
||||
for (let plugin of plugins) {
|
||||
if (sourceCode.indexOf("smEcV") != -1) {
|
||||
break
|
||||
for (const plugin of plugins) {
|
||||
// Check for specific string in sourceCode to break early
|
||||
if (sourceCode.indexOf('smEcV') !== -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
const code = plugin.plugin(sourceCode);
|
||||
if (code && code !== processedCode) {
|
||||
@@ -50,18 +66,29 @@ for (let plugin of plugins) {
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`插件 ${plugin.name} 处理时发生错误: ${error.message}`);
|
||||
// 继续循环尝试下一个插件
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let time = new Date();
|
||||
|
||||
// Check if processed code differs from source code
|
||||
if (processedCode !== sourceCode) {
|
||||
// 输出代码
|
||||
fs.writeFile(decodeFile, "//" + time + '\n' + "//Base:https://github.com/echo094/decode-js" + '\n' + "//Modify:https://github.com/smallfawn/decode_action" + '\n' + processedCode, (err) => {
|
||||
if (err) throw err;
|
||||
console.log(`使用插件 ${pluginUsed} 成功处理并写入文件 ${decodeFile}`);
|
||||
time = new Date();
|
||||
const header = [
|
||||
`//${time}`,
|
||||
"//Base:<url id=\"cv1cref6o68qmpt26ol0\" type=\"url\" status=\"parsed\" title=\"GitHub - echo094/decode-js: JS混淆代码的AST分析工具 AST analysis tool for obfuscated JS code\" wc=\"2165\">https://github.com/echo094/decode-js</url>",
|
||||
"//Modify:<url id=\"cv1cref6o68qmpt26olg\" type=\"url\" status=\"parsed\" title=\"GitHub - smallfawn/decode_action: 世界上本来不存在加密,加密的人多了,也便成就了解密\" wc=\"741\">https://github.com/smallfawn/decode_action</url>"
|
||||
].join('\n');
|
||||
|
||||
// Combine header and processed code
|
||||
const outputCode = header + '\n' + processedCode;
|
||||
|
||||
// Write to file
|
||||
fs.writeFile(decodeFile, outputCode, (err) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
} else {
|
||||
console.log(`使用插件 ${pluginUsed} 成功处理并写入文件 ${decodeFile}`);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log(`所有插件处理后的代码与原代码一致,未写入文件。`);
|
||||
}
|
||||
|
||||
}
|
||||
+7
-5
@@ -2,10 +2,12 @@
|
||||
* Reference:
|
||||
* * [某宝登录bx-ua参数逆向思路(fireyejs 225算法)](https://zhuanlan.zhihu.com/p/626187669)
|
||||
*/
|
||||
const { parse } = require('@babel/parser')
|
||||
const generator = require('@babel/generator').default
|
||||
const traverse = require('@babel/traverse').default
|
||||
const t = require('@babel/types')
|
||||
import { parse } from '@babel/parser'
|
||||
import _generate from '@babel/generator'
|
||||
const generator = _generate.default
|
||||
import _traverse from '@babel/traverse'
|
||||
const traverse = _traverse.default
|
||||
import * as t from '@babel/types'
|
||||
|
||||
function RemoveVoid(path) {
|
||||
if (path.node.operator === 'void') {
|
||||
@@ -204,7 +206,7 @@ function LintBlock(path) {
|
||||
path.replaceWith(t.blockStatement(arr))
|
||||
}
|
||||
|
||||
module.exports = function (code) {
|
||||
export default function (code) {
|
||||
let ast = parse(code)
|
||||
// Lint
|
||||
traverse(ast, {
|
||||
|
||||
+12
-8
@@ -1,8 +1,14 @@
|
||||
const { parse } = require('@babel/parser')
|
||||
const generator = require('@babel/generator').default
|
||||
const traverse = require('@babel/traverse').default
|
||||
import { parse } from '@babel/parser'
|
||||
import _generate from '@babel/generator'
|
||||
const generator = _generate.default
|
||||
import _traverse from '@babel/traverse'
|
||||
const traverse = _traverse.default
|
||||
import deleteUnreachableCode from '../visitor/delete-unreachable-code.js'
|
||||
import deleteNestedBlocks from '../visitor/delete-nested-blocks.js'
|
||||
import calculateConstantExp from '../visitor/calculate-constant-exp.js'
|
||||
import calculateRString from '../visitor/calculate-rstring.js'
|
||||
|
||||
module.exports = function (code) {
|
||||
export default function (code) {
|
||||
let ast
|
||||
try {
|
||||
ast = parse(code, { errorRecovery: true })
|
||||
@@ -10,11 +16,9 @@ module.exports = function (code) {
|
||||
console.error(`Cannot parse code: ${e.reasonCode}`)
|
||||
return null
|
||||
}
|
||||
const deleteExtra = require('../visitor/delete-extra')
|
||||
traverse(ast, deleteExtra)
|
||||
const calculateConstantExp = require('../visitor/calculate-constant-exp')
|
||||
traverse(ast, deleteUnreachableCode)
|
||||
traverse(ast, deleteNestedBlocks)
|
||||
traverse(ast, calculateConstantExp)
|
||||
const calculateRString = require('../visitor/calculate-rstring')
|
||||
traverse(ast, calculateRString)
|
||||
code = generator(ast).code
|
||||
return code
|
||||
|
||||
+7
-5
@@ -1,7 +1,9 @@
|
||||
const { parse } = require('@babel/parser')
|
||||
const generator = require('@babel/generator').default
|
||||
const traverse = require('@babel/traverse').default
|
||||
const t = require('@babel/types')
|
||||
import { parse } from '@babel/parser'
|
||||
import _generate from '@babel/generator'
|
||||
const generator = _generate.default
|
||||
import _traverse from '@babel/traverse'
|
||||
const traverse = _traverse.default
|
||||
import * as t from '@babel/types'
|
||||
|
||||
function unpack(code) {
|
||||
let ast = parse(code, { errorRecovery: true })
|
||||
@@ -46,7 +48,7 @@ function pack(code) {
|
||||
return code
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
unpack,
|
||||
pack,
|
||||
}
|
||||
@@ -57,7 +57,7 @@ function getCode(code) {
|
||||
* This encoding method originates from http://utf-8.jp/public/jjencode.html,
|
||||
* and it does not change the original code (encoder, not obfuscation).
|
||||
*/
|
||||
module.exports = function (code) {
|
||||
export default function (code) {
|
||||
code = getCode(code)
|
||||
if (!code) {
|
||||
return null
|
||||
|
||||
+20
-29
@@ -3,13 +3,24 @@
|
||||
* * cilame/v_jstools
|
||||
* * Cqxstevexw/decodeObfuscator
|
||||
*/
|
||||
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 PluginEval = require('./eval.js')
|
||||
const calculateConstantExp = require('../visitor/calculate-constant-exp')
|
||||
import { parse } from '@babel/parser'
|
||||
import _generate from '@babel/generator'
|
||||
const generator = _generate.default
|
||||
import _traverse from '@babel/traverse'
|
||||
const traverse = _traverse.default
|
||||
import * as t from '@babel/types'
|
||||
import ivm from 'isolated-vm'
|
||||
import PluginEval from './eval.js'
|
||||
import calculateConstantExp from '../visitor/calculate-constant-exp.js'
|
||||
import deleteIllegalReturn from '../visitor/delete-illegal-return.js'
|
||||
import deleteUnusedVar from '../visitor/delete-unused-var.js'
|
||||
import lintIfStatement from '../visitor/lint-if-statement.js'
|
||||
import mergeObject from '../visitor/merge-object.js'
|
||||
import parseControlFlowStorage from '../visitor/parse-control-flow-storage.js'
|
||||
import pruneIfBranch from '../visitor/prune-if-branch.js'
|
||||
import splitAssignment from '../visitor/split-assignment.js'
|
||||
import splitSequence from '../visitor/split-sequence.js'
|
||||
import splitVarDeclaration from '../visitor/split-variable-declaration.js'
|
||||
|
||||
const isolate = new ivm.Isolate()
|
||||
const globalContext = isolate.createContextSync()
|
||||
@@ -609,10 +620,8 @@ function decodeCodeBlock(ast) {
|
||||
// 合并字面量
|
||||
traverse(ast, calculateConstantExp)
|
||||
// 先合并分离的Object定义
|
||||
const mergeObject = require('../visitor/merge-object')
|
||||
traverse(ast, mergeObject)
|
||||
// 在变量定义完成后判断是否为代码块加密内容
|
||||
const parseControlFlowStorage = require('../visitor/parse-control-flow-storage')
|
||||
traverse(ast, parseControlFlowStorage)
|
||||
// 合并字面量(在解除区域混淆后会出现新的可合并分割)
|
||||
traverse(ast, calculateConstantExp)
|
||||
@@ -719,24 +728,11 @@ function cleanSwitchCode(path) {
|
||||
|
||||
function cleanDeadCode(ast) {
|
||||
traverse(ast, calculateConstantExp)
|
||||
const pruneIfBranch = require('../visitor/prune-if-branch')
|
||||
traverse(ast, pruneIfBranch)
|
||||
traverse(ast, { WhileStatement: { exit: cleanSwitchCode } })
|
||||
return ast
|
||||
}
|
||||
|
||||
const splitVariableDeclarator = {
|
||||
VariableDeclarator(path) {
|
||||
const init = path.get('init')
|
||||
if (!init.isAssignmentExpression()) {
|
||||
return
|
||||
}
|
||||
path.parentPath.insertBefore(init.node)
|
||||
init.replaceWith(init.node.left)
|
||||
path.parentPath.scope.crawl()
|
||||
},
|
||||
}
|
||||
|
||||
function standardIfStatement(path) {
|
||||
const consequent = path.get('consequent')
|
||||
const alternate = path.get('alternate')
|
||||
@@ -795,9 +791,8 @@ function purifyCode(ast) {
|
||||
path.remove()
|
||||
},
|
||||
})
|
||||
traverse(ast, splitAssignment)
|
||||
// 删除未使用的变量
|
||||
traverse(ast, splitVariableDeclarator)
|
||||
const deleteUnusedVar = require('../visitor/delete-unused-var')
|
||||
traverse(ast, deleteUnusedVar)
|
||||
// 替换索引器
|
||||
function FormatMember(path) {
|
||||
@@ -844,7 +839,6 @@ function purifyCode(ast) {
|
||||
})
|
||||
|
||||
// 拆分语句
|
||||
const splitSequence = require('../visitor/split-sequence')
|
||||
traverse(ast, splitSequence)
|
||||
return ast
|
||||
}
|
||||
@@ -1041,7 +1035,7 @@ function unlockEnv(ast) {
|
||||
return ast
|
||||
}
|
||||
|
||||
module.exports = function (code) {
|
||||
export default function (code) {
|
||||
let ret = PluginEval.unpack(code)
|
||||
let global_eval = false
|
||||
if (ret) {
|
||||
@@ -1056,13 +1050,10 @@ module.exports = function (code) {
|
||||
return null
|
||||
}
|
||||
// IllegalReturn
|
||||
const deleteIllegalReturn = require('../visitor/delete-illegal-return')
|
||||
traverse(ast, deleteIllegalReturn)
|
||||
// Lint before split statements
|
||||
const lintIfStatement = require('../visitor/lint-if-statement')
|
||||
traverse(ast, lintIfStatement)
|
||||
// Split declarations to avoid bugs
|
||||
const splitVarDeclaration = require('../visitor/split-variable-declaration')
|
||||
traverse(ast, splitVarDeclaration)
|
||||
// 清理二进制显示内容
|
||||
traverse(ast, {
|
||||
|
||||
+14
-12
@@ -1,13 +1,19 @@
|
||||
/**
|
||||
* 在 babel_asttool.js 的基础上修改而来
|
||||
*/
|
||||
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 PluginEval = require('./eval.js')
|
||||
const calculateConstantExp = require('../visitor/calculate-constant-exp')
|
||||
import { parse } from '@babel/parser'
|
||||
import _generate from '@babel/generator'
|
||||
const generator = _generate.default
|
||||
import _traverse from '@babel/traverse'
|
||||
const traverse = _traverse.default
|
||||
import * as t from '@babel/types'
|
||||
import ivm from 'isolated-vm'
|
||||
import PluginEval from './eval.js'
|
||||
import calculateConstantExp from '../visitor/calculate-constant-exp.js'
|
||||
import deleteUnusedVar from '../visitor/delete-unused-var.js'
|
||||
import parseControlFlowStorage from '../visitor/parse-control-flow-storage.js'
|
||||
import pruneIfBranch from '../visitor/prune-if-branch.js'
|
||||
import splitSequence from '../visitor/split-sequence.js'
|
||||
|
||||
const isolate = new ivm.Isolate()
|
||||
const globalContext = isolate.createContextSync()
|
||||
@@ -166,7 +172,6 @@ function cleanSwitchCode(path) {
|
||||
|
||||
function cleanDeadCode(ast) {
|
||||
traverse(ast, calculateConstantExp)
|
||||
const pruneIfBranch = require('../visitor/prune-if-branch')
|
||||
traverse(ast, pruneIfBranch)
|
||||
traverse(ast, { WhileStatement: { exit: cleanSwitchCode } })
|
||||
return ast
|
||||
@@ -469,7 +474,6 @@ function purifyCode(ast) {
|
||||
}
|
||||
traverse(ast, { MemberExpression: FormatMember })
|
||||
// 分割表达式
|
||||
const splitSequence = require('../visitor/split-sequence')
|
||||
traverse(ast, splitSequence)
|
||||
// 删除空语句
|
||||
traverse(ast, {
|
||||
@@ -478,12 +482,11 @@ function purifyCode(ast) {
|
||||
},
|
||||
})
|
||||
// 删除未使用的变量
|
||||
const deleteUnusedVar = require('../visitor/delete-unused-var')
|
||||
traverse(ast, deleteUnusedVar)
|
||||
return ast
|
||||
}
|
||||
|
||||
module.exports = function (code) {
|
||||
export default function (code) {
|
||||
let ret = PluginEval.unpack(code)
|
||||
let global_eval = false
|
||||
if (ret) {
|
||||
@@ -508,7 +511,6 @@ module.exports = function (code) {
|
||||
return null
|
||||
}
|
||||
console.log('处理代码块加密...')
|
||||
const parseControlFlowStorage = require('../visitor/parse-control-flow-storage')
|
||||
traverse(ast, parseControlFlowStorage)
|
||||
console.log('清理死代码...')
|
||||
ast = cleanDeadCode(ast)
|
||||
|
||||
+29
-14
@@ -1,13 +1,20 @@
|
||||
/**
|
||||
* For jsjiami.com.v7
|
||||
*/
|
||||
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 PluginEval = require('./eval.js')
|
||||
const calculateConstantExp = require('../visitor/calculate-constant-exp')
|
||||
import { parse } from '@babel/parser'
|
||||
import _generate from '@babel/generator'
|
||||
const generator = _generate.default
|
||||
import _traverse from '@babel/traverse'
|
||||
const traverse = _traverse.default
|
||||
import * as t from '@babel/types'
|
||||
import ivm from 'isolated-vm'
|
||||
import PluginEval from './eval.js'
|
||||
import calculateConstantExp from '../visitor/calculate-constant-exp.js'
|
||||
import deleteIllegalReturn from '../visitor/delete-illegal-return.js'
|
||||
import deleteUnusedVar from '../visitor/delete-unused-var.js'
|
||||
import parseControlFlowStorage from '../visitor/parse-control-flow-storage.js'
|
||||
import pruneIfBranch from '../visitor/prune-if-branch.js'
|
||||
import splitSequence from '../visitor/split-sequence.js'
|
||||
|
||||
const isolate = new ivm.Isolate()
|
||||
const globalContext = isolate.createContextSync()
|
||||
@@ -283,7 +290,11 @@ function decodeGlobal(ast) {
|
||||
if (item.path.isFunctionDeclaration()) {
|
||||
scope = item.path.parentPath.scope
|
||||
}
|
||||
const refs = scope.bindings[cur_val].referencePaths
|
||||
// var is function scoped and let is block scoped
|
||||
// Hence, var may not be in the current scope, e.g., in a for-loop
|
||||
const binding = scope.getBinding(cur_val)
|
||||
scope = binding.scope
|
||||
const refs = binding.referencePaths
|
||||
const refs_next = []
|
||||
for (let ref of refs) {
|
||||
const parent = ref.parentPath
|
||||
@@ -294,12 +305,21 @@ function decodeGlobal(ast) {
|
||||
path: parent,
|
||||
code: 'var ' + parent,
|
||||
})
|
||||
} else if (ref.key === 'right') {
|
||||
// AssignmentExpression
|
||||
refs_next.push({
|
||||
name: parent.node.left.name,
|
||||
path: parent,
|
||||
code: 'var ' + parent,
|
||||
})
|
||||
} else if (ref.key === 'object') {
|
||||
// MemberExpression
|
||||
memToStr(parent)
|
||||
} else if (ref.key === 'callee') {
|
||||
// CallExpression
|
||||
funToStr(parent)
|
||||
} else {
|
||||
console.error('Unexpected reference')
|
||||
}
|
||||
}
|
||||
for (let ref of refs_next) {
|
||||
@@ -477,7 +497,6 @@ function cleanSwitchCode2(path) {
|
||||
|
||||
function cleanDeadCode(ast) {
|
||||
traverse(ast, calculateConstantExp)
|
||||
const pruneIfBranch = require('../visitor/prune-if-branch')
|
||||
traverse(ast, pruneIfBranch)
|
||||
traverse(ast, { WhileStatement: { exit: cleanSwitchCode1 } })
|
||||
traverse(ast, { ForStatement: { exit: cleanSwitchCode2 } })
|
||||
@@ -722,7 +741,6 @@ function purifyCode(ast) {
|
||||
}
|
||||
traverse(ast, { MemberExpression: FormatMember })
|
||||
// 分割表达式
|
||||
const splitSequence = require('../visitor/split-sequence')
|
||||
traverse(ast, splitSequence)
|
||||
// 删除空语句
|
||||
traverse(ast, {
|
||||
@@ -731,11 +749,10 @@ function purifyCode(ast) {
|
||||
},
|
||||
})
|
||||
// 删除未使用的变量
|
||||
const deleteUnusedVar = require('../visitor/delete-unused-var')
|
||||
traverse(ast, deleteUnusedVar)
|
||||
}
|
||||
|
||||
module.exports = function (code) {
|
||||
export default function (code) {
|
||||
let ret = PluginEval.unpack(code)
|
||||
let global_eval = false
|
||||
if (ret) {
|
||||
@@ -750,7 +767,6 @@ module.exports = function (code) {
|
||||
return null
|
||||
}
|
||||
// IllegalReturn
|
||||
const deleteIllegalReturn = require('../visitor/delete-illegal-return')
|
||||
traverse(ast, deleteIllegalReturn)
|
||||
// 清理二进制显示内容
|
||||
traverse(ast, {
|
||||
@@ -769,7 +785,6 @@ module.exports = function (code) {
|
||||
return null
|
||||
}
|
||||
console.log('处理代码块加密...')
|
||||
const parseControlFlowStorage = require('../visitor/parse-control-flow-storage')
|
||||
traverse(ast, parseControlFlowStorage)
|
||||
console.log('清理死代码...')
|
||||
ast = cleanDeadCode(ast)
|
||||
|
||||
Reference in new issue
Block a user