Obfuscator.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import { injectable, inject } from 'inversify';
  2. import { ServiceIdentifiers } from './container/ServiceIdentifiers';
  3. import * as estraverse from 'estraverse';
  4. import * as ESTree from 'estree';
  5. import { TNodeTransformersFactory } from './types/container/TNodeTransformersFactory';
  6. import { TVisitorDirection } from './types/TVisitorDirection';
  7. import { ICustomNodeGroup } from './interfaces/custom-nodes/ICustomNodeGroup';
  8. import { IObfuscationEventEmitter } from './interfaces/event-emitters/IObfuscationEventEmitter';
  9. import { IObfuscator } from './interfaces/IObfuscator';
  10. import { IOptions } from './interfaces/options/IOptions';
  11. import { INodeTransformer } from './interfaces/node-transformers/INodeTransformer';
  12. import { IStackTraceAnalyzer } from './interfaces/stack-trace-analyzer/IStackTraceAnalyzer';
  13. import { IStackTraceData } from './interfaces/stack-trace-analyzer/IStackTraceData';
  14. import { IStorage } from './interfaces/storages/IStorage';
  15. import { NodeTransformers } from './enums/container/NodeTransformers';
  16. import { NodeType } from './enums/NodeType';
  17. import { ObfuscationEvents } from './enums/ObfuscationEvents';
  18. import { VisitorDirection } from './enums/VisitorDirection';
  19. import { Node } from './node/Node';
  20. import { NodeUtils } from './node/NodeUtils';
  21. @injectable()
  22. export class Obfuscator implements IObfuscator {
  23. /**
  24. * @type {Map<string, NodeTransformers[]>}
  25. */
  26. private static readonly nodeControlFlowTransformersMap: Map <string, NodeTransformers[]> = new Map([
  27. [NodeType.BlockStatement, [NodeTransformers.BlockStatementControlFlowTransformer]],
  28. [NodeType.FunctionDeclaration, [NodeTransformers.FunctionControlFlowTransformer]],
  29. [NodeType.FunctionExpression, [NodeTransformers.FunctionControlFlowTransformer]]
  30. ]);
  31. /**
  32. * @type {Map<string, NodeTransformers[]>}
  33. */
  34. private static readonly nodeObfuscatorsMap: Map <string, NodeTransformers[]> = new Map([
  35. [NodeType.ArrowFunctionExpression, [NodeTransformers.FunctionTransformer]],
  36. [NodeType.ClassDeclaration, [NodeTransformers.FunctionDeclarationTransformer]],
  37. [NodeType.CatchClause, [NodeTransformers.CatchClauseTransformer]],
  38. [NodeType.FunctionDeclaration, [
  39. NodeTransformers.FunctionDeclarationTransformer,
  40. NodeTransformers.FunctionTransformer
  41. ]],
  42. [NodeType.FunctionExpression, [NodeTransformers.FunctionTransformer]],
  43. [NodeType.MemberExpression, [NodeTransformers.MemberExpressionTransformer]],
  44. [NodeType.MethodDefinition, [NodeTransformers.MethodDefinitionTransformer]],
  45. [NodeType.ObjectExpression, [NodeTransformers.ObjectExpressionTransformer]],
  46. [NodeType.VariableDeclaration, [NodeTransformers.VariableDeclarationTransformer]],
  47. [NodeType.LabeledStatement, [NodeTransformers.LabeledStatementTransformer]],
  48. [NodeType.TemplateLiteral, [NodeTransformers.TemplateLiteralTransformer]],
  49. [NodeType.Literal, [NodeTransformers.LiteralTransformer]] // should be latest in the chain of obfuscators
  50. ]);
  51. /**
  52. * @type {IStorage<ICustomNodeGroup>}
  53. */
  54. private readonly customNodeGroupStorage: IStorage<ICustomNodeGroup>;
  55. /**
  56. * @type {TNodeTransformersFactory}
  57. */
  58. private readonly nodeTransformersFactory: TNodeTransformersFactory;
  59. /**
  60. * @type {IObfuscationEventEmitter}
  61. */
  62. private readonly obfuscationEventEmitter: IObfuscationEventEmitter;
  63. /**
  64. * @type {IOptions}
  65. */
  66. private readonly options: IOptions;
  67. /**
  68. * @type {IStackTraceAnalyzer}
  69. */
  70. private readonly stackTraceAnalyzer: IStackTraceAnalyzer;
  71. /**
  72. * @param stackTraceAnalyzer
  73. * @param obfuscationEventEmitter
  74. * @param customNodeGroupStorage
  75. * @param nodeTransformersFactory
  76. * @param options
  77. */
  78. constructor (
  79. @inject(ServiceIdentifiers.IStackTraceAnalyzer) stackTraceAnalyzer: IStackTraceAnalyzer,
  80. @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
  81. @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: IStorage<ICustomNodeGroup>,
  82. @inject(ServiceIdentifiers.Factory__INodeTransformer) nodeTransformersFactory: TNodeTransformersFactory,
  83. @inject(ServiceIdentifiers.IOptions) options: IOptions
  84. ) {
  85. this.stackTraceAnalyzer = stackTraceAnalyzer;
  86. this.obfuscationEventEmitter = obfuscationEventEmitter;
  87. this.customNodeGroupStorage = customNodeGroupStorage;
  88. this.nodeTransformersFactory = nodeTransformersFactory;
  89. this.options = options;
  90. }
  91. /**
  92. * @param astTree
  93. * @returns {ESTree.Program}
  94. */
  95. public obfuscateAstTree (astTree: ESTree.Program): ESTree.Program {
  96. if (Node.isProgramNode(astTree) && !astTree.body.length) {
  97. return astTree;
  98. }
  99. astTree = <ESTree.Program>NodeUtils.parentize(astTree);
  100. const stackTraceData: IStackTraceData[] = this.stackTraceAnalyzer.analyze(astTree.body);
  101. // initialize custom node groups and configure custom nodes
  102. this.customNodeGroupStorage
  103. .getStorage()
  104. .forEach((customNodeGroup: ICustomNodeGroup) => {
  105. customNodeGroup.initialize();
  106. this.obfuscationEventEmitter.once(
  107. customNodeGroup.getAppendEvent(),
  108. customNodeGroup.appendCustomNodes.bind(customNodeGroup)
  109. );
  110. });
  111. this.obfuscationEventEmitter.emit(ObfuscationEvents.BeforeObfuscation, astTree, stackTraceData);
  112. // first pass: control flow flattening
  113. if (this.options.controlFlowFlattening) {
  114. astTree = this.transformAstTree(
  115. astTree,
  116. VisitorDirection.leave,
  117. this.nodeTransformersFactory(Obfuscator.nodeControlFlowTransformersMap)
  118. );
  119. }
  120. // second pass: nodes obfuscation
  121. astTree = this.transformAstTree(
  122. astTree,
  123. VisitorDirection.enter,
  124. this.nodeTransformersFactory(Obfuscator.nodeObfuscatorsMap)
  125. );
  126. this.obfuscationEventEmitter.emit(ObfuscationEvents.AfterObfuscation, astTree, stackTraceData);
  127. return astTree;
  128. }
  129. /**
  130. * @param astTree
  131. * @param direction
  132. * @param nodeTransformersConcreteFactory
  133. */
  134. private transformAstTree (
  135. astTree: ESTree.Program,
  136. direction: TVisitorDirection,
  137. nodeTransformersConcreteFactory: (nodeType: string) => INodeTransformer[]
  138. ): ESTree.Program {
  139. estraverse.replace(astTree, {
  140. [direction]: (node: ESTree.Node, parentNode: ESTree.Node): ESTree.Node => {
  141. const nodeTransformers: INodeTransformer[] = nodeTransformersConcreteFactory(node.type);
  142. nodeTransformers.forEach((nodeTransformer: INodeTransformer) => {
  143. node = nodeTransformer.transformNode(node, parentNode);
  144. });
  145. return node;
  146. }
  147. });
  148. return astTree;
  149. }
  150. }