Skip to content

Commit 0168cac

Browse files
authored
obfuscator: bug fix and improve compatibility (#57)
Signed-off-by: echo094 <20028238+echo094@users.noreply.github.com>
1 parent bc30bc3 commit 0168cac

File tree

1 file changed

+65
-12
lines changed

1 file changed

+65
-12
lines changed

src/plugin/obfuscator.js

Lines changed: 65 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ function decodeObject(ast) {
6161
if (!Object.prototype.hasOwnProperty.call(obj_node, name.name)) {
6262
return
6363
}
64+
if (t.isIdentifier(key) && path.node.computed) {
65+
// In this case, the identifier points to another value
66+
return
67+
}
6468
path.replaceWith(obj_node[name.name][key.name])
6569
obj_used[name.name] = true
6670
}
@@ -112,23 +116,24 @@ function stringArrayV2(ast) {
112116
if (
113117
!callee.isFunctionExpression() ||
114118
callee.node.params.length !== 2 ||
115-
args.length !== 2 ||
119+
args.length == 0 ||
120+
args.length > 2 ||
116121
!t.isIdentifier(args[0])
117122
) {
118123
return
119124
}
120125
const arr = callee.node.params[0].name
121-
const cmpV = callee.node.params[1].name
122-
const fp = `while(){try{if(==${cmpV})else${arr}push(${arr}shift())}catch(){${arr}push(${arr}shift())}}`
126+
// const cmpV = callee.node.params[1].name
127+
const fp = `(){try{if()break${arr}push(${arr}shift())}catch(){${arr}push(${arr}shift())}}`
123128
const code = '' + callee.get('body')
124129
if (!checkPattern(code, fp)) {
125130
return
126131
}
127132
obj.stringArrayName = args[0].name
128133
// The string array can be found by its binding
129134
const bind = path.scope.getBinding(obj.stringArrayName)
130-
const def = bind.path.parentPath
131-
obj.stringArrayCodes.push(generator(def.node, { minified: true }).code)
135+
const def = t.variableDeclaration('var', [bind.path.node])
136+
obj.stringArrayCodes.push(generator(def, { minified: true }).code)
132137
// The calls can be found by its references
133138
for (let ref of bind.referencePaths) {
134139
if (ref?.listKey === 'arguments') {
@@ -172,12 +177,16 @@ function stringArrayV2(ast) {
172177
up2.remove()
173178
}
174179
// Remove the string array
175-
def.remove()
180+
bind.path.remove()
176181
// Add the rotate function
177182
const node = t.expressionStatement(path.node)
178183
obj.stringArrayCodes.push(generator(node, { minified: true }).code)
179184
path.stop()
180-
path.remove()
185+
if (path.parentPath.isUnaryExpression()) {
186+
path.parentPath.remove()
187+
} else {
188+
path.remove()
189+
}
181190
}
182191
traverse(ast, { CallExpression: find_rotate_function })
183192
if (obj.stringArrayCodes.length < 3 || !obj.stringArrayCalls.length) {
@@ -363,13 +372,18 @@ function decodeGlobal(ast) {
363372
function do_collect_remove(path) {
364373
// 可以删除所有已收集混淆函数的定义
365374
// 因为根函数已被删除 即使保留也无法运行
366-
let name = path.node?.left?.name
367-
if (!name) {
368-
name = path.node?.id?.name
375+
let node = path.node?.left
376+
if (!node) {
377+
node = path.node?.id
369378
}
379+
let name = node?.name
370380
if (exist_names.indexOf(name) != -1) {
371381
// console.log(`del: ${name}`)
372-
path.remove()
382+
if (path.parentPath.isCallExpression()) {
383+
path.replaceWith(node)
384+
} else {
385+
path.remove()
386+
}
373387
}
374388
}
375389
function do_collect_func(path) {
@@ -445,6 +459,44 @@ function decodeGlobal(ast) {
445459
return true
446460
}
447461

462+
function stringArrayLite(ast) {
463+
const visitor = {
464+
VariableDeclarator(path) {
465+
const name = path.node.id.name
466+
if (!path.get('init').isArrayExpression()) {
467+
return
468+
}
469+
const elements = path.node.init.elements
470+
for (const element of elements) {
471+
if (!t.isLiteral(element)) {
472+
return
473+
}
474+
}
475+
const bind = path.scope.getBinding(name)
476+
if (!bind.constant) {
477+
return
478+
}
479+
for (const ref of bind.referencePaths) {
480+
if (
481+
!ref.parentPath.isMemberExpression() ||
482+
ref.key !== 'object' ||
483+
!t.isNumericLiteral(ref.parent.property)
484+
) {
485+
return
486+
}
487+
}
488+
console.log(`Extract string array: ${name}`)
489+
for (const ref of bind.referencePaths) {
490+
const i = ref.parent.property.value
491+
ref.parentPath.replaceWith(elements[i])
492+
}
493+
bind.scope.crawl()
494+
path.remove()
495+
},
496+
}
497+
traverse(ast, visitor)
498+
}
499+
448500
function mergeObject(path) {
449501
// var _0xb28de8 = {};
450502
// _0xb28de8["abcd"] = function(_0x22293f, _0x5a165e) {
@@ -673,7 +725,7 @@ function unpackCall(path) {
673725
if (!t.isIdentifier(retStmt.argument.callee)) {
674726
return
675727
}
676-
if (retStmt.argument.callee.name !== prop.value.params[0].name) {
728+
if (retStmt.argument.callee.name !== prop.value.params[0]?.name) {
677729
return
678730
}
679731
repfunc = function (_path, args) {
@@ -1328,6 +1380,7 @@ module.exports = function (jscode) {
13281380
console.log('提高代码可读性...')
13291381
ast = purifyCode(ast)
13301382
console.log('处理代码块加密...')
1383+
stringArrayLite(ast)
13311384
ast = decodeCodeBlock(ast)
13321385
console.log('清理死代码...')
13331386
ast = cleanDeadCode(ast)

0 commit comments

Comments
 (0)