js-confuser 2.0.0-alpha.2 → 2.0.0-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierrc +4 -0
- package/CHANGELOG.md +42 -8
- package/Migration.md +23 -8
- package/README.md +2 -2
- package/dist/constants.js +11 -2
- package/dist/index.js +49 -6
- package/dist/obfuscator.js +121 -10
- package/dist/order.js +0 -1
- package/dist/probability.js +1 -96
- package/dist/templates/getGlobalTemplate.js +4 -1
- package/dist/templates/integrityTemplate.js +1 -1
- package/dist/templates/stringCompressionTemplate.js +3 -3
- package/dist/templates/tamperProtectionTemplates.js +1 -1
- package/dist/templates/template.js +17 -12
- package/dist/transforms/controlFlowFlattening.js +112 -83
- package/dist/transforms/deadCode.js +21 -22
- package/dist/transforms/dispatcher.js +62 -37
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -0
- package/dist/transforms/extraction/objectExtraction.js +1 -2
- package/dist/transforms/finalizer.js +1 -1
- package/dist/transforms/flatten.js +2 -19
- package/dist/transforms/identifier/globalConcealing.js +3 -4
- package/dist/transforms/identifier/movedDeclarations.js +12 -5
- package/dist/transforms/identifier/renameVariables.js +40 -6
- package/dist/transforms/lock/integrity.js +9 -1
- package/dist/transforms/lock/lock.js +16 -9
- package/dist/transforms/minify.js +64 -27
- package/dist/transforms/opaquePredicates.js +6 -7
- package/dist/transforms/pack.js +32 -5
- package/dist/transforms/plugin.js +20 -39
- package/dist/transforms/preparation.js +25 -36
- package/dist/transforms/renameLabels.js +1 -2
- package/dist/transforms/rgf.js +36 -16
- package/dist/transforms/shuffle.js +10 -11
- package/dist/transforms/string/stringCompression.js +14 -10
- package/dist/transforms/string/stringConcealing.js +7 -5
- package/dist/transforms/string/stringEncoding.js +4 -2
- package/dist/transforms/string/stringSplitting.js +4 -2
- package/dist/transforms/variableMasking.js +3 -2
- package/dist/utils/NameGen.js +5 -2
- package/dist/utils/PredicateGen.js +62 -0
- package/dist/utils/ast-utils.js +24 -9
- package/dist/utils/random-utils.js +10 -0
- package/dist/validateOptions.js +2 -2
- package/index.d.ts +16 -2
- package/package.json +2 -2
- package/src/constants.ts +15 -5
- package/src/index.ts +15 -5
- package/src/obfuscationResult.ts +7 -1
- package/src/obfuscator.ts +152 -12
- package/src/options.ts +26 -8
- package/src/order.ts +0 -2
- package/src/templates/getGlobalTemplate.ts +5 -1
- package/src/templates/integrityTemplate.ts +14 -19
- package/src/templates/stringCompressionTemplate.ts +4 -28
- package/src/templates/tamperProtectionTemplates.ts +7 -3
- package/src/templates/template.ts +5 -3
- package/src/transforms/controlFlowFlattening.ts +139 -83
- package/src/transforms/deadCode.ts +27 -30
- package/src/transforms/dispatcher.ts +24 -5
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +10 -1
- package/src/transforms/extraction/objectExtraction.ts +1 -2
- package/src/transforms/finalizer.ts +1 -1
- package/src/transforms/flatten.ts +3 -22
- package/src/transforms/identifier/globalConcealing.ts +26 -17
- package/src/transforms/identifier/movedDeclarations.ts +18 -6
- package/src/transforms/identifier/renameVariables.ts +48 -6
- package/src/transforms/lock/integrity.ts +11 -1
- package/src/transforms/lock/lock.ts +26 -10
- package/src/transforms/minify.ts +85 -38
- package/src/transforms/opaquePredicates.ts +6 -9
- package/src/transforms/pack.ts +41 -5
- package/src/transforms/plugin.ts +47 -69
- package/src/transforms/preparation.ts +33 -46
- package/src/transforms/renameLabels.ts +1 -2
- package/src/transforms/rgf.ts +52 -23
- package/src/transforms/shuffle.ts +28 -26
- package/src/transforms/string/encoding.ts +1 -1
- package/src/transforms/string/stringCompression.ts +22 -13
- package/src/transforms/string/stringConcealing.ts +13 -7
- package/src/transforms/string/stringEncoding.ts +6 -2
- package/src/transforms/string/stringSplitting.ts +9 -4
- package/src/transforms/variableMasking.ts +2 -2
- package/src/utils/NameGen.ts +13 -3
- package/src/utils/PredicateGen.ts +61 -0
- package/src/utils/ast-utils.ts +16 -9
- package/src/utils/random-utils.ts +14 -0
- package/src/validateOptions.ts +7 -4
- package/src/probability.ts +0 -110
- package/src/transforms/functionOutlining.ts +0 -225
- package/src/utils/ControlObject.ts +0 -141
package/src/transforms/plugin.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { NodePath, Visitor } from "@babel/traverse";
|
|
2
2
|
import Obfuscator from "../obfuscator";
|
|
3
|
-
import {
|
|
3
|
+
import { getRandomString } from "../utils/random-utils";
|
|
4
4
|
import { Order } from "../order";
|
|
5
5
|
import * as t from "@babel/types";
|
|
6
|
-
import { FN_LENGTH, NodeSymbol, SKIP
|
|
6
|
+
import { FN_LENGTH, NodeSymbol, SKIP } from "../constants";
|
|
7
7
|
import { SetFunctionLengthTemplate } from "../templates/setFunctionLengthTemplate";
|
|
8
8
|
import { prepend, prependProgram } from "../utils/ast-utils";
|
|
9
|
-
import ControlObject from "../utils/ControlObject";
|
|
10
|
-
import { ok } from "assert";
|
|
11
9
|
import { numericLiteral } from "../utils/node";
|
|
12
10
|
|
|
13
11
|
export interface PluginObject {
|
|
@@ -30,9 +28,14 @@ export class PluginInstance {
|
|
|
30
28
|
constructor(
|
|
31
29
|
public pluginOptions: { name?: string; order?: number },
|
|
32
30
|
public obfuscator: Obfuscator
|
|
33
|
-
) {
|
|
31
|
+
) {
|
|
32
|
+
this.computeProbabilityMap = obfuscator.computeProbabilityMap.bind(
|
|
33
|
+
this.obfuscator
|
|
34
|
+
);
|
|
35
|
+
}
|
|
34
36
|
|
|
35
37
|
public changeData: { [key: string]: number } = {};
|
|
38
|
+
public computeProbabilityMap: Obfuscator["computeProbabilityMap"];
|
|
36
39
|
|
|
37
40
|
get name() {
|
|
38
41
|
return this.pluginOptions.name || "unnamed";
|
|
@@ -74,43 +77,48 @@ export class PluginInstance {
|
|
|
74
77
|
setFunctionLength(path: NodePath<t.Function>, originalLength: number) {
|
|
75
78
|
(path.node as NodeSymbol)[FN_LENGTH] = originalLength;
|
|
76
79
|
|
|
77
|
-
//
|
|
78
|
-
if (this.options.preserveFunctionLength
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
} else if (
|
|
102
|
-
t.isFunctionExpression(path.node) ||
|
|
103
|
-
t.isArrowFunctionExpression(path.node)
|
|
104
|
-
) {
|
|
105
|
-
path.replaceWith(
|
|
80
|
+
// Skip if user disabled this feature
|
|
81
|
+
if (!this.options.preserveFunctionLength) return;
|
|
82
|
+
|
|
83
|
+
// Skip if function has no parameters
|
|
84
|
+
if (originalLength === 0) return;
|
|
85
|
+
|
|
86
|
+
// Create the function length setter if it doesn't exist
|
|
87
|
+
if (!this.setFunctionLengthName) {
|
|
88
|
+
this.setFunctionLengthName = this.getPlaceholder("fnLength");
|
|
89
|
+
|
|
90
|
+
this.skip(
|
|
91
|
+
prependProgram(
|
|
92
|
+
path,
|
|
93
|
+
SetFunctionLengthTemplate.compile({
|
|
94
|
+
fnName: this.setFunctionLengthName,
|
|
95
|
+
})
|
|
96
|
+
)
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (t.isFunctionDeclaration(path.node)) {
|
|
101
|
+
prepend(
|
|
102
|
+
path.parentPath,
|
|
103
|
+
t.expressionStatement(
|
|
106
104
|
t.callExpression(t.identifier(this.setFunctionLengthName), [
|
|
107
|
-
path.node,
|
|
105
|
+
t.identifier(path.node.id.name),
|
|
108
106
|
numericLiteral(originalLength),
|
|
109
107
|
])
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
)
|
|
109
|
+
);
|
|
110
|
+
} else if (
|
|
111
|
+
t.isFunctionExpression(path.node) ||
|
|
112
|
+
t.isArrowFunctionExpression(path.node)
|
|
113
|
+
) {
|
|
114
|
+
path.replaceWith(
|
|
115
|
+
t.callExpression(t.identifier(this.setFunctionLengthName), [
|
|
116
|
+
path.node,
|
|
117
|
+
numericLiteral(originalLength),
|
|
118
|
+
])
|
|
119
|
+
);
|
|
120
|
+
} else {
|
|
121
|
+
// TODO
|
|
114
122
|
}
|
|
115
123
|
}
|
|
116
124
|
|
|
@@ -125,36 +133,6 @@ export class PluginInstance {
|
|
|
125
133
|
return "__p_" + getRandomString(4) + (suffix ? "_" + suffix : "");
|
|
126
134
|
}
|
|
127
135
|
|
|
128
|
-
/**
|
|
129
|
-
* Retrieves (or creates) a `ControlObject` for the given `blockPath`.
|
|
130
|
-
*/
|
|
131
|
-
getControlObject(blockPath: NodePath<t.Block>, createMultiple = true) {
|
|
132
|
-
ok(blockPath.isBlock());
|
|
133
|
-
|
|
134
|
-
var controlObjects = (blockPath.node as NodeSymbol)[CONTROL_OBJECTS];
|
|
135
|
-
if (!controlObjects) {
|
|
136
|
-
controlObjects = [];
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (
|
|
140
|
-
controlObjects.length === 0 ||
|
|
141
|
-
(createMultiple &&
|
|
142
|
-
chance(
|
|
143
|
-
controlObjects[0].propertyNames.size - 15 * controlObjects.length
|
|
144
|
-
))
|
|
145
|
-
) {
|
|
146
|
-
var newControlObject = new ControlObject(this, blockPath);
|
|
147
|
-
|
|
148
|
-
controlObjects.push(newControlObject);
|
|
149
|
-
|
|
150
|
-
(blockPath.node as NodeSymbol)[CONTROL_OBJECTS] = controlObjects;
|
|
151
|
-
|
|
152
|
-
return newControlObject;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return choice(controlObjects);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
136
|
/**
|
|
159
137
|
* Logs a message to the console, only if `verbose` is enabled.
|
|
160
138
|
* @param messages
|
|
@@ -2,7 +2,6 @@ import { NodePath } from "@babel/traverse";
|
|
|
2
2
|
import { PluginArg, PluginObject } from "./plugin";
|
|
3
3
|
import * as t from "@babel/types";
|
|
4
4
|
import { Order } from "../order";
|
|
5
|
-
import path from "path";
|
|
6
5
|
import {
|
|
7
6
|
NodeSymbol,
|
|
8
7
|
PREDICTABLE,
|
|
@@ -13,8 +12,10 @@ import { ok } from "assert";
|
|
|
13
12
|
import {
|
|
14
13
|
getParentFunctionOrProgram,
|
|
15
14
|
getPatternIdentifierNames,
|
|
15
|
+
isVariableIdentifier,
|
|
16
16
|
} from "../utils/ast-utils";
|
|
17
17
|
import { isVariableFunctionIdentifier } from "../utils/function-utils";
|
|
18
|
+
import Template from "../templates/template";
|
|
18
19
|
|
|
19
20
|
/**
|
|
20
21
|
* Preparation arranges the user's code into an AST the obfuscator can easily transform.
|
|
@@ -53,6 +54,37 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
53
54
|
},
|
|
54
55
|
},
|
|
55
56
|
|
|
57
|
+
// @js-confuser-var "myVar" -> __JS_CONFUSER_VAR__(myVar)
|
|
58
|
+
StringLiteral: {
|
|
59
|
+
exit(path) {
|
|
60
|
+
// Check for @js-confuser-var comment
|
|
61
|
+
if (
|
|
62
|
+
path.node.leadingComments?.find((comment) =>
|
|
63
|
+
comment.value.includes("@js-confuser-var")
|
|
64
|
+
)
|
|
65
|
+
) {
|
|
66
|
+
var identifierName = path.node.value;
|
|
67
|
+
ok(
|
|
68
|
+
t.isValidIdentifier(identifierName),
|
|
69
|
+
"Invalid identifier name: " + identifierName
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// Create a new __JS_CONFUSER_VAR__ call with the identifier
|
|
73
|
+
var newExpression = new Template(
|
|
74
|
+
`__JS_CONFUSER_VAR__({identifier})`
|
|
75
|
+
).expression({
|
|
76
|
+
identifier: t.identifier(identifierName),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
path.replaceWith(newExpression);
|
|
80
|
+
|
|
81
|
+
// Remove comment and skip further processing
|
|
82
|
+
path.node.leadingComments = [];
|
|
83
|
+
path.skip();
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
|
|
56
88
|
// `Hello ${username}` -> "Hello " + username
|
|
57
89
|
TemplateLiteral: {
|
|
58
90
|
exit(path) {
|
|
@@ -310,51 +342,6 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
310
342
|
}
|
|
311
343
|
},
|
|
312
344
|
},
|
|
313
|
-
|
|
314
|
-
// function a(param = ()=>b)
|
|
315
|
-
// _getB = ()=> ()=>b
|
|
316
|
-
// function a(param = _getB())
|
|
317
|
-
// Basically Babel scope.rename misses this edge case, so we need to manually handle it
|
|
318
|
-
// Here were essentially making the variables easier to understand
|
|
319
|
-
Function: {
|
|
320
|
-
exit(path) {
|
|
321
|
-
for (var param of path.get("params")) {
|
|
322
|
-
param.traverse({
|
|
323
|
-
"FunctionExpression|ArrowFunctionExpression"(_innerPath) {
|
|
324
|
-
let innerPath = _innerPath as NodePath<
|
|
325
|
-
t.FunctionExpression | t.ArrowFunctionExpression
|
|
326
|
-
>;
|
|
327
|
-
const child = innerPath.find((path) =>
|
|
328
|
-
path.parentPath?.isAssignmentPattern()
|
|
329
|
-
);
|
|
330
|
-
|
|
331
|
-
if (!child) return;
|
|
332
|
-
|
|
333
|
-
if (
|
|
334
|
-
t.isAssignmentPattern(child.parent) &&
|
|
335
|
-
child.parent.right === child.node
|
|
336
|
-
) {
|
|
337
|
-
var creatorName = me.getPlaceholder();
|
|
338
|
-
var insertPath = path.insertBefore(
|
|
339
|
-
t.variableDeclaration("const", [
|
|
340
|
-
t.variableDeclarator(
|
|
341
|
-
t.identifier(creatorName),
|
|
342
|
-
t.arrowFunctionExpression([], innerPath.node, false)
|
|
343
|
-
),
|
|
344
|
-
])
|
|
345
|
-
)[0];
|
|
346
|
-
|
|
347
|
-
path.scope.parent.registerDeclaration(insertPath);
|
|
348
|
-
|
|
349
|
-
innerPath.replaceWith(
|
|
350
|
-
t.callExpression(t.identifier(creatorName), [])
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
},
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
},
|
|
357
|
-
},
|
|
358
345
|
},
|
|
359
346
|
};
|
|
360
347
|
};
|
|
@@ -4,7 +4,6 @@ import { PluginArg, PluginObject } from "./plugin";
|
|
|
4
4
|
import { Order } from "../order";
|
|
5
5
|
import { NameGen } from "../utils/NameGen";
|
|
6
6
|
import { ok } from "assert";
|
|
7
|
-
import { computeProbabilityMap } from "../probability";
|
|
8
7
|
|
|
9
8
|
const LABEL = Symbol("label");
|
|
10
9
|
|
|
@@ -127,7 +126,7 @@ export default function ({ Plugin }: PluginArg): PluginObject {
|
|
|
127
126
|
if (isRequired) {
|
|
128
127
|
var newName = labelInterface.label;
|
|
129
128
|
if (
|
|
130
|
-
computeProbabilityMap(
|
|
129
|
+
me.computeProbabilityMap(
|
|
131
130
|
me.options.renameLabels,
|
|
132
131
|
labelInterface.label
|
|
133
132
|
)
|
package/src/transforms/rgf.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { PluginArg, PluginObject } from "./plugin";
|
|
|
3
3
|
import { Order } from "../order";
|
|
4
4
|
import * as t from "@babel/types";
|
|
5
5
|
import Obfuscator from "../obfuscator";
|
|
6
|
-
import { computeProbabilityMap } from "../probability";
|
|
7
6
|
import {
|
|
8
7
|
append,
|
|
9
8
|
getFunctionName,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
prepend,
|
|
14
13
|
} from "../utils/ast-utils";
|
|
15
14
|
import {
|
|
15
|
+
MULTI_TRANSFORM,
|
|
16
16
|
NodeSymbol,
|
|
17
17
|
PREDICTABLE,
|
|
18
18
|
reservedIdentifiers,
|
|
@@ -24,6 +24,8 @@ import { numericLiteral } from "../utils/node";
|
|
|
24
24
|
import Template from "../templates/template";
|
|
25
25
|
import { createEvalIntegrityTemplate } from "../templates/tamperProtectionTemplates";
|
|
26
26
|
|
|
27
|
+
const RGF_ELIGIBLE = Symbol("rgfEligible");
|
|
28
|
+
|
|
27
29
|
/**
|
|
28
30
|
* RGF (Runtime-Generated-Function) uses the `new Function("code")` syntax to create executable code from strings.
|
|
29
31
|
*
|
|
@@ -96,14 +98,21 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
96
98
|
},
|
|
97
99
|
},
|
|
98
100
|
"FunctionDeclaration|FunctionExpression": {
|
|
99
|
-
|
|
101
|
+
enter(_path) {
|
|
100
102
|
if (!active) return;
|
|
103
|
+
|
|
104
|
+
// On enter, determine if Function is eligible for RGF transformation
|
|
105
|
+
|
|
101
106
|
const path = _path as NodePath<
|
|
102
107
|
t.FunctionDeclaration | t.FunctionExpression
|
|
103
108
|
>;
|
|
104
109
|
|
|
105
110
|
if (me.isSkipped(path)) return;
|
|
106
111
|
|
|
112
|
+
// Skip nested functions if the parent function is already deemed eligible
|
|
113
|
+
if (path.find((p) => p.node[RGF_ELIGIBLE] || p.node[MULTI_TRANSFORM]))
|
|
114
|
+
return;
|
|
115
|
+
|
|
107
116
|
// Skip async and generator functions
|
|
108
117
|
if (path.node.async || path.node.generator) return;
|
|
109
118
|
|
|
@@ -111,10 +120,8 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
111
120
|
if (name === me.options.lock?.countermeasures) return;
|
|
112
121
|
if (me.obfuscator.isInternalVariable(name)) return;
|
|
113
122
|
|
|
114
|
-
me.log(name);
|
|
115
|
-
|
|
116
123
|
if (
|
|
117
|
-
!computeProbabilityMap(
|
|
124
|
+
!me.computeProbabilityMap(
|
|
118
125
|
me.options.rgf,
|
|
119
126
|
name,
|
|
120
127
|
path.getFunctionParent() === null
|
|
@@ -140,13 +147,14 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
140
147
|
|
|
141
148
|
const binding = idPath.scope.getBinding(name);
|
|
142
149
|
if (!binding) {
|
|
143
|
-
|
|
144
|
-
idPath.stop();
|
|
150
|
+
// Global variables are allowed
|
|
145
151
|
return;
|
|
146
152
|
}
|
|
147
153
|
|
|
154
|
+
var isOutsideVariable =
|
|
155
|
+
path.scope.parent.getBinding(name) === binding;
|
|
148
156
|
// If the binding is not in the current scope, it is an outside reference
|
|
149
|
-
if (
|
|
157
|
+
if (isOutsideVariable) {
|
|
150
158
|
identifierPreventingTransform = name;
|
|
151
159
|
idPath.stop();
|
|
152
160
|
}
|
|
@@ -163,9 +171,24 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
163
171
|
return;
|
|
164
172
|
}
|
|
165
173
|
|
|
174
|
+
me.log("Function " + name + " is eligible for RGF transformation");
|
|
175
|
+
path.node[RGF_ELIGIBLE] = true;
|
|
176
|
+
},
|
|
177
|
+
exit(_path) {
|
|
178
|
+
if (!active) return;
|
|
179
|
+
|
|
180
|
+
const path = _path as NodePath<
|
|
181
|
+
t.FunctionDeclaration | t.FunctionExpression
|
|
182
|
+
>;
|
|
183
|
+
|
|
184
|
+
if (me.isSkipped(path)) return;
|
|
185
|
+
|
|
186
|
+
// Function is not eligible for RGF transformation
|
|
187
|
+
if (!path.node[RGF_ELIGIBLE]) return;
|
|
188
|
+
|
|
166
189
|
const embeddedName = me.getPlaceholder() + "_embedded";
|
|
167
190
|
const replacementName = me.getPlaceholder() + "_replacement";
|
|
168
|
-
const
|
|
191
|
+
const argumentsName = me.getPlaceholder() + "_args";
|
|
169
192
|
|
|
170
193
|
const lastNode = t.expressionStatement(t.identifier(embeddedName));
|
|
171
194
|
(lastNode as NodeSymbol)[SKIP] = true;
|
|
@@ -179,10 +202,10 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
179
202
|
t.variableDeclaration("var", [
|
|
180
203
|
t.variableDeclarator(
|
|
181
204
|
t.arrayPattern([
|
|
182
|
-
t.identifier(thisName),
|
|
183
205
|
t.identifier(rgfArrayName),
|
|
206
|
+
t.identifier(argumentsName),
|
|
184
207
|
]),
|
|
185
|
-
t.
|
|
208
|
+
t.identifier("arguments")
|
|
186
209
|
),
|
|
187
210
|
]),
|
|
188
211
|
t.functionDeclaration(
|
|
@@ -196,7 +219,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
196
219
|
t.identifier(replacementName),
|
|
197
220
|
t.identifier("apply")
|
|
198
221
|
),
|
|
199
|
-
[t.
|
|
222
|
+
[t.thisExpression(), t.identifier(argumentsName)]
|
|
200
223
|
)
|
|
201
224
|
),
|
|
202
225
|
])
|
|
@@ -225,16 +248,20 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
225
248
|
.map((plugin) => plugin.pluginInstance.order)
|
|
226
249
|
);
|
|
227
250
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
)
|
|
233
|
-
|
|
251
|
+
// Global Concealing will likely cause issues when Pack is also enabled
|
|
252
|
+
const disallowedTransforms = new Set([Order.GlobalConcealing]);
|
|
253
|
+
|
|
254
|
+
newObfuscator.plugins = newObfuscator.plugins.filter(
|
|
255
|
+
({ pluginInstance }) => {
|
|
256
|
+
return (
|
|
257
|
+
(pluginInstance.order == Order.Preparation ||
|
|
258
|
+
!hasRan.has(pluginInstance.order)) &&
|
|
259
|
+
!disallowedTransforms.has(pluginInstance.order)
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
);
|
|
234
263
|
|
|
235
|
-
newObfuscator.obfuscateAST(evalFile
|
|
236
|
-
disablePack: true,
|
|
237
|
-
});
|
|
264
|
+
newObfuscator.obfuscateAST(evalFile);
|
|
238
265
|
|
|
239
266
|
const generated = Obfuscator.generateCode(evalFile);
|
|
240
267
|
|
|
@@ -272,17 +299,19 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
272
299
|
true
|
|
273
300
|
),
|
|
274
301
|
[
|
|
302
|
+
t.thisExpression(),
|
|
275
303
|
t.arrayExpression([
|
|
276
|
-
t.thisExpression(),
|
|
277
304
|
t.identifier(rgfArrayName),
|
|
305
|
+
t.identifier("arguments"),
|
|
278
306
|
]),
|
|
279
|
-
t.identifier("arguments"),
|
|
280
307
|
]
|
|
281
308
|
)
|
|
282
309
|
),
|
|
283
310
|
])
|
|
284
311
|
);
|
|
285
312
|
|
|
313
|
+
path.skip();
|
|
314
|
+
|
|
286
315
|
me.setFunctionLength(path, originalLength);
|
|
287
316
|
|
|
288
317
|
me.changeData.functions++;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { NodePath } from "@babel/traverse";
|
|
2
1
|
import { PluginArg, PluginObject } from "./plugin";
|
|
3
2
|
import * as t from "@babel/types";
|
|
4
|
-
import { computeProbabilityMap } from "../probability";
|
|
5
3
|
import { getRandomInteger } from "../utils/random-utils";
|
|
6
4
|
import Template from "../templates/template";
|
|
7
5
|
import { Order } from "../order";
|
|
8
6
|
import { isStaticValue } from "../utils/static-utils";
|
|
9
|
-
import {
|
|
7
|
+
import { PREDICTABLE } from "../constants";
|
|
10
8
|
import { numericLiteral } from "../utils/node";
|
|
9
|
+
import { prependProgram } from "../utils/ast-utils";
|
|
11
10
|
|
|
12
11
|
export default ({ Plugin }: PluginArg): PluginObject => {
|
|
13
12
|
const me = Plugin(Order.Shuffle, {
|
|
@@ -16,6 +15,8 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
16
15
|
},
|
|
17
16
|
});
|
|
18
17
|
|
|
18
|
+
let fnName: string | null = null;
|
|
19
|
+
|
|
19
20
|
return {
|
|
20
21
|
visitor: {
|
|
21
22
|
ArrayExpression: {
|
|
@@ -29,10 +30,31 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
29
30
|
|
|
30
31
|
if (illegalElement) return;
|
|
31
32
|
|
|
32
|
-
if (!computeProbabilityMap(me.options.shuffle)) {
|
|
33
|
+
if (!me.computeProbabilityMap(me.options.shuffle)) {
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
// Create un-shuffling function
|
|
38
|
+
if (!fnName) {
|
|
39
|
+
fnName = me.getPlaceholder() + "_shuffle";
|
|
40
|
+
|
|
41
|
+
prependProgram(
|
|
42
|
+
path,
|
|
43
|
+
new Template(
|
|
44
|
+
`
|
|
45
|
+
function ${fnName}(arr, shift) {
|
|
46
|
+
for (var i = 0; i < shift; i++) {
|
|
47
|
+
arr["push"](arr["shift"]());
|
|
48
|
+
}
|
|
49
|
+
return arr;
|
|
50
|
+
}
|
|
51
|
+
`
|
|
52
|
+
)
|
|
53
|
+
.addSymbols(PREDICTABLE)
|
|
54
|
+
.single<t.FunctionDeclaration>()
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
36
58
|
var shift = getRandomInteger(
|
|
37
59
|
1,
|
|
38
60
|
Math.min(30, path.node.elements.length * 6)
|
|
@@ -43,30 +65,10 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
43
65
|
shiftedElements.unshift(shiftedElements.pop());
|
|
44
66
|
}
|
|
45
67
|
|
|
46
|
-
var block = path.find((p) => p.isBlock()) as NodePath<t.Block>;
|
|
47
|
-
|
|
48
|
-
var functionExpression = new Template(
|
|
49
|
-
`
|
|
50
|
-
(function(arr) {
|
|
51
|
-
for (var i = 0; i < {shiftNode}; i++) {
|
|
52
|
-
arr.push(arr.shift());
|
|
53
|
-
}
|
|
54
|
-
return arr;
|
|
55
|
-
})
|
|
56
|
-
`
|
|
57
|
-
).expression<t.FunctionExpression>({
|
|
58
|
-
shiftNode: numericLiteral(shift),
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
(functionExpression as NodeSymbol)[PREDICTABLE] = true;
|
|
62
|
-
|
|
63
|
-
var memberExpression = me
|
|
64
|
-
.getControlObject(block)
|
|
65
|
-
.addProperty(functionExpression);
|
|
66
|
-
|
|
67
68
|
path.replaceWith(
|
|
68
|
-
t.callExpression(
|
|
69
|
+
t.callExpression(t.identifier(fnName), [
|
|
69
70
|
t.arrayExpression(shiftedElements),
|
|
71
|
+
numericLiteral(shift),
|
|
70
72
|
])
|
|
71
73
|
);
|
|
72
74
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CustomStringEncoding } from "../../options";
|
|
2
2
|
import Template from "../../templates/template";
|
|
3
|
-
import {
|
|
3
|
+
import { shuffle } from "../../utils/random-utils";
|
|
4
4
|
import * as t from "@babel/types";
|
|
5
5
|
|
|
6
6
|
let hasAllEncodings = false;
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { PluginArg, PluginObject } from "../plugin";
|
|
2
2
|
import * as t from "@babel/types";
|
|
3
3
|
import { Order } from "../../order";
|
|
4
|
-
import { computeProbabilityMap } from "../../probability";
|
|
5
4
|
import {
|
|
6
5
|
ensureComputedExpression,
|
|
6
|
+
isModuleImport,
|
|
7
7
|
prependProgram,
|
|
8
8
|
} from "../../utils/ast-utils";
|
|
9
9
|
import { numericLiteral } from "../../utils/node";
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
StringCompressionLibraryMinified,
|
|
12
12
|
StringCompressionTemplate,
|
|
13
13
|
} from "../../templates/stringCompressionTemplate";
|
|
14
14
|
import Obfuscator from "../../obfuscator";
|
|
15
15
|
import { createGetGlobalTemplate } from "../../templates/getGlobalTemplate";
|
|
16
16
|
import { NO_RENAME } from "../../constants";
|
|
17
|
-
const
|
|
17
|
+
const LZString = require("lz-string");
|
|
18
18
|
|
|
19
19
|
export default ({ Plugin }: PluginArg): PluginObject => {
|
|
20
20
|
const me = Plugin(Order.StringCompression, {
|
|
@@ -23,6 +23,9 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
23
23
|
},
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
+
// String Compression is only applied to the main obfuscator
|
|
27
|
+
// Any RGF functions will not have string compression due to the size of the decompression function
|
|
28
|
+
|
|
26
29
|
const stringDelimiter = "|";
|
|
27
30
|
|
|
28
31
|
return {
|
|
@@ -36,6 +39,9 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
36
39
|
programPath.traverse({
|
|
37
40
|
StringLiteral: {
|
|
38
41
|
exit: (path) => {
|
|
42
|
+
// Don't change module imports
|
|
43
|
+
if (isModuleImport(path)) return;
|
|
44
|
+
|
|
39
45
|
const originalValue = path.node.value;
|
|
40
46
|
|
|
41
47
|
// Must be at least 3 characters long
|
|
@@ -48,7 +54,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
48
54
|
if (typeof index === "undefined") {
|
|
49
55
|
// Allow user option to skip compression for certain strings
|
|
50
56
|
if (
|
|
51
|
-
!computeProbabilityMap(
|
|
57
|
+
!me.computeProbabilityMap(
|
|
52
58
|
me.options.stringCompression,
|
|
53
59
|
originalValue
|
|
54
60
|
)
|
|
@@ -81,11 +87,10 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
81
87
|
);
|
|
82
88
|
|
|
83
89
|
// Compress the string
|
|
84
|
-
var
|
|
85
|
-
var compressedBase64 =
|
|
86
|
-
Buffer.from(compressedBuffer).toString("base64");
|
|
90
|
+
var compressedString = LZString.compressToUTF16(stringPayload);
|
|
87
91
|
|
|
88
|
-
let
|
|
92
|
+
let stringCompressionLibraryName =
|
|
93
|
+
me.obfuscator.getStringCompressionLibraryName();
|
|
89
94
|
let insertStringCompressionLibrary = !me.obfuscator.parentObfuscator;
|
|
90
95
|
|
|
91
96
|
prependProgram(
|
|
@@ -95,19 +100,23 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
95
100
|
stringName: me.getPlaceholder(),
|
|
96
101
|
stringArray: me.getPlaceholder(),
|
|
97
102
|
stringDelimiter: () => t.stringLiteral(stringDelimiter),
|
|
98
|
-
stringValue: () => t.stringLiteral(
|
|
103
|
+
stringValue: () => t.stringLiteral(compressedString),
|
|
99
104
|
GetGlobalTemplate: createGetGlobalTemplate(me, programPath),
|
|
100
105
|
getGlobalFnName: me.getPlaceholder(),
|
|
101
|
-
|
|
106
|
+
StringCompressionLibrary: stringCompressionLibraryName,
|
|
102
107
|
})
|
|
103
108
|
);
|
|
104
109
|
|
|
105
110
|
if (insertStringCompressionLibrary) {
|
|
106
|
-
// RGF
|
|
111
|
+
// RGF functions should not clone the entire decompression function
|
|
107
112
|
prependProgram(
|
|
108
113
|
programPath,
|
|
109
|
-
Obfuscator.parseCode(
|
|
110
|
-
.
|
|
114
|
+
Obfuscator.parseCode(
|
|
115
|
+
StringCompressionLibraryMinified.replace(
|
|
116
|
+
/{StringCompressionLibrary}/g,
|
|
117
|
+
stringCompressionLibraryName
|
|
118
|
+
)
|
|
119
|
+
).program.body
|
|
111
120
|
)[0]
|
|
112
121
|
.get("declarations")[0]
|
|
113
122
|
.get("id").node[NO_RENAME] = true;
|