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.
Files changed (94) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/README.md +7 -6
  3. package/dist/options.js +5 -1
  4. package/dist/parser.js +1 -2
  5. package/dist/presets.js +2 -2
  6. package/dist/transforms/calculator.js +48 -60
  7. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +482 -95
  8. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +4 -0
  9. package/dist/transforms/controlFlowFlattening/{switchCaseObfucation.js → switchCaseObfuscation.js} +2 -2
  10. package/dist/transforms/deadCode.js +1 -1
  11. package/dist/transforms/dispatcher.js +14 -13
  12. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +5 -10
  13. package/dist/transforms/flatten.js +5 -1
  14. package/dist/transforms/hideInitializingCode.js +17 -2
  15. package/dist/transforms/identifier/globalConcealing.js +46 -25
  16. package/dist/transforms/identifier/movedDeclarations.js +69 -68
  17. package/dist/transforms/identifier/renameVariables.js +22 -98
  18. package/dist/transforms/identifier/variableAnalysis.js +133 -0
  19. package/dist/transforms/label.js +11 -2
  20. package/dist/transforms/lock/antiDebug.js +32 -13
  21. package/dist/transforms/lock/lock.js +13 -2
  22. package/dist/transforms/minify.js +117 -120
  23. package/dist/transforms/opaquePredicates.js +4 -2
  24. package/dist/transforms/preparation/preparation.js +8 -0
  25. package/dist/transforms/renameLabels.js +17 -3
  26. package/dist/transforms/rgf.js +8 -3
  27. package/dist/transforms/shuffle.js +25 -9
  28. package/dist/transforms/stack.js +5 -9
  29. package/dist/transforms/string/encoding.js +209 -0
  30. package/dist/transforms/string/stringCompression.js +10 -10
  31. package/dist/transforms/string/stringConcealing.js +94 -65
  32. package/dist/transforms/string/stringSplitting.js +7 -7
  33. package/dist/transforms/transform.js +10 -0
  34. package/dist/traverse.js +1 -35
  35. package/dist/util/gen.js +3 -1
  36. package/dist/util/identifiers.js +9 -19
  37. package/dist/util/insert.js +6 -40
  38. package/dist/util/scope.js +17 -0
  39. package/package.json +2 -2
  40. package/src/options.ts +19 -3
  41. package/src/parser.ts +1 -2
  42. package/src/presets.ts +2 -2
  43. package/src/transforms/calculator.ts +87 -91
  44. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +742 -142
  45. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +6 -0
  46. package/src/transforms/controlFlowFlattening/{switchCaseObfucation.ts → switchCaseObfuscation.ts} +6 -2
  47. package/src/transforms/deadCode.ts +8 -0
  48. package/src/transforms/dispatcher.ts +29 -14
  49. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +43 -19
  50. package/src/transforms/flatten.ts +15 -2
  51. package/src/transforms/hideInitializingCode.ts +432 -406
  52. package/src/transforms/identifier/globalConcealing.ts +148 -46
  53. package/src/transforms/identifier/movedDeclarations.ts +78 -101
  54. package/src/transforms/identifier/renameVariables.ts +21 -96
  55. package/src/transforms/identifier/variableAnalysis.ts +124 -0
  56. package/src/transforms/label.ts +20 -2
  57. package/src/transforms/lock/antiDebug.ts +69 -26
  58. package/src/transforms/lock/lock.ts +37 -3
  59. package/src/transforms/minify.ts +154 -130
  60. package/src/transforms/opaquePredicates.ts +25 -3
  61. package/src/transforms/preparation/preparation.ts +8 -1
  62. package/src/transforms/renameLabels.ts +26 -3
  63. package/src/transforms/rgf.ts +6 -1
  64. package/src/transforms/shuffle.ts +87 -29
  65. package/src/transforms/stack.ts +6 -8
  66. package/src/transforms/string/encoding.ts +310 -0
  67. package/src/transforms/string/stringCompression.ts +37 -24
  68. package/src/transforms/string/stringConcealing.ts +157 -160
  69. package/src/transforms/string/stringSplitting.ts +12 -8
  70. package/src/transforms/transform.ts +15 -2
  71. package/src/traverse.ts +1 -31
  72. package/src/util/gen.ts +5 -3
  73. package/src/util/identifiers.ts +20 -20
  74. package/src/util/insert.ts +12 -78
  75. package/src/util/scope.ts +9 -0
  76. package/test/{transforms/compare.test.ts → compare.test.ts} +2 -2
  77. package/test/index.test.ts +109 -1
  78. package/test/templates/template.test.ts +14 -0
  79. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +392 -10
  80. package/test/transforms/dispatcher.test.ts +30 -0
  81. package/test/transforms/flatten.test.ts +28 -0
  82. package/test/transforms/hideInitializingCode.test.ts +336 -336
  83. package/test/transforms/identifier/globalConcealing.test.ts +1 -2
  84. package/test/transforms/identifier/movedDeclarations.test.ts +137 -112
  85. package/test/transforms/identifier/renameVariables.test.ts +124 -13
  86. package/test/transforms/lock/antiDebug.test.ts +43 -0
  87. package/test/transforms/lock/selfDefending.test.ts +68 -0
  88. package/test/transforms/minify.test.ts +137 -0
  89. package/test/transforms/renameLabels.test.ts +33 -0
  90. package/test/transforms/rgf.test.ts +29 -0
  91. package/test/transforms/string/stringSplitting.test.ts +33 -0
  92. package/test/util/identifiers.test.ts +105 -17
  93. package/dist/util/expr.js +0 -60
  94. package/src/util/expr.ts +0 -56
@@ -1,6 +1,6 @@
1
1
  import { ok } from "assert";
2
- import { getBlock, isBlock, getBlocks } from "../traverse";
3
- import { Node, Location } from "./gen";
2
+ import { getBlock, isBlock } from "../traverse";
3
+ import { Node } from "./gen";
4
4
  import { getIdentifierInfo, validateChain } from "./identifiers";
5
5
 
6
6
  /**
@@ -125,35 +125,18 @@ export function getDefiningContext(o: Node, p: Node[]): Node {
125
125
  return getVarContext(o, p);
126
126
  }
127
127
 
128
- export function getReferencingContexts(o: Node, p: Node[]): Node[] {
128
+ export function getReferencingContexts(
129
+ o: Node,
130
+ p: Node[],
131
+ info?: ReturnType<typeof getIdentifierInfo>
132
+ ): Node[] {
129
133
  validateChain(o, p);
130
134
  ok(o.type == "Identifier");
131
135
 
132
- var info = getIdentifierInfo(o, p);
133
- ok(info.spec.isReferenced);
134
-
135
- var assignmentPatternIndex = p.findIndex(
136
- (x) => x.type == "AssignmentPattern"
137
- );
138
- if (assignmentPatternIndex != -1) {
139
- if (
140
- p[assignmentPatternIndex].right == (p[assignmentPatternIndex - 1] || o)
141
- ) {
142
- var sliced = p.slice(assignmentPatternIndex);
143
- var fnIndex = sliced.findIndex((x) => isFunction(x));
144
- var associatedFn = sliced[fnIndex];
145
- if (
146
- fnIndex !== -1 &&
147
- sliced[fnIndex].params == (sliced[fnIndex - 1] || o)
148
- ) {
149
- if (associatedFn == getVarContext(o, p)) {
150
- return isLexContext(associatedFn.body)
151
- ? [associatedFn, associatedFn.body]
152
- : [associatedFn];
153
- }
154
- }
155
- }
136
+ if (!info) {
137
+ info = getIdentifierInfo(o, p);
156
138
  }
139
+ ok(info.spec.isReferenced);
157
140
 
158
141
  return [getVarContext(o, p), getLexContext(o, p)];
159
142
  }
@@ -314,11 +297,11 @@ export function isForInitialize(o, p): "initializer" | "left-hand" | false {
314
297
  );
315
298
  if (forIndex !== -1) {
316
299
  if (p[forIndex].type == "ForStatement") {
317
- if (p[forIndex].init == p[forIndex - 1] || o) {
300
+ if (p[forIndex].init == (p[forIndex - 1] || o)) {
318
301
  return "initializer";
319
302
  }
320
303
  } else {
321
- if (p[forIndex].left == p[forIndex - 1] || o) {
304
+ if (p[forIndex].left == (p[forIndex - 1] || o)) {
322
305
  return "left-hand";
323
306
  }
324
307
  }
@@ -326,52 +309,3 @@ export function isForInitialize(o, p): "initializer" | "left-hand" | false {
326
309
 
327
310
  return false;
328
311
  }
329
-
330
- export function isInBranch(object: Node, parents: Node[], context: Node) {
331
- ok(object);
332
- ok(parents);
333
- ok(context);
334
-
335
- ok(parents.includes(context));
336
-
337
- var definingContext =
338
- parents[0].type == "FunctionDeclaration" && parents[0].id == object
339
- ? getVarContext(parents[0], parents.slice(1))
340
- : getVarContext(object, parents);
341
-
342
- var contextIndex = parents.findIndex((x) => x === context);
343
- var slicedParents = parents.slice(0, contextIndex);
344
-
345
- ok(!slicedParents.includes(object), "slicedParents includes object");
346
-
347
- var slicedTypes = new Set(slicedParents.map((x) => x.type));
348
-
349
- var isBranch = definingContext !== context;
350
- if (!isBranch) {
351
- if (
352
- [
353
- "IfStatement",
354
- "ForStatement",
355
- "ForInStatement",
356
- "ForOfStatement",
357
- "WhileStatement",
358
- "DoWhileStatement",
359
- "SwitchStatement",
360
- "ConditionalExpression",
361
- "LogicalExpression",
362
- "TryStatement",
363
- "ChainExpression",
364
- "BinaryExpression",
365
- "FunctionExpression",
366
- "FunctionDeclaration",
367
- "ArrowFunctionExpression",
368
- "ClassExpression",
369
- "ClassDeclaration",
370
- ].find((x) => slicedTypes.has(x))
371
- ) {
372
- isBranch = true;
373
- }
374
- }
375
-
376
- return isBranch;
377
- }
@@ -0,0 +1,9 @@
1
+ import { isBlock } from "../traverse";
2
+
3
+ export function isLexicalScope(object) {
4
+ return isBlock(object) || object.type == "SwitchCase";
5
+ }
6
+
7
+ export function getLexicalScope(object, parents) {
8
+ return [object, ...parents].find((node) => isLexicalScope(node));
9
+ }
@@ -1,10 +1,10 @@
1
- import { isIndependent } from "../../src/util/compare";
1
+ import { isIndependent } from "../src/util/compare";
2
2
  import {
3
3
  ArrayExpression,
4
4
  FunctionExpression,
5
5
  Identifier,
6
6
  Literal,
7
- } from "../../src/util/gen";
7
+ } from "../src/util/gen";
8
8
 
9
9
  describe("isIndependent", () => {
10
10
  it("should return true for literals", () => {
@@ -1,4 +1,7 @@
1
- import JsConfuser from "../src/index";
1
+ import JsConfuser, {
2
+ debugObfuscation,
3
+ debugTransformations,
4
+ } from "../src/index";
2
5
 
3
6
  it("should be a function", async () => {
4
7
  expect(typeof JsConfuser).toBe("function");
@@ -126,3 +129,108 @@ it("should error when invalid endDate is passed in", async () => {
126
129
  return await JsConfuser("5+5", invalid);
127
130
  }).rejects.toThrow();
128
131
  });
132
+
133
+ it("should error when source code is not a string", async () => {
134
+ await expect(async () => {
135
+ return await JsConfuser({} as any, {
136
+ target: "node",
137
+ preset: "low",
138
+ });
139
+ }).rejects.toThrow();
140
+ });
141
+
142
+ it("should error when invalid source code is passed in", async () => {
143
+ await expect(async () => {
144
+ return await JsConfuser("#?!if?//for:;1(function:class{))]][]", {
145
+ target: "node",
146
+ preset: "low",
147
+ });
148
+ }).rejects.toThrow();
149
+ });
150
+
151
+ describe("obfuscateAST", () => {
152
+ test("Variant #1: Mutate AST", async () => {
153
+ var AST = {
154
+ type: "Program",
155
+ body: [
156
+ {
157
+ type: "ExpressionStatement",
158
+ expression: { type: "Literal", value: true },
159
+ },
160
+ ],
161
+ };
162
+ var before = JSON.stringify(AST);
163
+
164
+ JsConfuser.obfuscateAST(AST, { target: "node", es5: true });
165
+
166
+ var after = JSON.stringify(AST);
167
+
168
+ // Same object reference
169
+ expect(AST === AST).toStrictEqual(true);
170
+
171
+ // Different string
172
+ expect(before !== after).toStrictEqual(false);
173
+ });
174
+
175
+ test("Variant #2: Error on invalid parameters", async () => {
176
+ await expect(async () => {
177
+ return await JsConfuser.obfuscateAST("string", {
178
+ target: "node",
179
+ preset: "low",
180
+ });
181
+ }).rejects.toThrow();
182
+ });
183
+
184
+ test("Variant #3: Error on invalid AST", async () => {
185
+ await expect(async () => {
186
+ var invalidAST = {
187
+ type: "NotProgram",
188
+ };
189
+
190
+ return await JsConfuser.obfuscateAST(invalidAST, {
191
+ target: "node",
192
+ preset: "low",
193
+ });
194
+ }).rejects.toThrow();
195
+ });
196
+ });
197
+
198
+ describe("debugTransformations", () => {
199
+ test("Variant #1: Return array of objects containing `name`, `code`, and `ms` properties", async () => {
200
+ var frames = await debugTransformations(`console.log(1)`, {
201
+ target: "node",
202
+ preset: "low",
203
+ });
204
+
205
+ expect(Array.isArray(frames)).toStrictEqual(true);
206
+ expect(frames.length).toBeTruthy();
207
+
208
+ frames.forEach((frame) => {
209
+ expect(typeof frame.name).toStrictEqual("string");
210
+ expect(typeof frame.code).toStrictEqual("string");
211
+ expect(typeof frame.ms).toStrictEqual("number");
212
+ });
213
+ });
214
+ });
215
+
216
+ describe("debugObfuscation", () => {
217
+ test("Variant #1: Return array of objects containing code, ms, and name properties", async () => {
218
+ var called = false;
219
+
220
+ var callback = (name, complete, totalTransforms) => {
221
+ expect(typeof name).toStrictEqual("string");
222
+ expect(typeof complete).toStrictEqual("number");
223
+ expect(typeof totalTransforms).toStrictEqual("number");
224
+
225
+ called = true;
226
+ };
227
+ var output = await debugObfuscation(
228
+ `console.log(1)`,
229
+ { target: "node", preset: "low" },
230
+ callback
231
+ );
232
+
233
+ expect(typeof output).toStrictEqual("string");
234
+ expect(called).toStrictEqual(true);
235
+ });
236
+ });
@@ -0,0 +1,14 @@
1
+ import Template from "../../src/templates/template";
2
+
3
+ describe("Template", () => {
4
+ test("Variant #1: Error when invalid code passed in", () => {
5
+ var _consoleError = console.error;
6
+ console.error = null;
7
+
8
+ expect(() => {
9
+ Template(`#&!#Ylet{}class)--1]?|:!@#`).compile();
10
+ }).toThrow();
11
+
12
+ console.error = _consoleError;
13
+ });
14
+ });