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.
Files changed (139) hide show
  1. package/.github/workflows/node.js.yml +2 -2
  2. package/CHANGELOG.md +69 -0
  3. package/README.md +143 -7
  4. package/dist/index.js +33 -4
  5. package/dist/obfuscator.js +30 -31
  6. package/dist/options.js +4 -5
  7. package/dist/order.js +4 -6
  8. package/dist/probability.js +2 -4
  9. package/dist/templates/bufferToString.js +13 -0
  10. package/dist/templates/crash.js +2 -2
  11. package/dist/templates/es5.js +18 -0
  12. package/dist/transforms/antiTooling.js +1 -1
  13. package/dist/transforms/calculator.js +77 -21
  14. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +980 -367
  15. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +8 -3
  16. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +25 -26
  17. package/dist/transforms/deadCode.js +33 -25
  18. package/dist/transforms/dispatcher.js +7 -6
  19. package/dist/transforms/es5/antiClass.js +6 -2
  20. package/dist/transforms/es5/antiDestructuring.js +3 -1
  21. package/dist/transforms/es5/es5.js +31 -34
  22. package/dist/transforms/eval.js +11 -0
  23. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +8 -5
  24. package/dist/transforms/extraction/objectExtraction.js +6 -1
  25. package/dist/transforms/finalizer.js +82 -0
  26. package/dist/transforms/flatten.js +82 -55
  27. package/dist/transforms/hexadecimalNumbers.js +34 -9
  28. package/dist/transforms/identifier/globalAnalysis.js +88 -0
  29. package/dist/transforms/identifier/globalConcealing.js +10 -83
  30. package/dist/transforms/identifier/movedDeclarations.js +2 -8
  31. package/dist/transforms/identifier/renameVariables.js +39 -27
  32. package/dist/transforms/identifier/variableAnalysis.js +58 -62
  33. package/dist/transforms/minify.js +80 -61
  34. package/dist/transforms/opaquePredicates.js +1 -1
  35. package/dist/transforms/preparation/preparation.js +2 -2
  36. package/dist/transforms/preparation.js +231 -0
  37. package/dist/transforms/renameLabels.js +1 -1
  38. package/dist/transforms/rgf.js +4 -5
  39. package/dist/transforms/stack.js +87 -26
  40. package/dist/transforms/string/encoding.js +150 -179
  41. package/dist/transforms/string/stringCompression.js +14 -15
  42. package/dist/transforms/string/stringConcealing.js +25 -8
  43. package/dist/transforms/string/stringEncoding.js +13 -24
  44. package/dist/transforms/transform.js +11 -18
  45. package/dist/traverse.js +24 -18
  46. package/dist/util/compare.js +2 -2
  47. package/dist/util/gen.js +15 -0
  48. package/dist/util/insert.js +31 -7
  49. package/dist/util/random.js +15 -0
  50. package/package.json +5 -5
  51. package/src/index.ts +57 -19
  52. package/src/obfuscator.ts +26 -29
  53. package/src/options.ts +17 -21
  54. package/src/order.ts +4 -8
  55. package/src/probability.ts +2 -3
  56. package/src/templates/bufferToString.ts +68 -0
  57. package/src/templates/crash.ts +5 -9
  58. package/src/templates/es5.ts +131 -0
  59. package/src/transforms/antiTooling.ts +1 -1
  60. package/src/transforms/calculator.ts +122 -59
  61. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +1583 -571
  62. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +18 -3
  63. package/src/transforms/deadCode.ts +383 -26
  64. package/src/transforms/dispatcher.ts +8 -6
  65. package/src/transforms/es5/antiClass.ts +10 -1
  66. package/src/transforms/es5/antiDestructuring.ts +3 -1
  67. package/src/transforms/es5/es5.ts +32 -77
  68. package/src/transforms/eval.ts +18 -0
  69. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +9 -6
  70. package/src/transforms/extraction/objectExtraction.ts +12 -5
  71. package/src/transforms/finalizer.ts +75 -0
  72. package/src/transforms/flatten.ts +194 -151
  73. package/src/transforms/identifier/globalAnalysis.ts +85 -0
  74. package/src/transforms/identifier/globalConcealing.ts +14 -103
  75. package/src/transforms/identifier/movedDeclarations.ts +4 -11
  76. package/src/transforms/identifier/renameVariables.ts +37 -30
  77. package/src/transforms/identifier/variableAnalysis.ts +66 -73
  78. package/src/transforms/minify.ts +116 -77
  79. package/src/transforms/opaquePredicates.ts +2 -2
  80. package/src/transforms/preparation.ts +238 -0
  81. package/src/transforms/renameLabels.ts +2 -2
  82. package/src/transforms/rgf.ts +6 -7
  83. package/src/transforms/stack.ts +97 -37
  84. package/src/transforms/string/encoding.ts +115 -212
  85. package/src/transforms/string/stringCompression.ts +27 -18
  86. package/src/transforms/string/stringConcealing.ts +41 -11
  87. package/src/transforms/string/stringEncoding.ts +18 -18
  88. package/src/transforms/transform.ts +15 -21
  89. package/src/traverse.ts +24 -12
  90. package/src/types.ts +11 -2
  91. package/src/util/compare.ts +2 -2
  92. package/src/util/gen.ts +21 -1
  93. package/src/util/insert.ts +49 -9
  94. package/src/util/random.ts +13 -0
  95. package/test/code/Cash.test.ts +1 -1
  96. package/test/code/Dynamic.test.ts +12 -10
  97. package/test/code/ES6.src.js +136 -0
  98. package/test/code/ES6.test.ts +28 -2
  99. package/test/code/NewFeatures.test.ts +19 -0
  100. package/test/index.test.ts +15 -2
  101. package/test/probability.test.ts +44 -0
  102. package/test/templates/template.test.ts +1 -1
  103. package/test/transforms/antiTooling.test.ts +52 -0
  104. package/test/transforms/calculator.test.ts +40 -0
  105. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +713 -149
  106. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +173 -0
  107. package/test/transforms/deadCode.test.ts +66 -15
  108. package/test/transforms/dispatcher.test.ts +44 -1
  109. package/test/transforms/es5/antiClass.test.ts +33 -0
  110. package/test/transforms/es5/antiDestructuring.test.ts +16 -0
  111. package/test/transforms/eval.test.ts +53 -0
  112. package/test/transforms/extraction/objectExtraction.test.ts +21 -0
  113. package/test/transforms/flatten.test.ts +195 -3
  114. package/test/transforms/identifier/movedDeclarations.test.ts +27 -0
  115. package/test/transforms/identifier/renameVariables.test.ts +108 -0
  116. package/test/transforms/lock/antiDebug.test.ts +2 -2
  117. package/test/transforms/minify.test.ts +151 -0
  118. package/test/transforms/preparation.test.ts +157 -0
  119. package/test/transforms/rgf.test.ts +56 -29
  120. package/test/transforms/stack.test.ts +91 -21
  121. package/test/transforms/string/stringCompression.test.ts +39 -0
  122. package/test/transforms/string/stringConcealing.test.ts +115 -0
  123. package/test/transforms/string/stringEncoding.test.ts +53 -2
  124. package/test/transforms/transform.test.ts +66 -0
  125. package/test/traverse.test.ts +139 -0
  126. package/test/util/compare.test.ts +23 -1
  127. package/src/transforms/controlFlowFlattening/choiceFlowObfuscation.ts +0 -87
  128. package/src/transforms/controlFlowFlattening/controlFlowObfuscation.ts +0 -203
  129. package/src/transforms/controlFlowFlattening/switchCaseObfuscation.ts +0 -130
  130. package/src/transforms/hexadecimalNumbers.ts +0 -31
  131. package/src/transforms/hideInitializingCode.ts +0 -432
  132. package/src/transforms/label.ts +0 -64
  133. package/src/transforms/preparation/nameConflicts.ts +0 -102
  134. package/src/transforms/preparation/preparation.ts +0 -176
  135. package/test/transforms/controlFlowFlattening/controlFlowObfuscation.test.ts +0 -101
  136. package/test/transforms/controlFlowFlattening/switchCaseObfuscation.test.ts +0 -120
  137. package/test/transforms/hideInitializingCode.test.ts +0 -336
  138. package/test/transforms/preparation/nameConflicts.test.ts +0 -52
  139. package/test/transforms/preparation/preparation.test.ts +0 -62
@@ -1,87 +0,0 @@
1
- import {
2
- AssignmentExpression,
3
- BlockStatement,
4
- CatchClause,
5
- ExpressionStatement,
6
- Identifier,
7
- IfStatement,
8
- Literal,
9
- ThrowStatement,
10
- TryStatement,
11
- UnaryExpression,
12
- VariableDeclaration,
13
- VariableDeclarator,
14
- } from "../../util/gen";
15
- import Transform from "../transform";
16
-
17
- export default class ChoiceFlowObfuscation extends Transform {
18
- constructor(o) {
19
- super(o);
20
- }
21
-
22
- match(object, parents) {
23
- return object.type == "IfStatement";
24
- }
25
-
26
- transform(object, parents) {
27
- return () => {
28
- var body = parents[0];
29
- var element = object;
30
- if (parents[0].type == "LabeledStatement") {
31
- body = parents[1];
32
- element = parents[0];
33
- }
34
-
35
- var before = [];
36
-
37
- var isNested =
38
- parents[0].type == "IfStatement" && parents[0].alternate === object;
39
-
40
- if (!isNested && (!Array.isArray(body) || body.indexOf(element) === -1)) {
41
- return;
42
- }
43
-
44
- var result = this.getPlaceholder();
45
- before.push(VariableDeclaration(VariableDeclarator(result)));
46
-
47
- var yesBody = object.consequent
48
- ? object.consequent.type == "BlockStatement"
49
- ? [...object.consequent.body]
50
- : [object.consequent]
51
- : [];
52
-
53
- yesBody.unshift(
54
- ExpressionStatement(
55
- AssignmentExpression("=", Identifier(result), Literal(1))
56
- )
57
- );
58
-
59
- var noBody = object.alternate
60
- ? object.alternate.type == "BlockStatement"
61
- ? [...object.alternate.body]
62
- : [object.alternate]
63
- : [];
64
-
65
- noBody.unshift(
66
- ExpressionStatement(
67
- AssignmentExpression("=", Identifier(result), Literal(1))
68
- )
69
- );
70
-
71
- var elseTest = UnaryExpression("!", Identifier(result));
72
-
73
- var newObject = TryStatement(
74
- [IfStatement({ ...object.test }, [ThrowStatement(Identifier(result))])],
75
- CatchClause(Identifier(this.getPlaceholder()), yesBody),
76
- [IfStatement(elseTest, noBody)]
77
- );
78
-
79
- if (isNested) {
80
- this.replace(object, BlockStatement([...before, { ...newObject }]));
81
- } else {
82
- body.splice(body.indexOf(element), 0, ...before);
83
- this.replace(object, newObject);
84
- }
85
- };
86
- }
87
- }
@@ -1,203 +0,0 @@
1
- import { ok } from "assert";
2
- import { ComputeProbabilityMap } from "../../probability";
3
- import { walk } from "../../traverse";
4
- import {
5
- AssignmentExpression,
6
- BinaryExpression,
7
- BreakStatement,
8
- ExpressionStatement,
9
- Identifier,
10
- IfStatement,
11
- Literal,
12
- Node,
13
- SwitchCase,
14
- SwitchStatement,
15
- VariableDeclaration,
16
- VariableDeclarator,
17
- WhileStatement,
18
- } from "../../util/gen";
19
- import { containsLexicallyBoundVariables } from "../../util/identifiers";
20
- import { clone, getBlockBody } from "../../util/insert";
21
- import { getRandomInteger, shuffle } from "../../util/random";
22
- import Transform from "../transform";
23
-
24
- /**
25
- * Obfuscates For and While statements.
26
- */
27
- export default class ControlFlowObfuscation extends Transform {
28
- constructor(o) {
29
- super(o);
30
- }
31
-
32
- match(object: Node, parents: Node[]) {
33
- return object.type === "ForStatement" || object.type === "WhileStatement";
34
- }
35
-
36
- transform(object: Node, parents: Node[]) {
37
- return () => {
38
- if (object.$controlFlowObfuscation) {
39
- // avoid infinite loop
40
- return;
41
- }
42
-
43
- if (containsLexicallyBoundVariables(object, parents)) {
44
- return;
45
- }
46
-
47
- var illegal = false;
48
- walk(object, parents, (o, p) => {
49
- if (o.type == "FunctionDeclaration" || o.type == "BreakStatement") {
50
- illegal = true;
51
- return "EXIT";
52
- }
53
- });
54
-
55
- if (illegal) {
56
- return;
57
- }
58
-
59
- var body =
60
- parents[0].type == "LabeledStatement" ? parents[1] : parents[0];
61
- var element = parents[0].type == "LabeledStatement" ? parents[0] : object;
62
-
63
- // No place to insert more statements
64
- if (!Array.isArray(body)) {
65
- return;
66
- }
67
-
68
- // No place to insert variable declaration
69
- if (body.indexOf(element) === -1) {
70
- return;
71
- }
72
-
73
- if (
74
- !ComputeProbabilityMap(this.options.controlFlowFlattening, (x) => x)
75
- ) {
76
- return;
77
- }
78
-
79
- var init = [];
80
- var update = [];
81
- var test: Node = null;
82
- var consequent = [];
83
-
84
- if (object.type === "ForStatement") {
85
- if (object.init) {
86
- init.push(object.init);
87
- }
88
- if (object.update) {
89
- update.push(ExpressionStatement(object.update));
90
- }
91
- if (object.test) {
92
- test = object.test || Literal(true);
93
- }
94
- } else if (object.type === "WhileStatement") {
95
- if (object.test) {
96
- test = object.test;
97
- }
98
- } else {
99
- throw new Error("Unknown type: " + object.type);
100
- }
101
-
102
- if (object.body.type == "BlockStatement") {
103
- consequent.push(...getBlockBody(object.body));
104
- } else {
105
- consequent.push(object.body);
106
- }
107
-
108
- if (!test) {
109
- test = Literal(true);
110
- }
111
-
112
- ok(test);
113
-
114
- init.forEach((o) => {
115
- if (
116
- o.type !== "VariableDeclaration" &&
117
- o.type !== "ExpressionStatement"
118
- ) {
119
- this.replace(o, ExpressionStatement(clone(o)));
120
- }
121
- });
122
-
123
- var stateVar = this.getPlaceholder();
124
-
125
- var selection = new Set();
126
-
127
- // init 0 test 1 run 2 update 3 end 4
128
- var states: number[] = [];
129
-
130
- // Create 5 random unique number
131
- while (states.length < 5) {
132
- var newState;
133
- do {
134
- newState = getRandomInteger(0, 1000 + states.length);
135
- } while (selection.has(newState));
136
-
137
- ok(!isNaN(newState));
138
-
139
- states.push(newState);
140
- selection.add(newState);
141
- }
142
- ok(selection.size === states.length);
143
- ok(states.length === 5);
144
-
145
- var startState = states[0];
146
- var testState = states[1];
147
- var bodyState = states[2];
148
- var updateState = states[3];
149
- var endState = states[4];
150
-
151
- body.splice(
152
- body.indexOf(element),
153
- 0,
154
- VariableDeclaration(VariableDeclarator(stateVar, Literal(startState)))
155
- );
156
-
157
- function goto(from: number, to: number) {
158
- var diff = to - from;
159
- ok(!isNaN(diff));
160
- return ExpressionStatement(
161
- AssignmentExpression("+=", Identifier(stateVar), Literal(diff))
162
- );
163
- }
164
-
165
- var cases = [
166
- SwitchCase(Literal(startState), [
167
- ...init,
168
- goto(startState, testState),
169
- BreakStatement(),
170
- ]),
171
- SwitchCase(Literal(testState), [
172
- IfStatement(
173
- test,
174
- [goto(testState, bodyState)],
175
- [goto(testState, endState)]
176
- ),
177
- BreakStatement(),
178
- ]),
179
- SwitchCase(Literal(bodyState), [
180
- ...consequent,
181
- goto(bodyState, updateState),
182
- BreakStatement(),
183
- ]),
184
- SwitchCase(Literal(updateState), [
185
- ...update,
186
- goto(updateState, testState),
187
- BreakStatement(),
188
- ]),
189
- ];
190
-
191
- this.replace(
192
- object,
193
- WhileStatement(
194
- BinaryExpression("!=", Identifier(stateVar), Literal(endState)),
195
- [SwitchStatement(Identifier(stateVar), cases)]
196
- )
197
- );
198
-
199
- // Marked to not be infinite
200
- object.$controlFlowObfuscation = 1;
201
- };
202
- }
203
- }
@@ -1,130 +0,0 @@
1
- import Template from "../../templates/template";
2
- import { walk } from "../../traverse";
3
- import {
4
- BinaryExpression,
5
- Identifier,
6
- Literal,
7
- VariableDeclaration,
8
- VariableDeclarator,
9
- } from "../../util/gen";
10
- import { clone } from "../../util/insert";
11
- import { getRandomInteger } from "../../util/random";
12
- import Transform from "../transform";
13
-
14
- /**
15
- * Does complex math to the state variable, after both CFF and CFO have run.
16
- *
17
- * The switch statements are ones with numbered cases and a simple discriminant.
18
- */
19
- export default class SwitchCaseObfuscation extends Transform {
20
- constructor(o) {
21
- super(o);
22
- }
23
-
24
- match(object, parents) {
25
- return (
26
- object.type == "SwitchStatement" &&
27
- !object.cases.find(
28
- (x) =>
29
- !(
30
- x.test &&
31
- typeof x.test === "object" &&
32
- x.test.type == "Literal" &&
33
- typeof x.test.value === "number" &&
34
- Math.abs(x.test.value) < 100_000
35
- )
36
- )
37
- );
38
- }
39
-
40
- transform(object, parents) {
41
- var types = new Set();
42
- walk(object.discriminant, [object, ...parents], (o, p) => {
43
- if (o.type) {
44
- if (
45
- object.$controlFlowFlattening &&
46
- o.type == "BinaryExpression" &&
47
- o.operator === "+"
48
- ) {
49
- } else {
50
- types.add(o.type);
51
- }
52
- }
53
- });
54
-
55
- types.delete("Identifier");
56
- if (types.size) {
57
- return;
58
- }
59
-
60
- var body = parents[0];
61
- var element = object;
62
-
63
- if (parents[0].type == "LabeledStatement") {
64
- body = parents[1];
65
- element = parents[0];
66
- }
67
-
68
- if (!Array.isArray(body)) {
69
- return;
70
- }
71
-
72
- var index = body.indexOf(element);
73
- if (index === -1) {
74
- return;
75
- }
76
-
77
- var factor = getRandomInteger(-150, 150);
78
- if (factor == 0) {
79
- factor = 2;
80
- }
81
- var offset = getRandomInteger(-250, 250);
82
-
83
- var newVar = this.getPlaceholder();
84
-
85
- var newStates = [];
86
- var max;
87
- object.cases.forEach((x) => {
88
- var current = x.test.value;
89
- var value = current * factor + offset;
90
-
91
- newStates.push(value);
92
- if (!max || Math.abs(value) > max) {
93
- max = Math.abs(value);
94
- }
95
- });
96
-
97
- if (max > 100_000) {
98
- return;
99
- }
100
-
101
- if (new Set(newStates).size !== newStates.length) {
102
- // not possible because of clashing case test
103
- return;
104
- }
105
-
106
- // State variable declaration
107
- body.splice(
108
- index,
109
- 0,
110
- VariableDeclaration(
111
- VariableDeclarator(
112
- newVar,
113
-
114
- BinaryExpression(
115
- "+",
116
- BinaryExpression("*", clone(object.discriminant), Literal(factor)),
117
- Literal(offset)
118
- )
119
- )
120
- )
121
- );
122
-
123
- object.discriminant = Identifier(newVar);
124
-
125
- // possible so override
126
- object.cases.forEach((x, i) => {
127
- x.test = Literal(newStates[i]);
128
- });
129
- }
130
- }
@@ -1,31 +0,0 @@
1
- import Transform from "./transform";
2
- import { ObfuscateOrder } from "../order";
3
- import { ExitCallback } from "../traverse";
4
- import { Identifier, Node } from "../util/gen";
5
-
6
- export default class HexadecimalNumbers extends Transform {
7
- constructor(o) {
8
- super(o, ObfuscateOrder.HexadecimalNumbers);
9
- }
10
-
11
- match(object: Node, parents: Node[]): boolean {
12
- return (
13
- object.type === "Literal" &&
14
- typeof object.value === "number" &&
15
- Math.floor(object.value) === object.value
16
- );
17
- }
18
-
19
- transform(object: Node, parents: Node[]): void | ExitCallback {
20
- return () => {
21
- // Technically, a Literal will never be negative because it's supposed to be inside a UnaryExpression with a "-" operator.
22
- // This code handles it regardless
23
- var isNegative = object.value < 0;
24
- var hex = Math.abs(object.value).toString(16);
25
-
26
- var newStr = (isNegative ? "-" : "") + "0x" + hex;
27
-
28
- this.replace(object, Identifier(newStr));
29
- };
30
- }
31
- }