js-confuser 1.2.1 → 1.4.1
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 +171 -0
- package/README.md +7 -6
- package/dist/options.js +5 -1
- package/dist/parser.js +1 -2
- package/dist/presets.js +2 -2
- package/dist/transforms/calculator.js +48 -60
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +482 -95
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -0
- package/dist/transforms/controlFlowFlattening/{switchCaseObfucation.js → switchCaseObfuscation.js} +2 -2
- package/dist/transforms/deadCode.js +1 -1
- package/dist/transforms/dispatcher.js +14 -13
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -10
- package/dist/transforms/flatten.js +5 -1
- package/dist/transforms/hideInitializingCode.js +17 -2
- package/dist/transforms/identifier/globalConcealing.js +46 -25
- package/dist/transforms/identifier/movedDeclarations.js +69 -68
- package/dist/transforms/identifier/renameVariables.js +22 -98
- package/dist/transforms/identifier/variableAnalysis.js +133 -0
- package/dist/transforms/label.js +11 -2
- package/dist/transforms/lock/antiDebug.js +32 -13
- package/dist/transforms/lock/lock.js +13 -2
- package/dist/transforms/minify.js +117 -120
- package/dist/transforms/opaquePredicates.js +4 -2
- package/dist/transforms/preparation/preparation.js +8 -0
- package/dist/transforms/renameLabels.js +17 -3
- package/dist/transforms/rgf.js +8 -3
- package/dist/transforms/shuffle.js +25 -9
- package/dist/transforms/stack.js +5 -9
- package/dist/transforms/string/encoding.js +209 -0
- package/dist/transforms/string/stringCompression.js +10 -10
- package/dist/transforms/string/stringConcealing.js +94 -65
- package/dist/transforms/string/stringSplitting.js +7 -7
- package/dist/transforms/transform.js +10 -0
- package/dist/traverse.js +1 -35
- package/dist/util/gen.js +3 -1
- package/dist/util/identifiers.js +9 -19
- package/dist/util/insert.js +6 -40
- package/dist/util/scope.js +17 -0
- package/package.json +2 -2
- package/src/options.ts +19 -3
- package/src/parser.ts +1 -2
- package/src/presets.ts +2 -2
- package/src/transforms/calculator.ts +87 -91
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +742 -142
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +6 -0
- package/src/transforms/controlFlowFlattening/{switchCaseObfucation.ts → switchCaseObfuscation.ts} +6 -2
- package/src/transforms/deadCode.ts +8 -0
- package/src/transforms/dispatcher.ts +29 -14
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +43 -19
- package/src/transforms/flatten.ts +15 -2
- package/src/transforms/hideInitializingCode.ts +432 -406
- package/src/transforms/identifier/globalConcealing.ts +148 -46
- package/src/transforms/identifier/movedDeclarations.ts +78 -101
- package/src/transforms/identifier/renameVariables.ts +21 -96
- package/src/transforms/identifier/variableAnalysis.ts +124 -0
- package/src/transforms/label.ts +20 -2
- package/src/transforms/lock/antiDebug.ts +69 -26
- package/src/transforms/lock/lock.ts +37 -3
- package/src/transforms/minify.ts +154 -130
- package/src/transforms/opaquePredicates.ts +25 -3
- package/src/transforms/preparation/preparation.ts +8 -1
- package/src/transforms/renameLabels.ts +26 -3
- package/src/transforms/rgf.ts +6 -1
- package/src/transforms/shuffle.ts +87 -29
- package/src/transforms/stack.ts +6 -8
- package/src/transforms/string/encoding.ts +310 -0
- package/src/transforms/string/stringCompression.ts +37 -24
- package/src/transforms/string/stringConcealing.ts +157 -160
- package/src/transforms/string/stringSplitting.ts +12 -8
- package/src/transforms/transform.ts +15 -2
- package/src/traverse.ts +1 -31
- package/src/util/gen.ts +5 -3
- package/src/util/identifiers.ts +20 -20
- package/src/util/insert.ts +12 -78
- package/src/util/scope.ts +9 -0
- package/test/{transforms/compare.test.ts → compare.test.ts} +2 -2
- package/test/index.test.ts +109 -1
- package/test/templates/template.test.ts +14 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +392 -10
- package/test/transforms/dispatcher.test.ts +30 -0
- package/test/transforms/flatten.test.ts +28 -0
- package/test/transforms/hideInitializingCode.test.ts +336 -336
- package/test/transforms/identifier/globalConcealing.test.ts +1 -2
- package/test/transforms/identifier/movedDeclarations.test.ts +137 -112
- package/test/transforms/identifier/renameVariables.test.ts +124 -13
- package/test/transforms/lock/antiDebug.test.ts +43 -0
- package/test/transforms/lock/selfDefending.test.ts +68 -0
- package/test/transforms/minify.test.ts +137 -0
- package/test/transforms/renameLabels.test.ts +33 -0
- package/test/transforms/rgf.test.ts +29 -0
- package/test/transforms/string/stringSplitting.test.ts +33 -0
- package/test/util/identifiers.test.ts +105 -17
- package/dist/util/expr.js +0 -60
- package/src/util/expr.ts +0 -56
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { ok } from "assert";
|
|
2
|
+
import { reservedIdentifiers } from "../../constants";
|
|
3
|
+
import { walk } from "../../traverse";
|
|
4
|
+
import { isValidIdentifier } from "../../util/compare";
|
|
5
|
+
import { Node } from "../../util/gen";
|
|
6
|
+
import { getIdentifierInfo } from "../../util/identifiers";
|
|
7
|
+
import {
|
|
8
|
+
getDefiningContext,
|
|
9
|
+
getVarContext,
|
|
10
|
+
getLexContext,
|
|
11
|
+
isContext,
|
|
12
|
+
getReferencingContexts,
|
|
13
|
+
} from "../../util/insert";
|
|
14
|
+
import Transform from "../transform";
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Keeps track of what identifiers are defined and referenced in each context.
|
|
18
|
+
*/
|
|
19
|
+
export default class VariableAnalysis extends Transform {
|
|
20
|
+
/**
|
|
21
|
+
* Node being the context.
|
|
22
|
+
*/
|
|
23
|
+
defined: Map<Node, Set<string>>;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Context->Nodes referenced (does not include nested)
|
|
27
|
+
*/
|
|
28
|
+
references: Map<Node, Set<string>>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Set of global identifiers to never be redefined
|
|
32
|
+
*/
|
|
33
|
+
globals: Set<string>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Set of identifers that are defined within the program
|
|
37
|
+
*/
|
|
38
|
+
notGlobals: Set<string>;
|
|
39
|
+
|
|
40
|
+
constructor(o) {
|
|
41
|
+
super(o);
|
|
42
|
+
|
|
43
|
+
this.defined = new Map();
|
|
44
|
+
this.references = new Map();
|
|
45
|
+
this.globals = new Set();
|
|
46
|
+
this.notGlobals = new Set();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
match(object, parents) {
|
|
50
|
+
return isContext(object);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
transform(object, parents) {
|
|
54
|
+
walk(object, parents, (o, p) => {
|
|
55
|
+
if (o.type == "Identifier") {
|
|
56
|
+
var name = o.name;
|
|
57
|
+
ok(typeof name === "string");
|
|
58
|
+
if (!isValidIdentifier(name)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (reservedIdentifiers.has(name)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (this.options.globalVariables.has(name)) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var info = getIdentifierInfo(o, p);
|
|
70
|
+
if (!info.spec.isReferenced) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (info.spec.isExported) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
var isDefined = info.spec.isDefined;
|
|
79
|
+
|
|
80
|
+
// Keep track of defined names within the program
|
|
81
|
+
if (isDefined) {
|
|
82
|
+
this.notGlobals.add(o.name);
|
|
83
|
+
this.globals.delete(o.name);
|
|
84
|
+
} else if (!this.notGlobals.has(o.name)) {
|
|
85
|
+
this.globals.add(o.name);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
var definingContexts = info.spec.isDefined
|
|
89
|
+
? [getDefiningContext(o, p)]
|
|
90
|
+
: getReferencingContexts(o, p, info);
|
|
91
|
+
|
|
92
|
+
ok(definingContexts.length);
|
|
93
|
+
|
|
94
|
+
definingContexts.forEach((definingContext) => {
|
|
95
|
+
ok(
|
|
96
|
+
isContext(definingContext),
|
|
97
|
+
`${definingContext.type} is not a context`
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
if (isDefined) {
|
|
101
|
+
// Add to defined Map
|
|
102
|
+
if (!this.defined.has(definingContext)) {
|
|
103
|
+
this.defined.set(definingContext, new Set());
|
|
104
|
+
}
|
|
105
|
+
this.defined.get(definingContext).add(name);
|
|
106
|
+
this.references.has(definingContext) &&
|
|
107
|
+
this.references.get(definingContext).delete(name);
|
|
108
|
+
} else {
|
|
109
|
+
// Add to references Map
|
|
110
|
+
if (
|
|
111
|
+
!this.defined.has(definingContext) ||
|
|
112
|
+
!this.defined.get(definingContext).has(name)
|
|
113
|
+
) {
|
|
114
|
+
if (!this.references.has(definingContext)) {
|
|
115
|
+
this.references.set(definingContext, new Set());
|
|
116
|
+
}
|
|
117
|
+
this.references.get(definingContext).add(name);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
}
|
package/src/transforms/label.ts
CHANGED
|
@@ -16,7 +16,13 @@ export default class Label extends Transform {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
match(object, parents) {
|
|
19
|
-
return
|
|
19
|
+
return (
|
|
20
|
+
isLoop(object) ||
|
|
21
|
+
(object.type == "BlockStatement" &&
|
|
22
|
+
parents[0] &&
|
|
23
|
+
parents[0].type == "LabeledStatement" &&
|
|
24
|
+
parents[0].body === object)
|
|
25
|
+
);
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
transform(object, parents) {
|
|
@@ -28,7 +34,19 @@ export default class Label extends Transform {
|
|
|
28
34
|
|
|
29
35
|
walk(object, parents, (o, p) => {
|
|
30
36
|
if (o.type == "BreakStatement" || o.type == "ContinueStatement") {
|
|
31
|
-
|
|
37
|
+
function isContinuableStatement(x) {
|
|
38
|
+
return isLoop(x) && x.type !== "SwitchStatement";
|
|
39
|
+
}
|
|
40
|
+
function isBreakableStatement(x) {
|
|
41
|
+
return isLoop(x) || (o.label && x.type == "BlockStatement");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
var fn =
|
|
45
|
+
o.type == "ContinueStatement"
|
|
46
|
+
? isContinuableStatement
|
|
47
|
+
: isBreakableStatement;
|
|
48
|
+
|
|
49
|
+
var loop = p.find(fn);
|
|
32
50
|
if (object == loop) {
|
|
33
51
|
if (!o.label) {
|
|
34
52
|
o.label = Identifier(label);
|
|
@@ -1,51 +1,86 @@
|
|
|
1
1
|
import { ObfuscateOrder } from "../../order";
|
|
2
2
|
import Template from "../../templates/template";
|
|
3
3
|
import { isBlock } from "../../traverse";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
AssignmentExpression,
|
|
6
|
+
DebuggerStatement,
|
|
7
|
+
ExpressionStatement,
|
|
8
|
+
FunctionDeclaration,
|
|
9
|
+
Identifier,
|
|
10
|
+
IfStatement,
|
|
11
|
+
Literal,
|
|
12
|
+
WhileStatement,
|
|
13
|
+
} from "../../util/gen";
|
|
5
14
|
import { getBlockBody, prepend } from "../../util/insert";
|
|
6
15
|
import { getRandomInteger } from "../../util/random";
|
|
7
16
|
import Transform from "../transform";
|
|
17
|
+
import Lock from "./lock";
|
|
8
18
|
|
|
9
19
|
var DevToolsDetection = Template(
|
|
10
20
|
`
|
|
11
|
-
function $jsc_debug(){
|
|
12
|
-
var startTime = new Date();
|
|
13
|
-
debugger;
|
|
14
|
-
var endTime = new Date();
|
|
15
|
-
var isDev = endTime-startTime > 600;
|
|
16
|
-
|
|
17
|
-
while (isDev) {
|
|
18
|
-
debugger;
|
|
19
|
-
(function () {}). constructor ("debugger") ()
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
}
|
|
23
21
|
try {
|
|
24
22
|
if ( setInterval ) {
|
|
25
23
|
setInterval(()=>{
|
|
26
|
-
|
|
24
|
+
{functionName}();
|
|
27
25
|
}, 4000);
|
|
28
26
|
}
|
|
29
27
|
} catch ( e ) {
|
|
30
28
|
|
|
31
29
|
}
|
|
32
|
-
|
|
33
30
|
`
|
|
34
31
|
);
|
|
35
32
|
|
|
36
33
|
export default class AntiDebug extends Transform {
|
|
37
34
|
made: number;
|
|
35
|
+
lock: Lock;
|
|
38
36
|
|
|
39
|
-
constructor(o) {
|
|
37
|
+
constructor(o, lock) {
|
|
40
38
|
super(o, ObfuscateOrder.Lock);
|
|
41
39
|
|
|
40
|
+
this.lock = lock;
|
|
42
41
|
this.made = 0;
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
apply(tree) {
|
|
46
45
|
super.apply(tree);
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
var fnName = this.getPlaceholder();
|
|
48
|
+
var startTimeName = this.getPlaceholder();
|
|
49
|
+
var endTimeName = this.getPlaceholder();
|
|
50
|
+
var isDevName = this.getPlaceholder();
|
|
51
|
+
var functionDeclaration = FunctionDeclaration(
|
|
52
|
+
fnName,
|
|
53
|
+
[],
|
|
54
|
+
[
|
|
55
|
+
...Template(`
|
|
56
|
+
var ${startTimeName} = new Date();
|
|
57
|
+
debugger;
|
|
58
|
+
var ${endTimeName} = new Date();
|
|
59
|
+
var ${isDevName} = ${endTimeName}-${startTimeName} > 1000;
|
|
60
|
+
`).compile(),
|
|
61
|
+
|
|
62
|
+
IfStatement(
|
|
63
|
+
Identifier(isDevName),
|
|
64
|
+
this.options.lock.countermeasures
|
|
65
|
+
? this.lock.getCounterMeasuresCode()
|
|
66
|
+
: [
|
|
67
|
+
WhileStatement(Identifier(isDevName), [
|
|
68
|
+
ExpressionStatement(
|
|
69
|
+
AssignmentExpression(
|
|
70
|
+
"=",
|
|
71
|
+
Identifier(startTimeName),
|
|
72
|
+
Identifier(endTimeName)
|
|
73
|
+
)
|
|
74
|
+
),
|
|
75
|
+
]),
|
|
76
|
+
],
|
|
77
|
+
null
|
|
78
|
+
),
|
|
79
|
+
]
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
tree.body.unshift(...DevToolsDetection.compile({ functionName: fnName }));
|
|
83
|
+
tree.body.push(functionDeclaration);
|
|
49
84
|
}
|
|
50
85
|
|
|
51
86
|
match(object, parents) {
|
|
@@ -53,17 +88,25 @@ export default class AntiDebug extends Transform {
|
|
|
53
88
|
}
|
|
54
89
|
|
|
55
90
|
transform(object, parents) {
|
|
56
|
-
|
|
91
|
+
return () => {
|
|
92
|
+
var body = getBlockBody(object.body);
|
|
93
|
+
|
|
94
|
+
[...body].forEach((stmt, i) => {
|
|
95
|
+
var addDebugger = Math.random() < 0.1 / (this.made || 1);
|
|
96
|
+
|
|
97
|
+
if (object.type == "Program" && i == 0) {
|
|
98
|
+
addDebugger = true;
|
|
99
|
+
}
|
|
57
100
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
body.splice(index, 0, DebuggerStatement());
|
|
101
|
+
if (addDebugger) {
|
|
102
|
+
var index = getRandomInteger(0, body.length);
|
|
103
|
+
if (body[index].type != "DebuggerStatement") {
|
|
104
|
+
body.splice(index, 0, DebuggerStatement());
|
|
63
105
|
|
|
64
|
-
|
|
106
|
+
this.made++;
|
|
107
|
+
}
|
|
65
108
|
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
109
|
+
});
|
|
110
|
+
};
|
|
68
111
|
}
|
|
69
112
|
}
|
|
@@ -62,7 +62,7 @@ export default class Lock extends Transform {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
if (this.options.lock.antiDebug) {
|
|
65
|
-
this.before.push(new AntiDebug(o));
|
|
65
|
+
this.before.push(new AntiDebug(o, this));
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
this.made = 0;
|
|
@@ -112,8 +112,7 @@ export default class Lock extends Transform {
|
|
|
112
112
|
throw new Error(
|
|
113
113
|
"Countermeasures function named '" +
|
|
114
114
|
this.options.lock.countermeasures +
|
|
115
|
-
"' was not found.
|
|
116
|
-
Array.from(defined).slice(0, 100).join(", ")
|
|
115
|
+
"' was not found."
|
|
117
116
|
);
|
|
118
117
|
}
|
|
119
118
|
}
|
|
@@ -215,6 +214,9 @@ export default class Lock extends Transform {
|
|
|
215
214
|
if (this.options.lock.osLock && this.options.lock.osLock.length) {
|
|
216
215
|
choices.push("osLock");
|
|
217
216
|
}
|
|
217
|
+
if (this.options.lock.selfDefending) {
|
|
218
|
+
choices.push("selfDefending");
|
|
219
|
+
}
|
|
218
220
|
|
|
219
221
|
if (!choices.length) {
|
|
220
222
|
return;
|
|
@@ -261,6 +263,38 @@ export default class Lock extends Transform {
|
|
|
261
263
|
var offset = 0;
|
|
262
264
|
|
|
263
265
|
switch (type) {
|
|
266
|
+
case "selfDefending":
|
|
267
|
+
// A very simple mechanism inspired from https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/src/custom-code-helpers/self-defending/templates/SelfDefendingNoEvalTemplate.ts
|
|
268
|
+
// regExp checks for a newline, formatters add these
|
|
269
|
+
var callExpression = Template(
|
|
270
|
+
`
|
|
271
|
+
(
|
|
272
|
+
function(){
|
|
273
|
+
// Breaks JSNice.org, beautifier.io
|
|
274
|
+
var namedFunction = function(){
|
|
275
|
+
const test = function(){
|
|
276
|
+
const regExp=new RegExp('\\n');
|
|
277
|
+
return regExp['test'](namedFunction)
|
|
278
|
+
};
|
|
279
|
+
return test()
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return namedFunction();
|
|
283
|
+
}
|
|
284
|
+
)()
|
|
285
|
+
`
|
|
286
|
+
).single().expression;
|
|
287
|
+
|
|
288
|
+
nodes.push(
|
|
289
|
+
IfStatement(
|
|
290
|
+
callExpression,
|
|
291
|
+
this.getCounterMeasuresCode() || [],
|
|
292
|
+
null
|
|
293
|
+
)
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
break;
|
|
297
|
+
|
|
264
298
|
case "nativeFunction":
|
|
265
299
|
var set = this.options.lock.nativeFunctions;
|
|
266
300
|
if (set === true) {
|