Obfuscator.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import * as estraverse from 'estraverse';
  2. import * as ESTree from 'estree';
  3. import { TNodeGroup } from './types/TNodeGroup';
  4. import { TNodeTransformer } from './types/TNodeTransformer';
  5. import { ICustomNode } from './interfaces/custom-nodes/ICustomNode';
  6. import { IObfuscator } from './interfaces/IObfuscator';
  7. import { IOptions } from './interfaces/IOptions';
  8. import { IStackTraceData } from './interfaces/stack-trace-analyzer/IStackTraceData';
  9. import { AppendState } from './enums/AppendState';
  10. import { NodeType } from './enums/NodeType';
  11. import { CatchClauseObfuscator } from './node-transformers/node-obfuscators/CatchClauseObfuscator';
  12. import { ConsoleOutputNodesGroup } from './node-groups/ConsoleOutputNodesGroup';
  13. import { DebugProtectionNodesGroup } from './node-groups/DebugProtectionNodesGroup';
  14. import { DomainLockNodesGroup } from './node-groups/DomainLockNodesGroup';
  15. import { FunctionDeclarationObfuscator } from './node-transformers/node-obfuscators/FunctionDeclarationObfuscator';
  16. import { FunctionObfuscator } from './node-transformers/node-obfuscators/FunctionObfuscator';
  17. import { LabeledStatementObfuscator } from './node-transformers/node-obfuscators/LabeledStatementObfuscator';
  18. import { LiteralObfuscator } from './node-transformers/node-obfuscators/LiteralObfuscator';
  19. import { MemberExpressionObfuscator } from './node-transformers/node-obfuscators/MemberExpressionObfuscator';
  20. import { MethodDefinitionObfuscator } from './node-transformers/node-obfuscators/MethodDefinitionObfuscator';
  21. import { Node } from './node/Node';
  22. import { NodeUtils } from './node/NodeUtils';
  23. import { ObjectExpressionObfuscator } from './node-transformers/node-obfuscators/ObjectExpressionObfuscator';
  24. import { SelfDefendingNodesGroup } from './node-groups/SelfDefendingNodesGroup';
  25. import { StackTraceAnalyzer } from './stack-trace-analyzer/StackTraceAnalyzer';
  26. import { StringArrayNodesGroup } from './node-groups/StringArrayNodesGroup';
  27. import { VariableDeclarationObfuscator } from './node-transformers/node-obfuscators/VariableDeclarationObfuscator';
  28. import { FunctionControlFlowTransformer } from './node-transformers/node-control-flow-transformers/FunctionControlFlowTransformer';
  29. export class Obfuscator implements IObfuscator {
  30. /**
  31. * @type {Map<string, TNodeTransformer[]>}
  32. */
  33. private static nodeControlFlowChangers: Map <string, TNodeTransformer[]> = new Map <string, TNodeTransformer[]> ([
  34. [NodeType.FunctionDeclaration, [FunctionControlFlowTransformer]],
  35. [NodeType.FunctionExpression, [FunctionControlFlowTransformer]]
  36. ]);
  37. /**
  38. * @type {TNodeGroup[]}
  39. */
  40. private static nodeGroups: TNodeGroup[] = [
  41. DomainLockNodesGroup,
  42. SelfDefendingNodesGroup,
  43. ConsoleOutputNodesGroup,
  44. DebugProtectionNodesGroup,
  45. StringArrayNodesGroup
  46. ];
  47. /**
  48. * @type {Map<string, TNodeTransformer[]>}
  49. */
  50. private static nodeObfuscators: Map <string, TNodeTransformer[]> = new Map <string, TNodeTransformer[]> ([
  51. [NodeType.ArrowFunctionExpression, [FunctionObfuscator]],
  52. [NodeType.ClassDeclaration, [FunctionDeclarationObfuscator]],
  53. [NodeType.CatchClause, [CatchClauseObfuscator]],
  54. [NodeType.FunctionDeclaration, [
  55. FunctionDeclarationObfuscator,
  56. FunctionObfuscator
  57. ]],
  58. [NodeType.FunctionExpression, [FunctionObfuscator]],
  59. [NodeType.MemberExpression, [MemberExpressionObfuscator]],
  60. [NodeType.MethodDefinition, [MethodDefinitionObfuscator]],
  61. [NodeType.ObjectExpression, [ObjectExpressionObfuscator]],
  62. [NodeType.VariableDeclaration, [VariableDeclarationObfuscator]],
  63. [NodeType.LabeledStatement, [LabeledStatementObfuscator]],
  64. [NodeType.Literal, [LiteralObfuscator]]
  65. ]);
  66. /**
  67. * @type {Map<string, AbstractCustomNode>}
  68. */
  69. private customNodes: Map <string, ICustomNode> = new Map <string, ICustomNode> ();
  70. /**
  71. * @type {IOptions}
  72. */
  73. private options: IOptions;
  74. /**
  75. * @param options
  76. */
  77. constructor (options: IOptions) {
  78. this.options = options;
  79. }
  80. /**
  81. * @param node
  82. * @returns {ESTree.Node}
  83. */
  84. public obfuscateNode (node: ESTree.Program): ESTree.Node {
  85. if (Node.isProgramNode(node) && !node.body.length) {
  86. return node;
  87. }
  88. NodeUtils.parentize(node);
  89. const stackTraceData: IStackTraceData[] = new StackTraceAnalyzer(node.body).analyze();
  90. this.initializeCustomNodes(stackTraceData);
  91. this.beforeObfuscation(node);
  92. this.obfuscate(node);
  93. this.afterObfuscation(node);
  94. return node;
  95. }
  96. /**
  97. * @param astTree
  98. */
  99. private afterObfuscation (astTree: ESTree.Node): void {
  100. this.customNodes.forEach((node: ICustomNode) => {
  101. if (node.getAppendState() === AppendState.AfterObfuscation) {
  102. node.appendNode(astTree);
  103. }
  104. });
  105. }
  106. /**
  107. * @param astTree
  108. */
  109. private beforeObfuscation (astTree: ESTree.Node): void {
  110. this.customNodes.forEach((node: ICustomNode) => {
  111. if (node.getAppendState() === AppendState.BeforeObfuscation) {
  112. node.appendNode(astTree);
  113. }
  114. });
  115. };
  116. /**
  117. * @param stackTraceData
  118. */
  119. private initializeCustomNodes (stackTraceData: IStackTraceData[]): void {
  120. let customNodes: [string, ICustomNode][] = [];
  121. Obfuscator.nodeGroups.forEach((nodeGroupConstructor: TNodeGroup) => {
  122. const nodeGroupNodes: Map <string, ICustomNode> | undefined = new nodeGroupConstructor(
  123. stackTraceData, this.options
  124. ).getNodes();
  125. if (!nodeGroupNodes) {
  126. return;
  127. }
  128. customNodes.push(...nodeGroupNodes);
  129. });
  130. this.customNodes = new Map <string, ICustomNode> (customNodes);
  131. }
  132. /**
  133. * @param node
  134. * @param parentNode
  135. */
  136. private initializeNodeControlFlowChangers (node: ESTree.Node, parentNode: ESTree.Node): void {
  137. this.initializeNodeTransformers(node, parentNode, Obfuscator.nodeControlFlowChangers);
  138. }
  139. /**
  140. * @param node
  141. * @param parentNode
  142. */
  143. private initializeNodeObfuscators (node: ESTree.Node, parentNode: ESTree.Node): void {
  144. this.initializeNodeTransformers(node, parentNode, Obfuscator.nodeObfuscators);
  145. }
  146. /**
  147. * @param node
  148. * @param parentNode
  149. * @param nodeTransformersMap
  150. */
  151. private initializeNodeTransformers (
  152. node: ESTree.Node,
  153. parentNode: ESTree.Node,
  154. nodeTransformersMap: Map <string, TNodeTransformer[]>
  155. ): void {
  156. let nodeTransformers: TNodeTransformer[] | undefined = nodeTransformersMap.get(node.type);
  157. if (!nodeTransformers) {
  158. return;
  159. }
  160. nodeTransformers.forEach((transformer: TNodeTransformer) => {
  161. new transformer(this.customNodes, this.options).transformNode(node, parentNode);
  162. });
  163. }
  164. /**
  165. * @param node
  166. */
  167. private obfuscate (node: ESTree.Node): void {
  168. // first pass: control flow flattening
  169. if (this.options.controlFlowFlattening) {
  170. estraverse.traverse(node, {
  171. leave: (node: ESTree.Node, parentNode: ESTree.Node): void => {
  172. this.initializeNodeControlFlowChangers(node, parentNode);
  173. }
  174. });
  175. }
  176. // second pass: nodes obfuscation
  177. estraverse.traverse(node, {
  178. enter: (node: ESTree.Node, parentNode: ESTree.Node): void => {
  179. this.initializeNodeObfuscators(node, parentNode);
  180. }
  181. });
  182. }
  183. }