StringLiteralReplacer.ts 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import { TStringArrayCallsWrapper } from '../../types/custom-nodes/TStringArrayCallsWrapper';
  2. import { TStringArrayNode } from '../../types/custom-nodes/TStringArrayNode';
  3. import { StringArrayEncoding } from '../../enums/StringArrayEncoding';
  4. import { AbstractReplacer } from './AbstractReplacer';
  5. import { NumberLiteralReplacer } from './NumberLiteralReplacer';
  6. import { StringArray } from '../../StringArray';
  7. import { Utils } from '../../Utils';
  8. export class StringLiteralReplacer extends AbstractReplacer {
  9. /**
  10. * @type {number}
  11. */
  12. private static minimumLengthForStringArray: number = 3;
  13. /**
  14. * @type {string[]}
  15. */
  16. private static rc4Keys: string[] = Utils.getRandomGenerator()
  17. .n(() => Utils.getRandomGenerator().string({length: 4}), 50);
  18. /**
  19. * @param nodeValue
  20. * @returns {string}
  21. */
  22. public replace (nodeValue: string): string {
  23. const replaceWithStringArrayFlag: boolean = (
  24. nodeValue.length >= StringLiteralReplacer.minimumLengthForStringArray
  25. && Utils.getRandomFloat(0, 1) <= this.options.stringArrayThreshold
  26. );
  27. if (this.options.stringArray && replaceWithStringArrayFlag) {
  28. return this.replaceStringLiteralWithStringArrayCall(nodeValue);
  29. }
  30. return `'${Utils.stringToUnicodeEscapeSequence(nodeValue)}'`;
  31. }
  32. /**
  33. * @param value
  34. * @returns {string}
  35. */
  36. private replaceStringLiteralWithStringArrayCall (value: string): string {
  37. const stringArrayNode: TStringArrayNode = <TStringArrayNode>this.nodes.get('stringArrayNode');
  38. if (!stringArrayNode) {
  39. throw new ReferenceError('`stringArrayNode` node is not found in Map with custom node.');
  40. }
  41. let rc4Key: string = '';
  42. switch (this.options.stringArrayEncoding) {
  43. case StringArrayEncoding.base64:
  44. value = Utils.btoa(value);
  45. break;
  46. case StringArrayEncoding.rc4:
  47. rc4Key = Utils.getRandomGenerator().pickone(StringLiteralReplacer.rc4Keys);
  48. value = Utils.btoa(Utils.rc4(value, rc4Key));
  49. break;
  50. }
  51. if (this.options.unicodeEscapeSequence) {
  52. value = Utils.stringToUnicodeEscapeSequence(value);
  53. }
  54. let stringArray: StringArray = stringArrayNode.getNodeData(),
  55. indexOfExistingValue: number = stringArray.getIndexOf(value),
  56. indexOfValue: number,
  57. hexadecimalIndex: string;
  58. if (indexOfExistingValue >= 0) {
  59. indexOfValue = indexOfExistingValue;
  60. } else {
  61. indexOfValue = stringArray.getLength();
  62. stringArrayNode.updateNodeData(value);
  63. }
  64. hexadecimalIndex = new NumberLiteralReplacer(this.nodes, this.options)
  65. .replace(indexOfValue);
  66. const stringArrayCallsWrapper: TStringArrayCallsWrapper = <TStringArrayCallsWrapper>this.nodes.get('stringArrayCallsWrapper');
  67. if (!stringArrayCallsWrapper) {
  68. throw new ReferenceError('`stringArrayCallsWrapper` node is not found in Map with custom node.');
  69. }
  70. if (this.options.stringArrayEncoding === StringArrayEncoding.rc4) {
  71. return `${stringArrayCallsWrapper.getNodeIdentifier()}('${hexadecimalIndex}', '${Utils.stringToUnicodeEscapeSequence(rc4Key)}')`;
  72. }
  73. return `${stringArrayCallsWrapper.getNodeIdentifier()}('${hexadecimalIndex}')`;
  74. }
  75. }