js-confuser 1.7.1 → 1.7.3

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 (153) hide show
  1. package/.github/workflows/node.js.yml +1 -1
  2. package/CHANGELOG.md +73 -0
  3. package/README.md +32 -31
  4. package/dist/compiler.js +2 -8
  5. package/dist/constants.js +22 -10
  6. package/dist/index.js +15 -30
  7. package/dist/obfuscator.js +15 -62
  8. package/dist/options.js +33 -40
  9. package/dist/order.js +4 -7
  10. package/dist/parser.js +5 -13
  11. package/dist/precedence.js +6 -8
  12. package/dist/presets.js +4 -6
  13. package/dist/probability.js +13 -24
  14. package/dist/templates/bufferToString.js +121 -5
  15. package/dist/templates/core.js +35 -0
  16. package/dist/templates/crash.js +22 -11
  17. package/dist/templates/es5.js +125 -6
  18. package/dist/templates/functionLength.js +24 -6
  19. package/dist/templates/globals.js +9 -0
  20. package/dist/templates/template.js +189 -43
  21. package/dist/transforms/antiTooling.js +26 -22
  22. package/dist/transforms/calculator.js +19 -55
  23. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +242 -333
  24. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +46 -25
  25. package/dist/transforms/deadCode.js +542 -31
  26. package/dist/transforms/dispatcher.js +112 -112
  27. package/dist/transforms/es5/antiClass.js +70 -44
  28. package/dist/transforms/es5/antiDestructuring.js +14 -38
  29. package/dist/transforms/es5/antiES6Object.js +39 -48
  30. package/dist/transforms/es5/antiSpreadOperator.js +5 -14
  31. package/dist/transforms/es5/antiTemplate.js +10 -19
  32. package/dist/transforms/es5/es5.js +7 -40
  33. package/dist/transforms/extraction/classExtraction.js +83 -0
  34. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +41 -80
  35. package/dist/transforms/extraction/objectExtraction.js +24 -56
  36. package/dist/transforms/finalizer.js +6 -20
  37. package/dist/transforms/flatten.js +51 -99
  38. package/dist/transforms/identifier/globalAnalysis.js +21 -26
  39. package/dist/transforms/identifier/globalConcealing.js +72 -56
  40. package/dist/transforms/identifier/movedDeclarations.js +66 -38
  41. package/dist/transforms/identifier/renameVariables.js +36 -68
  42. package/dist/transforms/identifier/variableAnalysis.js +21 -48
  43. package/dist/transforms/lock/antiDebug.js +20 -25
  44. package/dist/transforms/lock/integrity.js +53 -52
  45. package/dist/transforms/lock/lock.js +161 -126
  46. package/dist/transforms/minify.js +77 -108
  47. package/dist/transforms/opaquePredicates.js +12 -49
  48. package/dist/transforms/preparation.js +28 -49
  49. package/dist/transforms/renameLabels.js +5 -22
  50. package/dist/transforms/rgf.js +125 -72
  51. package/dist/transforms/shuffle.js +42 -47
  52. package/dist/transforms/stack.js +41 -98
  53. package/dist/transforms/string/encoding.js +76 -27
  54. package/dist/transforms/string/stringCompression.js +75 -68
  55. package/dist/transforms/string/stringConcealing.js +127 -135
  56. package/dist/transforms/string/stringEncoding.js +6 -26
  57. package/dist/transforms/string/stringSplitting.js +5 -30
  58. package/dist/transforms/transform.js +76 -104
  59. package/dist/traverse.js +11 -18
  60. package/dist/util/compare.js +27 -29
  61. package/dist/util/gen.js +32 -86
  62. package/dist/util/guard.js +5 -1
  63. package/dist/util/identifiers.js +9 -72
  64. package/dist/util/insert.js +27 -77
  65. package/dist/util/math.js +0 -3
  66. package/dist/util/object.js +3 -7
  67. package/dist/util/random.js +31 -36
  68. package/dist/util/scope.js +6 -3
  69. package/docs/Countermeasures.md +13 -6
  70. package/docs/Integrity.md +35 -28
  71. package/docs/RGF.md +6 -1
  72. package/docs/RenameVariables.md +116 -0
  73. package/docs/TamperProtection.md +100 -0
  74. package/docs/Template.md +117 -0
  75. package/package.json +3 -3
  76. package/src/constants.ts +17 -0
  77. package/src/index.ts +7 -5
  78. package/src/options.ts +60 -7
  79. package/src/order.ts +2 -2
  80. package/src/templates/bufferToString.ts +79 -11
  81. package/src/templates/core.ts +29 -0
  82. package/src/templates/crash.ts +6 -38
  83. package/src/templates/es5.ts +1 -1
  84. package/src/templates/functionLength.ts +21 -3
  85. package/src/templates/globals.ts +3 -0
  86. package/src/templates/template.ts +205 -46
  87. package/src/transforms/antiTooling.ts +33 -11
  88. package/src/transforms/calculator.ts +4 -2
  89. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +12 -5
  90. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +46 -10
  91. package/src/transforms/deadCode.ts +74 -42
  92. package/src/transforms/dispatcher.ts +99 -73
  93. package/src/transforms/es5/antiClass.ts +25 -12
  94. package/src/transforms/es5/antiDestructuring.ts +1 -1
  95. package/src/transforms/es5/antiES6Object.ts +2 -2
  96. package/src/transforms/es5/antiTemplate.ts +1 -1
  97. package/src/transforms/extraction/classExtraction.ts +168 -0
  98. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +11 -16
  99. package/src/transforms/extraction/objectExtraction.ts +4 -15
  100. package/src/transforms/flatten.ts +20 -5
  101. package/src/transforms/identifier/globalAnalysis.ts +18 -1
  102. package/src/transforms/identifier/globalConcealing.ts +119 -72
  103. package/src/transforms/identifier/movedDeclarations.ts +90 -24
  104. package/src/transforms/identifier/renameVariables.ts +16 -1
  105. package/src/transforms/lock/antiDebug.ts +2 -2
  106. package/src/transforms/lock/integrity.ts +13 -11
  107. package/src/transforms/lock/lock.ts +122 -30
  108. package/src/transforms/minify.ts +28 -13
  109. package/src/transforms/opaquePredicates.ts +2 -2
  110. package/src/transforms/preparation.ts +16 -0
  111. package/src/transforms/rgf.ts +139 -12
  112. package/src/transforms/shuffle.ts +3 -3
  113. package/src/transforms/stack.ts +19 -4
  114. package/src/transforms/string/encoding.ts +88 -51
  115. package/src/transforms/string/stringCompression.ts +86 -17
  116. package/src/transforms/string/stringConcealing.ts +148 -118
  117. package/src/transforms/string/stringEncoding.ts +1 -2
  118. package/src/transforms/string/stringSplitting.ts +1 -2
  119. package/src/transforms/transform.ts +63 -46
  120. package/src/types.ts +2 -0
  121. package/src/util/compare.ts +39 -5
  122. package/src/util/gen.ts +10 -3
  123. package/src/util/guard.ts +10 -0
  124. package/src/util/insert.ts +17 -0
  125. package/src/util/random.ts +81 -1
  126. package/src/util/scope.ts +14 -2
  127. package/test/code/Cash.test.ts +94 -5
  128. package/test/code/StrictMode.src.js +65 -0
  129. package/test/code/StrictMode.test.js +37 -0
  130. package/test/compare.test.ts +62 -2
  131. package/test/options.test.ts +129 -55
  132. package/test/templates/template.test.ts +211 -1
  133. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +37 -18
  134. package/test/transforms/dispatcher.test.ts +55 -0
  135. package/test/transforms/extraction/classExtraction.test.ts +86 -0
  136. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +8 -0
  137. package/test/transforms/extraction/objectExtraction.test.ts +2 -0
  138. package/test/transforms/identifier/globalConcealing.test.ts +89 -0
  139. package/test/transforms/identifier/movedDeclarations.test.ts +61 -0
  140. package/test/transforms/identifier/renameVariables.test.ts +75 -1
  141. package/test/transforms/lock/tamperProtection.test.ts +336 -0
  142. package/test/transforms/minify.test.ts +37 -0
  143. package/test/transforms/rgf.test.ts +50 -0
  144. package/dist/transforms/controlFlowFlattening/choiceFlowObfuscation.js +0 -62
  145. package/dist/transforms/controlFlowFlattening/controlFlowObfuscation.js +0 -159
  146. package/dist/transforms/controlFlowFlattening/switchCaseObfuscation.js +0 -106
  147. package/dist/transforms/eval.js +0 -84
  148. package/dist/transforms/hexadecimalNumbers.js +0 -63
  149. package/dist/transforms/hideInitializingCode.js +0 -270
  150. package/dist/transforms/identifier/nameRecycling.js +0 -218
  151. package/dist/transforms/label.js +0 -67
  152. package/dist/transforms/preparation/nameConflicts.js +0 -116
  153. package/dist/transforms/preparation/preparation.js +0 -188
package/docs/Integrity.md CHANGED
@@ -1,15 +1,21 @@
1
1
  ## `Integrity`
2
2
 
3
- JSConfuser can detect changes to the source and prevent execution.
3
+ JS-Confuser can detect changes to the source code and terminate execution.
4
4
 
5
- If the code is determined modified, the tampered code will not run.
5
+ - **⚠️ This can break your code!**
6
6
 
7
- ## Usage
7
+ Option name: `lock.integrity`
8
+
9
+ Option values: `true/false`
10
+
11
+ ### Usage
8
12
 
9
13
  ```js
10
14
  var JsConfuser = require("js-confuser");
11
15
 
12
- JsConfuser.obfuscate("console.log(1)", {
16
+ var sourceCode = "console.log(1)"
17
+
18
+ JsConfuser.obfuscate(sourceCode, {
13
19
  target: "browser",
14
20
  lock: {
15
21
  integrity: true,
@@ -19,35 +25,22 @@ JsConfuser.obfuscate("console.log(1)", {
19
25
  });
20
26
  ```
21
27
 
22
- ## CLI Usage
23
-
24
- ```shell
25
- <coming soon>
26
- ```
27
-
28
- ## Example
28
+ ### Example
29
29
 
30
30
  Consider the following code:
31
31
 
32
32
  ```js
33
33
  console.log(1)
34
- ```
35
-
36
- The output:
37
34
 
38
- ```
39
- > 1
35
+ // 1
40
36
  ```
41
37
 
42
38
  The obfuscated code (from Usage):
43
39
 
44
40
  ```js
45
41
  (function(){var jXwFUz=Math.imul||function(jXwFUz,m9pBnlk){m9pBnlk|=0;var n1mfO$O=(jXwFUz&4194303)*m9pBnlk;if(jXwFUz&4290772992)n1mfO$O+=(jXwFUz&4290772992)*m9pBnlk|0;return n1mfO$O|0};function m9pBnlk(n1mfO$O,humOEA){var DGCgjl=3735928559^humOEA;var S$63Fy1=1103547991^humOEA;for(var Lop2FFS=0,GC2VbAQ;Lop2FFS<n1mfO$O.length;Lop2FFS++){GC2VbAQ=n1mfO$O.charCodeAt(Lop2FFS);DGCgjl=jXwFUz(DGCgjl^GC2VbAQ,2654435761);S$63Fy1=jXwFUz(S$63Fy1^GC2VbAQ,1597334677)}DGCgjl=jXwFUz(DGCgjl^DGCgjl>>>16,2246822507)^jXwFUz(S$63Fy1^S$63Fy1>>>13,3266489909);S$63Fy1=jXwFUz(S$63Fy1^S$63Fy1>>>16,2246822507)^jXwFUz(DGCgjl^DGCgjl>>>13,3266489909);return 4294967296*(2097151&S$63Fy1)+(DGCgjl>>>0)}function n1mfO$O(jXwFUz){return jXwFUz.toString().replace(/ |\n|;|,|\{|\}|\(|\)/g,'')}function y3EzuX9(){console['log'](1)}var yzLesc=m9pBnlk(n1mfO$O(y3EzuX9),957);if(yzLesc==0x7a77799eaf937){return y3EzuX9.apply(this,arguments)}}())
46
- ```
47
42
 
48
- The output:
49
- ```
50
- > 1
43
+ // 1
51
44
  ```
52
45
 
53
46
  Since only Integrity is enabled, it's pretty easy to find the original code: `console['log'](1)`.
@@ -58,18 +51,32 @@ Let's try to change the `console['log'](1)` to `console['log'](2)`:
58
51
  (function(){var jXwFUz=Math.imul||function(jXwFUz,m9pBnlk){m9pBnlk|=0;var n1mfO$O=(jXwFUz&4194303)*m9pBnlk;if(jXwFUz&4290772992)n1mfO$O+=(jXwFUz&4290772992)*m9pBnlk|0;return n1mfO$O|0};function m9pBnlk(n1mfO$O,humOEA){var DGCgjl=3735928559^humOEA;var S$63Fy1=1103547991^humOEA;for(var Lop2FFS=0,GC2VbAQ;Lop2FFS<n1mfO$O.length;Lop2FFS++){GC2VbAQ=n1mfO$O.charCodeAt(Lop2FFS);DGCgjl=jXwFUz(DGCgjl^GC2VbAQ,2654435761);S$63Fy1=jXwFUz(S$63Fy1^GC2VbAQ,1597334677)}DGCgjl=jXwFUz(DGCgjl^DGCgjl>>>16,2246822507)^jXwFUz(S$63Fy1^S$63Fy1>>>13,3266489909);S$63Fy1=jXwFUz(S$63Fy1^S$63Fy1>>>16,2246822507)^jXwFUz(DGCgjl^DGCgjl>>>13,3266489909);return 4294967296*(2097151&S$63Fy1)+(DGCgjl>>>0)}function n1mfO$O(jXwFUz){return jXwFUz.toString().replace(/ |\n|;|,|\{|\}|\(|\)/g,'')}function y3EzuX9(){console['log'](2)}var yzLesc=m9pBnlk(n1mfO$O(y3EzuX9),957);if(yzLesc==0x7a77799eaf937){return y3EzuX9.apply(this,arguments)}}())
59
52
  ```
60
53
 
61
- The program no longer outputs anything. Integrity detected the change and stopped execution.
54
+ The program no longer outputs anything. Integrity has detected the change and stopped execution.
55
+
56
+ ### How is this possible?
57
+
58
+ JavaScript has a sneaky method to view the source code any function. Calling `Function.toString()` on any function reveals the raw source code.
59
+
60
+ Integrity uses a hashing algorithm on the obfuscated code during the obfuscation-phase. The obfuscator then places checksum functions throughout the output code to verify it's unchanged at runtime.
61
+
62
+ An additional RegEx is utilized to remove spaces, newlines, braces, and commas. This ensures the hash isn't too sensitive.
62
63
 
63
- ## How is this possible?
64
+ ### Tamper Detection
64
65
 
65
- JavaScript has a sneaky method to view the source code any function. Calling `.toString()` on any function reveals the raw source code.
66
- Integrity hashes the code during obfuscation phase and embeds an IF-statement within the code. We used an additional regex to remove spaces, newlines, braces,
67
- and commas to ensure the hash isn't too sensitive.
66
+ If tampering is detected, the `lock.countermeasures` function will be invoked. If you don't provide a `lock.countermeasures` function, the default behavior is to crash the program.
68
67
 
69
- ## Potential Issues
68
+ [Learn more about the countermeasures function](Countermeasures.md).
69
+
70
+ ### Potential Issues
70
71
 
71
72
  If you decide to use Integrity, consider the following:
72
73
 
73
- 1. Any build-tools must not modify the locked code. The code can't be changed after JsConfuser runs.
74
- 2. `.toString()` functionality may not be enabled in your environment (bytenode)
74
+ 1. Any build-tools must not modify the locked code. The code can't be changed after JS-Confuser is applied.
75
+ 2. `Function.toString()` functionality may not be enabled in your environment (bytenode)
76
+
77
+ ### See also
78
+
79
+ - [Countermeasures](Countermeasures.md)
80
+ - [Tamper Protection](TamperProtection.md)
81
+
75
82
 
package/docs/RGF.md CHANGED
@@ -416,4 +416,9 @@ RGF only applies to:
416
416
  - Function Declarations or Expressions
417
417
  - Cannot be async / generator function
418
418
  - Cannot rely on outside-scoped variables
419
- - Cannot use `this`, `arguments`, or `eval`
419
+ - Cannot use `this`, `arguments`, or `eval`
420
+
421
+ ### See also
422
+
423
+ - [Control Flow Flattening](./ControlFlowFlattening.md)
424
+ - [Tamper Protection](./TamperProtection.md)
@@ -0,0 +1,116 @@
1
+ ## `Rename Variables`
2
+
3
+ Determines if variables should be renamed. (`true/false`)
4
+
5
+ Option name: `controlFlowFlattening`
6
+
7
+ Option values: `true/false`
8
+
9
+ ```js
10
+ // Input
11
+ var twoSum = function (nums, target) {
12
+ var hash = {};
13
+ var len = nums.length;
14
+ for (var i = 0; i < len; i++) {
15
+ if (nums[i] in hash) return [hash[nums[i]], i];
16
+ hash[target - nums[i]] = i;
17
+ }
18
+ return [-1, -1];
19
+ };
20
+
21
+ var test = function () {
22
+ var inputNums = [2, 7, 11, 15];
23
+ var inputTarget = 9;
24
+ var expectedResult = [0, 1];
25
+
26
+ var actualResult = twoSum(inputNums, inputTarget);
27
+ ok(actualResult[0] === expectedResult[0]);
28
+ ok(actualResult[1] === expectedResult[1]);
29
+ };
30
+
31
+ test();
32
+
33
+ // Output
34
+ var _O2mOcF = function (kB4uXM, w_07HXS) {
35
+ var ZLTJcx = {};
36
+ var sXQOaUx = kB4uXM["length"];
37
+ for (var JYYxEk = 0; JYYxEk < sXQOaUx; JYYxEk++) {
38
+ if (kB4uXM[JYYxEk] in ZLTJcx) {
39
+ return [ZLTJcx[kB4uXM[JYYxEk]], JYYxEk];
40
+ }
41
+ ZLTJcx[w_07HXS - kB4uXM[JYYxEk]] = JYYxEk;
42
+ }
43
+ return [-1, -1];
44
+ };
45
+ var qFaI6S = function () {
46
+ var fZpeOw = [2, 7, 11, 15];
47
+ var UJ62R2c = 9;
48
+ var dG6R0cV = [0, 1];
49
+ var WgYXwn = _O2mOcF(fZpeOw, UJ62R2c);
50
+ void (ok(WgYXwn[0] === dG6R0cV[0]), ok(WgYXwn[1] === dG6R0cV[1]));
51
+ };
52
+ qFaI6S();
53
+ ```
54
+
55
+ ### Custom Implementation
56
+
57
+ A custom function can provided as the `renameVariables` option, determining if a variable should be renamed.
58
+
59
+ | Parameter | Type | Description |
60
+ | --- | --- | --- |
61
+ | `name` | `string` | The variable proposed to be renamed |
62
+ | `isGlobal` | `boolean` | Is the variable defined at the global level? |
63
+
64
+ ```js
65
+ {
66
+ target: "node",
67
+
68
+ // Avoid renaming a certain variable
69
+ renameVariables: name=>name != "jQuery",
70
+ }
71
+ ```
72
+
73
+ ### Access the renamed variable
74
+
75
+ The `__JS_CONFUSER_VAR__` function provides a method to access variable mappings. This is especially useful for `eval()` scenarios where you want preserve the mapping.
76
+
77
+
78
+ ```js
79
+ // Input
80
+ var message = "Hello world!";
81
+ eval(`console.log(${ __JS_CONFUSER_VAR__(message) })`);
82
+
83
+ console.log("message was renamed to", __JS_CONFUSER_VAR__(message));
84
+
85
+ // Output
86
+ var nSgZyJf = "Hello world!";
87
+ eval(`console.log(${"nSgZyJf"})`) // "Hello world!"
88
+ console["log"]("message was renamed to", "nSgZyJf") // message was renamed to nSgZyJf
89
+ ```
90
+
91
+ Even if `Rename Variables` is disabled, the `__JS_CONFUSER_VAR__` will still be removed. (The original name will be returned as a string)
92
+
93
+ ### Never rename a variable
94
+
95
+ The `__NO_JS_CONFUSER_RENAME__` prefix disables renaming a certain variable. This can be useful for debugging the obfuscator.
96
+
97
+ ```js
98
+ // Input
99
+ var __NO_JS_CONFUSER_RENAME__message1 = "My first message"
100
+ var message2 = "My other message"
101
+
102
+ console.log(__NO_JS_CONFUSER_RENAME__message1)
103
+ console.log(message2)
104
+
105
+ // Output
106
+ var __NO_JS_CONFUSER_RENAME__message1 = "My first message";
107
+ var jRLf713 = "My other message";
108
+
109
+ console.log(__NO_JS_CONFUSER_RENAME__message1),
110
+ console.log(jRLf713)
111
+ ```
112
+
113
+
114
+
115
+
116
+
@@ -0,0 +1,100 @@
1
+ ## `Tamper Protection`
2
+
3
+ Tamper Protection safeguards the runtime behavior from being altered by JavaScript pitfalls.
4
+
5
+ **⚠️ Tamper Protection requires eval and ran in a non-strict mode environment!**
6
+
7
+ - **This can break your code.**
8
+ - **Due to the security concerns of arbitrary code execution, you must enable this yourself.**
9
+
10
+ Option name: `lock.tamperProtection`
11
+
12
+ Option values: `true/false/Function`
13
+
14
+ ### 1. Improves `Global Concealing`
15
+
16
+ Tamper Protection with `Global Concealing` can detect at runtime if certain global functions have been monkey-patched. The following code exemplifies this:
17
+
18
+ #### (a) Native function check
19
+
20
+ ```js
21
+ var _fetch = fetch;
22
+ fetch = (...args)=>{
23
+ console.log("Fetch request intercepted!", ...args)
24
+ return _fetch(...args)
25
+ }
26
+ ```
27
+
28
+ This monkey-patch can be detected by inspecting the `fetch.toString()` value:
29
+
30
+ ```js
31
+ // Untampered
32
+ fetch.toString() // "function fetch() { [native code] }"
33
+
34
+
35
+ // Tampered
36
+ fetch.toString() // "(...args)=>{\n console.log("Fetch request intercepted!", ...args)\n return _fetch(...args)\n}"
37
+ ```
38
+
39
+ Certain global functions are checked before each invocation to ensure that (1) the arguments cannot be intercepted and (2) their behavior cannot be altered.
40
+
41
+ #### (b) Stealthy global
42
+
43
+ A direct `eval` invocation can access the local scope, only if it has not been redefined.
44
+
45
+ ```js
46
+ let root = {};
47
+ eval("root=this"); // Window {window: ...}
48
+ ```
49
+
50
+ This method securely obtains the real global object for both the browser and NodeJS. Properties on the global object can still be changed however.
51
+
52
+ ### 2. Improves `RGF`
53
+
54
+ RGF (Runtime-Generated-Functions) behavior's can be altered by overriding the default `Function` constructor.
55
+ This allows a reverse engineer to inspect the concealed code and alter the behavior of the application.
56
+
57
+ When `lock.tamperProtection` is enabled, `RGF` will no longer use the `Function` constructor.
58
+ Instead, `eval` will be used with a strict integrity check.
59
+
60
+ ```js
61
+ let check = false;
62
+ eval("check = true")
63
+ if (!check) {
64
+ throw new Error("Eval was redefined")
65
+ }
66
+
67
+ const myFunction = eval("function abc(){}; abc");
68
+ ```
69
+
70
+ Eval loses it's local scope access when redefined by a monkey-patched function. This example ensures the concealed code cannot be inspected or behavior be changed.
71
+
72
+ [Learn more about RGF](RGF.md).
73
+
74
+ ### Custom Implementation
75
+
76
+ You can provide a custom implementation for `lock.tamperProtection` to control which functions get the native function check.
77
+
78
+ ```js
79
+ {
80
+ target: "node",
81
+ lock: {
82
+ tamperProtection: (fnName) => fnName === "console.log"
83
+ }
84
+ }
85
+ ```
86
+
87
+ ### Disallows Strict Mode
88
+
89
+ Tamper Protection requires the script to run in non-strict mode. Detection of the script in Strict Mode will be considered tampering. You can control the tampering response using the `lock.countermeasures` option, as detailed in the next section.
90
+
91
+ ### Tamper Detection
92
+
93
+ If tampering is detected, the `lock.countermeasures` function will be invoked. If you don't provide a `lock.countermeasures` function, the default behavior is to crash the program.
94
+
95
+ [Learn more about the countermeasures function](Countermeasures.md).
96
+
97
+ ### See also
98
+
99
+ - [Countermeasures](Countermeasures.md)
100
+ - [RGF](RGF.md)
@@ -0,0 +1,117 @@
1
+ ## `Template`
2
+
3
+ The Template API provides an easy way to parse code snippets into AST subtrees.
4
+ These AST subtrees can added to the obfuscated code, tailored with custom variable names and logic.
5
+
6
+
7
+ ### 1. Basic string interpolation
8
+
9
+ Interpolated strings can use the `{name}` syntax to be replaced. This allows you to create custom-named functions exemplified in the following example:
10
+
11
+ ```js
12
+ import JsConfuser from "js-confuser"
13
+
14
+ var Base64Template = new JsConfuser.Template(`
15
+ function {name}(str){
16
+ return btoa(str)
17
+ }
18
+ `);
19
+
20
+ var functionDeclaration = Base64Template.single({
21
+ name: "atob"
22
+ });
23
+
24
+ console.log(functionDeclaration);
25
+ // Node {
26
+ // type: 'FunctionDeclaration',
27
+ // start: 3,
28
+ // end: 47,
29
+ // id: Node { type: 'Identifier', start: 12, end: 16, name: 'atob' },
30
+ // expression: false,
31
+ // generator: false,
32
+ // async: false,
33
+ // params: [ Node { type: 'Identifier', start: 17, end: 20, name: 'str' } ],
34
+ // body: Node { type: 'BlockStatement', start: 21, end: 47, body: [ [Node] ] }
35
+ // }
36
+ ```
37
+
38
+ This simply preprocesses the `{name}` to `"atob"` before parsing. This behavior can let additional code to be inserted and does not properly escape strings. To avoid these pitfalls, use AST subtree insertion.
39
+
40
+ ### 2. AST subtree insertion
41
+
42
+ ```js
43
+ var Base64Template = new JsConfuser.Template(`
44
+ function {name}(str){
45
+ {getWindow}
46
+ return {getWindowName}btoa(str)
47
+ }`)
48
+
49
+ var functionDeclaration = Base64Template.single({
50
+ name: "atob",
51
+ getWindowName: "newWindow",
52
+ getWindow: () => {
53
+ var code = "var newWindow = {}";
54
+ return acorn.parse(code).body[0];
55
+ }
56
+ });
57
+ ```
58
+
59
+ Here, the `getWindow` variable is passed as function that returns an AST subtree. This must be a `Node` object, `Node[]` array, or another Template.
60
+ Optionally, the function can be replaced with the return value if it's already computed.
61
+
62
+ When utilizing AST-interpolated variables, an additional traversal will need to be ran to replace the plain Identifier nodes.
63
+
64
+ Regular string interpolation does not require an additional traversal.
65
+
66
+ ### 3. Template subtree insertion
67
+
68
+ ```js
69
+ var NewWindowTemplate = new JsConfuser.Template(`
70
+ var {NewWindowName} = {};
71
+ `);
72
+
73
+ var Base64Template = new JsConfuser.Template(`
74
+ function {name}(str){
75
+ {NewWindowTemplate}
76
+ return {NewWindowName}.btoa(str)
77
+ }`)
78
+
79
+ var functionDeclaration = Base64Template.single({
80
+ name: "atob",
81
+ NewWindowName: "newWindow",
82
+ NewWindowTemplate: NewWindowTemplate
83
+ });
84
+ ```
85
+
86
+ The variables are passed into the child templates. This allows you to not have to repeat the `NewWindowName` variable.
87
+
88
+ ### `new Template(template)`
89
+
90
+ Creates a new Template instance. You can pass multiple templates and a random one will be chosen each interpolation.
91
+
92
+ | Parameter | Type | Description |
93
+ | --- | --- | --- |
94
+ | `template` | `string` | The source code for the Template |
95
+
96
+ ### `template.compile(variables)`
97
+
98
+ Compiles the template and returns a Node array (`Node[]`)
99
+
100
+ Returns the equivalent of a [ESTree `Program.body`](https://github.com/estree/estree/blob/master/es5.md#programs)
101
+
102
+ | Parameter | Type | Description |
103
+ | --- | --- | --- |
104
+ | `variables` | `object` | An object of variables |
105
+
106
+ ### `template.single(variables)`
107
+
108
+ Compiles the template and returns the first Node. (`Node`)
109
+
110
+ An error will thrown if multiple nodes were parsed. Use this function for singular expressions/declarations.
111
+
112
+
113
+ Returns the equivalent of a [ESTree `Program.body[0]`](https://github.com/estree/estree/blob/master/es5.md#programs)
114
+
115
+ | Parameter | Type | Description |
116
+ | --- | --- | --- |
117
+ | `variables` | `object` | An object of variables |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js-confuser",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "JavaScript Obfuscation Tool.",
5
5
  "main": "dist/index.js",
6
6
  "types": "index.d.ts",
@@ -22,8 +22,8 @@
22
22
  "author": "MichaelXF",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "acorn": "^8.10.0",
26
- "escodegen": "^2.0.0"
25
+ "acorn": "^8.12.1",
26
+ "escodegen": "^2.1.0"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@babel/cli": "^7.17.6",
package/src/constants.ts CHANGED
@@ -82,3 +82,20 @@ export const reservedIdentifiers = new Set([
82
82
 
83
83
  export const noRenameVariablePrefix = "__NO_JS_CONFUSER_RENAME__";
84
84
  export const placeholderVariablePrefix = "__p_";
85
+
86
+ /**
87
+ * Tells the obfuscator this function is predictable:
88
+ * - Never called with extraneous parameters
89
+ */
90
+ export const predictableFunctionTag = "__JS_PREDICT__";
91
+
92
+ /**
93
+ * Tells the obfuscator this function is critical for the Obfuscated code.
94
+ * - Example: string decryption function
95
+ */
96
+ export const criticalFunctionTag = "__JS_CRITICAL__";
97
+
98
+ /**
99
+ * Allows the user to grab the variable name of a renamed variable.
100
+ */
101
+ export const variableFunctionName = "__JS_CONFUSER_VAR__";
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ import compileJs, { compileJsSync } from "./compiler";
2
2
  import parseJS, { parseSync } from "./parser";
3
3
  import Obfuscator from "./obfuscator";
4
4
  import Transform from "./transforms/transform";
5
+ import Template from "./templates/template";
5
6
  import { remove$Properties } from "./util/object";
6
7
  import presets from "./presets";
7
8
 
@@ -39,7 +40,7 @@ export async function obfuscateAST(AST, options: ObfuscateOptions) {
39
40
 
40
41
  options = await correctOptions(options);
41
42
 
42
- var obfuscator = new Obfuscator(options);
43
+ var obfuscator = new Obfuscator(options as any);
43
44
 
44
45
  await obfuscator.apply(AST);
45
46
 
@@ -70,7 +71,7 @@ var JsConfuser: IJsConfuser = async function (
70
71
 
71
72
  options.verbose && console.log("* Obfuscating...");
72
73
 
73
- var obfuscator = new Obfuscator(options);
74
+ var obfuscator = new Obfuscator(options as any);
74
75
 
75
76
  await obfuscator.apply(tree);
76
77
 
@@ -96,7 +97,7 @@ export const debugTransformations: IJsConfuserDebugTransformations =
96
97
  var frames = [];
97
98
 
98
99
  var tree = parseSync(code);
99
- var obfuscator = new Obfuscator(options);
100
+ var obfuscator = new Obfuscator(options as any);
100
101
 
101
102
  var time = Date.now();
102
103
 
@@ -141,7 +142,7 @@ export const debugObfuscation: IJsConfuserDebugObfuscation = async function (
141
142
 
142
143
  const parseTime = performance.now() - beforeParseTime;
143
144
 
144
- var obfuscator = new Obfuscator(options);
145
+ var obfuscator = new Obfuscator(options as any);
145
146
  var totalTransforms = obfuscator.array.length;
146
147
 
147
148
  var transformationTimes = Object.create(null);
@@ -183,6 +184,7 @@ JsConfuser.debugTransformations = debugTransformations;
183
184
  JsConfuser.debugObfuscation = debugObfuscation;
184
185
  JsConfuser.Obfuscator = Obfuscator;
185
186
  JsConfuser.Transform = Transform;
187
+ JsConfuser.Template = Template;
186
188
 
187
189
  if (typeof window !== "undefined") {
188
190
  window["JsConfuser"] = JsConfuser;
@@ -193,4 +195,4 @@ if (typeof global !== "undefined") {
193
195
 
194
196
  export default JsConfuser;
195
197
 
196
- export { presets, Obfuscator, Transform };
198
+ export { presets, Obfuscator, Transform, Template };