js-confuser 1.5.5 → 1.5.7
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 +34 -2
- package/README.md +2 -2
- package/dist/transforms/flatten.js +1 -1
- package/dist/transforms/identifier/variableAnalysis.js +4 -2
- package/dist/transforms/lock/integrity.js +6 -2
- package/dist/transforms/lock/lock.js +40 -32
- package/dist/transforms/minify.js +2 -2
- package/dist/transforms/preparation/preparation.js +0 -7
- package/dist/transforms/rgf.js +80 -10
- package/dist/transforms/string/stringSplitting.js +1 -22
- package/package.json +2 -2
- package/src/transforms/flatten.ts +2 -2
- package/src/transforms/identifier/variableAnalysis.ts +4 -4
- package/src/transforms/lock/integrity.ts +13 -1
- package/src/transforms/lock/lock.ts +81 -44
- package/src/transforms/minify.ts +5 -4
- package/src/transforms/preparation/preparation.ts +2 -21
- package/src/transforms/rgf.ts +164 -29
- package/src/transforms/string/stringSplitting.ts +1 -25
- package/test/transforms/lock/countermeasures.test.ts +18 -0
- package/test/transforms/minify.test.ts +50 -5
- package/test/transforms/rgf.test.ts +134 -0
|
@@ -11,17 +11,12 @@ import {
|
|
|
11
11
|
Literal,
|
|
12
12
|
UnaryExpression,
|
|
13
13
|
NewExpression,
|
|
14
|
-
FunctionDeclaration,
|
|
15
|
-
ReturnStatement,
|
|
16
14
|
VariableDeclaration,
|
|
17
|
-
ObjectExpression,
|
|
18
|
-
Property,
|
|
19
|
-
ArrayExpression,
|
|
20
|
-
FunctionExpression,
|
|
21
15
|
ThisExpression,
|
|
22
16
|
VariableDeclarator,
|
|
23
17
|
Location,
|
|
24
18
|
LogicalExpression,
|
|
19
|
+
SequenceExpression,
|
|
25
20
|
} from "../../util/gen";
|
|
26
21
|
import traverse, { getBlock, isBlock } from "../../traverse";
|
|
27
22
|
import { choice, getRandomInteger } from "../../util/random";
|
|
@@ -47,6 +42,12 @@ export default class Lock extends Transform {
|
|
|
47
42
|
counterMeasuresNode: Location;
|
|
48
43
|
iosDetectFn: string;
|
|
49
44
|
|
|
45
|
+
/**
|
|
46
|
+
* This is a boolean variable injected into the source code determining wether the countermeasures function has been called.
|
|
47
|
+
* This is used to prevent infinite loops from happening
|
|
48
|
+
*/
|
|
49
|
+
counterMeasuresActivated: string;
|
|
50
|
+
|
|
50
51
|
made: number;
|
|
51
52
|
|
|
52
53
|
constructor(o) {
|
|
@@ -73,36 +74,32 @@ export default class Lock extends Transform {
|
|
|
73
74
|
typeof this.options.lock.countermeasures === "string" &&
|
|
74
75
|
isValidIdentifier(this.options.lock.countermeasures)
|
|
75
76
|
) {
|
|
76
|
-
var defined = new Set<string>();
|
|
77
77
|
traverse(tree, (object, parents) => {
|
|
78
|
-
if (
|
|
78
|
+
if (
|
|
79
|
+
object.type == "Identifier" &&
|
|
80
|
+
object.name === this.options.lock.countermeasures
|
|
81
|
+
) {
|
|
79
82
|
var info = getIdentifierInfo(object, parents);
|
|
80
83
|
if (info.spec.isDefined) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
if (this.counterMeasuresNode) {
|
|
85
|
+
throw new Error(
|
|
86
|
+
"Countermeasures function was already defined, it must have a unique name from the rest of your code"
|
|
87
|
+
);
|
|
88
|
+
} else {
|
|
89
|
+
var definingContext = getVarContext(parents[0], parents.slice(1));
|
|
90
|
+
if (definingContext != tree) {
|
|
84
91
|
throw new Error(
|
|
85
|
-
"Countermeasures function
|
|
86
|
-
);
|
|
87
|
-
} else {
|
|
88
|
-
var definingContext = getVarContext(
|
|
89
|
-
parents[0],
|
|
90
|
-
parents.slice(1)
|
|
92
|
+
"Countermeasures function must be defined at the global level"
|
|
91
93
|
);
|
|
92
|
-
if (definingContext != tree) {
|
|
93
|
-
throw new Error(
|
|
94
|
-
"Countermeasures function must be defined at the global level"
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
var chain: Location = [object, parents];
|
|
98
|
-
if (info.isFunctionDeclaration) {
|
|
99
|
-
chain = [parents[0], parents.slice(1)];
|
|
100
|
-
} else if (info.isVariableDeclaration) {
|
|
101
|
-
chain = [parents[1], parents.slice(2)];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
this.counterMeasuresNode = chain;
|
|
105
94
|
}
|
|
95
|
+
var chain: Location = [object, parents];
|
|
96
|
+
if (info.isFunctionDeclaration) {
|
|
97
|
+
chain = [parents[0], parents.slice(1)];
|
|
98
|
+
} else if (info.isVariableDeclaration) {
|
|
99
|
+
chain = [parents[1], parents.slice(2)];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this.counterMeasuresNode = chain;
|
|
106
103
|
}
|
|
107
104
|
}
|
|
108
105
|
}
|
|
@@ -120,7 +117,7 @@ export default class Lock extends Transform {
|
|
|
120
117
|
super.apply(tree);
|
|
121
118
|
}
|
|
122
119
|
|
|
123
|
-
getCounterMeasuresCode(): Node[] {
|
|
120
|
+
getCounterMeasuresCode(object: Node, parents: Node[]): Node[] {
|
|
124
121
|
var opt = this.options.lock.countermeasures;
|
|
125
122
|
|
|
126
123
|
if (opt === false) {
|
|
@@ -129,10 +126,30 @@ export default class Lock extends Transform {
|
|
|
129
126
|
|
|
130
127
|
// Call function
|
|
131
128
|
if (typeof opt === "string") {
|
|
129
|
+
if (!this.counterMeasuresActivated) {
|
|
130
|
+
this.counterMeasuresActivated = this.getPlaceholder();
|
|
131
|
+
|
|
132
|
+
prepend(
|
|
133
|
+
parents[parents.length - 1] || object,
|
|
134
|
+
VariableDeclaration(VariableDeclarator(this.counterMeasuresActivated))
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
132
138
|
// Since Lock occurs before variable renaming, we are using the pre-obfuscated function name
|
|
133
139
|
return [
|
|
134
140
|
ExpressionStatement(
|
|
135
|
-
|
|
141
|
+
LogicalExpression(
|
|
142
|
+
"||",
|
|
143
|
+
Identifier(this.counterMeasuresActivated),
|
|
144
|
+
SequenceExpression([
|
|
145
|
+
AssignmentExpression(
|
|
146
|
+
"=",
|
|
147
|
+
Identifier(this.counterMeasuresActivated),
|
|
148
|
+
Literal(true)
|
|
149
|
+
),
|
|
150
|
+
CallExpression(Template(opt).single().expression, []),
|
|
151
|
+
])
|
|
152
|
+
)
|
|
136
153
|
),
|
|
137
154
|
];
|
|
138
155
|
}
|
|
@@ -288,7 +305,7 @@ export default class Lock extends Transform {
|
|
|
288
305
|
nodes.push(
|
|
289
306
|
IfStatement(
|
|
290
307
|
callExpression,
|
|
291
|
-
this.getCounterMeasuresCode() || [],
|
|
308
|
+
this.getCounterMeasuresCode(object, parents) || [],
|
|
292
309
|
null
|
|
293
310
|
)
|
|
294
311
|
);
|
|
@@ -324,7 +341,11 @@ export default class Lock extends Transform {
|
|
|
324
341
|
}
|
|
325
342
|
|
|
326
343
|
nodes.push(
|
|
327
|
-
IfStatement(
|
|
344
|
+
IfStatement(
|
|
345
|
+
test,
|
|
346
|
+
this.getCounterMeasuresCode(object, parents) || [],
|
|
347
|
+
null
|
|
348
|
+
)
|
|
328
349
|
);
|
|
329
350
|
}
|
|
330
351
|
|
|
@@ -338,7 +359,11 @@ export default class Lock extends Transform {
|
|
|
338
359
|
);
|
|
339
360
|
|
|
340
361
|
nodes.push(
|
|
341
|
-
IfStatement(
|
|
362
|
+
IfStatement(
|
|
363
|
+
test,
|
|
364
|
+
this.getCounterMeasuresCode(object, parents) || [],
|
|
365
|
+
null
|
|
366
|
+
)
|
|
342
367
|
);
|
|
343
368
|
|
|
344
369
|
break;
|
|
@@ -351,7 +376,11 @@ export default class Lock extends Transform {
|
|
|
351
376
|
);
|
|
352
377
|
|
|
353
378
|
nodes.push(
|
|
354
|
-
IfStatement(
|
|
379
|
+
IfStatement(
|
|
380
|
+
test,
|
|
381
|
+
this.getCounterMeasuresCode(object, parents) || [],
|
|
382
|
+
null
|
|
383
|
+
)
|
|
355
384
|
);
|
|
356
385
|
|
|
357
386
|
break;
|
|
@@ -359,6 +388,8 @@ export default class Lock extends Transform {
|
|
|
359
388
|
case "context":
|
|
360
389
|
var prop = choice(this.options.lock.context);
|
|
361
390
|
|
|
391
|
+
var code = this.getCounterMeasuresCode(object, parents) || [];
|
|
392
|
+
|
|
362
393
|
// Todo: Alternative to `this`
|
|
363
394
|
if (!this.globalVar) {
|
|
364
395
|
offset = 1;
|
|
@@ -384,9 +415,7 @@ export default class Lock extends Transform {
|
|
|
384
415
|
"!",
|
|
385
416
|
MemberExpression(Identifier(this.globalVar), Literal(prop), true)
|
|
386
417
|
);
|
|
387
|
-
nodes.push(
|
|
388
|
-
IfStatement(test, this.getCounterMeasuresCode() || [], null)
|
|
389
|
-
);
|
|
418
|
+
nodes.push(IfStatement(test, code, null));
|
|
390
419
|
|
|
391
420
|
break;
|
|
392
421
|
|
|
@@ -397,6 +426,8 @@ export default class Lock extends Transform {
|
|
|
397
426
|
|
|
398
427
|
ok(this.options.lock.osLock);
|
|
399
428
|
|
|
429
|
+
var code = this.getCounterMeasuresCode(object, parents) || [];
|
|
430
|
+
|
|
400
431
|
this.options.lock.osLock.forEach((osName) => {
|
|
401
432
|
var agentMatcher = {
|
|
402
433
|
windows: "Win",
|
|
@@ -449,9 +480,7 @@ export default class Lock extends Transform {
|
|
|
449
480
|
});
|
|
450
481
|
|
|
451
482
|
test = UnaryExpression("!", { ...test });
|
|
452
|
-
nodes.push(
|
|
453
|
-
IfStatement(test, this.getCounterMeasuresCode() || [], null)
|
|
454
|
-
);
|
|
483
|
+
nodes.push(IfStatement(test, code, null));
|
|
455
484
|
break;
|
|
456
485
|
|
|
457
486
|
case "browserLock":
|
|
@@ -488,7 +517,11 @@ export default class Lock extends Transform {
|
|
|
488
517
|
|
|
489
518
|
test = UnaryExpression("!", { ...test });
|
|
490
519
|
nodes.push(
|
|
491
|
-
IfStatement(
|
|
520
|
+
IfStatement(
|
|
521
|
+
test,
|
|
522
|
+
this.getCounterMeasuresCode(object, parents) || [],
|
|
523
|
+
null
|
|
524
|
+
)
|
|
492
525
|
);
|
|
493
526
|
break;
|
|
494
527
|
|
|
@@ -540,7 +573,11 @@ export default class Lock extends Transform {
|
|
|
540
573
|
);
|
|
541
574
|
}
|
|
542
575
|
nodes.push(
|
|
543
|
-
IfStatement(
|
|
576
|
+
IfStatement(
|
|
577
|
+
test,
|
|
578
|
+
this.getCounterMeasuresCode(object, parents) || [],
|
|
579
|
+
null
|
|
580
|
+
)
|
|
544
581
|
);
|
|
545
582
|
}
|
|
546
583
|
|
package/src/transforms/minify.ts
CHANGED
|
@@ -61,9 +61,10 @@ export default class Minify extends Transform {
|
|
|
61
61
|
|
|
62
62
|
body.forEach((stmt, i) => {
|
|
63
63
|
if (
|
|
64
|
-
stmt.type
|
|
65
|
-
stmt.type
|
|
66
|
-
stmt.type
|
|
64
|
+
stmt.type === "ReturnStatement" ||
|
|
65
|
+
stmt.type === "BreakStatement" ||
|
|
66
|
+
stmt.type === "ContinueStatement" ||
|
|
67
|
+
stmt.type === "ThrowStatement"
|
|
67
68
|
) {
|
|
68
69
|
if (earlyReturn > i + 1) {
|
|
69
70
|
earlyReturn = i + 1;
|
|
@@ -156,7 +157,7 @@ export default class Minify extends Transform {
|
|
|
156
157
|
) {
|
|
157
158
|
lastDec = x;
|
|
158
159
|
} else {
|
|
159
|
-
lastDec.declarations.push(...x.declarations);
|
|
160
|
+
lastDec.declarations.push(...clone(x.declarations));
|
|
160
161
|
remove.unshift(i);
|
|
161
162
|
}
|
|
162
163
|
} else {
|
|
@@ -3,24 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import Transform from "../transform";
|
|
5
5
|
|
|
6
|
-
import {
|
|
7
|
-
BlockStatement,
|
|
8
|
-
Identifier,
|
|
9
|
-
LabeledStatement,
|
|
10
|
-
Literal,
|
|
11
|
-
Location,
|
|
12
|
-
Node,
|
|
13
|
-
ReturnStatement,
|
|
14
|
-
} from "../../util/gen";
|
|
6
|
+
import { BlockStatement, Literal, ReturnStatement } from "../../util/gen";
|
|
15
7
|
import { ObfuscateOrder } from "../../order";
|
|
16
|
-
import {
|
|
17
|
-
import { ok } from "assert";
|
|
8
|
+
import { clone, getFunction } from "../../util/insert";
|
|
18
9
|
import { getIdentifierInfo } from "../../util/identifiers";
|
|
19
|
-
import { walk } from "../../traverse";
|
|
20
10
|
import Label from "../label";
|
|
21
|
-
import NameConflicts from "./nameConflicts";
|
|
22
|
-
import AntiDestructuring from "../es5/antiDestructuring";
|
|
23
|
-
import { OPERATOR_PRECEDENCE } from "../../precedence";
|
|
24
11
|
import { isLoop } from "../../util/compare";
|
|
25
12
|
|
|
26
13
|
/**
|
|
@@ -181,12 +168,6 @@ export default class Preparation extends Transform {
|
|
|
181
168
|
this.before.push(new Label(o));
|
|
182
169
|
this.before.push(new ExplicitIdentifiers(o));
|
|
183
170
|
this.before.push(new ExplicitDeclarations(o));
|
|
184
|
-
|
|
185
|
-
if (this.options.es5) {
|
|
186
|
-
this.before.push(new AntiDestructuring(o));
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// this.before.push(new NameConflicts(o));
|
|
190
171
|
}
|
|
191
172
|
|
|
192
173
|
match() {
|
package/src/transforms/rgf.ts
CHANGED
|
@@ -7,7 +7,10 @@ import Template from "../templates/template";
|
|
|
7
7
|
import traverse, { walk } from "../traverse";
|
|
8
8
|
import {
|
|
9
9
|
ArrayExpression,
|
|
10
|
+
AssignmentExpression,
|
|
10
11
|
CallExpression,
|
|
12
|
+
ConditionalExpression,
|
|
13
|
+
ExpressionStatement,
|
|
11
14
|
FunctionExpression,
|
|
12
15
|
Identifier,
|
|
13
16
|
Literal,
|
|
@@ -27,7 +30,9 @@ import {
|
|
|
27
30
|
isVarContext,
|
|
28
31
|
isFunction,
|
|
29
32
|
prepend,
|
|
33
|
+
getDefiningContext,
|
|
30
34
|
} from "../util/insert";
|
|
35
|
+
import { getRandomString } from "../util/random";
|
|
31
36
|
import Transform from "./transform";
|
|
32
37
|
|
|
33
38
|
/**
|
|
@@ -70,6 +75,8 @@ export default class RGF extends Transform {
|
|
|
70
75
|
}[] = [];
|
|
71
76
|
var queue: Location[] = [];
|
|
72
77
|
var names = new Map<string, number>();
|
|
78
|
+
var referenceSignatures: { [name: string]: string } = {};
|
|
79
|
+
|
|
73
80
|
var definingNodes = new Map<string, Node>();
|
|
74
81
|
|
|
75
82
|
walk(contextObject, contextParents, (object, parents) => {
|
|
@@ -81,12 +88,63 @@ export default class RGF extends Transform {
|
|
|
81
88
|
!object.generator &&
|
|
82
89
|
getVarContext(parents[0], parents.slice(1)) === contextObject
|
|
83
90
|
) {
|
|
91
|
+
// Discard getter/setter methods
|
|
92
|
+
if (parents[0].type === "Property" && parents[0].value === object) {
|
|
93
|
+
if (
|
|
94
|
+
parents[0].method ||
|
|
95
|
+
parents[0].kind === "get" ||
|
|
96
|
+
parents[0].kind === "set"
|
|
97
|
+
) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Discard class methods
|
|
103
|
+
if (
|
|
104
|
+
parents[0].type === "MethodDefinition" &&
|
|
105
|
+
parents[0].value === object
|
|
106
|
+
) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Avoid applying to the countermeasures function
|
|
111
|
+
if (typeof this.options.lock?.countermeasures === "string") {
|
|
112
|
+
// function countermeasures(){...}
|
|
113
|
+
if (
|
|
114
|
+
object.type === "FunctionDeclaration" &&
|
|
115
|
+
object.id.type === "Identifier" &&
|
|
116
|
+
object.id.name === this.options.lock.countermeasures
|
|
117
|
+
) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// var countermeasures = function(){...}
|
|
122
|
+
if (
|
|
123
|
+
parents[0].type === "VariableDeclarator" &&
|
|
124
|
+
parents[0].init === object &&
|
|
125
|
+
parents[0].id.type === "Identifier" &&
|
|
126
|
+
parents[0].id.name === this.options.lock.countermeasures
|
|
127
|
+
) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
84
132
|
var defined = new Set<string>(),
|
|
85
133
|
referenced = new Set<string>();
|
|
86
134
|
|
|
87
135
|
var isBound = false;
|
|
88
136
|
|
|
89
|
-
|
|
137
|
+
/**
|
|
138
|
+
* The fnTraverses serves two important purposes
|
|
139
|
+
*
|
|
140
|
+
* - Identify all the variables referenced and defined here
|
|
141
|
+
* - Identify is the 'this' keyword is used anywhere
|
|
142
|
+
*
|
|
143
|
+
* @param o
|
|
144
|
+
* @param p
|
|
145
|
+
* @returns
|
|
146
|
+
*/
|
|
147
|
+
const fnTraverser = (o, p) => {
|
|
90
148
|
if (
|
|
91
149
|
o.type == "Identifier" &&
|
|
92
150
|
!reservedIdentifiers.has(o.name) &&
|
|
@@ -96,7 +154,7 @@ export default class RGF extends Transform {
|
|
|
96
154
|
if (!info.spec.isReferenced) {
|
|
97
155
|
return;
|
|
98
156
|
}
|
|
99
|
-
if (info.spec.isDefined) {
|
|
157
|
+
if (info.spec.isDefined && getDefiningContext(o, p) === object) {
|
|
100
158
|
defined.add(o.name);
|
|
101
159
|
} else {
|
|
102
160
|
referenced.add(o.name);
|
|
@@ -106,7 +164,10 @@ export default class RGF extends Transform {
|
|
|
106
164
|
if (o.type == "ThisExpression" || o.type == "Super") {
|
|
107
165
|
isBound = true;
|
|
108
166
|
}
|
|
109
|
-
}
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
walk(object.params, [object, ...parents], fnTraverser);
|
|
170
|
+
walk(object.body, [object, ...parents], fnTraverser);
|
|
110
171
|
|
|
111
172
|
if (!isBound) {
|
|
112
173
|
defined.forEach((identifier) => {
|
|
@@ -177,6 +238,8 @@ export default class RGF extends Transform {
|
|
|
177
238
|
var index = names.size;
|
|
178
239
|
|
|
179
240
|
names.set(object.id.name, index);
|
|
241
|
+
referenceSignatures[index] = getRandomString(10);
|
|
242
|
+
|
|
180
243
|
definingNodes.set(object.id.name, object.id);
|
|
181
244
|
}
|
|
182
245
|
}
|
|
@@ -186,7 +249,8 @@ export default class RGF extends Transform {
|
|
|
186
249
|
return;
|
|
187
250
|
}
|
|
188
251
|
|
|
189
|
-
|
|
252
|
+
// An array containing all the function declarations
|
|
253
|
+
var referenceArray = "_" + getRandomString(10);
|
|
190
254
|
|
|
191
255
|
walk(contextObject, contextParents, (o, p) => {
|
|
192
256
|
if (o.type == "Identifier" && !reservedIdentifiers.has(o.name)) {
|
|
@@ -204,27 +268,50 @@ export default class RGF extends Transform {
|
|
|
204
268
|
if (pointingTo == shouldBe) {
|
|
205
269
|
this.log(o.name, "->", `${referenceArray}[${index}]`);
|
|
206
270
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
271
|
+
var memberExpression = MemberExpression(
|
|
272
|
+
Identifier(referenceArray),
|
|
273
|
+
Literal(index),
|
|
274
|
+
true
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
// Allow re-assignment to the RGF function
|
|
278
|
+
if (
|
|
279
|
+
p[0] &&
|
|
280
|
+
p[0].type === "AssignmentExpression" &&
|
|
281
|
+
p[0].left === o
|
|
282
|
+
) {
|
|
283
|
+
// fn = ...
|
|
284
|
+
|
|
285
|
+
this.replace(o, memberExpression);
|
|
286
|
+
} else {
|
|
287
|
+
// fn()
|
|
288
|
+
// fn
|
|
289
|
+
|
|
290
|
+
// In most cases the identifier is being used like this (call expression, or referenced to be called later)
|
|
291
|
+
// Replace it with a simple wrapper function that will pass on the reference array
|
|
292
|
+
|
|
293
|
+
var conditionalExpression = ConditionalExpression(
|
|
294
|
+
Template(
|
|
295
|
+
`typeof ${referenceArray}[${index}] === "function" && ${referenceArray}[${index}]["${
|
|
296
|
+
referenceSignatures[index] || "_"
|
|
297
|
+
}"]`
|
|
298
|
+
).single().expression,
|
|
299
|
+
FunctionExpression(
|
|
300
|
+
[],
|
|
301
|
+
[
|
|
302
|
+
ReturnStatement(
|
|
303
|
+
CallExpression(memberExpression, [
|
|
220
304
|
Identifier(referenceArray),
|
|
221
305
|
SpreadElement(Identifier("arguments")),
|
|
222
|
-
]
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
306
|
+
])
|
|
307
|
+
),
|
|
308
|
+
]
|
|
309
|
+
),
|
|
310
|
+
memberExpression
|
|
311
|
+
);
|
|
312
|
+
|
|
313
|
+
this.replace(o, conditionalExpression);
|
|
314
|
+
}
|
|
228
315
|
}
|
|
229
316
|
}
|
|
230
317
|
}
|
|
@@ -243,6 +330,7 @@ export default class RGF extends Transform {
|
|
|
243
330
|
var name = object?.id?.name;
|
|
244
331
|
var hasName = !!name;
|
|
245
332
|
var params = object.params.map((x) => x.name) || [];
|
|
333
|
+
var signature = referenceSignatures[names.get(name)];
|
|
246
334
|
|
|
247
335
|
var embeddedName = name || this.getPlaceholder();
|
|
248
336
|
|
|
@@ -280,11 +368,11 @@ export default class RGF extends Transform {
|
|
|
280
368
|
CallExpression(
|
|
281
369
|
MemberExpression(
|
|
282
370
|
Identifier(embeddedName),
|
|
283
|
-
|
|
284
|
-
|
|
371
|
+
Literal("call"),
|
|
372
|
+
true
|
|
285
373
|
),
|
|
286
374
|
[
|
|
287
|
-
|
|
375
|
+
Identifier("undefined"),
|
|
288
376
|
SpreadElement(
|
|
289
377
|
Template(
|
|
290
378
|
`Array.prototype.slice.call(arguments, 1)`
|
|
@@ -322,8 +410,38 @@ export default class RGF extends Transform {
|
|
|
322
410
|
Literal(toString),
|
|
323
411
|
]);
|
|
324
412
|
|
|
325
|
-
|
|
326
|
-
|
|
413
|
+
function applySignature(fn) {
|
|
414
|
+
if (!signature) {
|
|
415
|
+
return fn;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// This code marks the function object with a unique property
|
|
419
|
+
return CallExpression(
|
|
420
|
+
FunctionExpression(
|
|
421
|
+
[],
|
|
422
|
+
[
|
|
423
|
+
VariableDeclaration(VariableDeclarator("fn", fn)),
|
|
424
|
+
ExpressionStatement(
|
|
425
|
+
AssignmentExpression(
|
|
426
|
+
"=",
|
|
427
|
+
MemberExpression(
|
|
428
|
+
Identifier("fn"),
|
|
429
|
+
Literal(signature),
|
|
430
|
+
true
|
|
431
|
+
),
|
|
432
|
+
Literal(true)
|
|
433
|
+
)
|
|
434
|
+
),
|
|
435
|
+
ReturnStatement(Identifier("fn")),
|
|
436
|
+
]
|
|
437
|
+
),
|
|
438
|
+
[]
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (object.type === "FunctionDeclaration") {
|
|
443
|
+
arrayExpression.elements[names.get(name)] =
|
|
444
|
+
applySignature(newFunction);
|
|
327
445
|
|
|
328
446
|
if (Array.isArray(parents[0])) {
|
|
329
447
|
parents[0].splice(parents[0].indexOf(object), 1);
|
|
@@ -336,7 +454,24 @@ export default class RGF extends Transform {
|
|
|
336
454
|
);
|
|
337
455
|
}
|
|
338
456
|
} else {
|
|
339
|
-
|
|
457
|
+
// The wrapper function passes the reference array around
|
|
458
|
+
var wrapperFunction = FunctionExpression(
|
|
459
|
+
[],
|
|
460
|
+
[
|
|
461
|
+
ReturnStatement(
|
|
462
|
+
CallExpression(
|
|
463
|
+
MemberExpression(newFunction, Literal("call"), true),
|
|
464
|
+
[
|
|
465
|
+
Identifier("undefined"),
|
|
466
|
+
Identifier(referenceArray),
|
|
467
|
+
SpreadElement(Identifier("arguments")),
|
|
468
|
+
]
|
|
469
|
+
)
|
|
470
|
+
),
|
|
471
|
+
]
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
this.replace(object, applySignature(wrapperFunction));
|
|
340
475
|
}
|
|
341
476
|
});
|
|
342
477
|
};
|
|
@@ -25,34 +25,11 @@ export default class StringSplitting extends Transform {
|
|
|
25
25
|
this.vars = [];
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
apply(tree) {
|
|
29
|
-
super.apply(tree);
|
|
30
|
-
|
|
31
|
-
if (this.vars.length) {
|
|
32
|
-
shuffle(this.adders);
|
|
33
|
-
shuffle(this.vars);
|
|
34
|
-
|
|
35
|
-
var body: Node[] = tree.body;
|
|
36
|
-
|
|
37
|
-
this.adders.forEach((nodes) => {
|
|
38
|
-
nodes.forEach((x) => body.unshift(x));
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
var variableDeclaration = {
|
|
42
|
-
type: "VariableDeclaration",
|
|
43
|
-
declarations: [],
|
|
44
|
-
kind: "var",
|
|
45
|
-
};
|
|
46
|
-
this.vars.forEach((node) => variableDeclaration.declarations.push(node));
|
|
47
|
-
|
|
48
|
-
body.unshift(variableDeclaration);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
28
|
match(object: Node, parents: Node[]) {
|
|
53
29
|
return (
|
|
54
30
|
object.type == "Literal" &&
|
|
55
31
|
typeof object.value === "string" &&
|
|
32
|
+
object.value.length >= 8 &&
|
|
56
33
|
!isModuleSource(object, parents) &&
|
|
57
34
|
!isDirective(object, parents)
|
|
58
35
|
);
|
|
@@ -87,7 +64,6 @@ export default class StringSplitting extends Transform {
|
|
|
87
64
|
var last = chunks.pop();
|
|
88
65
|
chunks.forEach((chunk, i) => {
|
|
89
66
|
if (i == 0) {
|
|
90
|
-
ok(i == 0);
|
|
91
67
|
parent = binaryExpression = BinaryExpression(
|
|
92
68
|
"+",
|
|
93
69
|
Literal(chunk),
|
|
@@ -80,3 +80,21 @@ test("Variant #4: Should work when countermeasures is variable declaration", asy
|
|
|
80
80
|
}
|
|
81
81
|
);
|
|
82
82
|
});
|
|
83
|
+
|
|
84
|
+
// https://github.com/MichaelXF/js-confuser/issues/66
|
|
85
|
+
test("Variant #5: Should work with RGF enabled", async () => {
|
|
86
|
+
await JsConfuser.obfuscate(
|
|
87
|
+
`
|
|
88
|
+
function myCountermeasuresFunction(){
|
|
89
|
+
|
|
90
|
+
}
|
|
91
|
+
`,
|
|
92
|
+
{
|
|
93
|
+
target: "node",
|
|
94
|
+
lock: {
|
|
95
|
+
countermeasures: "myCountermeasuresFunction",
|
|
96
|
+
},
|
|
97
|
+
rgf: true,
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
});
|