js-confuser 1.7.2 → 2.0.0-alpha.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/ISSUE_TEMPLATE/bug_report.md +6 -4
- package/.github/workflows/node.js.yml +1 -1
- package/CHANGELOG.md +105 -0
- package/Migration.md +57 -0
- package/README.md +23 -913
- package/dist/constants.js +69 -13
- package/dist/index.js +108 -152
- package/dist/obfuscator.js +316 -118
- package/dist/options.js +1 -109
- package/dist/order.js +30 -30
- package/dist/presets.js +47 -45
- package/dist/probability.js +25 -32
- package/dist/templates/bufferToStringTemplate.js +9 -0
- package/dist/templates/deadCodeTemplates.js +9 -0
- package/dist/templates/getGlobalTemplate.js +19 -0
- package/dist/templates/integrityTemplate.js +30 -0
- package/dist/templates/setFunctionLengthTemplate.js +9 -0
- package/dist/templates/stringCompressionTemplate.js +10 -0
- package/dist/templates/tamperProtectionTemplates.js +21 -0
- package/dist/templates/template.js +213 -93
- package/dist/transforms/astScrambler.js +100 -0
- package/dist/transforms/calculator.js +70 -127
- package/dist/transforms/controlFlowFlattening.js +1182 -0
- package/dist/transforms/deadCode.js +62 -577
- package/dist/transforms/dispatcher.js +300 -309
- package/dist/transforms/extraction/duplicateLiteralsRemoval.js +88 -189
- package/dist/transforms/extraction/objectExtraction.js +131 -215
- package/dist/transforms/finalizer.js +56 -59
- package/dist/transforms/flatten.js +275 -276
- package/dist/transforms/functionOutlining.js +230 -0
- package/dist/transforms/identifier/globalConcealing.js +217 -103
- package/dist/transforms/identifier/movedDeclarations.js +167 -91
- package/dist/transforms/identifier/renameVariables.js +240 -187
- package/dist/transforms/lock/integrity.js +61 -184
- package/dist/transforms/lock/lock.js +263 -303
- package/dist/transforms/minify.js +431 -436
- package/dist/transforms/opaquePredicates.js +65 -118
- package/dist/transforms/pack.js +160 -0
- package/dist/transforms/plugin.js +179 -0
- package/dist/transforms/preparation.js +263 -163
- package/dist/transforms/renameLabels.js +132 -56
- package/dist/transforms/rgf.js +142 -240
- package/dist/transforms/shuffle.js +52 -145
- package/dist/transforms/string/encoding.js +45 -173
- package/dist/transforms/string/stringCompression.js +81 -126
- package/dist/transforms/string/stringConcealing.js +189 -224
- package/dist/transforms/string/stringEncoding.js +32 -40
- package/dist/transforms/string/stringSplitting.js +54 -55
- package/dist/transforms/variableMasking.js +232 -0
- package/dist/utils/ControlObject.js +125 -0
- package/dist/utils/IntGen.js +46 -0
- package/dist/utils/NameGen.js +106 -0
- package/dist/utils/ast-utils.js +560 -0
- package/dist/utils/function-utils.js +56 -0
- package/dist/utils/gen-utils.js +48 -0
- package/dist/utils/node.js +77 -0
- package/dist/utils/object-utils.js +21 -0
- package/dist/utils/random-utils.js +91 -0
- package/dist/utils/static-utils.js +64 -0
- package/dist/validateOptions.js +122 -0
- package/index.d.ts +1 -17
- package/package.json +27 -22
- package/src/constants.ts +139 -77
- package/src/index.ts +70 -163
- package/src/obfuscationResult.ts +43 -0
- package/src/obfuscator.ts +328 -135
- package/src/options.ts +154 -623
- package/src/order.ts +14 -14
- package/src/presets.ts +39 -34
- package/src/probability.ts +21 -36
- package/src/templates/{bufferToString.ts → bufferToStringTemplate.ts} +5 -54
- package/src/templates/deadCodeTemplates.ts +1185 -0
- package/src/templates/getGlobalTemplate.ts +72 -0
- package/src/templates/integrityTemplate.ts +69 -0
- package/src/templates/setFunctionLengthTemplate.ts +11 -0
- package/src/templates/stringCompressionTemplate.ts +42 -0
- package/src/templates/tamperProtectionTemplates.ts +116 -0
- package/src/templates/template.ts +183 -92
- package/src/transforms/astScrambler.ts +99 -0
- package/src/transforms/calculator.ts +96 -224
- package/src/transforms/controlFlowFlattening.ts +1594 -0
- package/src/transforms/deadCode.ts +85 -628
- package/src/transforms/dispatcher.ts +431 -636
- package/src/transforms/extraction/duplicateLiteralsRemoval.ts +147 -299
- package/src/transforms/extraction/objectExtraction.ts +160 -333
- package/src/transforms/finalizer.ts +63 -64
- package/src/transforms/flatten.ts +439 -557
- package/src/transforms/functionOutlining.ts +225 -0
- package/src/transforms/identifier/globalConcealing.ts +261 -189
- package/src/transforms/identifier/movedDeclarations.ts +228 -142
- package/src/transforms/identifier/renameVariables.ts +252 -258
- package/src/transforms/lock/integrity.ts +84 -260
- package/src/transforms/lock/lock.ts +342 -491
- package/src/transforms/minify.ts +523 -663
- package/src/transforms/opaquePredicates.ts +90 -229
- package/src/transforms/pack.ts +195 -0
- package/src/transforms/plugin.ts +185 -0
- package/src/transforms/preparation.ts +337 -215
- package/src/transforms/renameLabels.ts +176 -77
- package/src/transforms/rgf.ts +293 -386
- package/src/transforms/shuffle.ts +80 -254
- package/src/transforms/string/encoding.ts +26 -129
- package/src/transforms/string/stringCompression.ts +118 -236
- package/src/transforms/string/stringConcealing.ts +255 -339
- package/src/transforms/string/stringEncoding.ts +28 -47
- package/src/transforms/string/stringSplitting.ts +61 -75
- package/src/transforms/variableMasking.ts +257 -0
- package/src/utils/ControlObject.ts +141 -0
- package/src/utils/IntGen.ts +33 -0
- package/src/utils/NameGen.ts +106 -0
- package/src/utils/ast-utils.ts +667 -0
- package/src/utils/function-utils.ts +50 -0
- package/src/utils/gen-utils.ts +48 -0
- package/src/utils/node.ts +78 -0
- package/src/utils/object-utils.ts +21 -0
- package/src/utils/random-utils.ts +79 -0
- package/src/utils/static-utils.ts +66 -0
- package/src/validateOptions.ts +256 -0
- package/tsconfig.json +13 -8
- package/babel.config.js +0 -12
- package/dev.js +0 -8
- package/dist/compiler.js +0 -34
- package/dist/parser.js +0 -59
- package/dist/precedence.js +0 -66
- package/dist/templates/bufferToString.js +0 -108
- package/dist/templates/crash.js +0 -59
- package/dist/templates/es5.js +0 -137
- package/dist/templates/functionLength.js +0 -34
- package/dist/templates/globals.js +0 -9
- package/dist/transforms/antiTooling.js +0 -88
- package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +0 -1281
- package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +0 -131
- package/dist/transforms/es5/antiClass.js +0 -164
- package/dist/transforms/es5/antiDestructuring.js +0 -193
- package/dist/transforms/es5/antiES6Object.js +0 -185
- package/dist/transforms/es5/antiSpreadOperator.js +0 -35
- package/dist/transforms/es5/antiTemplate.js +0 -66
- package/dist/transforms/es5/es5.js +0 -123
- package/dist/transforms/extraction/classExtraction.js +0 -83
- package/dist/transforms/identifier/globalAnalysis.js +0 -70
- package/dist/transforms/identifier/variableAnalysis.js +0 -104
- package/dist/transforms/lock/antiDebug.js +0 -76
- package/dist/transforms/stack.js +0 -343
- package/dist/transforms/transform.js +0 -350
- package/dist/traverse.js +0 -110
- package/dist/util/compare.js +0 -145
- package/dist/util/gen.js +0 -564
- package/dist/util/guard.js +0 -9
- package/dist/util/identifiers.js +0 -355
- package/dist/util/insert.js +0 -362
- package/dist/util/math.js +0 -19
- package/dist/util/object.js +0 -40
- package/dist/util/random.js +0 -130
- package/dist/util/scope.js +0 -20
- package/docs/ControlFlowFlattening.md +0 -595
- package/docs/Countermeasures.md +0 -63
- package/docs/ES5.md +0 -197
- package/docs/Integrity.md +0 -75
- package/docs/RGF.md +0 -419
- package/samples/example.js +0 -15
- package/samples/high.js +0 -1
- package/samples/input.js +0 -3
- package/samples/javascriptobfuscator.com.js +0 -8
- package/samples/jscrambler_advanced.js +0 -1894
- package/samples/jscrambler_light.js +0 -1134
- package/samples/low.js +0 -1
- package/samples/medium.js +0 -1
- package/samples/obfuscator.io.js +0 -1686
- package/samples/preemptive.com.js +0 -16
- package/src/compiler.ts +0 -35
- package/src/parser.ts +0 -49
- package/src/precedence.ts +0 -61
- package/src/templates/crash.ts +0 -55
- package/src/templates/es5.ts +0 -131
- package/src/templates/functionLength.ts +0 -32
- package/src/templates/globals.ts +0 -3
- package/src/transforms/antiTooling.ts +0 -102
- package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +0 -2146
- package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +0 -179
- package/src/transforms/es5/antiClass.ts +0 -272
- package/src/transforms/es5/antiDestructuring.ts +0 -294
- package/src/transforms/es5/antiES6Object.ts +0 -267
- package/src/transforms/es5/antiSpreadOperator.ts +0 -56
- package/src/transforms/es5/antiTemplate.ts +0 -98
- package/src/transforms/es5/es5.ts +0 -149
- package/src/transforms/extraction/classExtraction.ts +0 -168
- package/src/transforms/identifier/globalAnalysis.ts +0 -85
- package/src/transforms/identifier/variableAnalysis.ts +0 -118
- package/src/transforms/lock/antiDebug.ts +0 -112
- package/src/transforms/stack.ts +0 -551
- package/src/transforms/transform.ts +0 -453
- package/src/traverse.ts +0 -120
- package/src/types.ts +0 -131
- package/src/util/compare.ts +0 -181
- package/src/util/gen.ts +0 -651
- package/src/util/guard.ts +0 -7
- package/src/util/identifiers.ts +0 -494
- package/src/util/insert.ts +0 -419
- package/src/util/math.ts +0 -15
- package/src/util/object.ts +0 -39
- package/src/util/random.ts +0 -141
- package/src/util/scope.ts +0 -21
- package/test/code/Cash.src.js +0 -1011
- package/test/code/Cash.test.ts +0 -49
- package/test/code/Dynamic.src.js +0 -118
- package/test/code/Dynamic.test.ts +0 -49
- package/test/code/ES6.src.js +0 -235
- package/test/code/ES6.test.ts +0 -42
- package/test/code/NewFeatures.test.ts +0 -19
- package/test/code/StrictMode.src.js +0 -65
- package/test/code/StrictMode.test.js +0 -37
- package/test/compare.test.ts +0 -104
- package/test/index.test.ts +0 -249
- package/test/options.test.ts +0 -132
- package/test/presets.test.ts +0 -22
- package/test/probability.test.ts +0 -44
- package/test/templates/template.test.ts +0 -14
- package/test/transforms/antiTooling.test.ts +0 -52
- package/test/transforms/calculator.test.ts +0 -78
- package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +0 -1274
- package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +0 -192
- package/test/transforms/deadCode.test.ts +0 -85
- package/test/transforms/dispatcher.test.ts +0 -457
- package/test/transforms/es5/antiClass.test.ts +0 -427
- package/test/transforms/es5/antiDestructuring.test.ts +0 -157
- package/test/transforms/es5/antiES6Object.test.ts +0 -245
- package/test/transforms/es5/antiTemplate.test.ts +0 -116
- package/test/transforms/es5/es5.test.ts +0 -110
- package/test/transforms/extraction/classExtraction.test.ts +0 -86
- package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +0 -200
- package/test/transforms/extraction/objectExtraction.test.ts +0 -491
- package/test/transforms/flatten.test.ts +0 -721
- package/test/transforms/hexadecimalNumbers.test.ts +0 -62
- package/test/transforms/identifier/globalConcealing.test.ts +0 -72
- package/test/transforms/identifier/movedDeclarations.test.ts +0 -275
- package/test/transforms/identifier/renameVariables.test.ts +0 -621
- package/test/transforms/lock/antiDebug.test.ts +0 -66
- package/test/transforms/lock/browserLock.test.ts +0 -129
- package/test/transforms/lock/countermeasures.test.ts +0 -100
- package/test/transforms/lock/integrity.test.ts +0 -161
- package/test/transforms/lock/lock.test.ts +0 -204
- package/test/transforms/lock/osLock.test.ts +0 -312
- package/test/transforms/lock/selfDefending.test.ts +0 -68
- package/test/transforms/minify.test.ts +0 -575
- package/test/transforms/opaquePredicates.test.ts +0 -43
- package/test/transforms/preparation.test.ts +0 -157
- package/test/transforms/renameLabels.test.ts +0 -95
- package/test/transforms/rgf.test.ts +0 -378
- package/test/transforms/shuffle.test.ts +0 -135
- package/test/transforms/stack.test.ts +0 -573
- package/test/transforms/string/stringCompression.test.ts +0 -120
- package/test/transforms/string/stringConcealing.test.ts +0 -299
- package/test/transforms/string/stringEncoding.test.ts +0 -95
- package/test/transforms/string/stringSplitting.test.ts +0 -135
- package/test/transforms/transform.test.ts +0 -66
- package/test/traverse.test.ts +0 -139
- package/test/util/compare.test.ts +0 -34
- package/test/util/gen.test.ts +0 -121
- package/test/util/identifiers.test.ts +0 -253
- package/test/util/insert.test.ts +0 -142
- package/test/util/math.test.ts +0 -5
- package/test/util/random.test.ts +0 -71
- /package/dist/{types.js → obfuscationResult.js} +0 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { reservedKeywords } from "../constants";
|
|
2
|
+
import { shuffle } from "./random-utils";
|
|
3
|
+
|
|
4
|
+
export function alphabeticalGenerator(index: number) {
|
|
5
|
+
let name = "";
|
|
6
|
+
while (index > 0) {
|
|
7
|
+
var t = (index - 1) % 52;
|
|
8
|
+
var thisChar =
|
|
9
|
+
t >= 26 ? String.fromCharCode(65 + t - 26) : String.fromCharCode(97 + t);
|
|
10
|
+
name = thisChar + name;
|
|
11
|
+
index = ((index - t) / 52) | 0;
|
|
12
|
+
}
|
|
13
|
+
if (!name) {
|
|
14
|
+
name = "_";
|
|
15
|
+
}
|
|
16
|
+
return name;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createZeroWidthGenerator() {
|
|
20
|
+
var maxSize = 0;
|
|
21
|
+
var currentKeyWordsArray: string[] = [];
|
|
22
|
+
|
|
23
|
+
function generateArray() {
|
|
24
|
+
var result = reservedKeywords
|
|
25
|
+
.map(
|
|
26
|
+
(keyWord) =>
|
|
27
|
+
keyWord + "\u200C".repeat(Math.max(maxSize - keyWord.length, 1))
|
|
28
|
+
)
|
|
29
|
+
.filter((craftedVariableName) => craftedVariableName.length == maxSize);
|
|
30
|
+
|
|
31
|
+
if (!result.length) {
|
|
32
|
+
++maxSize;
|
|
33
|
+
return generateArray();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return shuffle(result);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function getNextVariable(): string {
|
|
40
|
+
if (!currentKeyWordsArray.length) {
|
|
41
|
+
++maxSize;
|
|
42
|
+
currentKeyWordsArray = generateArray();
|
|
43
|
+
}
|
|
44
|
+
return currentKeyWordsArray.pop();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return { generate: getNextVariable };
|
|
48
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
import { ok } from "assert";
|
|
3
|
+
|
|
4
|
+
export type LiteralValue = string | number | boolean | undefined | null;
|
|
5
|
+
export const createLiteral = (value: LiteralValue) => {
|
|
6
|
+
if (value === null) return t.nullLiteral();
|
|
7
|
+
if (value === undefined) return t.identifier("undefined");
|
|
8
|
+
|
|
9
|
+
switch (typeof value) {
|
|
10
|
+
case "string":
|
|
11
|
+
return t.stringLiteral(value);
|
|
12
|
+
|
|
13
|
+
case "number":
|
|
14
|
+
return numericLiteral(value);
|
|
15
|
+
|
|
16
|
+
case "boolean":
|
|
17
|
+
return t.booleanLiteral(value);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
ok(false);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Handles both positive and negative numeric literals
|
|
25
|
+
* @param value
|
|
26
|
+
* @returns
|
|
27
|
+
*/
|
|
28
|
+
export function numericLiteral(
|
|
29
|
+
value: number
|
|
30
|
+
): t.NumericLiteral | t.UnaryExpression {
|
|
31
|
+
ok(typeof value === "number");
|
|
32
|
+
|
|
33
|
+
if (value < 0) {
|
|
34
|
+
return t.unaryExpression("-", t.numericLiteral(-value));
|
|
35
|
+
}
|
|
36
|
+
return t.numericLiteral(value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function deepClone(node: t.Node | t.Node[]) {
|
|
40
|
+
function deepClone(obj) {
|
|
41
|
+
// Handle non-objects like null, undefined, primitive values, or functions
|
|
42
|
+
if (obj === null || typeof obj !== "object") {
|
|
43
|
+
return obj;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Handle Date
|
|
47
|
+
if (obj instanceof Date) {
|
|
48
|
+
return new Date(obj);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Handle Array
|
|
52
|
+
if (Array.isArray(obj)) {
|
|
53
|
+
return obj.map(deepClone);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Handle Objects
|
|
57
|
+
const clonedObj = {};
|
|
58
|
+
|
|
59
|
+
// Handle string and symbol property keys
|
|
60
|
+
|
|
61
|
+
Object.getOwnPropertyNames(obj).forEach((key) => {
|
|
62
|
+
const value = obj[key];
|
|
63
|
+
clonedObj[key] = deepClone(value);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Copy simple symbols (Avoid objects = infinite recursion)
|
|
67
|
+
Object.getOwnPropertySymbols(obj).forEach((symbol) => {
|
|
68
|
+
const value = obj[symbol];
|
|
69
|
+
if (typeof value !== "object") {
|
|
70
|
+
clonedObj[symbol] = deepClone(value);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
return clonedObj;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return deepClone(node);
|
|
78
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates an object from the given keys and values arrays.
|
|
3
|
+
* @param keys
|
|
4
|
+
* @param values
|
|
5
|
+
*/
|
|
6
|
+
export function createObject<T>(
|
|
7
|
+
keys: string[],
|
|
8
|
+
values: T[]
|
|
9
|
+
): { [key: string]: T } {
|
|
10
|
+
if (keys.length !== values.length) {
|
|
11
|
+
throw new Error("length mismatch");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
var newObject = {};
|
|
15
|
+
|
|
16
|
+
keys.forEach((x, i) => {
|
|
17
|
+
newObject[x] = values[i];
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
return newObject;
|
|
21
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { ok } from "assert";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns a random element from the given array
|
|
5
|
+
* @param choices Array of items
|
|
6
|
+
* @returns One of the items in the array at random
|
|
7
|
+
*/
|
|
8
|
+
export function choice<T>(choices: T[]): T {
|
|
9
|
+
var index = Math.floor(Math.random() * choices.length);
|
|
10
|
+
return choices[index];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns a true/false based on the percent chance (0%-100%)
|
|
15
|
+
* @param percentChance AS A PERCENTAGE 0 - 100%
|
|
16
|
+
*/
|
|
17
|
+
export function chance(percentChance: number): boolean {
|
|
18
|
+
return Math.random() < percentChance / 100;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* **Mutates the given array**
|
|
23
|
+
* @param array
|
|
24
|
+
*/
|
|
25
|
+
export function shuffle<T>(array: T[]): T[] {
|
|
26
|
+
array.sort(() => Math.random() - 0.5);
|
|
27
|
+
return array;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns a random hexadecimal string.
|
|
32
|
+
*
|
|
33
|
+
* @example getRandomHexString(6) => "CA96BF"
|
|
34
|
+
* @param length
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
export function getRandomHexString(length: number) {
|
|
38
|
+
return [...Array(length)]
|
|
39
|
+
.map(() => Math.floor(Math.random() * 16).toString(16))
|
|
40
|
+
.join("")
|
|
41
|
+
.toUpperCase();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Returns a random string.
|
|
46
|
+
*/
|
|
47
|
+
export function getRandomString(length: number) {
|
|
48
|
+
var result = "";
|
|
49
|
+
var characters =
|
|
50
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
51
|
+
var charactersLength = characters.length;
|
|
52
|
+
for (var i = 0; i < length; i++) {
|
|
53
|
+
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
54
|
+
}
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function getRandom(min: number, max: number) {
|
|
59
|
+
return Math.random() * (max - min) + min;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function getRandomInteger(min: number, max: number) {
|
|
63
|
+
return Math.floor(getRandom(min, max));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function splitIntoChunks(str: string, size: number) {
|
|
67
|
+
ok(typeof str === "string", "str must be typeof string");
|
|
68
|
+
ok(typeof size === "number", "size must be typeof number");
|
|
69
|
+
ok(Math.floor(size) === size, "size must be integer");
|
|
70
|
+
|
|
71
|
+
const numChunks = Math.ceil(str.length / size);
|
|
72
|
+
const chunks: string[] = new Array(numChunks);
|
|
73
|
+
|
|
74
|
+
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
|
|
75
|
+
chunks[i] = str.substr(o, size);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return chunks;
|
|
79
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as t from "@babel/types";
|
|
2
|
+
|
|
3
|
+
// Function to check if a node is a static value
|
|
4
|
+
export function isStaticValue(node: t.Node): boolean {
|
|
5
|
+
// Check for literals which are considered static
|
|
6
|
+
if (
|
|
7
|
+
t.isStringLiteral(node) ||
|
|
8
|
+
t.isNumericLiteral(node) ||
|
|
9
|
+
t.isBooleanLiteral(node) ||
|
|
10
|
+
t.isNullLiteral(node)
|
|
11
|
+
) {
|
|
12
|
+
if (t.isDirectiveLiteral(node)) return false;
|
|
13
|
+
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Handle unary expressions like -42
|
|
18
|
+
if (t.isUnaryExpression(node)) {
|
|
19
|
+
// Only consider certain operators as static (e.g., -, +)
|
|
20
|
+
if (["-", "+", "!", "~", "void"].includes(node.operator)) {
|
|
21
|
+
return isStaticValue(node.argument);
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Handle binary expressions with static values only
|
|
27
|
+
if (t.isBinaryExpression(node)) {
|
|
28
|
+
return isStaticValue(node.left) && isStaticValue(node.right);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Handle logical expressions (&&, ||) with static values only
|
|
32
|
+
if (t.isLogicalExpression(node)) {
|
|
33
|
+
return isStaticValue(node.left) && isStaticValue(node.right);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Handle conditional (ternary) expressions with static values
|
|
37
|
+
if (t.isConditionalExpression(node)) {
|
|
38
|
+
return (
|
|
39
|
+
isStaticValue(node.test) &&
|
|
40
|
+
isStaticValue(node.consequent) &&
|
|
41
|
+
isStaticValue(node.alternate)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Handle array expressions where all elements are static
|
|
46
|
+
if (t.isArrayExpression(node)) {
|
|
47
|
+
return node.elements.every(
|
|
48
|
+
(element) => element !== null && isStaticValue(element)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Handle object expressions where all properties are static
|
|
53
|
+
if (t.isObjectExpression(node)) {
|
|
54
|
+
return node.properties.every((prop) => {
|
|
55
|
+
if (t.isObjectProperty(prop)) {
|
|
56
|
+
return isStaticValue(prop.key) && isStaticValue(prop.value);
|
|
57
|
+
} else if (t.isSpreadElement(prop)) {
|
|
58
|
+
return isStaticValue(prop.argument);
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Add more cases as needed, depending on what you consider "static"
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { ok } from "assert";
|
|
2
|
+
import { ObfuscateOptions } from "./options";
|
|
3
|
+
import presets from "./presets";
|
|
4
|
+
|
|
5
|
+
const validProperties = new Set([
|
|
6
|
+
"preset",
|
|
7
|
+
"target",
|
|
8
|
+
"indent",
|
|
9
|
+
"compact",
|
|
10
|
+
"hexadecimalNumbers",
|
|
11
|
+
"minify",
|
|
12
|
+
"es5",
|
|
13
|
+
"renameVariables",
|
|
14
|
+
"renameGlobals",
|
|
15
|
+
"renameLabels",
|
|
16
|
+
"identifierGenerator",
|
|
17
|
+
"controlFlowFlattening",
|
|
18
|
+
"globalConcealing",
|
|
19
|
+
"stringCompression",
|
|
20
|
+
"stringConcealing",
|
|
21
|
+
"stringEncoding",
|
|
22
|
+
"stringSplitting",
|
|
23
|
+
"duplicateLiteralsRemoval",
|
|
24
|
+
"dispatcher",
|
|
25
|
+
"rgf",
|
|
26
|
+
"objectExtraction",
|
|
27
|
+
"flatten",
|
|
28
|
+
"deadCode",
|
|
29
|
+
"calculator",
|
|
30
|
+
"lock",
|
|
31
|
+
"movedDeclarations",
|
|
32
|
+
"opaquePredicates",
|
|
33
|
+
"shuffle",
|
|
34
|
+
"variableMasking",
|
|
35
|
+
"verbose",
|
|
36
|
+
"globalVariables",
|
|
37
|
+
"debugComments",
|
|
38
|
+
"preserveFunctionLength",
|
|
39
|
+
"astScrambler",
|
|
40
|
+
"customStringEncodings",
|
|
41
|
+
"functionOutlining",
|
|
42
|
+
"pack",
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
const validLockProperties = new Set([
|
|
46
|
+
"selfDefending",
|
|
47
|
+
"antiDebug",
|
|
48
|
+
"tamperProtection",
|
|
49
|
+
"startDate",
|
|
50
|
+
"endDate",
|
|
51
|
+
"domainLock",
|
|
52
|
+
"integrity",
|
|
53
|
+
"countermeasures",
|
|
54
|
+
"customLocks",
|
|
55
|
+
]);
|
|
56
|
+
|
|
57
|
+
export function validateOptions(options: ObfuscateOptions) {
|
|
58
|
+
if (!options || Object.keys(options).length <= 1) {
|
|
59
|
+
/**
|
|
60
|
+
* Give a welcoming introduction to those who skipped the documentation.
|
|
61
|
+
*/
|
|
62
|
+
var line = `You provided zero obfuscation options. By default everything is disabled.\nYou can use a preset with:\n\n> {target: '${
|
|
63
|
+
options.target || "node"
|
|
64
|
+
}', preset: 'high' | 'medium' | 'low'}.\n\n\nView all settings here:\nhttps://github.com/MichaelXF/js-confuser#options`;
|
|
65
|
+
throw new Error(
|
|
66
|
+
`\n\n` +
|
|
67
|
+
line
|
|
68
|
+
.split("\n")
|
|
69
|
+
.map((x) => `\t${x}`)
|
|
70
|
+
.join("\n") +
|
|
71
|
+
`\n\n`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
ok(options, "options cannot be null");
|
|
76
|
+
ok(
|
|
77
|
+
options.target,
|
|
78
|
+
"Missing options.target option (required, must one the following: 'browser' or 'node')"
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
ok(
|
|
82
|
+
["browser", "node"].includes(options.target),
|
|
83
|
+
`'${options.target}' is not a valid target mode`
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
Object.keys(options).forEach((key) => {
|
|
87
|
+
if (!validProperties.has(key)) {
|
|
88
|
+
throw new TypeError("Invalid option: '" + key + "'");
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
if (options.lock) {
|
|
93
|
+
ok(typeof options.lock === "object", "options.lock must be an object");
|
|
94
|
+
Object.keys(options.lock).forEach((key) => {
|
|
95
|
+
if (!validLockProperties.has(key)) {
|
|
96
|
+
throw new TypeError("Invalid lock option: '" + key + "'");
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Validate domain-lock option
|
|
101
|
+
if (
|
|
102
|
+
options.lock.domainLock &&
|
|
103
|
+
typeof options.lock.domainLock !== "undefined"
|
|
104
|
+
) {
|
|
105
|
+
ok(Array.isArray(options.lock.domainLock), "domainLock must be an array");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Validate start-date option
|
|
109
|
+
if (
|
|
110
|
+
typeof options.lock.startDate !== "undefined" &&
|
|
111
|
+
options.lock.startDate
|
|
112
|
+
) {
|
|
113
|
+
ok(
|
|
114
|
+
typeof options.lock.startDate === "number" ||
|
|
115
|
+
options.lock.startDate instanceof Date,
|
|
116
|
+
"startDate must be Date object or number"
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Validate end-date option
|
|
121
|
+
if (typeof options.lock.endDate !== "undefined" && options.lock.endDate) {
|
|
122
|
+
ok(
|
|
123
|
+
typeof options.lock.endDate === "number" ||
|
|
124
|
+
options.lock.endDate instanceof Date,
|
|
125
|
+
"endDate must be Date object or number"
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (options.preset) {
|
|
131
|
+
if (!presets[options.preset]) {
|
|
132
|
+
throw new TypeError("Unknown preset of '" + options.preset + "'");
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Sets the default values and validates the configuration.
|
|
139
|
+
*/
|
|
140
|
+
export function applyDefaultsToOptions(
|
|
141
|
+
options: ObfuscateOptions
|
|
142
|
+
): ObfuscateOptions {
|
|
143
|
+
if (options.preset) {
|
|
144
|
+
// Clone and allow overriding
|
|
145
|
+
options = Object.assign({}, presets[options.preset], options);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (!options.hasOwnProperty("compact")) {
|
|
149
|
+
options.compact = true; // Compact is on by default
|
|
150
|
+
}
|
|
151
|
+
if (!options.hasOwnProperty("renameGlobals")) {
|
|
152
|
+
options.renameGlobals = true; // RenameGlobals is on by default
|
|
153
|
+
}
|
|
154
|
+
if (!options.hasOwnProperty("preserveFunctionLength")) {
|
|
155
|
+
options.preserveFunctionLength = true; // preserveFunctionLength is on by default
|
|
156
|
+
}
|
|
157
|
+
if (!options.hasOwnProperty("renameLabels")) {
|
|
158
|
+
options.renameLabels = true; // RenameLabels is on by default
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (options.globalVariables && !(options.globalVariables instanceof Set)) {
|
|
162
|
+
options.globalVariables = new Set(Object.keys(options.globalVariables));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (options.lock) {
|
|
166
|
+
ok(typeof options.lock === "object", "options.lock must be an object");
|
|
167
|
+
|
|
168
|
+
if (options.lock.selfDefending) {
|
|
169
|
+
options.compact = true; // self defending forcibly enables this
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (!options.lock.customLocks) {
|
|
173
|
+
options.lock.customLocks = [];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Convert 'startDate' and 'endDate' to Dates
|
|
177
|
+
if (typeof options.lock.startDate === "number") {
|
|
178
|
+
options.lock.startDate = new Date(options.lock.startDate);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (typeof options.lock.endDate === "number") {
|
|
182
|
+
options.lock.endDate = new Date(options.lock.endDate);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// options.globalVariables outlines generic globals that should be present in the execution context
|
|
187
|
+
if (!options.hasOwnProperty("globalVariables")) {
|
|
188
|
+
options.globalVariables = new Set([]);
|
|
189
|
+
|
|
190
|
+
if (options.target == "browser") {
|
|
191
|
+
// browser
|
|
192
|
+
[
|
|
193
|
+
"window",
|
|
194
|
+
"document",
|
|
195
|
+
"postMessage",
|
|
196
|
+
"alert",
|
|
197
|
+
"confirm",
|
|
198
|
+
"location",
|
|
199
|
+
"btoa",
|
|
200
|
+
"atob",
|
|
201
|
+
"unescape",
|
|
202
|
+
"encodeURIComponent",
|
|
203
|
+
].forEach((x) => options.globalVariables.add(x));
|
|
204
|
+
} else {
|
|
205
|
+
// node
|
|
206
|
+
[
|
|
207
|
+
"global",
|
|
208
|
+
"Buffer",
|
|
209
|
+
"require",
|
|
210
|
+
"process",
|
|
211
|
+
"exports",
|
|
212
|
+
"module",
|
|
213
|
+
"__dirname",
|
|
214
|
+
"__filename",
|
|
215
|
+
].forEach((x) => options.globalVariables.add(x));
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
[
|
|
219
|
+
"globalThis",
|
|
220
|
+
"console",
|
|
221
|
+
"parseInt",
|
|
222
|
+
"parseFloat",
|
|
223
|
+
"Math",
|
|
224
|
+
"JSON",
|
|
225
|
+
"RegExp",
|
|
226
|
+
"Promise",
|
|
227
|
+
"String",
|
|
228
|
+
"Boolean",
|
|
229
|
+
"Function",
|
|
230
|
+
"Object",
|
|
231
|
+
"Array",
|
|
232
|
+
"Proxy",
|
|
233
|
+
"Error",
|
|
234
|
+
"TypeError",
|
|
235
|
+
"ReferenceError",
|
|
236
|
+
"RangeError",
|
|
237
|
+
"EvalError",
|
|
238
|
+
"setTimeout",
|
|
239
|
+
"clearTimeout",
|
|
240
|
+
"setInterval",
|
|
241
|
+
"clearInterval",
|
|
242
|
+
"setImmediate",
|
|
243
|
+
"clearImmediate",
|
|
244
|
+
"queueMicrotask",
|
|
245
|
+
"isNaN",
|
|
246
|
+
"isFinite",
|
|
247
|
+
"Set",
|
|
248
|
+
"Map",
|
|
249
|
+
"WeakSet",
|
|
250
|
+
"WeakMap",
|
|
251
|
+
"Symbol",
|
|
252
|
+
].forEach((x) => options.globalVariables.add(x));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return options;
|
|
256
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"module": "esnext",
|
|
4
|
+
"target": "es6",
|
|
5
|
+
"strict": true,
|
|
6
|
+
"esModuleInterop": true,
|
|
7
|
+
"moduleResolution": "node",
|
|
8
|
+
"outDir": "./dist",
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"noImplicitAny": false,
|
|
11
|
+
"strictNullChecks": false
|
|
12
|
+
},
|
|
13
|
+
"include": ["src/**/*"]
|
|
14
|
+
}
|
package/babel.config.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
// babel.config.js
|
|
2
|
-
// Jest uses this & for building
|
|
3
|
-
module.exports = {
|
|
4
|
-
presets: [
|
|
5
|
-
["@babel/preset-env", { targets: "defaults, not ie 11, not ie_mob 11" }],
|
|
6
|
-
"@babel/preset-typescript",
|
|
7
|
-
],
|
|
8
|
-
plugins: [
|
|
9
|
-
"@babel/plugin-proposal-class-properties",
|
|
10
|
-
"@babel/plugin-proposal-optional-chaining",
|
|
11
|
-
],
|
|
12
|
-
};
|
package/dev.js
DELETED
package/dist/compiler.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.compileJsSync = compileJsSync;
|
|
7
|
-
exports.default = compileJs;
|
|
8
|
-
const escodegen = require("escodegen");
|
|
9
|
-
async function compileJs(tree, options) {
|
|
10
|
-
return compileJsSync(tree, options);
|
|
11
|
-
}
|
|
12
|
-
function compileJsSync(tree, options) {
|
|
13
|
-
var api = {
|
|
14
|
-
format: {
|
|
15
|
-
...escodegen.FORMAT_MINIFY
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
if (!options.compact) {
|
|
19
|
-
api = {};
|
|
20
|
-
if (options.indent && options.indent != 4) {
|
|
21
|
-
api.format = {};
|
|
22
|
-
api.format.indent = {
|
|
23
|
-
style: {
|
|
24
|
-
2: " ",
|
|
25
|
-
tabs: "\t"
|
|
26
|
-
}[options.indent] || " "
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
if (options.debugComments) {
|
|
31
|
-
api.comment = true;
|
|
32
|
-
}
|
|
33
|
-
return escodegen.generate(tree, api);
|
|
34
|
-
}
|
package/dist/parser.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = parseJS;
|
|
7
|
-
exports.parseSnippet = parseSnippet;
|
|
8
|
-
exports.parseSync = parseSync;
|
|
9
|
-
var assert = _interopRequireWildcard(require("assert"));
|
|
10
|
-
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
11
|
-
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
12
|
-
const acorn = require("acorn");
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Uses `acorn` to parse Javascript Code. Returns an AST tree.
|
|
16
|
-
* @param code
|
|
17
|
-
* @returns
|
|
18
|
-
*/
|
|
19
|
-
async function parseJS(code) {
|
|
20
|
-
assert.ok(typeof code === "string", "code must be a string");
|
|
21
|
-
try {
|
|
22
|
-
var parsed = parseSync(code);
|
|
23
|
-
return parsed;
|
|
24
|
-
} catch (e) {
|
|
25
|
-
throw e;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Parses a snippet code. Returns an AST Tree.
|
|
31
|
-
* @param code
|
|
32
|
-
* @returns
|
|
33
|
-
*/
|
|
34
|
-
function parseSnippet(code) {
|
|
35
|
-
return acorn.parse(code, {
|
|
36
|
-
ecmaVersion: "latest",
|
|
37
|
-
allowReturnOutsideFunction: true,
|
|
38
|
-
sourceType: "module"
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Parses synchronously. Attempts to parse as a es-module, then fallbacks to a script.
|
|
44
|
-
* @param code
|
|
45
|
-
* @returns
|
|
46
|
-
*/
|
|
47
|
-
function parseSync(code) {
|
|
48
|
-
try {
|
|
49
|
-
return acorn.parse(code, {
|
|
50
|
-
ecmaVersion: "latest",
|
|
51
|
-
sourceType: "module"
|
|
52
|
-
});
|
|
53
|
-
} catch (e) {
|
|
54
|
-
return acorn.parse(code, {
|
|
55
|
-
ecmaVersion: "latest",
|
|
56
|
-
sourceType: "script"
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|