Skip to content

Commit dbf9f80

Browse files
committed
add Pack
1 parent 232e3ac commit dbf9f80

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

src/plugin/jsconfuser.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import jcDuplicateLiteral from '../visitor/jsconfuser/duplicate-literal.js'
1313
import jcGlobalConcealing from '../visitor/jsconfuser/global-concealing.js'
1414
import jcMinifyInit from '../visitor/jsconfuser/minify.js'
1515
import jcOpaquePredicates from '../visitor/jsconfuser/opaque-predicates.js'
16+
import jcPack from '../visitor/jsconfuser/pack.js'
1617
import jcStackInit from '../visitor/jsconfuser/stack.js'
1718
import jcStringCompression from '../visitor/jsconfuser/string-compression.js'
1819
import jcStringConceal from '../visitor/jsconfuser/string-concealing.js'
@@ -25,6 +26,8 @@ export default function (code) {
2526
console.error(`Cannot parse code: ${e.reasonCode}`)
2627
return null
2728
}
29+
// Pack
30+
ast = jcPack(ast)
2831
// AntiTooling
2932
traverse(ast, jcAntiTooling)
3033
// Minify

src/visitor/jsconfuser/pack.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { parse } from '@babel/parser'
2+
import _traverse from '@babel/traverse'
3+
const traverse = _traverse.default
4+
import * as t from '@babel/types'
5+
6+
function checkNode(node) {
7+
if (t.isExpressionStatement(node)) {
8+
node = node.expression
9+
}
10+
if (node?.callee?.callee?.name !== 'Function') {
11+
return undefined
12+
}
13+
if (node?.callee?.arguments?.length !== 2) {
14+
return undefined
15+
}
16+
if (node?.callee?.arguments[0].type !== 'StringLiteral') {
17+
return undefined
18+
}
19+
if (node?.callee?.arguments[1].type !== 'StringLiteral') {
20+
return undefined
21+
}
22+
if (node?.arguments?.length !== 1) {
23+
return undefined
24+
}
25+
if (node?.arguments[0].type !== 'ObjectExpression') {
26+
return undefined
27+
}
28+
const obj = {}
29+
for (const item of node.arguments[0].properties) {
30+
if (item.kind === 'get') {
31+
obj[item.key.value] = item.body.body[0].argument
32+
} else {
33+
obj[item.key.value] = item.body.body[0].argument.left
34+
}
35+
}
36+
return {
37+
objectName: node?.callee?.arguments[0].value,
38+
outputCode: node?.callee?.arguments[1].value,
39+
objectExpression: obj,
40+
}
41+
}
42+
43+
function parseOutputCode(code, objName, objValue) {
44+
const ast = parse(code, { errorRecovery: true })
45+
traverse(ast, {
46+
Identifier: function (path) {
47+
if (path.node?.name !== objName) {
48+
return
49+
}
50+
const item = path.parentPath
51+
const key = item.node.property.value
52+
item.replaceWith(objValue[key])
53+
},
54+
})
55+
return ast.program.body
56+
}
57+
58+
/**
59+
* All codes except ImportDeclaration are in the string outputCode:
60+
*
61+
* ```javascript
62+
* `
63+
* {prependNodes}
64+
* Function({objectName}, {outputCode})({objectExpression});
65+
* `
66+
* ```
67+
*/
68+
function dePack(ast) {
69+
const body = ast.program.body
70+
const last = body[body.length - 1]
71+
const data = checkNode(last)
72+
if (!data) {
73+
return
74+
}
75+
console.log(`[Pack] Object Name: ${data.objectName}`)
76+
const items = parseOutputCode(
77+
data.outputCode,
78+
data.objectName,
79+
data.objectExpression
80+
)
81+
body.pop()
82+
body.push(...items)
83+
return ast
84+
}
85+
86+
export default dePack

0 commit comments

Comments
 (0)