js-confuser 2.0.0-alpha.2 → 2.0.0-alpha.3
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/CHANGELOG.md +24 -6
- package/dist/constants.js +6 -2
- package/dist/index.js +12 -0
- package/dist/obfuscator.js +117 -6
- package/dist/order.js +0 -1
- package/dist/probability.js +1 -96
- package/dist/templates/getGlobalTemplate.js +4 -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 +2 -6
- package/dist/transforms/deadCode.js +8 -15
- package/dist/transforms/dispatcher.js +1 -2
- 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 +1 -2
- package/dist/transforms/identifier/movedDeclarations.js +12 -5
- package/dist/transforms/identifier/renameVariables.js +7 -6
- package/dist/transforms/lock/lock.js +9 -2
- package/dist/transforms/minify.js +14 -1
- package/dist/transforms/opaquePredicates.js +5 -6
- package/dist/transforms/pack.js +5 -0
- package/dist/transforms/plugin.js +20 -39
- package/dist/transforms/renameLabels.js +1 -2
- package/dist/transforms/rgf.js +29 -11
- package/dist/transforms/shuffle.js +10 -11
- package/dist/transforms/string/stringCompression.js +14 -10
- package/dist/transforms/string/stringConcealing.js +4 -4
- package/dist/transforms/string/stringEncoding.js +4 -2
- package/dist/transforms/string/stringSplitting.js +4 -2
- package/dist/transforms/variableMasking.js +1 -2
- package/dist/utils/NameGen.js +3 -2
- package/dist/utils/PredicateGen.js +62 -0
- package/dist/utils/ast-utils.js +24 -9
- package/dist/validateOptions.js +2 -2
- package/package.json +2 -2
- package/src/constants.ts +6 -5
- package/src/index.ts +1 -0
- package/src/obfuscator.ts +148 -7
- package/src/options.ts +14 -6
- package/src/order.ts +0 -2
- package/src/probability.ts +0 -110
- package/src/templates/getGlobalTemplate.ts +5 -1
- 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 +2 -7
- package/src/transforms/deadCode.ts +11 -23
- package/src/transforms/dispatcher.ts +1 -2
- 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 +4 -2
- package/src/transforms/identifier/movedDeclarations.ts +18 -6
- package/src/transforms/identifier/renameVariables.ts +10 -6
- package/src/transforms/lock/lock.ts +14 -3
- package/src/transforms/minify.ts +24 -2
- package/src/transforms/opaquePredicates.ts +5 -8
- package/src/transforms/pack.ts +6 -0
- package/src/transforms/plugin.ts +47 -69
- package/src/transforms/renameLabels.ts +1 -2
- package/src/transforms/rgf.ts +39 -14
- 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 +11 -7
- package/src/transforms/string/stringEncoding.ts +6 -2
- package/src/transforms/string/stringSplitting.ts +9 -4
- package/src/transforms/variableMasking.ts +1 -2
- package/src/utils/NameGen.ts +4 -2
- package/src/utils/PredicateGen.ts +61 -0
- package/src/utils/ast-utils.ts +16 -9
- package/src/validateOptions.ts +7 -4
- package/src/transforms/functionOutlining.ts +0 -225
- package/src/utils/ControlObject.ts +0 -141
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
|
])
|
|
@@ -272,17 +295,19 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
272
295
|
true
|
|
273
296
|
),
|
|
274
297
|
[
|
|
298
|
+
t.thisExpression(),
|
|
275
299
|
t.arrayExpression([
|
|
276
|
-
t.thisExpression(),
|
|
277
300
|
t.identifier(rgfArrayName),
|
|
301
|
+
t.identifier("arguments"),
|
|
278
302
|
]),
|
|
279
|
-
t.identifier("arguments"),
|
|
280
303
|
]
|
|
281
304
|
)
|
|
282
305
|
),
|
|
283
306
|
])
|
|
284
307
|
);
|
|
285
308
|
|
|
309
|
+
path.skip();
|
|
310
|
+
|
|
286
311
|
me.setFunctionLength(path, originalLength);
|
|
287
312
|
|
|
288
313
|
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;
|
|
@@ -3,7 +3,6 @@ import { NodePath } from "@babel/traverse";
|
|
|
3
3
|
import Template from "../../templates/template";
|
|
4
4
|
import { PluginArg, PluginObject } from "../plugin";
|
|
5
5
|
import { Order } from "../../order";
|
|
6
|
-
import { computeProbabilityMap } from "../../probability";
|
|
7
6
|
import { ok } from "assert";
|
|
8
7
|
import { BufferToStringTemplate } from "../../templates/bufferToStringTemplate";
|
|
9
8
|
import { createGetGlobalTemplate } from "../../templates/getGlobalTemplate";
|
|
@@ -22,6 +21,7 @@ import {
|
|
|
22
21
|
import { CustomStringEncoding } from "../../options";
|
|
23
22
|
import { createDefaultStringEncoding } from "./encoding";
|
|
24
23
|
import { numericLiteral } from "../../utils/node";
|
|
24
|
+
import { NO_REMOVE } from "../../constants";
|
|
25
25
|
|
|
26
26
|
interface StringConcealingInterface {
|
|
27
27
|
encodingImplementation: CustomStringEncoding;
|
|
@@ -139,7 +139,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
139
139
|
|
|
140
140
|
// Check user setting
|
|
141
141
|
if (
|
|
142
|
-
!computeProbabilityMap(
|
|
142
|
+
!me.computeProbabilityMap(
|
|
143
143
|
me.options.stringConcealing,
|
|
144
144
|
originalValue
|
|
145
145
|
)
|
|
@@ -271,17 +271,21 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
271
271
|
ok(encodingImplementation.code instanceof Template);
|
|
272
272
|
|
|
273
273
|
// The decoder function
|
|
274
|
-
const decoder = encodingImplementation.code
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
274
|
+
const decoder = encodingImplementation.code
|
|
275
|
+
.addSymbols(NO_REMOVE)
|
|
276
|
+
.compile({
|
|
277
|
+
fnName: decodeFnName,
|
|
278
|
+
__bufferToStringFunction__: bufferToStringName,
|
|
279
|
+
});
|
|
278
280
|
|
|
279
281
|
// The main function to get the string value
|
|
280
282
|
const retrieveFunctionDeclaration = new Template(`
|
|
281
283
|
function ${fnName}(index) {
|
|
282
284
|
return ${decodeFnName}(${stringArrayName}[index]);
|
|
283
285
|
}
|
|
284
|
-
`)
|
|
286
|
+
`)
|
|
287
|
+
.addSymbols(NO_REMOVE)
|
|
288
|
+
.single<t.FunctionDeclaration>();
|
|
285
289
|
|
|
286
290
|
prepend(block, [...decoder, retrieveFunctionDeclaration]);
|
|
287
291
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { PluginInstance, PluginObject } from "../plugin";
|
|
2
2
|
import * as t from "@babel/types";
|
|
3
3
|
import { choice } from "../../utils/random-utils";
|
|
4
|
-
import { computeProbabilityMap } from "../../probability";
|
|
5
4
|
import { GEN_NODE, NodeSymbol } from "../../constants";
|
|
5
|
+
import { isModuleImport } from "../../utils/ast-utils";
|
|
6
6
|
|
|
7
7
|
function pad(x: string, len: number): string {
|
|
8
8
|
while (x.length < len) {
|
|
@@ -51,10 +51,14 @@ export default (me: PluginInstance): PluginObject => {
|
|
|
51
51
|
visitor: {
|
|
52
52
|
StringLiteral: {
|
|
53
53
|
exit(path) {
|
|
54
|
+
// Ignore module imports
|
|
55
|
+
if (isModuleImport(path)) return;
|
|
56
|
+
|
|
54
57
|
const { value } = path.node;
|
|
55
58
|
|
|
56
59
|
// Allow percentages
|
|
57
|
-
if (!computeProbabilityMap(me.options.stringEncoding, value))
|
|
60
|
+
if (!me.computeProbabilityMap(me.options.stringEncoding, value))
|
|
61
|
+
return;
|
|
58
62
|
|
|
59
63
|
var type = choice(["hexadecimal", "unicode"]);
|
|
60
64
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { PluginArg,
|
|
1
|
+
import { PluginArg, PluginObject } from "../plugin";
|
|
2
2
|
import { getRandomInteger, splitIntoChunks } from "../../utils/random-utils";
|
|
3
|
-
import { computeProbabilityMap } from "../../probability";
|
|
4
3
|
import { binaryExpression, stringLiteral } from "@babel/types";
|
|
5
4
|
import { ok } from "assert";
|
|
6
5
|
import { Order } from "../../order";
|
|
7
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ensureComputedExpression,
|
|
8
|
+
isModuleImport,
|
|
9
|
+
} from "../../utils/ast-utils";
|
|
8
10
|
|
|
9
11
|
export default ({ Plugin }: PluginArg): PluginObject => {
|
|
10
12
|
const me = Plugin(Order.StringSplitting, {
|
|
@@ -19,6 +21,9 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
19
21
|
exit(path) {
|
|
20
22
|
var object = path.node;
|
|
21
23
|
|
|
24
|
+
// Don't change module imports
|
|
25
|
+
if (isModuleImport(path)) return;
|
|
26
|
+
|
|
22
27
|
var size = Math.round(
|
|
23
28
|
Math.max(6, object.value.length / getRandomInteger(3, 8))
|
|
24
29
|
);
|
|
@@ -32,7 +37,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
if (
|
|
35
|
-
!computeProbabilityMap(me.options.stringSplitting, object.value)
|
|
40
|
+
!me.computeProbabilityMap(me.options.stringSplitting, object.value)
|
|
36
41
|
) {
|
|
37
42
|
return;
|
|
38
43
|
}
|
|
@@ -2,7 +2,6 @@ import { Binding, NodePath } from "@babel/traverse";
|
|
|
2
2
|
import { PluginArg, PluginObject } from "./plugin";
|
|
3
3
|
import * as t from "@babel/types";
|
|
4
4
|
import Template from "../templates/template";
|
|
5
|
-
import { computeProbabilityMap } from "../probability";
|
|
6
5
|
import { Order } from "../order";
|
|
7
6
|
import {
|
|
8
7
|
NodeSymbol,
|
|
@@ -65,7 +64,7 @@ export default ({ Plugin }: PluginArg): PluginObject => {
|
|
|
65
64
|
|
|
66
65
|
const functionName = getFunctionName(fnPath);
|
|
67
66
|
|
|
68
|
-
if (!computeProbabilityMap(me.options.variableMasking, functionName)) {
|
|
67
|
+
if (!me.computeProbabilityMap(me.options.variableMasking, functionName)) {
|
|
69
68
|
return;
|
|
70
69
|
}
|
|
71
70
|
|
package/src/utils/NameGen.ts
CHANGED
|
@@ -2,8 +2,8 @@ import { ok } from "assert";
|
|
|
2
2
|
import { ObfuscateOptions } from "../options";
|
|
3
3
|
import { alphabeticalGenerator, createZeroWidthGenerator } from "./gen-utils";
|
|
4
4
|
import { choice, getRandomHexString, getRandomInteger } from "./random-utils";
|
|
5
|
-
import { computeProbabilityMap } from "../probability";
|
|
6
5
|
import { reservedKeywords, reservedObjectPrototype } from "../constants";
|
|
6
|
+
import Obfuscator from "../obfuscator";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Generate random names for variables and properties.
|
|
@@ -33,7 +33,9 @@ export class NameGen {
|
|
|
33
33
|
return value;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
var mode = computeProbabilityMap(
|
|
36
|
+
var mode = Obfuscator.prototype.computeProbabilityMap(
|
|
37
|
+
this.identifierGenerator
|
|
38
|
+
);
|
|
37
39
|
|
|
38
40
|
const randomizedLength = getRandomInteger(6, 8);
|
|
39
41
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { NodePath } from "@babel/traverse";
|
|
2
|
+
import { PluginInstance } from "../transforms/plugin";
|
|
3
|
+
import * as t from "@babel/types";
|
|
4
|
+
import { prepend } from "./ast-utils";
|
|
5
|
+
import { NameGen } from "./NameGen";
|
|
6
|
+
import Template from "../templates/template";
|
|
7
|
+
|
|
8
|
+
export default class PredicateGen {
|
|
9
|
+
constructor(public plugin: PluginInstance) {}
|
|
10
|
+
|
|
11
|
+
dummyFunctionName: string | null = null;
|
|
12
|
+
programPath: NodePath<t.Program> | null = null;
|
|
13
|
+
|
|
14
|
+
ensureCreated() {
|
|
15
|
+
if (this.dummyFunctionName) return;
|
|
16
|
+
|
|
17
|
+
this.dummyFunctionName = this.plugin.getPlaceholder("dummyFunction");
|
|
18
|
+
|
|
19
|
+
// Insert dummy function
|
|
20
|
+
prepend(
|
|
21
|
+
this.programPath,
|
|
22
|
+
|
|
23
|
+
this.plugin.skip(
|
|
24
|
+
t.functionDeclaration(
|
|
25
|
+
t.identifier(this.dummyFunctionName),
|
|
26
|
+
[],
|
|
27
|
+
t.blockStatement([])
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
generateTrueExpression(path: NodePath): t.Expression {
|
|
34
|
+
return t.unaryExpression("!", this.generateFalseExpression(path));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
generateFalseExpression(path: NodePath): t.Expression {
|
|
38
|
+
this.programPath = path.find((p) => p.isProgram()) as NodePath<t.Program>;
|
|
39
|
+
this.ensureCreated();
|
|
40
|
+
|
|
41
|
+
// Overcomplicated way to get a random property name that doesn't exist on the Function
|
|
42
|
+
var randomProperty: string;
|
|
43
|
+
var nameGen = new NameGen("randomized");
|
|
44
|
+
|
|
45
|
+
function PrototypeCollision() {}
|
|
46
|
+
PrototypeCollision(); // Call it for code coverage :D
|
|
47
|
+
|
|
48
|
+
do {
|
|
49
|
+
randomProperty = nameGen.generate();
|
|
50
|
+
} while (
|
|
51
|
+
!randomProperty ||
|
|
52
|
+
PrototypeCollision[randomProperty] !== undefined
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return this.plugin.skip(
|
|
56
|
+
new Template(
|
|
57
|
+
`"${randomProperty}" in ${this.dummyFunctionName}`
|
|
58
|
+
).expression()
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
package/src/utils/ast-utils.ts
CHANGED
|
@@ -312,17 +312,21 @@ export function prepend(
|
|
|
312
312
|
// Preserve import declarations
|
|
313
313
|
// Filter out import declarations
|
|
314
314
|
const body = listParent.get("body");
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
315
|
+
let afterImport = 0;
|
|
316
|
+
for (var stmt of body) {
|
|
317
|
+
if (!stmt.isImportDeclaration()) {
|
|
318
|
+
break;
|
|
319
|
+
}
|
|
320
|
+
afterImport++;
|
|
321
|
+
}
|
|
318
322
|
|
|
319
|
-
if (
|
|
320
|
-
// No
|
|
323
|
+
if (afterImport === 0) {
|
|
324
|
+
// No import declarations, so we can safely unshift everything
|
|
321
325
|
return registerPaths(listParent.unshiftContainer("body", nodes));
|
|
322
|
-
} else {
|
|
323
|
-
// Insert the nodes after the last import declaration
|
|
324
|
-
return registerPaths(body[lastImportIndex - 1].insertAfter(nodes));
|
|
325
326
|
}
|
|
327
|
+
|
|
328
|
+
// Insert the nodes after the last import declaration
|
|
329
|
+
return registerPaths(body[afterImport - 1].insertAfter(nodes));
|
|
326
330
|
}
|
|
327
331
|
|
|
328
332
|
if (listParent.isFunction()) {
|
|
@@ -343,7 +347,9 @@ export function prepend(
|
|
|
343
347
|
|
|
344
348
|
if (listParent.isBlock()) {
|
|
345
349
|
return registerPaths(listParent.unshiftContainer("body", nodes));
|
|
346
|
-
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (listParent.isSwitchCase()) {
|
|
347
353
|
return registerPaths(listParent.unshiftContainer("consequent", nodes));
|
|
348
354
|
}
|
|
349
355
|
|
|
@@ -356,6 +362,7 @@ export function prependProgram(
|
|
|
356
362
|
) {
|
|
357
363
|
var program = path.find((p) => p.isProgram());
|
|
358
364
|
ok(program);
|
|
365
|
+
ok(program.isProgram());
|
|
359
366
|
return prepend(program, ...nodes);
|
|
360
367
|
}
|
|
361
368
|
|
package/src/validateOptions.ts
CHANGED
|
@@ -190,10 +190,6 @@ export function applyDefaultsToOptions(
|
|
|
190
190
|
"alert",
|
|
191
191
|
"confirm",
|
|
192
192
|
"location",
|
|
193
|
-
"btoa",
|
|
194
|
-
"atob",
|
|
195
|
-
"unescape",
|
|
196
|
-
"encodeURIComponent",
|
|
197
193
|
].forEach((x) => options.globalVariables.add(x));
|
|
198
194
|
} else {
|
|
199
195
|
// node
|
|
@@ -248,7 +244,14 @@ export function applyDefaultsToOptions(
|
|
|
248
244
|
"Uint8Array",
|
|
249
245
|
"Uint16Array",
|
|
250
246
|
"Uint32Array",
|
|
247
|
+
"Int8Array",
|
|
248
|
+
"Int16Array",
|
|
249
|
+
"Int32Array",
|
|
251
250
|
"ArrayBuffer",
|
|
251
|
+
"btoa",
|
|
252
|
+
"atob",
|
|
253
|
+
"unescape",
|
|
254
|
+
"encodeURIComponent",
|
|
252
255
|
].forEach((x) => options.globalVariables.add(x));
|
|
253
256
|
}
|
|
254
257
|
|