js-confuser 1.5.8 → 1.6.0
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/.github/workflows/node.js.yml +2 -2
- package/CHANGELOG.md +69 -0
- package/README.md +143 -7
- package/dist/index.js +33 -4
- package/dist/obfuscator.js +30 -31
- package/dist/options.js +4 -5
- package/dist/order.js +4 -6
- package/dist/probability.js +2 -4
- package/dist/templates/bufferToString.js +13 -0
- package/dist/templates/crash.js +2 -2
- package/dist/templates/es5.js +18 -0
- package/dist/transforms/antiTooling.js +1 -1
- package/dist/transforms/calculator.js +77 -21
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
- package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
- package/dist/transforms/deadCode.js +33 -25
- package/dist/transforms/dispatcher.js +7 -6
- package/dist/transforms/es5/antiClass.js +6 -2
- package/dist/transforms/es5/antiDestructuring.js +3 -1
- package/dist/transforms/es5/es5.js +31 -34
- package/dist/transforms/eval.js +11 -0
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
- package/dist/transforms/extraction/objectExtraction.js +6 -1
- package/dist/transforms/finalizer.js +82 -0
- package/dist/transforms/flatten.js +82 -55
- package/dist/transforms/hexadecimalNumbers.js +34 -9
- package/dist/transforms/identifier/globalAnalysis.js +88 -0
- package/dist/transforms/identifier/globalConcealing.js +10 -83
- package/dist/transforms/identifier/movedDeclarations.js +2 -8
- package/dist/transforms/identifier/renameVariables.js +39 -27
- package/dist/transforms/identifier/variableAnalysis.js +58 -62
- package/dist/transforms/minify.js +80 -61
- package/dist/transforms/opaquePredicates.js +1 -1
- package/dist/transforms/preparation/preparation.js +2 -2
- package/dist/transforms/preparation.js +231 -0
- package/dist/transforms/renameLabels.js +1 -1
- package/dist/transforms/rgf.js +4 -5
- package/dist/transforms/stack.js +87 -26
- package/dist/transforms/string/encoding.js +150 -179
- package/dist/transforms/string/stringCompression.js +14 -15
- package/dist/transforms/string/stringConcealing.js +25 -8
- package/dist/transforms/string/stringEncoding.js +13 -24
- package/dist/transforms/transform.js +11 -18
- package/dist/traverse.js +24 -18
- package/dist/util/compare.js +2 -2
- package/dist/util/gen.js +15 -0
- package/dist/util/insert.js +31 -7
- package/dist/util/random.js +15 -0
- package/package.json +5 -5
- package/src/index.ts +57 -19
- package/src/obfuscator.ts +26 -29
- package/src/options.ts +17 -21
- package/src/order.ts +4 -8
- package/src/probability.ts +2 -3
- package/src/templates/bufferToString.ts +68 -0
- package/src/templates/crash.ts +5 -9
- package/src/templates/es5.ts +131 -0
- package/src/transforms/antiTooling.ts +1 -1
- package/src/transforms/calculator.ts +122 -59
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
- package/src/transforms/deadCode.ts +383 -26
- package/src/transforms/dispatcher.ts +8 -6
- package/src/transforms/es5/antiClass.ts +10 -1
- package/src/transforms/es5/antiDestructuring.ts +3 -1
- package/src/transforms/es5/es5.ts +32 -77
- package/src/transforms/eval.ts +18 -0
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
- package/src/transforms/extraction/objectExtraction.ts +12 -5
- package/src/transforms/finalizer.ts +75 -0
- package/src/transforms/flatten.ts +194 -151
- package/src/transforms/identifier/globalAnalysis.ts +85 -0
- package/src/transforms/identifier/globalConcealing.ts +14 -103
- package/src/transforms/identifier/movedDeclarations.ts +4 -11
- package/src/transforms/identifier/renameVariables.ts +37 -30
- package/src/transforms/identifier/variableAnalysis.ts +66 -73
- package/src/transforms/minify.ts +116 -77
- package/src/transforms/opaquePredicates.ts +2 -2
- package/src/transforms/preparation.ts +238 -0
- package/src/transforms/renameLabels.ts +2 -2
- package/src/transforms/rgf.ts +6 -7
- package/src/transforms/stack.ts +97 -37
- package/src/transforms/string/encoding.ts +115 -212
- package/src/transforms/string/stringCompression.ts +27 -18
- package/src/transforms/string/stringConcealing.ts +41 -11
- package/src/transforms/string/stringEncoding.ts +18 -18
- package/src/transforms/transform.ts +15 -21
- package/src/traverse.ts +24 -12
- package/src/types.ts +11 -2
- package/src/util/compare.ts +2 -2
- package/src/util/gen.ts +21 -1
- package/src/util/insert.ts +49 -9
- package/src/util/random.ts +13 -0
- package/test/code/Cash.test.ts +1 -1
- package/test/code/Dynamic.test.ts +12 -10
- package/test/code/ES6.src.js +136 -0
- package/test/code/ES6.test.ts +28 -2
- package/test/code/NewFeatures.test.ts +19 -0
- package/test/index.test.ts +15 -2
- package/test/probability.test.ts +44 -0
- package/test/templates/template.test.ts +1 -1
- package/test/transforms/antiTooling.test.ts +52 -0
- package/test/transforms/calculator.test.ts +40 -0
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
- package/test/transforms/deadCode.test.ts +66 -15
- package/test/transforms/dispatcher.test.ts +44 -1
- package/test/transforms/es5/antiClass.test.ts +33 -0
- package/test/transforms/es5/antiDestructuring.test.ts +16 -0
- package/test/transforms/eval.test.ts +53 -0
- package/test/transforms/extraction/objectExtraction.test.ts +21 -0
- package/test/transforms/flatten.test.ts +195 -3
- package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
- package/test/transforms/identifier/renameVariables.test.ts +108 -0
- package/test/transforms/lock/antiDebug.test.ts +2 -2
- package/test/transforms/minify.test.ts +151 -0
- package/test/transforms/preparation.test.ts +157 -0
- package/test/transforms/rgf.test.ts +56 -29
- package/test/transforms/stack.test.ts +91 -21
- package/test/transforms/string/stringCompression.test.ts +39 -0
- package/test/transforms/string/stringConcealing.test.ts +115 -0
- package/test/transforms/string/stringEncoding.test.ts +53 -2
- package/test/transforms/transform.test.ts +66 -0
- package/test/traverse.test.ts +139 -0
- package/test/util/compare.test.ts +23 -1
- package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
- package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
- package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
- package/src/transforms/hexadecimalNumbers.ts +0 -31
- package/src/transforms/hideInitializingCode.ts +0 -432
- package/src/transforms/label.ts +0 -64
- package/src/transforms/preparation/nameConflicts.ts +0 -102
- package/src/transforms/preparation/preparation.ts +0 -176
- package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
- package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
- package/test/transforms/hideInitializingCode.test.ts +0 -336
- package/test/transforms/preparation/nameConflicts.test.ts +0 -52
- package/test/transforms/preparation/preparation.test.ts +0 -62
package/dist/traverse.js
CHANGED
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.assertNoCircular = assertNoCircular;
|
|
6
7
|
exports.default = traverse;
|
|
7
8
|
exports.getBlock = getBlock;
|
|
8
9
|
exports.isBlock = isBlock;
|
|
9
10
|
exports.walk = walk;
|
|
10
11
|
|
|
11
|
-
var _identifiers = require("./util/identifiers");
|
|
12
|
-
|
|
13
12
|
/**
|
|
14
13
|
* A block refers to any object that has a **`.body`** property where code is nested.
|
|
15
14
|
*
|
|
@@ -40,21 +39,11 @@ function isBlock(object) {
|
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
function walk(object, parents, onEnter) {
|
|
43
|
-
let seen = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : new Set();
|
|
44
|
-
|
|
45
42
|
if (typeof object === "object" && object) {
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
seen.add(object);
|
|
52
|
-
var newParents = [object, ...parents];
|
|
53
|
-
|
|
54
|
-
if (!Array.isArray(object)) {
|
|
55
|
-
(0, _identifiers.validateChain)(object, parents);
|
|
56
|
-
} // 1. Call `onEnter` function and remember any onExit callback returned
|
|
57
|
-
|
|
43
|
+
var newParents = [object, ...parents]; // if (!Array.isArray(object)) {
|
|
44
|
+
// validateChain(object, parents);
|
|
45
|
+
// }
|
|
46
|
+
// 1. Call `onEnter` function and remember any onExit callback returned
|
|
58
47
|
|
|
59
48
|
var onExit = onEnter(object, parents); // 2. Traverse children
|
|
60
49
|
|
|
@@ -66,8 +55,6 @@ function walk(object, parents, onEnter) {
|
|
|
66
55
|
return "EXIT";
|
|
67
56
|
}
|
|
68
57
|
}
|
|
69
|
-
|
|
70
|
-
copy.forEach(x => {});
|
|
71
58
|
} else {
|
|
72
59
|
var keys = Object.keys(object);
|
|
73
60
|
|
|
@@ -108,4 +95,23 @@ function walk(object, parents, onEnter) {
|
|
|
108
95
|
|
|
109
96
|
function traverse(tree, onEnter) {
|
|
110
97
|
walk(tree, [], onEnter);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* This is debugging function used to test for circular references.
|
|
101
|
+
*/
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
function assertNoCircular(object) {
|
|
105
|
+
var seen = new Set();
|
|
106
|
+
traverse(object, (node, nodeParents) => {
|
|
107
|
+
if (node && typeof node === "object") {
|
|
108
|
+
if (seen.has(node)) {
|
|
109
|
+
console.log(nodeParents);
|
|
110
|
+
console.log(node);
|
|
111
|
+
throw new Error("FOUND CIRCULAR REFERENCE");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
seen.add(node);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
111
117
|
}
|
package/dist/util/compare.js
CHANGED
|
@@ -59,8 +59,8 @@ function isValidIdentifier(name) {
|
|
|
59
59
|
return false;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
var x = name.match(/^[A-z$_][A-z0-9$_]*/);
|
|
63
|
-
return x && x[0] == name;
|
|
62
|
+
var x = name.match(/^[A-Za-z$_][A-Za-z0-9$_]*/);
|
|
63
|
+
return !!(x && x[0] == name);
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
function isInsideType(type, object, parents) {
|
package/dist/util/gen.js
CHANGED
|
@@ -15,6 +15,7 @@ exports.BreakStatement = BreakStatement;
|
|
|
15
15
|
exports.CallExpression = CallExpression;
|
|
16
16
|
exports.CatchClause = CatchClause;
|
|
17
17
|
exports.ClassDeclaration = ClassDeclaration;
|
|
18
|
+
exports.ClassExpression = ClassExpression;
|
|
18
19
|
exports.ConditionalExpression = ConditionalExpression;
|
|
19
20
|
exports.DebuggerStatement = DebuggerStatement;
|
|
20
21
|
exports.ExpressionStatement = ExpressionStatement;
|
|
@@ -537,6 +538,20 @@ function ClassDeclaration(id) {
|
|
|
537
538
|
};
|
|
538
539
|
}
|
|
539
540
|
|
|
541
|
+
function ClassExpression(id) {
|
|
542
|
+
let superClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
543
|
+
let body = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
|
|
544
|
+
return {
|
|
545
|
+
type: "ClassExpression",
|
|
546
|
+
id: id,
|
|
547
|
+
superClass: superClass,
|
|
548
|
+
body: {
|
|
549
|
+
type: "ClassBody",
|
|
550
|
+
body: body
|
|
551
|
+
}
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
|
|
540
555
|
function ThrowStatement(argument) {
|
|
541
556
|
return {
|
|
542
557
|
type: "ThrowStatement",
|
package/dist/util/insert.js
CHANGED
|
@@ -139,8 +139,12 @@ function getDefiningContext(o, p) {
|
|
|
139
139
|
var variableDeclaration = p.find(x => x.type == "VariableDeclaration");
|
|
140
140
|
(0, _assert.ok)(variableDeclaration);
|
|
141
141
|
|
|
142
|
-
if (variableDeclaration.kind === "let") {
|
|
143
|
-
|
|
142
|
+
if (variableDeclaration.kind === "let" || variableDeclaration.kind === "const") {
|
|
143
|
+
var context = getVarContext(o, p);
|
|
144
|
+
|
|
145
|
+
if (context && context.type === "Program") {
|
|
146
|
+
return getLexContext(o, p);
|
|
147
|
+
}
|
|
144
148
|
}
|
|
145
149
|
}
|
|
146
150
|
|
|
@@ -287,17 +291,33 @@ function prepend(block) {
|
|
|
287
291
|
}
|
|
288
292
|
|
|
289
293
|
if (block.type == "Program") {
|
|
290
|
-
var
|
|
294
|
+
var moveBy = 0;
|
|
291
295
|
block.body.forEach((stmt, i) => {
|
|
292
296
|
if (stmt.type == "ImportDeclaration") {
|
|
293
|
-
if (
|
|
294
|
-
|
|
297
|
+
if (moveBy == i) {
|
|
298
|
+
moveBy++;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (stmt.type === "ExpressionStatement" && typeof stmt.directive === "string") {
|
|
303
|
+
if (moveBy == i) {
|
|
304
|
+
moveBy++;
|
|
295
305
|
}
|
|
296
306
|
}
|
|
297
307
|
});
|
|
298
|
-
block.body.splice(
|
|
308
|
+
block.body.splice(moveBy, 0, ...nodes);
|
|
309
|
+
} else if (block.type === "SwitchCase") {
|
|
310
|
+
block.consequent.unshift(...nodes);
|
|
299
311
|
} else {
|
|
300
|
-
getBlockBody(block)
|
|
312
|
+
var bodyArray = getBlockBody(block); // Check for 'use strict'
|
|
313
|
+
|
|
314
|
+
if (bodyArray[0] && bodyArray[0].directive) {
|
|
315
|
+
// Insert under 'use strict' directive
|
|
316
|
+
bodyArray.splice(1, 0, ...nodes);
|
|
317
|
+
} else {
|
|
318
|
+
// Prepend at the top of the block
|
|
319
|
+
bodyArray.unshift(...nodes);
|
|
320
|
+
}
|
|
301
321
|
}
|
|
302
322
|
}
|
|
303
323
|
|
|
@@ -351,6 +371,10 @@ function isForInitialize(o, p) {
|
|
|
351
371
|
(0, _identifiers.validateChain)(o, p);
|
|
352
372
|
var forIndex = p.findIndex(x => x.type == "ForStatement" || x.type == "ForInStatement" || x.type == "ForOfStatement");
|
|
353
373
|
|
|
374
|
+
if (p.slice(0, forIndex).find(x => ["ArrowFunctionExpression", "BlockStatement"].includes(x.type))) {
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
|
|
354
378
|
if (forIndex !== -1) {
|
|
355
379
|
if (p[forIndex].type == "ForStatement") {
|
|
356
380
|
if (p[forIndex].init == (p[forIndex - 1] || o)) {
|
package/dist/util/random.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.alphabeticalGenerator = alphabeticalGenerator;
|
|
7
|
+
exports.chance = chance;
|
|
7
8
|
exports.choice = choice;
|
|
8
9
|
exports.getRandom = getRandom;
|
|
9
10
|
exports.getRandomFalseExpression = getRandomFalseExpression;
|
|
@@ -17,10 +18,24 @@ var _assert = require("assert");
|
|
|
17
18
|
|
|
18
19
|
var _gen = require("./gen");
|
|
19
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Returns a random element from the given array
|
|
23
|
+
* @param choices Array of items
|
|
24
|
+
* @returns One of the items in the array at random
|
|
25
|
+
*/
|
|
20
26
|
function choice(choices) {
|
|
21
27
|
var index = Math.floor(Math.random() * choices.length);
|
|
22
28
|
return choices[index];
|
|
23
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns a true/false based on the percent chance (0%-100%)
|
|
32
|
+
* @param percentChance AS A PERCENTAGE 0 - 100%
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
function chance(percentChance) {
|
|
37
|
+
return Math.random() < percentChance / 100;
|
|
38
|
+
}
|
|
24
39
|
/**
|
|
25
40
|
* **Mutates the given array**
|
|
26
41
|
* @param array
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "js-confuser",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "JavaScript Obfuscation Tool.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"dev": "node ./dev.js",
|
|
9
9
|
"build": "./node_modules/.bin/babel src --out-dir dist --copy-files --extensions \".ts\"",
|
|
10
|
-
"test": "jest",
|
|
10
|
+
"test": "jest --forceExit",
|
|
11
11
|
"test:coverage": "jest --coverage",
|
|
12
|
-
"prepublishOnly": "npm run build & npm run test"
|
|
12
|
+
"prepublishOnly": "npm run build & npm run test --forceExit"
|
|
13
13
|
},
|
|
14
14
|
"keywords": [
|
|
15
15
|
"obfuscator",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@types/jest": "^26.0.24",
|
|
37
37
|
"@types/node": "^15.14.9",
|
|
38
38
|
"babel-jest": "^26.6.3",
|
|
39
|
-
"jest": "^
|
|
39
|
+
"jest": "^29.5.0"
|
|
40
40
|
},
|
|
41
41
|
"repository": {
|
|
42
42
|
"type": "git",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"bugs": {
|
|
46
46
|
"url": "https://github.com/MichaelXF/js-confuser/issues"
|
|
47
47
|
},
|
|
48
|
-
"homepage": "https://
|
|
48
|
+
"homepage": "https://js-confuser.com",
|
|
49
49
|
"jest": {
|
|
50
50
|
"coverageReporters": [
|
|
51
51
|
"html"
|
package/src/index.ts
CHANGED
|
@@ -85,8 +85,8 @@ var JsConfuser: IJsConfuser = async function (
|
|
|
85
85
|
return result;
|
|
86
86
|
} as any;
|
|
87
87
|
|
|
88
|
-
export
|
|
89
|
-
async function
|
|
88
|
+
export const debugTransformations: IJsConfuserDebugTransformations =
|
|
89
|
+
async function (
|
|
90
90
|
code: string,
|
|
91
91
|
options: ObfuscateOptions
|
|
92
92
|
): Promise<{ name: string; code: string; ms: number }[]> {
|
|
@@ -115,28 +115,66 @@ export var debugTransformations: IJsConfuserDebugTransformations =
|
|
|
115
115
|
return frames;
|
|
116
116
|
};
|
|
117
117
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
118
|
+
/**
|
|
119
|
+
* This method is used by the obfuscator website to display a progress bar and additional information
|
|
120
|
+
* about the obfuscation.
|
|
121
|
+
*
|
|
122
|
+
* @param code - Source code to obfuscate
|
|
123
|
+
* @param options - Options
|
|
124
|
+
* @param callback - Progress callback, called after each transformation
|
|
125
|
+
* @returns
|
|
126
|
+
*/
|
|
127
|
+
export const debugObfuscation: IJsConfuserDebugObfuscation = async function (
|
|
128
|
+
code: string,
|
|
129
|
+
options: ObfuscateOptions,
|
|
130
|
+
callback: (name: string, complete: number, totalTransforms: number) => void,
|
|
131
|
+
performance: Performance
|
|
132
|
+
) {
|
|
133
|
+
const startTime = performance.now();
|
|
126
134
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
var totalTransforms = obfuscator.array.length;
|
|
135
|
+
validateOptions(options);
|
|
136
|
+
options = await correctOptions(options);
|
|
130
137
|
|
|
131
|
-
|
|
132
|
-
callback(name, i, totalTransforms);
|
|
133
|
-
});
|
|
138
|
+
const beforeParseTime = performance.now();
|
|
134
139
|
|
|
135
|
-
|
|
140
|
+
var tree = parseSync(code);
|
|
141
|
+
|
|
142
|
+
const parseTime = performance.now() - beforeParseTime;
|
|
143
|
+
|
|
144
|
+
var obfuscator = new Obfuscator(options);
|
|
145
|
+
var totalTransforms = obfuscator.array.length;
|
|
146
|
+
|
|
147
|
+
var transformationTimes = Object.create(null);
|
|
148
|
+
var currentTransformTime = performance.now();
|
|
149
|
+
|
|
150
|
+
obfuscator.on("debug", (name: string, tree: Node, i: number) => {
|
|
151
|
+
var nowTime = performance.now();
|
|
152
|
+
transformationTimes[name] = nowTime - currentTransformTime;
|
|
153
|
+
currentTransformTime = nowTime;
|
|
154
|
+
|
|
155
|
+
callback(name, i, totalTransforms);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await obfuscator.apply(tree, true);
|
|
159
|
+
|
|
160
|
+
const beforeCompileTime = performance.now();
|
|
161
|
+
|
|
162
|
+
var output = await compileJs(tree, options);
|
|
163
|
+
|
|
164
|
+
const compileTime = performance.now() - beforeCompileTime;
|
|
165
|
+
|
|
166
|
+
const endTime = performance.now();
|
|
136
167
|
|
|
137
|
-
|
|
138
|
-
|
|
168
|
+
return {
|
|
169
|
+
obfuscated: output,
|
|
170
|
+
transformationTimes: transformationTimes,
|
|
171
|
+
obfuscationTime: endTime - startTime,
|
|
172
|
+
parseTime: parseTime,
|
|
173
|
+
compileTime: compileTime,
|
|
174
|
+
totalTransforms: totalTransforms,
|
|
175
|
+
totalPossibleTransforms: obfuscator.totalPossibleTransforms,
|
|
139
176
|
};
|
|
177
|
+
};
|
|
140
178
|
|
|
141
179
|
JsConfuser.obfuscate = obfuscate;
|
|
142
180
|
JsConfuser.obfuscateAST = obfuscateAST;
|
package/src/obfuscator.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { ProbabilityMap, isProbabilityMapProbable } from "./probability";
|
|
|
7
7
|
|
|
8
8
|
import Transform from "./transforms/transform";
|
|
9
9
|
|
|
10
|
-
import Preparation from "./transforms/preparation
|
|
10
|
+
import Preparation from "./transforms/preparation";
|
|
11
11
|
import ObjectExtraction from "./transforms/extraction/objectExtraction";
|
|
12
12
|
import Lock from "./transforms/lock/lock";
|
|
13
13
|
import Dispatcher from "./transforms/dispatcher";
|
|
@@ -17,8 +17,9 @@ import Calculator from "./transforms/calculator";
|
|
|
17
17
|
import ControlFlowFlattening from "./transforms/controlFlowFlattening/controlFlowFlattening";
|
|
18
18
|
import Eval from "./transforms/eval";
|
|
19
19
|
import GlobalConcealing from "./transforms/identifier/globalConcealing";
|
|
20
|
-
import StringConcealing from "./transforms/string/stringConcealing";
|
|
21
20
|
import StringSplitting from "./transforms/string/stringSplitting";
|
|
21
|
+
import StringConcealing from "./transforms/string/stringConcealing";
|
|
22
|
+
import StringCompression from "./transforms/string/stringCompression";
|
|
22
23
|
import DuplicateLiteralsRemoval from "./transforms/extraction/duplicateLiteralsRemoval";
|
|
23
24
|
import Shuffle from "./transforms/shuffle";
|
|
24
25
|
import MovedDeclarations from "./transforms/identifier/movedDeclarations";
|
|
@@ -26,15 +27,12 @@ import RenameVariables from "./transforms/identifier/renameVariables";
|
|
|
26
27
|
import RenameLabels from "./transforms/renameLabels";
|
|
27
28
|
import Minify from "./transforms/minify";
|
|
28
29
|
import ES5 from "./transforms/es5/es5";
|
|
29
|
-
import StringEncoding from "./transforms/string/stringEncoding";
|
|
30
30
|
import RGF from "./transforms/rgf";
|
|
31
31
|
import Flatten from "./transforms/flatten";
|
|
32
32
|
import Stack from "./transforms/stack";
|
|
33
|
-
import StringCompression from "./transforms/string/stringCompression";
|
|
34
33
|
import NameRecycling from "./transforms/identifier/nameRecycling";
|
|
35
34
|
import AntiTooling from "./transforms/antiTooling";
|
|
36
|
-
import
|
|
37
|
-
import HexadecimalNumbers from "./transforms/hexadecimalNumbers";
|
|
35
|
+
import Finalizer from "./transforms/finalizer";
|
|
38
36
|
|
|
39
37
|
/**
|
|
40
38
|
* The parent transformation holding the `state`.
|
|
@@ -47,17 +45,19 @@ export default class Obfuscator extends EventEmitter {
|
|
|
47
45
|
state: "transform" | "eval" = "transform";
|
|
48
46
|
generated: Set<string>;
|
|
49
47
|
|
|
48
|
+
totalPossibleTransforms: number;
|
|
49
|
+
|
|
50
50
|
constructor(public options: ObfuscateOptions) {
|
|
51
51
|
super();
|
|
52
52
|
|
|
53
53
|
this.varCount = 0;
|
|
54
54
|
this.transforms = Object.create(null);
|
|
55
55
|
this.generated = new Set();
|
|
56
|
-
|
|
57
|
-
this.push(new Preparation(this));
|
|
58
|
-
this.push(new RenameLabels(this));
|
|
56
|
+
this.totalPossibleTransforms = 0;
|
|
59
57
|
|
|
60
58
|
const test = <T>(map: ProbabilityMap<T>, ...transformers: any[]) => {
|
|
59
|
+
this.totalPossibleTransforms += transformers.length;
|
|
60
|
+
|
|
61
61
|
if (isProbabilityMapProbable(map)) {
|
|
62
62
|
// options.verbose && console.log("+ Added " + transformer.name);
|
|
63
63
|
|
|
@@ -68,36 +68,33 @@ export default class Obfuscator extends EventEmitter {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
// Optimization: Only add needed transformers. If a probability always return false, no need in running that extra code.
|
|
71
|
-
test(
|
|
72
|
-
test(
|
|
71
|
+
test(true, Preparation);
|
|
72
|
+
test(true, RenameLabels);
|
|
73
73
|
|
|
74
|
+
test(options.objectExtraction, ObjectExtraction);
|
|
75
|
+
test(options.flatten, Flatten);
|
|
76
|
+
test(options.rgf, RGF);
|
|
74
77
|
test(options.dispatcher, Dispatcher);
|
|
78
|
+
test(options.deadCode, DeadCode);
|
|
79
|
+
test(options.calculator, Calculator);
|
|
75
80
|
test(options.controlFlowFlattening, ControlFlowFlattening);
|
|
76
|
-
test(options.globalConcealing, GlobalConcealing);
|
|
77
|
-
test(options.stringCompression, StringCompression);
|
|
78
|
-
test(options.stringConcealing, StringConcealing);
|
|
79
|
-
test(options.stringEncoding, StringEncoding);
|
|
80
|
-
test(options.stringSplitting, StringSplitting);
|
|
81
|
-
test(options.renameVariables, RenameVariables);
|
|
82
|
-
test(options.nameRecycling, NameRecycling);
|
|
83
|
-
|
|
84
81
|
test(options.eval, Eval);
|
|
82
|
+
test(options.globalConcealing, GlobalConcealing);
|
|
85
83
|
test(options.opaquePredicates, OpaquePredicates);
|
|
84
|
+
test(options.stringSplitting, StringSplitting);
|
|
85
|
+
test(options.stringConcealing, StringConcealing);
|
|
86
|
+
test(options.stringCompression, StringCompression);
|
|
87
|
+
test(options.stack, Stack);
|
|
86
88
|
test(options.duplicateLiteralsRemoval, DuplicateLiteralsRemoval);
|
|
87
|
-
test(options.
|
|
88
|
-
|
|
89
|
-
test(options.calculator, Calculator);
|
|
89
|
+
test(options.shuffle, Shuffle);
|
|
90
|
+
test(options.nameRecycling, NameRecycling);
|
|
90
91
|
test(options.movedDeclarations, MovedDeclarations);
|
|
91
|
-
|
|
92
|
+
test(options.minify, Minify);
|
|
93
|
+
test(options.renameVariables, RenameVariables);
|
|
92
94
|
test(options.es5, ES5);
|
|
93
|
-
test(options.shuffle, Shuffle);
|
|
94
95
|
|
|
95
|
-
test(options.flatten, Flatten);
|
|
96
|
-
test(options.rgf, RGF);
|
|
97
|
-
test(options.stack, Stack);
|
|
98
96
|
test(true, AntiTooling);
|
|
99
|
-
test(
|
|
100
|
-
test(options.hexadecimalNumbers, HexadecimalNumbers);
|
|
97
|
+
test(true, Finalizer); // String Encoding, Hexadecimal Numbers, BigInt support is included
|
|
101
98
|
|
|
102
99
|
if (
|
|
103
100
|
options.lock &&
|
package/src/options.ts
CHANGED
|
@@ -10,9 +10,9 @@ export interface ObfuscateOptions {
|
|
|
10
10
|
*
|
|
11
11
|
* | Preset | Transforms | Performance Reduction | Sample |
|
|
12
12
|
* | --- | --- | --- | --- |
|
|
13
|
-
* | High |
|
|
14
|
-
* | Medium |
|
|
15
|
-
* | Low |
|
|
13
|
+
* | High | 22/25 | 98% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/high.js) |
|
|
14
|
+
* | Medium | 19/25 | 52% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/medium.js) |
|
|
15
|
+
* | Low | 15/25 | 30% | [Sample](https://github.com/MichaelXF/js-confuser/blob/master/samples/low.js) |
|
|
16
16
|
*
|
|
17
17
|
* You can extend each preset or all go without them entirely. (`"high"/"medium"/"low"`)
|
|
18
18
|
*
|
|
@@ -53,7 +53,7 @@ export interface ObfuscateOptions {
|
|
|
53
53
|
/**
|
|
54
54
|
* ### `hexadecimalNumbers`
|
|
55
55
|
*
|
|
56
|
-
* Uses the hexadecimal representation
|
|
56
|
+
* Uses the hexadecimal representation for numbers. (`true/false`)
|
|
57
57
|
*/
|
|
58
58
|
hexadecimalNumbers?: boolean;
|
|
59
59
|
|
|
@@ -144,6 +144,8 @@ export interface ObfuscateOptions {
|
|
|
144
144
|
/**
|
|
145
145
|
* ### `nameRecycling`
|
|
146
146
|
*
|
|
147
|
+
* (Experimental feature)
|
|
148
|
+
*
|
|
147
149
|
* Attempts to reuse released names.
|
|
148
150
|
*
|
|
149
151
|
* - Potency Medium
|
|
@@ -189,19 +191,6 @@ export interface ObfuscateOptions {
|
|
|
189
191
|
*/
|
|
190
192
|
controlFlowFlattening?: ProbabilityMap<boolean>;
|
|
191
193
|
|
|
192
|
-
/**
|
|
193
|
-
* ### `hideInitializingCode`
|
|
194
|
-
*
|
|
195
|
-
* Hides initializing code with complex ternary expressions. (`true/false`)
|
|
196
|
-
*
|
|
197
|
-
* - Potency High
|
|
198
|
-
* - Resilience High
|
|
199
|
-
* - Cost High
|
|
200
|
-
*
|
|
201
|
-
* [See all settings here](https://github.com/MichaelXF/js-confuser/blob/master/README.md#options)
|
|
202
|
-
*/
|
|
203
|
-
hideInitializingCode?: ProbabilityMap<boolean>;
|
|
204
|
-
|
|
205
194
|
/**
|
|
206
195
|
* ### `globalConcealing`
|
|
207
196
|
*
|
|
@@ -691,7 +680,6 @@ const validProperties = new Set([
|
|
|
691
680
|
"identifierGenerator",
|
|
692
681
|
"nameRecycling",
|
|
693
682
|
"controlFlowFlattening",
|
|
694
|
-
"hideInitializingCode",
|
|
695
683
|
"globalConcealing",
|
|
696
684
|
"stringCompression",
|
|
697
685
|
"stringConcealing",
|
|
@@ -726,7 +714,7 @@ const validBrowsers = new Set([
|
|
|
726
714
|
]);
|
|
727
715
|
|
|
728
716
|
export function validateOptions(options: ObfuscateOptions) {
|
|
729
|
-
if (Object.keys(options).length <= 1) {
|
|
717
|
+
if (!options || Object.keys(options).length <= 1) {
|
|
730
718
|
/**
|
|
731
719
|
* Give a welcoming introduction to those who skipped the documentation.
|
|
732
720
|
*/
|
|
@@ -867,8 +855,7 @@ export async function correctOptions(
|
|
|
867
855
|
options.compact = true; // self defending forcibly enables this
|
|
868
856
|
}
|
|
869
857
|
|
|
870
|
-
// options.globalVariables
|
|
871
|
-
// GlobalConcealing implicitly determines a global to be a variable referenced but never defined or modified.
|
|
858
|
+
// options.globalVariables outlines generic globals that should be present in the execution context
|
|
872
859
|
if (!options.hasOwnProperty("globalVariables")) {
|
|
873
860
|
options.globalVariables = new Set([]);
|
|
874
861
|
|
|
@@ -908,6 +895,10 @@ export async function correctOptions(
|
|
|
908
895
|
"Array",
|
|
909
896
|
"Proxy",
|
|
910
897
|
"Error",
|
|
898
|
+
"TypeError",
|
|
899
|
+
"ReferenceError",
|
|
900
|
+
"RangeError",
|
|
901
|
+
"EvalError",
|
|
911
902
|
"setTimeout",
|
|
912
903
|
"clearTimeout",
|
|
913
904
|
"setInterval",
|
|
@@ -919,6 +910,11 @@ export async function correctOptions(
|
|
|
919
910
|
"module",
|
|
920
911
|
"isNaN",
|
|
921
912
|
"isFinite",
|
|
913
|
+
"Set",
|
|
914
|
+
"Map",
|
|
915
|
+
"WeakSet",
|
|
916
|
+
"WeakMap",
|
|
917
|
+
"Symbol",
|
|
922
918
|
].forEach((x) => options.globalVariables.add(x));
|
|
923
919
|
}
|
|
924
920
|
|
package/src/order.ts
CHANGED
|
@@ -32,8 +32,6 @@ export enum ObfuscateOrder {
|
|
|
32
32
|
|
|
33
33
|
StringCompression = 18,
|
|
34
34
|
|
|
35
|
-
HideInitializingCode = 19,
|
|
36
|
-
|
|
37
35
|
Stack = 20,
|
|
38
36
|
|
|
39
37
|
DuplicateLiteralsRemoval = 22,
|
|
@@ -44,17 +42,15 @@ export enum ObfuscateOrder {
|
|
|
44
42
|
|
|
45
43
|
MovedDeclarations = 26,
|
|
46
44
|
|
|
47
|
-
|
|
45
|
+
RenameLabels = 27,
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
Minify = 28,
|
|
50
48
|
|
|
51
|
-
|
|
49
|
+
RenameVariables = 30,
|
|
52
50
|
|
|
53
51
|
ES5 = 31,
|
|
54
52
|
|
|
55
|
-
StringEncoding = 32,
|
|
56
|
-
|
|
57
53
|
AntiTooling = 34,
|
|
58
54
|
|
|
59
|
-
|
|
55
|
+
Finalizer = 35,
|
|
60
56
|
}
|
package/src/probability.ts
CHANGED
|
@@ -87,6 +87,8 @@ export function ComputeProbabilityMap<T>(
|
|
|
87
87
|
* @param map
|
|
88
88
|
*/
|
|
89
89
|
export function isProbabilityMapProbable<T>(map: ProbabilityMap<T>): boolean {
|
|
90
|
+
ok(!Number.isNaN(map), "Numbers cannot be NaN");
|
|
91
|
+
|
|
90
92
|
if (!map || typeof map === "undefined") {
|
|
91
93
|
return false;
|
|
92
94
|
}
|
|
@@ -97,9 +99,6 @@ export function isProbabilityMapProbable<T>(map: ProbabilityMap<T>): boolean {
|
|
|
97
99
|
if (map > 1 || map < 0) {
|
|
98
100
|
throw new Error(`Numbers must be between 0 and 1 for 0% - 100%`);
|
|
99
101
|
}
|
|
100
|
-
if (isNaN(map)) {
|
|
101
|
-
throw new Error("Numbers cannot be NaN");
|
|
102
|
-
}
|
|
103
102
|
}
|
|
104
103
|
if (Array.isArray(map)) {
|
|
105
104
|
ok(
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import Template from "./template";
|
|
2
|
+
|
|
3
|
+
export const BufferToStringTemplate = Template(`
|
|
4
|
+
function __getGlobal(){
|
|
5
|
+
try {
|
|
6
|
+
return global||window|| ( new Function("return this") )();
|
|
7
|
+
} catch ( e ) {
|
|
8
|
+
try {
|
|
9
|
+
return this;
|
|
10
|
+
} catch ( e ) {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
var __globalObject = __getGlobal() || {};
|
|
17
|
+
var __TextDecoder = __globalObject["TextDecoder"];
|
|
18
|
+
var __Uint8Array = __globalObject["Uint8Array"];
|
|
19
|
+
var __Buffer = __globalObject["Buffer"];
|
|
20
|
+
var __String = __globalObject["String"] || String;
|
|
21
|
+
var __Array = __globalObject["Array"] || Array;
|
|
22
|
+
|
|
23
|
+
var utf8ArrayToStr = (function () {
|
|
24
|
+
var charCache = new __Array(128); // Preallocate the cache for the common single byte chars
|
|
25
|
+
var charFromCodePt = __String["fromCodePoint"] || __String["fromCharCode"];
|
|
26
|
+
var result = [];
|
|
27
|
+
|
|
28
|
+
return function (array) {
|
|
29
|
+
var codePt, byte1;
|
|
30
|
+
var buffLen = array["length"];
|
|
31
|
+
|
|
32
|
+
result["length"] = 0;
|
|
33
|
+
|
|
34
|
+
for (var i = 0; i < buffLen;) {
|
|
35
|
+
byte1 = array[i++];
|
|
36
|
+
|
|
37
|
+
if (byte1 <= 0x7F) {
|
|
38
|
+
codePt = byte1;
|
|
39
|
+
} else if (byte1 <= 0xDF) {
|
|
40
|
+
codePt = ((byte1 & 0x1F) << 6) | (array[i++] & 0x3F);
|
|
41
|
+
} else if (byte1 <= 0xEF) {
|
|
42
|
+
codePt = ((byte1 & 0x0F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
|
|
43
|
+
} else if (__String["fromCodePoint"]) {
|
|
44
|
+
codePt = ((byte1 & 0x07) << 18) | ((array[i++] & 0x3F) << 12) | ((array[i++] & 0x3F) << 6) | (array[i++] & 0x3F);
|
|
45
|
+
} else {
|
|
46
|
+
codePt = 63; // Cannot convert four byte code points, so use "?" instead
|
|
47
|
+
i += 3;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
result["push"](charCache[codePt] || (charCache[codePt] = charFromCodePt(codePt)));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return result["join"]('');
|
|
54
|
+
};
|
|
55
|
+
})();
|
|
56
|
+
|
|
57
|
+
function {name}(buffer){
|
|
58
|
+
if(typeof __TextDecoder !== "undefined" && __TextDecoder) {
|
|
59
|
+
return new __TextDecoder()["decode"](new __Uint8Array(buffer));
|
|
60
|
+
} else if(typeof __Buffer !== "undefined" && __Buffer) {
|
|
61
|
+
return __Buffer["from"](buffer)["toString"]("utf-8");
|
|
62
|
+
} else {
|
|
63
|
+
return utf8ArrayToStr(buffer);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
`);
|