BinaryExpressionControlFlowReplacer.spec.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { assert } from 'chai';
  2. import { IObfuscationResult } from '../../../../../../src/interfaces/IObfuscationResult';
  3. import { NO_CUSTOM_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
  4. import { readFileAsString } from '../../../../../helpers/readFileAsString';
  5. import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscator';
  6. describe('BinaryExpressionControlFlowReplacer', function () {
  7. this.timeout(100000);
  8. describe('replace (binaryExpressionNode: ESTree.BinaryExpression,parentNode: ESTree.Node,controlFlowStorage: IStorage <ICustomNode>)', () => {
  9. describe('variant #1 - single binary expression', () => {
  10. const controlFlowStorageCallRegExp: RegExp = /var *_0x([a-f0-9]){4,6} *= *_0x([a-f0-9]){4,6}\['\w{5}'\]\(0x1, *0x2\);/;
  11. let obfuscatedCode: string;
  12. before(() => {
  13. const code: string = readFileAsString(__dirname + '/fixtures/input-1.js');
  14. const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
  15. code,
  16. {
  17. ...NO_CUSTOM_NODES_PRESET,
  18. controlFlowFlattening: true,
  19. controlFlowFlatteningThreshold: 1
  20. }
  21. );
  22. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  23. });
  24. it('should replace binary expression node with call to control flow storage node', () => {
  25. assert.match(obfuscatedCode, controlFlowStorageCallRegExp);
  26. });
  27. });
  28. describe('variant #2 - multiple binary expressions with threshold = 1', () => {
  29. const expectedMatchErrorsCount: number = 0;
  30. const expectedChance: number = 0.5;
  31. const samplesCount: number = 1000;
  32. const delta: number = 0.1;
  33. const controlFlowStorageCallRegExp1: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{5}'\])\(0x1, *0x2\);/;
  34. const controlFlowStorageCallRegExp2: RegExp = /var *_0x(?:[a-f0-9]){4,6} *= *(_0x([a-f0-9]){4,6}\['\w{5}'\])\(0x2, *0x3\);/;
  35. let matchErrorsCount: number = 0,
  36. usingExistingIdentifierChance: number;
  37. before(() => {
  38. const code: string = readFileAsString(__dirname + '/fixtures/input-2.js');
  39. let obfuscationResult: IObfuscationResult,
  40. obfuscatedCode: string,
  41. firstMatchArray: RegExpMatchArray | null,
  42. secondMatchArray: RegExpMatchArray | null,
  43. firstMatch: string | undefined,
  44. secondMatch: string | undefined,
  45. equalsValue: number = 0;
  46. for (let i = 0; i < samplesCount; i++) {
  47. obfuscationResult = JavaScriptObfuscator.obfuscate(
  48. code,
  49. {
  50. ...NO_CUSTOM_NODES_PRESET,
  51. controlFlowFlattening: true,
  52. controlFlowFlatteningThreshold: 1
  53. }
  54. );
  55. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  56. firstMatchArray = obfuscatedCode.match(controlFlowStorageCallRegExp1);
  57. secondMatchArray = obfuscatedCode.match(controlFlowStorageCallRegExp2);
  58. if (!firstMatchArray || !secondMatchArray) {
  59. matchErrorsCount++;
  60. continue;
  61. }
  62. firstMatch = firstMatchArray ? firstMatchArray[1] : undefined;
  63. secondMatch = secondMatchArray ? secondMatchArray[1] : undefined;
  64. if (firstMatch === secondMatch) {
  65. equalsValue++;
  66. }
  67. }
  68. usingExistingIdentifierChance = equalsValue / samplesCount;
  69. });
  70. it('should replace binary expression node with call to control flow storage node', () => {
  71. assert.equal(matchErrorsCount, expectedMatchErrorsCount);
  72. });
  73. it('should use existing identifier for control flow storage with expected chance', () => {
  74. assert.closeTo(usingExistingIdentifierChance, expectedChance, delta);
  75. });
  76. });
  77. });
  78. });