FunctionDeclarationTransformer.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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 { TNodeWithBlockStatement } from '../../types/node/TNodeWithBlockStatement';
  6. import { IOptions } from '../../interfaces/options/IOptions';
  7. import { IObfuscationReplacer } from '../../interfaces/node-transformers/IObfuscationReplacer';
  8. import { IObfuscationReplacerWithStorage } from '../../interfaces/node-transformers/IObfuscationReplacerWithStorage';
  9. import { IVisitor } from '../../interfaces/IVisitor';
  10. import { NodeObfuscatorsReplacers } from '../../enums/container/NodeObfuscationReplacers';
  11. import { NodeType } from '../../enums/NodeType';
  12. import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
  13. import { Node } from '../../node/Node';
  14. import { NodeUtils } from '../../node/NodeUtils';
  15. /**
  16. * replaces:
  17. * function foo () { //... };
  18. * foo();
  19. *
  20. * on:
  21. * function _0x12d45f () { //... };
  22. * _0x12d45f();
  23. */
  24. @injectable()
  25. export class FunctionDeclarationTransformer extends AbstractNodeTransformer {
  26. /**
  27. * @type {IObfuscationReplacerWithStorage}
  28. */
  29. private readonly identifierReplacer: IObfuscationReplacerWithStorage;
  30. /**
  31. * @type {Map<ESTree.Node, ESTree.Identifier[]>}
  32. */
  33. private readonly replaceableIdentifiers: Map <ESTree.Node, ESTree.Identifier[]> = new Map();
  34. /**
  35. * @param nodeObfuscatorsReplacersFactory
  36. * @param options
  37. */
  38. constructor (
  39. @inject(ServiceIdentifiers.Factory__IObfuscatorReplacer) nodeObfuscatorsReplacersFactory: (replacer: NodeObfuscatorsReplacers) => IObfuscationReplacer,
  40. @inject(ServiceIdentifiers.IOptions) options: IOptions
  41. ) {
  42. super(options);
  43. this.identifierReplacer = <IObfuscationReplacerWithStorage>nodeObfuscatorsReplacersFactory(NodeObfuscatorsReplacers.IdentifierReplacer);
  44. }
  45. /**
  46. * @return {IVisitor}
  47. */
  48. public getVisitor (): IVisitor {
  49. return {
  50. enter: (node: ESTree.Node, parentNode: ESTree.Node) => {
  51. if (Node.isFunctionDeclarationNode(node)) {
  52. return this.transformNode(node, parentNode);
  53. }
  54. }
  55. };
  56. }
  57. /**
  58. * @param functionDeclarationNode
  59. * @param parentNode
  60. * @returns {ESTree.Node}
  61. */
  62. public transformNode (functionDeclarationNode: ESTree.FunctionDeclaration, parentNode: ESTree.Node): ESTree.Node {
  63. const nodeIdentifier: number = this.nodeIdentifier++;
  64. const blockScopeOfFunctionDeclarationNode: TNodeWithBlockStatement = NodeUtils
  65. .getBlockScopesOfNode(functionDeclarationNode)[0];
  66. if (blockScopeOfFunctionDeclarationNode.type === NodeType.Program) {
  67. return functionDeclarationNode;
  68. }
  69. this.storeFunctionName(functionDeclarationNode, nodeIdentifier);
  70. this.replaceFunctionName(blockScopeOfFunctionDeclarationNode, nodeIdentifier);
  71. return functionDeclarationNode;
  72. }
  73. /**
  74. * @param functionDeclarationNode
  75. * @param nodeIdentifier
  76. */
  77. private storeFunctionName (functionDeclarationNode: ESTree.FunctionDeclaration, nodeIdentifier: number): void {
  78. this.identifierReplacer.storeNames(functionDeclarationNode.id.name, nodeIdentifier);
  79. }
  80. /**
  81. * @param scopeNode
  82. * @param nodeIdentifier
  83. */
  84. private replaceFunctionName (scopeNode: ESTree.Node, nodeIdentifier: number): void {
  85. let replaceableIdentifiersForCurrentScope: ESTree.Identifier[];
  86. // check for cached identifiers for current scope node. If exist - loop through them.
  87. if (this.replaceableIdentifiers.has(scopeNode)) {
  88. replaceableIdentifiersForCurrentScope = <ESTree.Identifier[]>this.replaceableIdentifiers.get(scopeNode);
  89. replaceableIdentifiersForCurrentScope.forEach((replaceableIdentifier: ESTree.Identifier) => {
  90. replaceableIdentifier.name = this.identifierReplacer.replace(replaceableIdentifier.name, nodeIdentifier);
  91. });
  92. return;
  93. }
  94. replaceableIdentifiersForCurrentScope = [];
  95. estraverse.replace(scopeNode, {
  96. enter: (node: ESTree.Node, parentNode: ESTree.Node): any => {
  97. if (Node.isReplaceableIdentifierNode(node, parentNode)) {
  98. const newNodeName: string = this.identifierReplacer.replace(node.name, nodeIdentifier);
  99. if (node.name !== newNodeName) {
  100. node.name = newNodeName;
  101. } else {
  102. replaceableIdentifiersForCurrentScope.push(node);
  103. }
  104. }
  105. }
  106. });
  107. this.replaceableIdentifiers.set(scopeNode, replaceableIdentifiersForCurrentScope);
  108. }
  109. }