js-confuser 1.7.3 → 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.
Files changed (269) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +6 -4
  2. package/CHANGELOG.md +70 -0
  3. package/Migration.md +57 -0
  4. package/README.md +23 -929
  5. package/dist/constants.js +65 -14
  6. package/dist/index.js +108 -160
  7. package/dist/obfuscator.js +316 -118
  8. package/dist/options.js +1 -119
  9. package/dist/order.js +30 -30
  10. package/dist/presets.js +47 -45
  11. package/dist/probability.js +25 -32
  12. package/dist/templates/bufferToStringTemplate.js +9 -0
  13. package/dist/templates/deadCodeTemplates.js +9 -0
  14. package/dist/templates/getGlobalTemplate.js +19 -0
  15. package/dist/templates/integrityTemplate.js +30 -0
  16. package/dist/templates/setFunctionLengthTemplate.js +9 -0
  17. package/dist/templates/stringCompressionTemplate.js +10 -0
  18. package/dist/templates/tamperProtectionTemplates.js +21 -0
  19. package/dist/templates/template.js +199 -184
  20. package/dist/transforms/astScrambler.js +100 -0
  21. package/dist/transforms/calculator.js +70 -127
  22. package/dist/transforms/controlFlowFlattening.js +1182 -0
  23. package/dist/transforms/deadCode.js +62 -587
  24. package/dist/transforms/dispatcher.js +300 -313
  25. package/dist/transforms/extraction/duplicateLiteralsRemoval.js +88 -189
  26. package/dist/transforms/extraction/objectExtraction.js +131 -215
  27. package/dist/transforms/finalizer.js +56 -59
  28. package/dist/transforms/flatten.js +275 -276
  29. package/dist/transforms/functionOutlining.js +230 -0
  30. package/dist/transforms/identifier/globalConcealing.js +214 -135
  31. package/dist/transforms/identifier/movedDeclarations.js +167 -91
  32. package/dist/transforms/identifier/renameVariables.js +239 -193
  33. package/dist/transforms/lock/integrity.js +61 -184
  34. package/dist/transforms/lock/lock.js +261 -387
  35. package/dist/transforms/minify.js +431 -436
  36. package/dist/transforms/opaquePredicates.js +65 -118
  37. package/dist/transforms/pack.js +160 -0
  38. package/dist/transforms/plugin.js +179 -0
  39. package/dist/transforms/preparation.js +261 -173
  40. package/dist/transforms/renameLabels.js +132 -56
  41. package/dist/transforms/rgf.js +140 -267
  42. package/dist/transforms/shuffle.js +52 -145
  43. package/dist/transforms/string/encoding.js +44 -175
  44. package/dist/transforms/string/stringCompression.js +79 -155
  45. package/dist/transforms/string/stringConcealing.js +189 -225
  46. package/dist/transforms/string/stringEncoding.js +32 -40
  47. package/dist/transforms/string/stringSplitting.js +54 -55
  48. package/dist/transforms/variableMasking.js +232 -0
  49. package/dist/utils/ControlObject.js +125 -0
  50. package/dist/utils/IntGen.js +46 -0
  51. package/dist/utils/NameGen.js +106 -0
  52. package/dist/utils/ast-utils.js +560 -0
  53. package/dist/utils/function-utils.js +56 -0
  54. package/dist/utils/gen-utils.js +48 -0
  55. package/dist/utils/node.js +77 -0
  56. package/dist/utils/object-utils.js +21 -0
  57. package/dist/utils/random-utils.js +91 -0
  58. package/dist/utils/static-utils.js +64 -0
  59. package/dist/validateOptions.js +122 -0
  60. package/index.d.ts +1 -17
  61. package/package.json +27 -22
  62. package/src/constants.ts +139 -82
  63. package/src/index.ts +70 -165
  64. package/src/obfuscationResult.ts +43 -0
  65. package/src/obfuscator.ts +328 -135
  66. package/src/options.ts +149 -658
  67. package/src/order.ts +14 -14
  68. package/src/presets.ts +39 -34
  69. package/src/probability.ts +21 -36
  70. package/src/templates/bufferToStringTemplate.ts +57 -0
  71. package/src/templates/deadCodeTemplates.ts +1185 -0
  72. package/src/templates/getGlobalTemplate.ts +72 -0
  73. package/src/templates/integrityTemplate.ts +69 -0
  74. package/src/templates/setFunctionLengthTemplate.ts +11 -0
  75. package/src/templates/stringCompressionTemplate.ts +42 -0
  76. package/src/templates/tamperProtectionTemplates.ts +116 -0
  77. package/src/templates/template.ts +149 -157
  78. package/src/transforms/astScrambler.ts +99 -0
  79. package/src/transforms/calculator.ts +96 -226
  80. package/src/transforms/controlFlowFlattening.ts +1594 -0
  81. package/src/transforms/deadCode.ts +85 -676
  82. package/src/transforms/dispatcher.ts +431 -640
  83. package/src/transforms/extraction/duplicateLiteralsRemoval.ts +147 -295
  84. package/src/transforms/extraction/objectExtraction.ts +160 -333
  85. package/src/transforms/finalizer.ts +63 -64
  86. package/src/transforms/flatten.ts +439 -557
  87. package/src/transforms/functionOutlining.ts +225 -0
  88. package/src/transforms/identifier/globalConcealing.ts +255 -266
  89. package/src/transforms/identifier/movedDeclarations.ts +228 -142
  90. package/src/transforms/identifier/renameVariables.ts +250 -271
  91. package/src/transforms/lock/integrity.ts +85 -263
  92. package/src/transforms/lock/lock.ts +338 -579
  93. package/src/transforms/minify.ts +523 -663
  94. package/src/transforms/opaquePredicates.ts +90 -229
  95. package/src/transforms/pack.ts +195 -0
  96. package/src/transforms/plugin.ts +185 -0
  97. package/src/transforms/preparation.ts +337 -231
  98. package/src/transforms/renameLabels.ts +176 -77
  99. package/src/transforms/rgf.ts +293 -424
  100. package/src/transforms/shuffle.ts +80 -254
  101. package/src/transforms/string/encoding.ts +20 -126
  102. package/src/transforms/string/stringCompression.ts +117 -307
  103. package/src/transforms/string/stringConcealing.ts +254 -342
  104. package/src/transforms/string/stringEncoding.ts +28 -47
  105. package/src/transforms/string/stringSplitting.ts +61 -75
  106. package/src/transforms/variableMasking.ts +257 -0
  107. package/src/utils/ControlObject.ts +141 -0
  108. package/src/utils/IntGen.ts +33 -0
  109. package/src/utils/NameGen.ts +106 -0
  110. package/src/utils/ast-utils.ts +667 -0
  111. package/src/utils/function-utils.ts +50 -0
  112. package/src/utils/gen-utils.ts +48 -0
  113. package/src/utils/node.ts +78 -0
  114. package/src/utils/object-utils.ts +21 -0
  115. package/src/utils/random-utils.ts +79 -0
  116. package/src/utils/static-utils.ts +66 -0
  117. package/src/validateOptions.ts +256 -0
  118. package/tsconfig.json +13 -8
  119. package/babel.config.js +0 -12
  120. package/dev.js +0 -8
  121. package/dist/compiler.js +0 -34
  122. package/dist/parser.js +0 -59
  123. package/dist/precedence.js +0 -66
  124. package/dist/templates/bufferToString.js +0 -129
  125. package/dist/templates/core.js +0 -35
  126. package/dist/templates/crash.js +0 -28
  127. package/dist/templates/es5.js +0 -137
  128. package/dist/templates/functionLength.js +0 -34
  129. package/dist/templates/globals.js +0 -9
  130. package/dist/transforms/antiTooling.js +0 -88
  131. package/dist/transforms/controlFlowFlattening/controlFlowFlattening.js +0 -1287
  132. package/dist/transforms/controlFlowFlattening/expressionObfuscation.js +0 -131
  133. package/dist/transforms/es5/antiClass.js +0 -164
  134. package/dist/transforms/es5/antiDestructuring.js +0 -193
  135. package/dist/transforms/es5/antiES6Object.js +0 -185
  136. package/dist/transforms/es5/antiSpreadOperator.js +0 -35
  137. package/dist/transforms/es5/antiTemplate.js +0 -66
  138. package/dist/transforms/es5/es5.js +0 -123
  139. package/dist/transforms/extraction/classExtraction.js +0 -83
  140. package/dist/transforms/identifier/globalAnalysis.js +0 -83
  141. package/dist/transforms/identifier/variableAnalysis.js +0 -104
  142. package/dist/transforms/lock/antiDebug.js +0 -76
  143. package/dist/transforms/stack.js +0 -349
  144. package/dist/transforms/transform.js +0 -372
  145. package/dist/traverse.js +0 -110
  146. package/dist/util/compare.js +0 -145
  147. package/dist/util/gen.js +0 -564
  148. package/dist/util/guard.js +0 -14
  149. package/dist/util/identifiers.js +0 -355
  150. package/dist/util/insert.js +0 -362
  151. package/dist/util/math.js +0 -19
  152. package/dist/util/object.js +0 -40
  153. package/dist/util/random.js +0 -156
  154. package/dist/util/scope.js +0 -20
  155. package/docs/ControlFlowFlattening.md +0 -595
  156. package/docs/Countermeasures.md +0 -70
  157. package/docs/ES5.md +0 -197
  158. package/docs/Integrity.md +0 -82
  159. package/docs/RGF.md +0 -424
  160. package/docs/RenameVariables.md +0 -116
  161. package/docs/TamperProtection.md +0 -100
  162. package/docs/Template.md +0 -117
  163. package/samples/example.js +0 -15
  164. package/samples/high.js +0 -1
  165. package/samples/input.js +0 -3
  166. package/samples/javascriptobfuscator.com.js +0 -8
  167. package/samples/jscrambler_advanced.js +0 -1894
  168. package/samples/jscrambler_light.js +0 -1134
  169. package/samples/low.js +0 -1
  170. package/samples/medium.js +0 -1
  171. package/samples/obfuscator.io.js +0 -1686
  172. package/samples/preemptive.com.js +0 -16
  173. package/src/compiler.ts +0 -35
  174. package/src/parser.ts +0 -49
  175. package/src/precedence.ts +0 -61
  176. package/src/templates/bufferToString.ts +0 -136
  177. package/src/templates/core.ts +0 -29
  178. package/src/templates/crash.ts +0 -23
  179. package/src/templates/es5.ts +0 -131
  180. package/src/templates/functionLength.ts +0 -32
  181. package/src/templates/globals.ts +0 -3
  182. package/src/transforms/antiTooling.ts +0 -102
  183. package/src/transforms/controlFlowFlattening/controlFlowFlattening.ts +0 -2153
  184. package/src/transforms/controlFlowFlattening/expressionObfuscation.ts +0 -179
  185. package/src/transforms/es5/antiClass.ts +0 -276
  186. package/src/transforms/es5/antiDestructuring.ts +0 -294
  187. package/src/transforms/es5/antiES6Object.ts +0 -267
  188. package/src/transforms/es5/antiSpreadOperator.ts +0 -56
  189. package/src/transforms/es5/antiTemplate.ts +0 -98
  190. package/src/transforms/es5/es5.ts +0 -149
  191. package/src/transforms/extraction/classExtraction.ts +0 -168
  192. package/src/transforms/identifier/globalAnalysis.ts +0 -102
  193. package/src/transforms/identifier/variableAnalysis.ts +0 -118
  194. package/src/transforms/lock/antiDebug.ts +0 -112
  195. package/src/transforms/stack.ts +0 -557
  196. package/src/transforms/transform.ts +0 -441
  197. package/src/traverse.ts +0 -120
  198. package/src/types.ts +0 -133
  199. package/src/util/compare.ts +0 -181
  200. package/src/util/gen.ts +0 -651
  201. package/src/util/guard.ts +0 -17
  202. package/src/util/identifiers.ts +0 -494
  203. package/src/util/insert.ts +0 -419
  204. package/src/util/math.ts +0 -15
  205. package/src/util/object.ts +0 -39
  206. package/src/util/random.ts +0 -221
  207. package/src/util/scope.ts +0 -21
  208. package/test/code/Cash.src.js +0 -1011
  209. package/test/code/Cash.test.ts +0 -132
  210. package/test/code/Dynamic.src.js +0 -118
  211. package/test/code/Dynamic.test.ts +0 -49
  212. package/test/code/ES6.src.js +0 -235
  213. package/test/code/ES6.test.ts +0 -42
  214. package/test/code/NewFeatures.test.ts +0 -19
  215. package/test/code/StrictMode.src.js +0 -65
  216. package/test/code/StrictMode.test.js +0 -37
  217. package/test/compare.test.ts +0 -104
  218. package/test/index.test.ts +0 -249
  219. package/test/options.test.ts +0 -150
  220. package/test/presets.test.ts +0 -22
  221. package/test/probability.test.ts +0 -44
  222. package/test/templates/template.test.ts +0 -224
  223. package/test/transforms/antiTooling.test.ts +0 -52
  224. package/test/transforms/calculator.test.ts +0 -78
  225. package/test/transforms/controlFlowFlattening/controlFlowFlattening.test.ts +0 -1274
  226. package/test/transforms/controlFlowFlattening/expressionObfuscation.test.ts +0 -192
  227. package/test/transforms/deadCode.test.ts +0 -85
  228. package/test/transforms/dispatcher.test.ts +0 -457
  229. package/test/transforms/es5/antiClass.test.ts +0 -427
  230. package/test/transforms/es5/antiDestructuring.test.ts +0 -157
  231. package/test/transforms/es5/antiES6Object.test.ts +0 -245
  232. package/test/transforms/es5/antiTemplate.test.ts +0 -116
  233. package/test/transforms/es5/es5.test.ts +0 -110
  234. package/test/transforms/extraction/classExtraction.test.ts +0 -86
  235. package/test/transforms/extraction/duplicateLiteralsRemoval.test.ts +0 -200
  236. package/test/transforms/extraction/objectExtraction.test.ts +0 -491
  237. package/test/transforms/flatten.test.ts +0 -721
  238. package/test/transforms/hexadecimalNumbers.test.ts +0 -62
  239. package/test/transforms/identifier/globalConcealing.test.ts +0 -142
  240. package/test/transforms/identifier/movedDeclarations.test.ts +0 -275
  241. package/test/transforms/identifier/renameVariables.test.ts +0 -695
  242. package/test/transforms/lock/antiDebug.test.ts +0 -66
  243. package/test/transforms/lock/browserLock.test.ts +0 -129
  244. package/test/transforms/lock/countermeasures.test.ts +0 -100
  245. package/test/transforms/lock/integrity.test.ts +0 -161
  246. package/test/transforms/lock/lock.test.ts +0 -204
  247. package/test/transforms/lock/osLock.test.ts +0 -312
  248. package/test/transforms/lock/selfDefending.test.ts +0 -68
  249. package/test/transforms/lock/tamperProtection.test.ts +0 -336
  250. package/test/transforms/minify.test.ts +0 -575
  251. package/test/transforms/opaquePredicates.test.ts +0 -43
  252. package/test/transforms/preparation.test.ts +0 -157
  253. package/test/transforms/renameLabels.test.ts +0 -95
  254. package/test/transforms/rgf.test.ts +0 -378
  255. package/test/transforms/shuffle.test.ts +0 -135
  256. package/test/transforms/stack.test.ts +0 -573
  257. package/test/transforms/string/stringCompression.test.ts +0 -120
  258. package/test/transforms/string/stringConcealing.test.ts +0 -299
  259. package/test/transforms/string/stringEncoding.test.ts +0 -95
  260. package/test/transforms/string/stringSplitting.test.ts +0 -135
  261. package/test/transforms/transform.test.ts +0 -66
  262. package/test/traverse.test.ts +0 -139
  263. package/test/util/compare.test.ts +0 -34
  264. package/test/util/gen.test.ts +0 -121
  265. package/test/util/identifiers.test.ts +0 -253
  266. package/test/util/insert.test.ts +0 -142
  267. package/test/util/math.test.ts +0 -5
  268. package/test/util/random.test.ts +0 -71
  269. /package/dist/{types.js → obfuscationResult.js} +0 -0
@@ -1,297 +1,286 @@
1
+ import * as t from "@babel/types";
2
+ import { NodePath } from "@babel/core";
3
+ import { NameGen } from "../../utils/NameGen";
1
4
  import Template from "../../templates/template";
2
- import Transform from "../transform";
3
- import { ObfuscateOrder } from "../../order";
5
+ import { PluginArg, PluginObject } from "../plugin";
6
+ import { Order } from "../../order";
7
+ import { computeProbabilityMap } from "../../probability";
4
8
  import {
5
- Node,
6
- Location,
7
- CallExpression,
8
- Identifier,
9
- Literal,
10
- FunctionDeclaration,
11
- ReturnStatement,
12
- MemberExpression,
13
- SwitchStatement,
14
- SwitchCase,
15
- LogicalExpression,
16
- VariableDeclarator,
17
- FunctionExpression,
18
- ExpressionStatement,
19
- AssignmentExpression,
20
- VariableDeclaration,
21
- BreakStatement,
22
- } from "../../util/gen";
23
- import { append, prepend } from "../../util/insert";
24
- import { chance, getRandomInteger } from "../../util/random";
25
- import {
26
- predictableFunctionTag,
9
+ MULTI_TRANSFORM,
27
10
  reservedIdentifiers,
28
11
  variableFunctionName,
29
12
  } from "../../constants";
30
- import { ComputeProbabilityMap } from "../../probability";
31
- import GlobalAnalysis from "./globalAnalysis";
32
- import { createGetGlobalTemplate } from "../../templates/bufferToString";
33
- import { isJSConfuserVar } from "../../util/guard";
34
-
35
- /**
36
- * Global Concealing hides global variables being accessed.
37
- *
38
- * - Any variable that is not defined is considered "global"
39
- */
40
- export default class GlobalConcealing extends Transform {
41
- globalAnalysis: GlobalAnalysis;
42
- ignoreGlobals = new Set([
43
- "require",
44
- "__dirname",
45
- "eval",
46
- variableFunctionName,
47
- ]);
48
-
49
- constructor(o) {
50
- super(o, ObfuscateOrder.GlobalConcealing);
51
-
52
- this.globalAnalysis = new GlobalAnalysis(o);
53
- this.before.push(this.globalAnalysis);
54
- }
55
-
56
- match(object: Node, parents: Node[]) {
57
- return object.type == "Program";
58
- }
59
-
60
- transform(object: Node, parents: Node[]) {
61
- return () => {
62
- var globals: { [name: string]: Location[] } = this.globalAnalysis.globals;
63
- this.globalAnalysis.notGlobals.forEach((del) => {
64
- delete globals[del];
13
+ import {
14
+ getMemberExpressionPropertyAsString,
15
+ isVariableIdentifier,
16
+ prepend,
17
+ } from "../../utils/ast-utils";
18
+ import { createGetGlobalTemplate } from "../../templates/getGlobalTemplate";
19
+ import { getRandomInteger, getRandomString } from "../../utils/random-utils";
20
+ import { ok } from "assert";
21
+
22
+ const ignoreGlobals = new Set([
23
+ "require",
24
+ "__dirname",
25
+ "eval",
26
+ "arguments",
27
+ variableFunctionName,
28
+ ...reservedIdentifiers,
29
+ ]);
30
+
31
+ export default ({ Plugin }: PluginArg): PluginObject => {
32
+ const me = Plugin(Order.GlobalConcealing, {
33
+ changeData: {
34
+ globals: 0,
35
+ nativeFunctions: 0,
36
+ },
37
+ });
38
+
39
+ var globalMapping = new Map<string, string>(),
40
+ globalFnName = me.getPlaceholder() + "_getGlobal",
41
+ globalVarName = me.getPlaceholder() + "_globalVar",
42
+ gen = new NameGen();
43
+
44
+ // Create the getGlobal function using a template
45
+ function createGlobalConcealingFunction(): t.FunctionDeclaration {
46
+ // Create fake global mappings
47
+
48
+ var fakeCount = getRandomInteger(20, 40);
49
+ for (var i = 0; i < fakeCount; i++) {
50
+ var fakeName = getRandomString(getRandomInteger(6, 8));
51
+ globalMapping.set(gen.generate(), fakeName);
52
+ }
53
+
54
+ const createSwitchStatement = () => {
55
+ const cases = Array.from(globalMapping.keys()).map((originalName) => {
56
+ var mappedKey = globalMapping.get(originalName);
57
+
58
+ return t.switchCase(t.stringLiteral(mappedKey), [
59
+ t.returnStatement(
60
+ t.memberExpression(
61
+ t.identifier(globalVarName),
62
+ t.stringLiteral(originalName),
63
+ true
64
+ )
65
+ ),
66
+ ]);
65
67
  });
66
68
 
67
- for (var varName of this.ignoreGlobals) {
68
- delete globals[varName];
69
- }
69
+ return t.switchStatement(t.identifier("mapping"), cases);
70
+ };
70
71
 
71
- reservedIdentifiers.forEach((x) => {
72
- delete globals[x];
73
- });
72
+ return t.functionDeclaration(
73
+ t.identifier(globalFnName),
74
+ [t.identifier("mapping")],
75
+ t.blockStatement([createSwitchStatement()])
76
+ );
77
+ }
74
78
 
75
- Object.keys(globals).forEach((x) => {
76
- if (this.globalAnalysis.globals[x].length < 1) {
77
- delete globals[x];
78
- } else if (
79
- !ComputeProbabilityMap(this.options.globalConcealing, (x) => x, x)
80
- ) {
81
- delete globals[x];
82
- }
83
- });
79
+ return {
80
+ visitor: {
81
+ Program: {
82
+ exit(programPath: NodePath<t.Program>) {
83
+ var illegalGlobals = new Set<string>();
84
+ var pendingReplacements = new Map<string, NodePath[]>();
84
85
 
85
- if (Object.keys(globals).length > 0) {
86
- var usedStates = new Set<number>();
86
+ programPath.traverse({
87
+ Identifier(identifierPath) {
88
+ if (!isVariableIdentifier(identifierPath)) return;
87
89
 
88
- // Make getter function
90
+ var identifierName = identifierPath.node.name;
89
91
 
90
- // holds "window" or "global"
91
- var globalVar = this.getPlaceholder();
92
+ if (ignoreGlobals.has(identifierName)) return;
92
93
 
93
- var getGlobalVariableFnName =
94
- this.getPlaceholder() + predictableFunctionTag;
94
+ const binding = identifierPath.scope.getBinding(identifierName);
95
+ if (binding) {
96
+ illegalGlobals.add(identifierName);
97
+ return;
98
+ }
95
99
 
96
- // Returns global variable or fall backs to `this`
97
- var getGlobalVariableFn = createGetGlobalTemplate(
98
- this,
99
- object,
100
- parents
101
- ).compile({
102
- getGlobalFnName: getGlobalVariableFnName,
103
- });
100
+ if (!identifierPath.scope.hasGlobal(identifierName)) {
101
+ return;
102
+ }
104
103
 
105
- // 2. Replace old accessors
106
- var globalFn = this.getPlaceholder() + predictableFunctionTag;
104
+ var assignmentChild = identifierPath.find((p) =>
105
+ p.parentPath?.isAssignmentExpression()
106
+ );
107
+ if (
108
+ assignmentChild &&
109
+ t.isAssignmentExpression(assignmentChild.parent) &&
110
+ assignmentChild.parent.left === assignmentChild.node &&
111
+ !t.isMemberExpression(identifierPath.parent)
112
+ ) {
113
+ illegalGlobals.add(identifierName);
114
+ return;
115
+ }
107
116
 
108
- var newNames: { [globalVarName: string]: number } = Object.create(null);
117
+ if (!pendingReplacements.has(identifierName)) {
118
+ pendingReplacements.set(identifierName, [identifierPath]);
119
+ } else {
120
+ pendingReplacements.get(identifierName).push(identifierPath);
121
+ }
122
+ },
123
+ });
109
124
 
110
- Object.keys(globals).forEach((name) => {
111
- var locations: Location[] = globals[name];
112
- var state: number;
113
- do {
114
- state = getRandomInteger(-1000, 1000 + usedStates.size);
115
- } while (usedStates.has(state));
116
- usedStates.add(state);
125
+ // Remove illegal globals
126
+ illegalGlobals.forEach((globalName) => {
127
+ pendingReplacements.delete(globalName);
128
+ });
117
129
 
118
- newNames[name] = state;
130
+ for (var [globalName, paths] of pendingReplacements) {
131
+ var mapping = globalMapping.get(globalName);
132
+ if (!mapping) {
133
+ // Allow user to disable custom global variables
134
+ if (
135
+ !computeProbabilityMap(me.options.globalConcealing, globalName)
136
+ )
137
+ continue;
119
138
 
120
- locations.forEach(([node, p]) => {
121
- if (p.find((x) => x.$multiTransformSkip)) {
122
- return;
139
+ mapping = gen.generate();
140
+ globalMapping.set(globalName, mapping);
123
141
  }
124
142
 
125
- var newExpression = CallExpression(Identifier(globalFn), [
126
- Literal(state),
127
- ]);
128
-
129
- this.replace(node, newExpression);
130
-
131
- if (
132
- this.options.lock?.tamperProtection &&
133
- this.lockTransform.nativeFunctionName
134
- ) {
135
- var isMemberExpression = false;
136
- var nameAndPropertyPath = [name];
137
- var callExpression: Node;
138
-
139
- var index = 0;
140
- do {
141
- if (p[index].type === "CallExpression") {
142
- callExpression = p[index];
143
- break;
144
- }
143
+ // Replace global reference with getGlobal("name")
144
+ const callExpression = t.callExpression(
145
+ t.identifier(globalFnName),
146
+ [t.stringLiteral(mapping)]
147
+ );
145
148
 
146
- var memberExpression = p[index];
147
- if (memberExpression.type !== "MemberExpression") return;
148
- var property = memberExpression.property;
149
- var stringValue =
150
- property.type === "Literal"
151
- ? property.value
152
- : memberExpression.computed
153
- ? null
154
- : property.type === "Identifier"
155
- ? property.name
156
- : null;
157
-
158
- if (!stringValue) return;
159
-
160
- isMemberExpression = true;
161
- nameAndPropertyPath.push(stringValue);
162
- index++;
163
- } while (index < p.length);
149
+ const { nativeFunctionName } = me.globalState.internals;
164
150
 
165
- if (
166
- !this.lockTransform.shouldTransformNativeFunction(
167
- nameAndPropertyPath
168
- )
169
- )
170
- return;
151
+ for (let path of paths) {
152
+ const replaceExpression = t.cloneNode(callExpression);
153
+ me.skip(replaceExpression);
171
154
 
172
- if (callExpression && callExpression.type === "CallExpression") {
173
- if (isMemberExpression) {
174
- callExpression.callee = CallExpression(
175
- Identifier(this.lockTransform.nativeFunctionName),
176
- [
177
- callExpression.callee.object,
178
- callExpression.callee.computed
179
- ? callExpression.callee.property
180
- : Literal(
181
- callExpression.callee.property.name ||
182
- callExpression.callee.property.value
183
- ),
184
- ]
185
- );
186
- } else {
187
- callExpression.callee = CallExpression(
188
- Identifier(this.lockTransform.nativeFunctionName),
189
- [{ ...callExpression.callee }]
190
- );
155
+ if (
156
+ // Native Function will only be populated if tamper protection is enabled
157
+ nativeFunctionName &&
158
+ // Avoid maximum call stack error
159
+ !path.find((p) => p.node[MULTI_TRANSFORM] || me.isSkipped(p))
160
+ ) {
161
+ // First extract the member expression chain
162
+ let nameAndPropertyPath = [globalName];
163
+ let cursorPath = path;
164
+ let callExpressionPath: NodePath<t.CallExpression> | null =
165
+ null;
166
+
167
+ const checkForCallExpression = () => {
168
+ if (
169
+ cursorPath.parentPath?.isCallExpression() &&
170
+ cursorPath.key === "callee"
171
+ ) {
172
+ callExpressionPath = cursorPath.parentPath;
173
+ return true;
174
+ }
175
+ };
176
+
177
+ if (!checkForCallExpression()) {
178
+ cursorPath = cursorPath?.parentPath;
179
+ while (cursorPath?.isMemberExpression()) {
180
+ let propertyString = getMemberExpressionPropertyAsString(
181
+ cursorPath.node
182
+ );
183
+ if (!propertyString || typeof propertyString !== "string") {
184
+ break;
185
+ }
186
+
187
+ nameAndPropertyPath.push(propertyString);
188
+
189
+ if (checkForCallExpression()) break;
190
+ cursorPath = cursorPath.parentPath;
191
+ }
191
192
  }
192
- }
193
- }
194
- });
195
- });
196
-
197
- // Adds all global variables to the switch statement
198
- this.options.globalVariables.forEach((name) => {
199
- if (!newNames[name]) {
200
- var state;
201
- do {
202
- state = getRandomInteger(
203
- 0,
204
- 1000 + usedStates.size + this.options.globalVariables.size * 100
205
- );
206
- } while (usedStates.has(state));
207
- usedStates.add(state);
208
193
 
209
- newNames[name] = state;
210
- }
211
- });
212
-
213
- var indexParamName = this.getPlaceholder();
214
- var returnName = this.getPlaceholder();
215
-
216
- var functionDeclaration = FunctionDeclaration(
217
- globalFn,
218
- [Identifier(indexParamName)],
219
- [
220
- VariableDeclaration(VariableDeclarator(returnName)),
221
- SwitchStatement(
222
- Identifier(indexParamName),
223
- Object.keys(newNames).map((name) => {
224
- var code = newNames[name];
225
- var body: Node[] = [
226
- ReturnStatement(
227
- MemberExpression(Identifier(globalVar), Literal(name), true)
228
- ),
229
- ];
230
- if (chance(50)) {
231
- body = [
232
- ExpressionStatement(
233
- AssignmentExpression(
234
- "=",
235
- Identifier(returnName),
236
- LogicalExpression(
237
- "||",
238
- Literal(name),
239
- MemberExpression(
240
- Identifier(globalVar),
241
- Literal(name),
242
- true
194
+ // Eligible member-expression/identifier
195
+ if (callExpressionPath) {
196
+ // Check user's custom implementation
197
+ var shouldTransform =
198
+ me.obfuscator.shouldTransformNativeFunction(
199
+ nameAndPropertyPath
200
+ );
201
+ if (shouldTransform) {
202
+ path.replaceWith(replaceExpression);
203
+
204
+ // console.log("Hello World") ->
205
+ // checkNative(getGlobal("console")["log"])("Hello World")
206
+
207
+ // Parent-most member expression must be wrapped
208
+ // This to preserve proper 'this' binding in member expression invocations
209
+ let callee = callExpressionPath.get(
210
+ "callee"
211
+ ) as NodePath<t.Expression>;
212
+ let callArgs: t.Expression[] = [callee.node];
213
+
214
+ if (callee.isMemberExpression()) {
215
+ const additionalPropertyString =
216
+ getMemberExpressionPropertyAsString(callee.node);
217
+ ok(
218
+ additionalPropertyString,
219
+ "Expected additional property to be a string"
220
+ );
221
+ callee = callee.get("object");
222
+ callArgs = [
223
+ callee.node,
224
+ t.stringLiteral(additionalPropertyString),
225
+ ];
226
+ }
227
+
228
+ // Method supports two signatures:
229
+ // checkNative(fetch)(...)
230
+ // checkNative(console, "log")(...)
231
+
232
+ callExpressionPath
233
+ .get("callee")
234
+ .replaceWith(
235
+ me.skip(
236
+ t.callExpression(
237
+ t.identifier(nativeFunctionName),
238
+ callArgs
243
239
  )
244
240
  )
245
- )
246
- ),
247
- BreakStatement(),
248
- ];
241
+ );
242
+
243
+ me.changeData.nativeFunctions++;
244
+ continue;
245
+ }
249
246
  }
247
+ }
250
248
 
251
- return SwitchCase(Literal(code), body);
252
- })
253
- ),
254
- ReturnStatement(
255
- MemberExpression(
256
- Identifier(globalVar),
257
- Identifier(returnName),
258
- true
259
- )
260
- ),
261
- ]
262
- );
263
-
264
- var tempVar = this.getPlaceholder();
265
-
266
- var variableDeclaration = new Template(`
267
- var ${globalVar};
268
- `).single();
269
-
270
- variableDeclaration.declarations.push(
271
- VariableDeclarator(
272
- tempVar,
273
- CallExpression(
274
- MemberExpression(
275
- FunctionExpression(
276
- [],
277
- [
278
- ...getGlobalVariableFn,
279
- new Template(
280
- `return ${globalVar} = ${getGlobalVariableFnName}["call"](this)`
281
- ).single(),
282
- ]
283
- ),
284
- Literal("call"),
285
- true
286
- ),
287
- []
288
- )
289
- )
290
- );
249
+ me.changeData.globals++;
291
250
 
292
- prepend(object, variableDeclaration);
293
- append(object, functionDeclaration);
294
- }
295
- };
296
- }
297
- }
251
+ // Regular replacement
252
+ // console -> getGlobal("console")
253
+ path.replaceWith(replaceExpression);
254
+ }
255
+ }
256
+
257
+ // No globals changed, no need to insert the getGlobal function
258
+ if (globalMapping.size === 0) return;
259
+
260
+ // The Global Concealing function returns the global variable from the specified parameter
261
+ const globalConcealingFunction = createGlobalConcealingFunction();
262
+
263
+ prepend(programPath, globalConcealingFunction);
264
+
265
+ const getGlobalVarFnName = me.getPlaceholder() + "_getGlobalVarFn";
266
+
267
+ // Insert the get global function
268
+ prepend(
269
+ programPath,
270
+ createGetGlobalTemplate(me, programPath).compile({
271
+ getGlobalFnName: getGlobalVarFnName,
272
+ })
273
+ );
274
+
275
+ // Call the get global function and store result in 'globalVarName'
276
+ prepend(
277
+ programPath,
278
+ new Template(
279
+ `var ${globalVarName} = ${getGlobalVarFnName}()`
280
+ ).single<t.Statement>()
281
+ );
282
+ },
283
+ },
284
+ },
285
+ };
286
+ };