Obfuscator.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import * as estraverse from 'estraverse';
  2. import { ICustomNode } from './interfaces/ICustomNode';
  3. import { INodeObfuscator } from './interfaces/INodeObfuscator';
  4. import { INodesGroup } from './interfaces/INodesGroup';
  5. import { INode } from './interfaces/nodes/INode';
  6. import { AppendState } from './enums/AppendState';
  7. import { NodeType } from './enums/NodeType';
  8. import { CatchClauseObfuscator } from './node-obfuscators/CatchClauseObfuscator';
  9. import { ConsoleOutputDisableExpressionNode } from './custom-nodes/console-output-nodes/ConsoleOutputDisableExpressionNode';
  10. import { DebugProtectionNodesGroup } from './node-groups/DebugProtectionNodesGroup';
  11. import { FunctionDeclarationObfuscator } from './node-obfuscators/FunctionDeclarationObfuscator';
  12. import { FunctionObfuscator } from './node-obfuscators/FunctionObfuscator';
  13. import { LiteralObfuscator } from './node-obfuscators/LiteralObfuscator';
  14. import { MemberExpressionObfuscator } from './node-obfuscators/MemberExpressionObfuscator';
  15. import { MethodDefinitionObfuscator } from './node-obfuscators/MethodDefinitionObfuscator';
  16. import { ObjectExpressionObfuscator } from './node-obfuscators/ObjectExpressionObfuscator';
  17. import { UnicodeArrayNode } from './custom-nodes/unicode-array-nodes/UnicodeArrayNode';
  18. import { UnicodeArrayNodesGroup } from './node-groups/UnicodeArrayNodesGroup';
  19. import { Utils } from './Utils';
  20. import { VariableDeclarationObfuscator } from './node-obfuscators/VariableDeclarationObfuscator';
  21. export class Obfuscator {
  22. /**
  23. * @type {Map<string, Node>}
  24. */
  25. private nodes: Map <string, ICustomNode> = new Map <string, ICustomNode> ();
  26. /**
  27. * @type {Map<string, Function[]>}
  28. */
  29. private nodeObfuscators: Map <string, Function[]> = new Map <string, Function[]> ([
  30. [NodeType.ArrowFunctionExpression, [FunctionObfuscator]],
  31. [NodeType.ClassDeclaration, [FunctionDeclarationObfuscator]],
  32. [NodeType.CatchClause, [CatchClauseObfuscator]],
  33. [NodeType.FunctionDeclaration, [
  34. FunctionDeclarationObfuscator,
  35. FunctionObfuscator
  36. ]],
  37. [NodeType.FunctionExpression, [FunctionObfuscator]],
  38. [NodeType.MemberExpression, [MemberExpressionObfuscator]],
  39. [NodeType.MethodDefinition, [MethodDefinitionObfuscator]],
  40. [NodeType.ObjectExpression, [ObjectExpressionObfuscator]],
  41. [NodeType.VariableDeclaration, [VariableDeclarationObfuscator]],
  42. [NodeType.Literal, [LiteralObfuscator]]
  43. ]);
  44. /**
  45. * @type any
  46. */
  47. private options: any;
  48. /**
  49. * @param options
  50. */
  51. constructor (options: any = {}) {
  52. this.options = options;
  53. }
  54. /**
  55. * @param node
  56. */
  57. public obfuscateNode (node: INode): void {
  58. this.setNewNodes();
  59. this.beforeObfuscation(node);
  60. estraverse.replace(node, {
  61. enter: (node: INode, parent: INode): any => this.nodeControllerFirstPass(node, parent)
  62. });
  63. estraverse.replace(node, {
  64. leave: (node: INode, parent: INode): any => this.nodeControllerSecondPass(node, parent)
  65. });
  66. this.afterObfuscation(node);
  67. }
  68. /**
  69. * @param nodeName
  70. * @param node
  71. */
  72. public setNode (nodeName: string, node: ICustomNode): void {
  73. this.nodes.set(nodeName, node);
  74. }
  75. /**
  76. * @param nodesGroup
  77. */
  78. public setNodesGroup (nodesGroup: INodesGroup): void {
  79. let nodes: Map <string, ICustomNode> = nodesGroup.getNodes();
  80. nodes.forEach((node: ICustomNode, key: string) => {
  81. this.nodes.set(key, node);
  82. });
  83. }
  84. /**
  85. * @param astTree
  86. */
  87. private afterObfuscation (astTree: INode): void {
  88. this.nodes.forEach((node: ICustomNode) => {
  89. if (node.getAppendState() === AppendState.AfterObfuscation) {
  90. node.appendNode(astTree);
  91. }
  92. });
  93. }
  94. /**
  95. * @param astTree
  96. */
  97. private beforeObfuscation (astTree: INode): void {
  98. this.nodes.forEach((node: ICustomNode) => {
  99. if (node.getAppendState() === AppendState.BeforeObfuscation) {
  100. node.appendNode(astTree);
  101. }
  102. });
  103. };
  104. private setNewNodes (): void {
  105. if (this.options['disableConsoleOutput']) {
  106. this.setNode(
  107. 'consoleOutputDisableExpressionNode',
  108. new ConsoleOutputDisableExpressionNode()
  109. );
  110. }
  111. if (this.options['debugProtection']) {
  112. this.setNodesGroup(new DebugProtectionNodesGroup(this.options));
  113. }
  114. /**
  115. * Important to set this nodes latest to prevent runtime errors cause by `rotateUnicodeArray` option
  116. */
  117. if (this.options['rotateUnicodeArray']) {
  118. this.setNodesGroup(new UnicodeArrayNodesGroup());
  119. } else {
  120. this.setNode(
  121. 'unicodeArrayNode',
  122. new UnicodeArrayNode(Utils.getRandomVariableName(UnicodeArrayNode.UNICODE_ARRAY_RANDOM_LENGTH))
  123. );
  124. }
  125. }
  126. /**
  127. * @param node
  128. * @param parent
  129. */
  130. private nodeControllerFirstPass (node: INode, parent: INode): void {
  131. Object.defineProperty(node, 'parentNode', {
  132. configurable: true,
  133. enumerable: true,
  134. value: parent || node,
  135. writable: true
  136. });
  137. }
  138. /**
  139. * @param node
  140. * @param parent
  141. */
  142. private nodeControllerSecondPass (node: INode, parent: INode): void {
  143. switch (node.type) {
  144. default:
  145. this.initializeNodeObfuscators(node, parent);
  146. }
  147. }
  148. /**
  149. * @param node
  150. * @param parent
  151. */
  152. private initializeNodeObfuscators (node: INode, parent: INode): void {
  153. if (!this.nodeObfuscators.has(node.type)) {
  154. return;
  155. }
  156. this.nodeObfuscators.get(node.type).forEach((obfuscator: Function) => {
  157. new (<INodeObfuscator> obfuscator(this.nodes)).obfuscateNode(node, parent);
  158. });
  159. }
  160. }