js-confuser 1.7.1 → 1.7.2
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 +38 -0
- package/README.md +12 -27
- package/dist/compiler.js +2 -8
- package/dist/constants.js +17 -10
- package/dist/index.js +7 -30
- package/dist/obfuscator.js +15 -62
- package/dist/options.js +21 -38
- package/dist/order.js +4 -7
- package/dist/parser.js +5 -13
- package/dist/precedence.js +6 -8
- package/dist/presets.js +4 -6
- package/dist/probability.js +13 -24
- package/dist/templates/bufferToString.js +100 -5
- package/dist/templates/crash.js +51 -9
- package/dist/templates/es5.js +125 -6
- package/dist/templates/functionLength.js +24 -6
- package/dist/templates/globals.js +9 -0
- package/dist/templates/template.js +71 -30
- package/dist/transforms/antiTooling.js +26 -22
- package/dist/transforms/calculator.js +18 -54
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +236 -333
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
- package/dist/transforms/deadCode.js +528 -27
- package/dist/transforms/dispatcher.js +106 -110
- package/dist/transforms/es5/antiClass.js +70 -44
- package/dist/transforms/es5/antiDestructuring.js +14 -38
- package/dist/transforms/es5/antiES6Object.js +39 -48
- package/dist/transforms/es5/antiSpreadOperator.js +5 -14
- package/dist/transforms/es5/antiTemplate.js +10 -19
- package/dist/transforms/es5/es5.js +7 -40
- package/dist/transforms/extraction/classExtraction.js +83 -0
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
- package/dist/transforms/extraction/objectExtraction.js +24 -56
- package/dist/transforms/finalizer.js +6 -20
- package/dist/transforms/flatten.js +51 -99
- package/dist/transforms/identifier/globalAnalysis.js +8 -26
- package/dist/transforms/identifier/globalConcealing.js +35 -54
- package/dist/transforms/identifier/movedDeclarations.js +66 -38
- package/dist/transforms/identifier/renameVariables.js +29 -68
- package/dist/transforms/identifier/variableAnalysis.js +21 -48
- package/dist/transforms/lock/antiDebug.js +20 -25
- package/dist/transforms/lock/integrity.js +48 -47
- package/dist/transforms/lock/lock.js +62 -113
- package/dist/transforms/minify.js +77 -108
- package/dist/transforms/opaquePredicates.js +11 -48
- package/dist/transforms/preparation.js +17 -50
- package/dist/transforms/renameLabels.js +5 -22
- package/dist/transforms/rgf.js +93 -69
- package/dist/transforms/shuffle.js +41 -46
- package/dist/transforms/stack.js +35 -98
- package/dist/transforms/string/encoding.js +73 -27
- package/dist/transforms/string/stringCompression.js +44 -68
- package/dist/transforms/string/stringConcealing.js +125 -134
- package/dist/transforms/string/stringEncoding.js +6 -26
- package/dist/transforms/string/stringSplitting.js +5 -30
- package/dist/transforms/transform.js +50 -100
- package/dist/traverse.js +11 -18
- package/dist/util/compare.js +27 -29
- package/dist/util/gen.js +32 -86
- package/dist/util/guard.js +0 -1
- package/dist/util/identifiers.js +9 -72
- package/dist/util/insert.js +27 -77
- package/dist/util/math.js +0 -3
- package/dist/util/object.js +3 -7
- package/dist/util/random.js +5 -36
- package/dist/util/scope.js +6 -3
- package/package.json +3 -3
- package/src/constants.ts +12 -0
- package/src/options.ts +13 -0
- package/src/order.ts +2 -2
- package/src/templates/bufferToString.ts +49 -11
- package/src/templates/functionLength.ts +21 -3
- package/src/templates/globals.ts +3 -0
- package/src/templates/template.ts +85 -25
- package/src/transforms/antiTooling.ts +33 -11
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +2 -2
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
- package/src/transforms/deadCode.ts +0 -16
- package/src/transforms/dispatcher.ts +91 -69
- package/src/transforms/es5/antiClass.ts +10 -1
- package/src/transforms/extraction/classExtraction.ts +168 -0
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -10
- package/src/transforms/extraction/objectExtraction.ts +4 -15
- package/src/transforms/flatten.ts +20 -5
- package/src/transforms/identifier/globalConcealing.ts +29 -65
- package/src/transforms/identifier/movedDeclarations.ts +90 -24
- package/src/transforms/minify.ts +27 -12
- package/src/transforms/rgf.ts +94 -5
- package/src/transforms/stack.ts +12 -3
- package/src/transforms/string/encoding.ts +85 -51
- package/src/transforms/string/stringCompression.ts +5 -8
- package/src/transforms/string/stringConcealing.ts +139 -113
- package/src/transforms/string/stringEncoding.ts +1 -2
- package/src/transforms/string/stringSplitting.ts +1 -2
- package/src/transforms/transform.ts +30 -1
- package/src/util/compare.ts +39 -5
- package/src/util/gen.ts +10 -3
- package/src/util/insert.ts +17 -0
- package/src/util/scope.ts +14 -2
- package/test/code/Cash.test.ts +10 -4
- package/test/code/StrictMode.src.js +65 -0
- package/test/code/StrictMode.test.js +37 -0
- package/test/compare.test.ts +62 -2
- package/test/options.test.ts +111 -55
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
- package/test/transforms/dispatcher.test.ts +55 -0
- package/test/transforms/extraction/classExtraction.test.ts +86 -0
- package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
- package/test/transforms/extraction/objectExtraction.test.ts +2 -0
- package/test/transforms/identifier/globalConcealing.test.ts +19 -0
- package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
- package/test/transforms/minify.test.ts +37 -0
- package/test/transforms/rgf.test.ts +50 -0
- package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
- package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
- package/dist/transforms/eval.js +0 -84
- package/dist/transforms/hexadecimalNumbers.js +0 -63
- package/dist/transforms/hideInitializingCode.js +0 -270
- package/dist/transforms/identifier/nameRecycling.js +0 -218
- package/dist/transforms/label.js +0 -67
- package/dist/transforms/preparation/nameConflicts.js +0 -116
- package/dist/transforms/preparation/preparation.js +0 -188
|
@@ -22,9 +22,10 @@ import {
|
|
|
22
22
|
} from "../../util/gen";
|
|
23
23
|
import { append, prepend } from "../../util/insert";
|
|
24
24
|
import { chance, getRandomInteger } from "../../util/random";
|
|
25
|
-
import { reservedIdentifiers } from "../../constants";
|
|
25
|
+
import { predictableFunctionTag, reservedIdentifiers } from "../../constants";
|
|
26
26
|
import { ComputeProbabilityMap } from "../../probability";
|
|
27
27
|
import GlobalAnalysis from "./globalAnalysis";
|
|
28
|
+
import { GetGlobalTemplate } from "../../templates/bufferToString";
|
|
28
29
|
|
|
29
30
|
/**
|
|
30
31
|
* Global Concealing hides global variables being accessed.
|
|
@@ -33,6 +34,7 @@ import GlobalAnalysis from "./globalAnalysis";
|
|
|
33
34
|
*/
|
|
34
35
|
export default class GlobalConcealing extends Transform {
|
|
35
36
|
globalAnalysis: GlobalAnalysis;
|
|
37
|
+
ignoreGlobals = new Set(["require", "__dirname", "eval"]);
|
|
36
38
|
|
|
37
39
|
constructor(o) {
|
|
38
40
|
super(o, ObfuscateOrder.GlobalConcealing);
|
|
@@ -52,7 +54,9 @@ export default class GlobalConcealing extends Transform {
|
|
|
52
54
|
delete globals[del];
|
|
53
55
|
});
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
for (var varName of this.ignoreGlobals) {
|
|
58
|
+
delete globals[varName];
|
|
59
|
+
}
|
|
56
60
|
|
|
57
61
|
reservedIdentifiers.forEach((x) => {
|
|
58
62
|
delete globals[x];
|
|
@@ -69,55 +73,33 @@ export default class GlobalConcealing extends Transform {
|
|
|
69
73
|
});
|
|
70
74
|
|
|
71
75
|
if (Object.keys(globals).length > 0) {
|
|
72
|
-
var
|
|
76
|
+
var usedStates = new Set<number>();
|
|
73
77
|
|
|
74
78
|
// Make getter function
|
|
75
79
|
|
|
76
80
|
// holds "window" or "global"
|
|
77
81
|
var globalVar = this.getPlaceholder();
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
// "window" or "global" in node
|
|
83
|
-
var global =
|
|
84
|
-
this.options.globalVariables.values().next().value || "window";
|
|
85
|
-
var alternateGlobal = global === "window" ? "global" : "window";
|
|
86
|
-
|
|
87
|
-
var getGlobalVariableFnName = this.getPlaceholder();
|
|
88
|
-
var getThisVariableFnName = this.getPlaceholder();
|
|
83
|
+
var getGlobalVariableFnName =
|
|
84
|
+
this.getPlaceholder() + predictableFunctionTag;
|
|
89
85
|
|
|
90
86
|
// Returns global variable or fall backs to `this`
|
|
91
|
-
var getGlobalVariableFn =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
return ${global} || ${alternateGlobal} || (new Function("return this"))();
|
|
95
|
-
} catch (e){
|
|
96
|
-
return ${getThisVariableFnName}["call"](this);
|
|
97
|
-
}
|
|
98
|
-
}`).single();
|
|
99
|
-
|
|
100
|
-
var getThisVariableFn = Template(`
|
|
101
|
-
var ${getThisVariableFnName} = function(){
|
|
102
|
-
try {
|
|
103
|
-
return this;
|
|
104
|
-
} catch (e){
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
}`).single();
|
|
87
|
+
var getGlobalVariableFn = GetGlobalTemplate.compile({
|
|
88
|
+
getGlobalFnName: getGlobalVariableFnName,
|
|
89
|
+
});
|
|
108
90
|
|
|
109
91
|
// 2. Replace old accessors
|
|
110
|
-
var globalFn = this.getPlaceholder();
|
|
92
|
+
var globalFn = this.getPlaceholder() + predictableFunctionTag;
|
|
111
93
|
|
|
112
94
|
var newNames: { [globalVarName: string]: number } = Object.create(null);
|
|
113
95
|
|
|
114
96
|
Object.keys(globals).forEach((name) => {
|
|
115
97
|
var locations: Location[] = globals[name];
|
|
116
|
-
var state;
|
|
98
|
+
var state: number;
|
|
117
99
|
do {
|
|
118
|
-
state = getRandomInteger(-1000, 1000 +
|
|
119
|
-
} while (
|
|
120
|
-
|
|
100
|
+
state = getRandomInteger(-1000, 1000 + usedStates.size);
|
|
101
|
+
} while (usedStates.has(state));
|
|
102
|
+
usedStates.add(state);
|
|
121
103
|
|
|
122
104
|
newNames[name] = state;
|
|
123
105
|
|
|
@@ -136,10 +118,10 @@ export default class GlobalConcealing extends Transform {
|
|
|
136
118
|
do {
|
|
137
119
|
state = getRandomInteger(
|
|
138
120
|
0,
|
|
139
|
-
1000 +
|
|
121
|
+
1000 + usedStates.size + this.options.globalVariables.size * 100
|
|
140
122
|
);
|
|
141
|
-
} while (
|
|
142
|
-
|
|
123
|
+
} while (usedStates.has(state));
|
|
124
|
+
usedStates.add(state);
|
|
143
125
|
|
|
144
126
|
newNames[name] = state;
|
|
145
127
|
}
|
|
@@ -159,15 +141,7 @@ export default class GlobalConcealing extends Transform {
|
|
|
159
141
|
var code = newNames[name];
|
|
160
142
|
var body: Node[] = [
|
|
161
143
|
ReturnStatement(
|
|
162
|
-
|
|
163
|
-
"||",
|
|
164
|
-
MemberExpression(
|
|
165
|
-
Identifier(globalVar),
|
|
166
|
-
Literal(name),
|
|
167
|
-
true
|
|
168
|
-
),
|
|
169
|
-
MemberExpression(Identifier(thisVar), Literal(name), true)
|
|
170
|
-
)
|
|
144
|
+
MemberExpression(Identifier(globalVar), Literal(name), true)
|
|
171
145
|
),
|
|
172
146
|
];
|
|
173
147
|
if (chance(50)) {
|
|
@@ -180,7 +154,7 @@ export default class GlobalConcealing extends Transform {
|
|
|
180
154
|
"||",
|
|
181
155
|
Literal(name),
|
|
182
156
|
MemberExpression(
|
|
183
|
-
Identifier(
|
|
157
|
+
Identifier(globalVar),
|
|
184
158
|
Literal(name),
|
|
185
159
|
true
|
|
186
160
|
)
|
|
@@ -195,18 +169,10 @@ export default class GlobalConcealing extends Transform {
|
|
|
195
169
|
})
|
|
196
170
|
),
|
|
197
171
|
ReturnStatement(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
Identifier(returnName),
|
|
203
|
-
true
|
|
204
|
-
),
|
|
205
|
-
MemberExpression(
|
|
206
|
-
Identifier(thisVar),
|
|
207
|
-
Identifier(returnName),
|
|
208
|
-
true
|
|
209
|
-
)
|
|
172
|
+
MemberExpression(
|
|
173
|
+
Identifier(globalVar),
|
|
174
|
+
Identifier(returnName),
|
|
175
|
+
true
|
|
210
176
|
)
|
|
211
177
|
),
|
|
212
178
|
]
|
|
@@ -215,7 +181,7 @@ export default class GlobalConcealing extends Transform {
|
|
|
215
181
|
var tempVar = this.getPlaceholder();
|
|
216
182
|
|
|
217
183
|
var variableDeclaration = Template(`
|
|
218
|
-
var ${globalVar}
|
|
184
|
+
var ${globalVar};
|
|
219
185
|
`).single();
|
|
220
186
|
|
|
221
187
|
variableDeclaration.declarations.push(
|
|
@@ -226,11 +192,9 @@ export default class GlobalConcealing extends Transform {
|
|
|
226
192
|
FunctionExpression(
|
|
227
193
|
[],
|
|
228
194
|
[
|
|
229
|
-
getGlobalVariableFn,
|
|
230
|
-
getThisVariableFn,
|
|
231
|
-
|
|
195
|
+
...getGlobalVariableFn,
|
|
232
196
|
Template(
|
|
233
|
-
`return ${
|
|
197
|
+
`return ${globalVar} = ${getGlobalVariableFnName}["call"](this)`
|
|
234
198
|
).single(),
|
|
235
199
|
]
|
|
236
200
|
),
|
|
@@ -6,10 +6,21 @@ import {
|
|
|
6
6
|
Identifier,
|
|
7
7
|
Node,
|
|
8
8
|
VariableDeclarator,
|
|
9
|
+
AssignmentPattern,
|
|
9
10
|
} from "../../util/gen";
|
|
10
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
isForInitialize,
|
|
13
|
+
isFunction,
|
|
14
|
+
isStrictModeFunction,
|
|
15
|
+
prepend,
|
|
16
|
+
} from "../../util/insert";
|
|
11
17
|
import { ok } from "assert";
|
|
12
18
|
import { ObfuscateOrder } from "../../order";
|
|
19
|
+
import { choice } from "../../util/random";
|
|
20
|
+
import { predictableFunctionTag } from "../../constants";
|
|
21
|
+
import { isIndependent, isMoveable } from "../../util/compare";
|
|
22
|
+
import { getFunctionParameters } from "../../util/identifiers";
|
|
23
|
+
import { isLexicalScope } from "../../util/scope";
|
|
13
24
|
|
|
14
25
|
/**
|
|
15
26
|
* Defines all the names at the top of every lexical block.
|
|
@@ -33,35 +44,86 @@ export default class MovedDeclarations extends Transform {
|
|
|
33
44
|
var forInitializeType = isForInitialize(object, parents);
|
|
34
45
|
|
|
35
46
|
// Get the block statement or Program node
|
|
36
|
-
var blockIndex = parents.findIndex((x) =>
|
|
47
|
+
var blockIndex = parents.findIndex((x) => isLexicalScope(x));
|
|
37
48
|
var block = parents[blockIndex];
|
|
38
|
-
var body =
|
|
39
|
-
|
|
49
|
+
var body: Node[] =
|
|
50
|
+
block.type === "SwitchCase" ? block.consequent : block.body;
|
|
51
|
+
ok(Array.isArray(body), "No body array found.");
|
|
40
52
|
|
|
41
|
-
|
|
53
|
+
var bodyObject = parents[blockIndex - 2] || object;
|
|
42
54
|
var index = body.indexOf(bodyObject);
|
|
43
|
-
if (index === -1 || index === 0) return;
|
|
44
55
|
|
|
45
|
-
var
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
var varName = object.declarations[0].id.name;
|
|
57
|
+
ok(typeof varName === "string");
|
|
58
|
+
|
|
59
|
+
var predictableFunctionIndex = parents.findIndex((x) => isFunction(x));
|
|
60
|
+
var predictableFunction = parents[predictableFunctionIndex];
|
|
61
|
+
|
|
62
|
+
var deleteStatement = false;
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
predictableFunction &&
|
|
66
|
+
((predictableFunction.id &&
|
|
67
|
+
predictableFunction.id.name.includes(predictableFunctionTag)) ||
|
|
68
|
+
predictableFunction[predictableFunctionTag]) && // Must have predictableFunctionTag in the name, or on object
|
|
69
|
+
predictableFunction[predictableFunctionTag] !== false && // If === false, the function is deemed not predictable
|
|
70
|
+
predictableFunction.params.length < 1000 && // Max 1,000 parameters
|
|
71
|
+
!predictableFunction.params.find((x) => x.type === "RestElement") && // Cannot add parameters after spread operator
|
|
72
|
+
!(
|
|
73
|
+
["Property", "MethodDefinition"].includes(
|
|
74
|
+
parents[predictableFunctionIndex + 1]?.type
|
|
75
|
+
) && parents[predictableFunctionIndex + 1]?.kind !== "init"
|
|
76
|
+
) && // Preserve getter/setter methods
|
|
77
|
+
!getFunctionParameters(
|
|
78
|
+
predictableFunction,
|
|
79
|
+
parents.slice(predictableFunctionIndex)
|
|
80
|
+
).find((entry) => entry[0].name === varName) // Ensure not duplicate param name
|
|
81
|
+
) {
|
|
82
|
+
// Use function f(..., x, y, z) to declare name
|
|
83
|
+
|
|
84
|
+
var value = object.declarations[0].init;
|
|
85
|
+
var isPredictablyComputed =
|
|
86
|
+
predictableFunction.body === block &&
|
|
87
|
+
!isStrictModeFunction(predictableFunction) &&
|
|
88
|
+
value &&
|
|
89
|
+
isIndependent(value, []) &&
|
|
90
|
+
isMoveable(value, [object.declarations[0], object, ...parents]);
|
|
91
|
+
|
|
92
|
+
var defineWithValue = isPredictablyComputed;
|
|
93
|
+
|
|
94
|
+
if (defineWithValue) {
|
|
95
|
+
predictableFunction.params.push(
|
|
96
|
+
AssignmentPattern(Identifier(varName), value)
|
|
97
|
+
);
|
|
98
|
+
object.declarations[0].init = null;
|
|
99
|
+
deleteStatement = true;
|
|
100
|
+
} else {
|
|
101
|
+
predictableFunction.params.push(Identifier(varName));
|
|
102
|
+
}
|
|
48
103
|
} else {
|
|
49
|
-
|
|
50
|
-
type: "VariableDeclaration",
|
|
51
|
-
declarations: [],
|
|
52
|
-
kind: "var",
|
|
53
|
-
};
|
|
104
|
+
// Use 'var x, y, z' to declare name
|
|
54
105
|
|
|
55
|
-
|
|
56
|
-
|
|
106
|
+
// Make sure in the block statement, and not already at the top of it
|
|
107
|
+
if (index === -1 || index === 0) return;
|
|
57
108
|
|
|
58
|
-
|
|
59
|
-
|
|
109
|
+
var topVariableDeclaration;
|
|
110
|
+
if (body[0].type === "VariableDeclaration" && body[0].kind === "var") {
|
|
111
|
+
topVariableDeclaration = body[0];
|
|
112
|
+
} else {
|
|
113
|
+
topVariableDeclaration = {
|
|
114
|
+
type: "VariableDeclaration",
|
|
115
|
+
declarations: [],
|
|
116
|
+
kind: "var",
|
|
117
|
+
};
|
|
60
118
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
119
|
+
prepend(block, topVariableDeclaration);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Add `var x` at the top of the block
|
|
123
|
+
topVariableDeclaration.declarations.push(
|
|
124
|
+
VariableDeclarator(Identifier(varName))
|
|
125
|
+
);
|
|
126
|
+
}
|
|
65
127
|
|
|
66
128
|
var assignmentExpression = AssignmentExpression(
|
|
67
129
|
"=",
|
|
@@ -79,8 +141,12 @@ export default class MovedDeclarations extends Transform {
|
|
|
79
141
|
this.replace(object, Identifier(varName));
|
|
80
142
|
}
|
|
81
143
|
} else {
|
|
82
|
-
|
|
83
|
-
|
|
144
|
+
if (deleteStatement && index !== -1) {
|
|
145
|
+
body.splice(index, 1);
|
|
146
|
+
} else {
|
|
147
|
+
// Replace `var x = value` to `x = value`
|
|
148
|
+
this.replace(object, ExpressionStatement(assignmentExpression));
|
|
149
|
+
}
|
|
84
150
|
}
|
|
85
151
|
};
|
|
86
152
|
}
|
package/src/transforms/minify.ts
CHANGED
|
@@ -29,6 +29,8 @@ import { walk, isBlock } from "../traverse";
|
|
|
29
29
|
import { ok } from "assert";
|
|
30
30
|
import { isLexicalScope } from "../util/scope";
|
|
31
31
|
import Template from "../templates/template";
|
|
32
|
+
import { ObjectDefineProperty } from "../templates/globals";
|
|
33
|
+
import { getIdentifierInfo } from "../util/identifiers";
|
|
32
34
|
|
|
33
35
|
/**
|
|
34
36
|
* Basic transformations to reduce code size.
|
|
@@ -259,25 +261,34 @@ export default class Minify extends Transform {
|
|
|
259
261
|
append(
|
|
260
262
|
parents[parents.length - 1] || object,
|
|
261
263
|
Template(`
|
|
262
|
-
function ${this.arrowFunctionName}(arrowFn, functionLength){
|
|
264
|
+
function ${this.arrowFunctionName}(arrowFn, functionLength = 0){
|
|
263
265
|
var functionObject = function(){ return arrowFn(...arguments) };
|
|
264
266
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
267
|
+
${
|
|
268
|
+
this.options.preserveFunctionLength
|
|
269
|
+
? `return {ObjectDefineProperty}(functionObject, "length", {
|
|
270
|
+
"value": functionLength,
|
|
271
|
+
"configurable": true
|
|
272
|
+
});`
|
|
273
|
+
: `return functionObject`
|
|
274
|
+
}
|
|
275
|
+
|
|
271
276
|
}
|
|
272
|
-
`).single(
|
|
277
|
+
`).single({
|
|
278
|
+
ObjectDefineProperty: this.options.preserveFunctionLength
|
|
279
|
+
? this.createInitVariable(ObjectDefineProperty, parents)
|
|
280
|
+
: undefined,
|
|
281
|
+
})
|
|
273
282
|
);
|
|
274
283
|
}
|
|
275
284
|
|
|
276
285
|
const wrap = (object: Node) => {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
286
|
+
var args: Node[] = [clone(object)];
|
|
287
|
+
var fnLength = computeFunctionLength(object.params);
|
|
288
|
+
if (this.options.preserveFunctionLength && fnLength != 0) {
|
|
289
|
+
args.push(Literal(fnLength));
|
|
290
|
+
}
|
|
291
|
+
return CallExpression(Identifier(this.arrowFunctionName), args);
|
|
281
292
|
};
|
|
282
293
|
|
|
283
294
|
if (object.type == "FunctionExpression") {
|
|
@@ -619,6 +630,7 @@ export default class Minify extends Transform {
|
|
|
619
630
|
|
|
620
631
|
if (
|
|
621
632
|
object.id.type == "ObjectPattern" &&
|
|
633
|
+
object.init &&
|
|
622
634
|
object.init.type == "ObjectExpression"
|
|
623
635
|
) {
|
|
624
636
|
if (
|
|
@@ -673,6 +685,9 @@ export default class Minify extends Transform {
|
|
|
673
685
|
}
|
|
674
686
|
if (object.type == "Identifier") {
|
|
675
687
|
return () => {
|
|
688
|
+
var info = getIdentifierInfo(object, parents);
|
|
689
|
+
if (info.spec.isDefined || info.spec.isModified) return;
|
|
690
|
+
|
|
676
691
|
if (object.name == "undefined" && !isForInitialize(object, parents)) {
|
|
677
692
|
this.replaceIdentifierOrLiteral(
|
|
678
693
|
object,
|
package/src/transforms/rgf.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { compileJsSync } from "../compiler";
|
|
2
|
-
import { reservedIdentifiers } from "../constants";
|
|
2
|
+
import { predictableFunctionTag, reservedIdentifiers } from "../constants";
|
|
3
3
|
import Obfuscator from "../obfuscator";
|
|
4
4
|
import { ObfuscateOrder } from "../order";
|
|
5
5
|
import { ComputeProbabilityMap } from "../probability";
|
|
6
|
+
import { FunctionLengthTemplate } from "../templates/functionLength";
|
|
7
|
+
import { ObjectDefineProperty } from "../templates/globals";
|
|
6
8
|
import { walk } from "../traverse";
|
|
7
9
|
import {
|
|
8
10
|
ArrayExpression,
|
|
9
11
|
BlockStatement,
|
|
10
12
|
CallExpression,
|
|
13
|
+
ExpressionStatement,
|
|
11
14
|
Identifier,
|
|
12
15
|
Literal,
|
|
13
16
|
MemberExpression,
|
|
@@ -19,7 +22,11 @@ import {
|
|
|
19
22
|
VariableDeclarator,
|
|
20
23
|
} from "../util/gen";
|
|
21
24
|
import { getIdentifierInfo } from "../util/identifiers";
|
|
22
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
prepend,
|
|
27
|
+
getDefiningContext,
|
|
28
|
+
computeFunctionLength,
|
|
29
|
+
} from "../util/insert";
|
|
23
30
|
import Integrity from "./lock/integrity";
|
|
24
31
|
import Transform from "./transform";
|
|
25
32
|
|
|
@@ -38,6 +45,16 @@ export default class RGF extends Transform {
|
|
|
38
45
|
// The name of the array holding all the `new Function` expressions
|
|
39
46
|
arrayExpressionName: string;
|
|
40
47
|
|
|
48
|
+
functionLengthName: string;
|
|
49
|
+
|
|
50
|
+
getFunctionLengthName(parents: Node[]) {
|
|
51
|
+
if (!this.functionLengthName) {
|
|
52
|
+
this.functionLengthName = this.getPlaceholder();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return this.functionLengthName;
|
|
56
|
+
}
|
|
57
|
+
|
|
41
58
|
constructor(o) {
|
|
42
59
|
super(o, ObfuscateOrder.RGF);
|
|
43
60
|
|
|
@@ -60,6 +77,19 @@ export default class RGF extends Transform {
|
|
|
60
77
|
)
|
|
61
78
|
);
|
|
62
79
|
}
|
|
80
|
+
|
|
81
|
+
// The function.length helper function must be placed last
|
|
82
|
+
if (this.functionLengthName) {
|
|
83
|
+
prepend(
|
|
84
|
+
tree,
|
|
85
|
+
FunctionLengthTemplate.single({
|
|
86
|
+
name: this.functionLengthName,
|
|
87
|
+
ObjectDefineProperty: this.createInitVariable(ObjectDefineProperty, [
|
|
88
|
+
tree,
|
|
89
|
+
]),
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
}
|
|
63
93
|
}
|
|
64
94
|
|
|
65
95
|
match(object, parents) {
|
|
@@ -141,6 +171,7 @@ export default class RGF extends Transform {
|
|
|
141
171
|
walk(object, parents, (o, p) => {
|
|
142
172
|
if (
|
|
143
173
|
o.type === "Identifier" &&
|
|
174
|
+
o.name !== this.arrayExpressionName &&
|
|
144
175
|
!reservedIdentifiers.has(o.name) &&
|
|
145
176
|
!this.options.globalVariables.has(o.name)
|
|
146
177
|
) {
|
|
@@ -226,9 +257,26 @@ export default class RGF extends Transform {
|
|
|
226
257
|
generator: false,
|
|
227
258
|
};
|
|
228
259
|
|
|
260
|
+
// The new program will look like this
|
|
261
|
+
// new Function(`
|
|
262
|
+
// var rgf_array = this[0]
|
|
263
|
+
// function greet(message){
|
|
264
|
+
// console.log(message)
|
|
265
|
+
// }
|
|
266
|
+
// return greet.apply(this[1], arguments)
|
|
267
|
+
// `)
|
|
268
|
+
//
|
|
269
|
+
// And called like
|
|
270
|
+
// f.apply([ rgf_array, this ], arguments)
|
|
229
271
|
var tree = {
|
|
230
272
|
type: "Program",
|
|
231
273
|
body: [
|
|
274
|
+
VariableDeclaration(
|
|
275
|
+
VariableDeclarator(
|
|
276
|
+
this.arrayExpressionName,
|
|
277
|
+
MemberExpression(ThisExpression(), Literal(0))
|
|
278
|
+
)
|
|
279
|
+
),
|
|
232
280
|
embeddedFunction,
|
|
233
281
|
ReturnStatement(
|
|
234
282
|
CallExpression(
|
|
@@ -237,7 +285,10 @@ export default class RGF extends Transform {
|
|
|
237
285
|
Literal("apply"),
|
|
238
286
|
true
|
|
239
287
|
),
|
|
240
|
-
[
|
|
288
|
+
[
|
|
289
|
+
MemberExpression(ThisExpression(), Literal(1)),
|
|
290
|
+
Identifier("arguments"),
|
|
291
|
+
]
|
|
241
292
|
)
|
|
242
293
|
),
|
|
243
294
|
],
|
|
@@ -261,12 +312,14 @@ export default class RGF extends Transform {
|
|
|
261
312
|
this.arrayExpressionElements.push(newFunctionExpression);
|
|
262
313
|
|
|
263
314
|
// The member expression to retrieve this function
|
|
264
|
-
var memberExpression = MemberExpression(
|
|
315
|
+
var memberExpression: Node = MemberExpression(
|
|
265
316
|
Identifier(this.arrayExpressionName),
|
|
266
317
|
Literal(newFunctionExpressionIndex),
|
|
267
318
|
true
|
|
268
319
|
);
|
|
269
320
|
|
|
321
|
+
var originalFunctionLength = computeFunctionLength(object.params);
|
|
322
|
+
|
|
270
323
|
// Replace based on type
|
|
271
324
|
|
|
272
325
|
// (1) Function Declaration:
|
|
@@ -276,19 +329,55 @@ export default class RGF extends Transform {
|
|
|
276
329
|
ReturnStatement(
|
|
277
330
|
CallExpression(
|
|
278
331
|
MemberExpression(memberExpression, Literal("apply"), true),
|
|
279
|
-
[
|
|
332
|
+
[
|
|
333
|
+
ArrayExpression([
|
|
334
|
+
Identifier(this.arrayExpressionName),
|
|
335
|
+
ThisExpression(),
|
|
336
|
+
]),
|
|
337
|
+
Identifier("arguments"),
|
|
338
|
+
]
|
|
280
339
|
)
|
|
281
340
|
),
|
|
282
341
|
]);
|
|
283
342
|
|
|
284
343
|
// The parameters are no longer needed ('arguments' is used to capture them)
|
|
285
344
|
object.params = [];
|
|
345
|
+
|
|
346
|
+
// The function is no longer guaranteed to not have extraneous parameters passed in
|
|
347
|
+
object[predictableFunctionTag] = false;
|
|
348
|
+
|
|
349
|
+
if (
|
|
350
|
+
this.options.preserveFunctionLength &&
|
|
351
|
+
originalFunctionLength !== 0
|
|
352
|
+
) {
|
|
353
|
+
var body = parents[0] as unknown as Node[];
|
|
354
|
+
|
|
355
|
+
body.splice(
|
|
356
|
+
body.indexOf(object),
|
|
357
|
+
0,
|
|
358
|
+
ExpressionStatement(
|
|
359
|
+
CallExpression(Identifier(this.getFunctionLengthName(parents)), [
|
|
360
|
+
Identifier(object.id.name),
|
|
361
|
+
Literal(originalFunctionLength),
|
|
362
|
+
])
|
|
363
|
+
)
|
|
364
|
+
);
|
|
365
|
+
}
|
|
286
366
|
return;
|
|
287
367
|
}
|
|
288
368
|
|
|
289
369
|
// (2) Function Expression:
|
|
290
370
|
// - Replace expression with member expression pointing to new function
|
|
291
371
|
if (object.type === "FunctionExpression") {
|
|
372
|
+
if (
|
|
373
|
+
this.options.preserveFunctionLength &&
|
|
374
|
+
originalFunctionLength !== 0
|
|
375
|
+
) {
|
|
376
|
+
memberExpression = CallExpression(
|
|
377
|
+
Identifier(this.getFunctionLengthName(parents)),
|
|
378
|
+
[memberExpression, Literal(originalFunctionLength)]
|
|
379
|
+
);
|
|
380
|
+
}
|
|
292
381
|
this.replace(object, memberExpression);
|
|
293
382
|
return;
|
|
294
383
|
}
|
package/src/transforms/stack.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ok } from "assert";
|
|
2
2
|
import { ObfuscateOrder } from "../order";
|
|
3
3
|
import { ComputeProbabilityMap } from "../probability";
|
|
4
|
-
import Template from "../templates/template";
|
|
4
|
+
import Template, { ITemplate } from "../templates/template";
|
|
5
5
|
import { walk } from "../traverse";
|
|
6
6
|
import {
|
|
7
7
|
AssignmentExpression,
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
RestElement,
|
|
17
17
|
ReturnStatement,
|
|
18
18
|
SequenceExpression,
|
|
19
|
+
VariableDeclaration,
|
|
20
|
+
VariableDeclarator,
|
|
19
21
|
} from "../util/gen";
|
|
20
22
|
import { getIdentifierInfo } from "../util/identifiers";
|
|
21
23
|
import {
|
|
@@ -32,6 +34,7 @@ import { chance, choice, getRandomInteger } from "../util/random";
|
|
|
32
34
|
import Transform from "./transform";
|
|
33
35
|
import { noRenameVariablePrefix } from "../constants";
|
|
34
36
|
import { FunctionLengthTemplate } from "../templates/functionLength";
|
|
37
|
+
import { ObjectDefineProperty } from "../templates/globals";
|
|
35
38
|
|
|
36
39
|
export default class Stack extends Transform {
|
|
37
40
|
mangledExpressionsMade: number;
|
|
@@ -497,12 +500,18 @@ export default class Stack extends Transform {
|
|
|
497
500
|
Template(`${stackName}["length"] = ${startingSize}`).single()
|
|
498
501
|
);
|
|
499
502
|
|
|
500
|
-
if (originalFunctionLength !== 0) {
|
|
503
|
+
if (this.options.preserveFunctionLength && originalFunctionLength !== 0) {
|
|
501
504
|
if (!this.functionLengthName) {
|
|
502
505
|
this.functionLengthName = this.getPlaceholder();
|
|
503
506
|
prepend(
|
|
504
507
|
parents[parents.length - 1] || object,
|
|
505
|
-
FunctionLengthTemplate.single({
|
|
508
|
+
FunctionLengthTemplate.single({
|
|
509
|
+
name: this.functionLengthName,
|
|
510
|
+
ObjectDefineProperty: this.createInitVariable(
|
|
511
|
+
ObjectDefineProperty,
|
|
512
|
+
parents
|
|
513
|
+
),
|
|
514
|
+
})
|
|
506
515
|
);
|
|
507
516
|
}
|
|
508
517
|
|