Obfuscator.ts 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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 { TNodeTransformerFactory } from './types/container/TNodeTransformerFactory';
  6. import { TVisitorDirection } from './types/TVisitorDirection';
  7. import { TVisitorFunction } from './types/TVisitorFunction';
  8. import { ICustomNodeGroup } from './interfaces/custom-nodes/ICustomNodeGroup';
  9. import { IObfuscationEventEmitter } from './interfaces/event-emitters/IObfuscationEventEmitter';
  10. import { IObfuscator } from './interfaces/IObfuscator';
  11. import { IOptions } from './interfaces/options/IOptions';
  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 { IVisitor } from './interfaces/IVisitor';
  16. import { NodeTransformers } from './enums/container/NodeTransformers';
  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 {NodeTransformers[]}
  25. */
  26. private static readonly controlFlowTransformersList: NodeTransformers[] = [
  27. NodeTransformers.BlockStatementControlFlowTransformer,
  28. NodeTransformers.FunctionControlFlowTransformer
  29. ];
  30. /**
  31. * @type {NodeTransformers[]}
  32. */
  33. private static readonly convertingTransformersList: NodeTransformers[] = [
  34. NodeTransformers.MemberExpressionTransformer,
  35. NodeTransformers.MethodDefinitionTransformer,
  36. NodeTransformers.TemplateLiteralTransformer
  37. ];
  38. /**
  39. * @type {NodeTransformers[]}
  40. */
  41. private static readonly deadCodeInjectionTransformersList: NodeTransformers[] = [
  42. NodeTransformers.DeadCodeInjectionTransformer
  43. ];
  44. /**
  45. * @type {NodeTransformers[]}
  46. */
  47. private static readonly obfuscatingTransformersList: NodeTransformers[] = [
  48. NodeTransformers.CatchClauseTransformer,
  49. NodeTransformers.FunctionDeclarationTransformer,
  50. NodeTransformers.FunctionTransformer,
  51. NodeTransformers.LabeledStatementTransformer,
  52. NodeTransformers.LiteralTransformer,
  53. NodeTransformers.ObjectExpressionTransformer,
  54. NodeTransformers.VariableDeclarationTransformer
  55. ];
  56. /**
  57. * @type {IStorage<ICustomNodeGroup>}
  58. */
  59. private readonly customNodeGroupStorage: IStorage<ICustomNodeGroup>;
  60. /**
  61. * @type {TNodeTransformerFactory}
  62. */
  63. private readonly nodeTransformerFactory: TNodeTransformerFactory;
  64. /**
  65. * @type {IObfuscationEventEmitter}
  66. */
  67. private readonly obfuscationEventEmitter: IObfuscationEventEmitter;
  68. /**
  69. * @type {IOptions}
  70. */
  71. private readonly options: IOptions;
  72. /**
  73. * @type {IStackTraceAnalyzer}
  74. */
  75. private readonly stackTraceAnalyzer: IStackTraceAnalyzer;
  76. /**
  77. * @param stackTraceAnalyzer
  78. * @param obfuscationEventEmitter
  79. * @param customNodeGroupStorage
  80. * @param nodeTransformerFactory
  81. * @param options
  82. */
  83. constructor (
  84. @inject(ServiceIdentifiers.IStackTraceAnalyzer) stackTraceAnalyzer: IStackTraceAnalyzer,
  85. @inject(ServiceIdentifiers.IObfuscationEventEmitter) obfuscationEventEmitter: IObfuscationEventEmitter,
  86. @inject(ServiceIdentifiers.TCustomNodeGroupStorage) customNodeGroupStorage: IStorage<ICustomNodeGroup>,
  87. @inject(ServiceIdentifiers.Factory__INodeTransformer) nodeTransformerFactory: TNodeTransformerFactory,
  88. @inject(ServiceIdentifiers.IOptions) options: IOptions
  89. ) {
  90. this.stackTraceAnalyzer = stackTraceAnalyzer;
  91. this.obfuscationEventEmitter = obfuscationEventEmitter;
  92. this.customNodeGroupStorage = customNodeGroupStorage;
  93. this.nodeTransformerFactory = nodeTransformerFactory;
  94. this.options = options;
  95. }
  96. /**
  97. * @param astTree
  98. * @returns {ESTree.Program}
  99. */
  100. public obfuscateAstTree (astTree: ESTree.Program): ESTree.Program {
  101. if (Node.isProgramNode(astTree) && !astTree.body.length) {
  102. return astTree;
  103. }
  104. astTree = <ESTree.Program>NodeUtils.parentize(astTree);
  105. const stackTraceData: IStackTraceData[] = this.stackTraceAnalyzer.analyze(astTree.body);
  106. // initialize custom node groups and configure custom nodes
  107. this.customNodeGroupStorage
  108. .getStorage()
  109. .forEach((customNodeGroup: ICustomNodeGroup) => {
  110. customNodeGroup.initialize();
  111. this.obfuscationEventEmitter.once(
  112. customNodeGroup.getAppendEvent(),
  113. customNodeGroup.appendCustomNodes.bind(customNodeGroup)
  114. );
  115. });
  116. this.obfuscationEventEmitter.emit(ObfuscationEvents.BeforeObfuscation, astTree, stackTraceData);
  117. // first pass transformers: dead code injection transformer
  118. astTree = this.transformAstTree(astTree, [
  119. ...this.options.deadCodeInjection ? Obfuscator.deadCodeInjectionTransformersList : []
  120. ]);
  121. // second pass transformers: control flow flattening transformers
  122. astTree = this.transformAstTree(astTree, [
  123. ...this.options.controlFlowFlattening ? Obfuscator.controlFlowTransformersList : []
  124. ]);
  125. // third pass: converting and obfuscating transformers
  126. astTree = this.transformAstTree(astTree, [
  127. ...Obfuscator.convertingTransformersList,
  128. ...Obfuscator.obfuscatingTransformersList
  129. ]);
  130. this.obfuscationEventEmitter.emit(ObfuscationEvents.AfterObfuscation, astTree, stackTraceData);
  131. return astTree;
  132. }
  133. /**
  134. * @param astTree
  135. * @param nodeTransformers
  136. */
  137. private transformAstTree (
  138. astTree: ESTree.Program,
  139. nodeTransformers: NodeTransformers[]
  140. ): ESTree.Program {
  141. if (!nodeTransformers.length) {
  142. return astTree;
  143. }
  144. const enterVisitors: IVisitor[] = [];
  145. const leaveVisitors: IVisitor[] = [];
  146. const nodeTransformersLength: number = nodeTransformers.length;
  147. let visitor: IVisitor;
  148. for (let i: number = 0; i < nodeTransformersLength; i++) {
  149. visitor = this.nodeTransformerFactory(nodeTransformers[i]).getVisitor();
  150. if (visitor.enter) {
  151. enterVisitors.push(visitor);
  152. }
  153. if (visitor.leave) {
  154. leaveVisitors.push(visitor);
  155. }
  156. }
  157. estraverse.replace(astTree, {
  158. enter: this.mergeVisitorsForDirection(enterVisitors, VisitorDirection.enter),
  159. leave: this.mergeVisitorsForDirection(leaveVisitors, VisitorDirection.leave)
  160. });
  161. return astTree;
  162. }
  163. /**
  164. * @param visitors
  165. * @param direction
  166. * @return {TVisitorDirection}
  167. */
  168. private mergeVisitorsForDirection (visitors: IVisitor[], direction: TVisitorDirection): TVisitorFunction {
  169. if (!visitors.length) {
  170. return (node: ESTree.Node, parentNode: ESTree.Node) => node;
  171. }
  172. const visitorsLength: number = visitors.length;
  173. let visitor: IVisitor;
  174. return (node: ESTree.Node, parentNode: ESTree.Node) => {
  175. for (let i: number = 0; i < visitorsLength; i++) {
  176. visitor = visitors[i];
  177. const visitorFunction: TVisitorFunction | undefined = visitor[direction];
  178. if (!visitorFunction) {
  179. continue;
  180. }
  181. const visitorResult: ESTree.Node | void = visitorFunction(node, parentNode);
  182. if (!visitorResult) {
  183. continue;
  184. }
  185. node = visitorResult;
  186. }
  187. return node;
  188. };
  189. }
  190. }