StringArrayCallsWrapperTemplate.spec.ts 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743
  1. import 'reflect-metadata';
  2. import format from 'string-template';
  3. import { assert } from 'chai';
  4. import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
  5. import { ICryptUtilsStringArray } from '../../../../../../src/interfaces/utils/ICryptUtilsStringArray';
  6. import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
  7. import { IObfuscationResult } from '../../../../../../src/interfaces/source-code/IObfuscationResult';
  8. import { IRandomGenerator } from '../../../../../../src/interfaces/utils/IRandomGenerator';
  9. import { AtobTemplate } from '../../../../../../src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/AtobTemplate';
  10. import { Rc4Template } from '../../../../../../src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/Rc4Template';
  11. import { StringArrayBase64DecodeTemplate } from '../../../../../../src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayBase64DecodeTemplate';
  12. import { StringArrayCallsWrapperTemplate } from '../../../../../../src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayCallsWrapperTemplate';
  13. import { StringArrayRC4DecodeTemplate } from '../../../../../../src/custom-code-helpers/string-array/templates/string-array-calls-wrapper/StringArrayRC4DecodeTemplate';
  14. import { StringArrayTemplate } from '../../../../../../src/custom-code-helpers/string-array/templates/string-array/StringArrayTemplate';
  15. import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
  16. import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
  17. import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscatorFacade';
  18. import { minimizeCode } from '../../../../../helpers/minimizeCode';
  19. import { readFileAsString } from '../../../../../helpers/readFileAsString';
  20. import { swapLettersCase } from '../../../../../helpers/swapLettersCase';
  21. describe('StringArrayCallsWrapperTemplate', () => {
  22. const stringArrayName: string = 'stringArrayName';
  23. const stringArrayFunctionName: string = 'stringArrayFunctionName';
  24. const stringArrayCallsWrapperName: string = 'stringArrayCallsWrapperName';
  25. const stringArrayCacheName: string = 'stringArrayCache';
  26. const atobFunctionName: string = 'atob';
  27. const rc4FunctionName: string = 'rc4';
  28. let cryptUtilsSwappedAlphabet: ICryptUtilsStringArray,
  29. randomGenerator: IRandomGenerator;
  30. before(() => {
  31. const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
  32. inversifyContainerFacade.load('', '', {});
  33. cryptUtilsSwappedAlphabet = inversifyContainerFacade
  34. .get<ICryptUtilsStringArray>(ServiceIdentifiers.ICryptUtilsStringArray);
  35. randomGenerator = inversifyContainerFacade
  36. .get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
  37. });
  38. describe('Variant #1: `base64` encoding', () => {
  39. describe('Variant #1: `selfDefending` option is disabled', () => {
  40. const selfDefendingEnabled: boolean = false;
  41. describe('Variant #1: index shift amount is `0`', () => {
  42. const index: string = '0x0';
  43. const indexShiftAmount: number = 0;
  44. const expectedDecodedValue: string = 'test1';
  45. let decodedValue: string;
  46. before(() => {
  47. const stringArrayTemplate = format(StringArrayTemplate(), {
  48. stringArrayName,
  49. stringArrayFunctionName,
  50. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa('test1')}'`
  51. });
  52. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  53. atobFunctionName
  54. });
  55. const atobDecodeTemplate: string = format(
  56. StringArrayBase64DecodeTemplate(randomGenerator),
  57. {
  58. atobPolyfill,
  59. atobFunctionName,
  60. selfDefendingCode: '',
  61. stringArrayCacheName,
  62. stringArrayCallsWrapperName
  63. }
  64. );
  65. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  66. decodeCodeHelperTemplate: atobDecodeTemplate,
  67. indexShiftAmount,
  68. stringArrayCacheName,
  69. stringArrayCallsWrapperName,
  70. stringArrayFunctionName
  71. });
  72. decodedValue = Function(`
  73. ${stringArrayTemplate}
  74. ${stringArrayCallsWrapperTemplate}
  75. return ${stringArrayCallsWrapperName}(${index});
  76. `)();
  77. });
  78. it('should correctly return decoded value', () => {
  79. assert.deepEqual(decodedValue, expectedDecodedValue);
  80. });
  81. });
  82. describe('Variant #2: index shift amount is `5`', () => {
  83. const index: string = '0x5';
  84. const indexShiftAmount: number = 5;
  85. const expectedDecodedValue: string = 'test1';
  86. let decodedValue: string;
  87. before(() => {
  88. const stringArrayTemplate = format(StringArrayTemplate(), {
  89. stringArrayName,
  90. stringArrayFunctionName,
  91. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa('test1')}'`
  92. });
  93. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  94. atobFunctionName
  95. });
  96. const atobDecodeTemplate: string = format(
  97. StringArrayBase64DecodeTemplate(randomGenerator),
  98. {
  99. atobPolyfill,
  100. atobFunctionName,
  101. selfDefendingCode: '',
  102. stringArrayCacheName,
  103. stringArrayCallsWrapperName
  104. }
  105. );
  106. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  107. decodeCodeHelperTemplate: atobDecodeTemplate,
  108. indexShiftAmount,
  109. stringArrayCacheName,
  110. stringArrayCallsWrapperName,
  111. stringArrayFunctionName
  112. });
  113. decodedValue = Function(`
  114. ${stringArrayTemplate}
  115. ${stringArrayCallsWrapperTemplate}
  116. return ${stringArrayCallsWrapperName}(${index});
  117. `)();
  118. });
  119. it('should correctly return decoded value', () => {
  120. assert.deepEqual(decodedValue, expectedDecodedValue);
  121. });
  122. });
  123. describe('Variant #3: no regexp inside atob template', () => {
  124. const indexShiftAmount: number = 0;
  125. const expectedRegExpTestValue: string = '12345';
  126. let decodedValue: string;
  127. before(() => {
  128. const stringArrayTemplate = format(StringArrayTemplate(), {
  129. stringArrayName,
  130. stringArrayFunctionName,
  131. stringArrayStorageItems: `'${swapLettersCase('c3RyaQ==')}'`
  132. });
  133. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  134. atobFunctionName
  135. });
  136. const atobDecodeTemplate: string = format(
  137. StringArrayBase64DecodeTemplate(randomGenerator),
  138. {
  139. atobPolyfill,
  140. atobFunctionName,
  141. selfDefendingCode: '',
  142. stringArrayCacheName,
  143. stringArrayCallsWrapperName
  144. }
  145. );
  146. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  147. decodeCodeHelperTemplate: atobDecodeTemplate,
  148. indexShiftAmount,
  149. stringArrayCacheName,
  150. stringArrayCallsWrapperName,
  151. stringArrayFunctionName
  152. });
  153. decodedValue = Function(`
  154. ${stringArrayTemplate}
  155. ${stringArrayCallsWrapperTemplate}
  156. /(.+)/.test("12345");
  157. ${stringArrayCallsWrapperName}(0x0);
  158. return RegExp.$1;
  159. `)();
  160. });
  161. it('should correctly return RegExp.$1 match without mutation by atob template', () => {
  162. assert.deepEqual(decodedValue, expectedRegExpTestValue);
  163. });
  164. });
  165. });
  166. describe('Variant #2: `selfDefending` option is enabled', () => {
  167. const selfDefendingEnabled: boolean = true;
  168. describe('Variant #1: correct code evaluation for single-line code', () => {
  169. describe('Variant #1: long decoded string', () => {
  170. const index: string = '0x0';
  171. const indexShiftAmount: number = 0;
  172. const expectedDecodedValue: string = 'test1test1';
  173. let decodedValue: string;
  174. before(async() => {
  175. const stringArrayTemplate = format(StringArrayTemplate(), {
  176. stringArrayName,
  177. stringArrayFunctionName,
  178. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa('test1test1')}'`
  179. });
  180. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  181. atobFunctionName
  182. });
  183. const atobDecodeTemplate: string = format(
  184. StringArrayBase64DecodeTemplate(randomGenerator),
  185. {
  186. atobPolyfill,
  187. atobFunctionName,
  188. selfDefendingCode: '',
  189. stringArrayCacheName,
  190. stringArrayCallsWrapperName
  191. }
  192. );
  193. const stringArrayCallsWrapperTemplate: string = await minimizeCode(
  194. format(StringArrayCallsWrapperTemplate(), {
  195. decodeCodeHelperTemplate: atobDecodeTemplate,
  196. indexShiftAmount,
  197. stringArrayCacheName,
  198. stringArrayCallsWrapperName,
  199. stringArrayFunctionName
  200. })
  201. );
  202. decodedValue = Function(`
  203. ${stringArrayTemplate}
  204. ${stringArrayCallsWrapperTemplate}
  205. return ${stringArrayCallsWrapperName}(${index});
  206. `)();
  207. });
  208. it('should correctly return decoded value', () => {
  209. assert.deepEqual(decodedValue, expectedDecodedValue);
  210. });
  211. });
  212. describe('Variant #2: 3-characters decoded string', () => {
  213. const index: string = '0x0';
  214. const indexShiftAmount: number = 0;
  215. const expectedDecodedValue: string = 'foo';
  216. let decodedValue: string;
  217. before(async() => {
  218. const stringArrayTemplate = format(StringArrayTemplate(), {
  219. stringArrayName,
  220. stringArrayFunctionName,
  221. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa('foo')}'`
  222. });
  223. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  224. atobFunctionName
  225. });
  226. const atobDecodeTemplate: string = format(
  227. StringArrayBase64DecodeTemplate(randomGenerator),
  228. {
  229. atobPolyfill,
  230. atobFunctionName,
  231. selfDefendingCode: '',
  232. stringArrayCacheName,
  233. stringArrayCallsWrapperName
  234. }
  235. );
  236. const stringArrayCallsWrapperTemplate: string = await minimizeCode(
  237. format(StringArrayCallsWrapperTemplate(), {
  238. decodeCodeHelperTemplate: atobDecodeTemplate,
  239. indexShiftAmount,
  240. stringArrayCacheName,
  241. stringArrayCallsWrapperName,
  242. stringArrayFunctionName
  243. })
  244. );
  245. decodedValue = Function(`
  246. ${stringArrayTemplate}
  247. ${stringArrayCallsWrapperTemplate}
  248. return ${stringArrayCallsWrapperName}(${index});
  249. `)();
  250. });
  251. it('should correctly return decoded value', () => {
  252. assert.deepEqual(decodedValue, expectedDecodedValue);
  253. });
  254. });
  255. });
  256. describe('Variant #2: invalid code evaluation for multi-line code', () => {
  257. describe('Variant #1: long decoded string', () => {
  258. const index: string = '0x0';
  259. const indexShiftAmount: number = 0;
  260. const expectedDecodedValue: string = 'test18est1';
  261. let decodedValue: string;
  262. before(() => {
  263. const stringArrayTemplate = format(StringArrayTemplate(), {
  264. stringArrayName,
  265. stringArrayFunctionName,
  266. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa('test1test1')}'`
  267. });
  268. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  269. atobFunctionName
  270. });
  271. const atobDecodeTemplate: string = format(
  272. StringArrayBase64DecodeTemplate(randomGenerator),
  273. {
  274. atobPolyfill,
  275. atobFunctionName,
  276. selfDefendingCode: '',
  277. stringArrayCacheName,
  278. stringArrayCallsWrapperName
  279. }
  280. );
  281. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  282. decodeCodeHelperTemplate: atobDecodeTemplate,
  283. indexShiftAmount,
  284. stringArrayCacheName,
  285. stringArrayCallsWrapperName,
  286. stringArrayFunctionName
  287. });
  288. decodedValue = Function(`
  289. ${stringArrayTemplate}
  290. ${stringArrayCallsWrapperTemplate}
  291. return ${stringArrayCallsWrapperName}(${index});
  292. `)();
  293. });
  294. it('should return invalid decoded value', () => {
  295. assert.deepEqual(decodedValue, expectedDecodedValue);
  296. });
  297. });
  298. describe('Variant #2: 3-characters decoded string', () => {
  299. const index: string = '0x0';
  300. const indexShiftAmount: number = 0;
  301. const expectedDecodedValue: string = 'foo';
  302. let decodedValue: string;
  303. before(() => {
  304. const stringArrayTemplate = format(StringArrayTemplate(), {
  305. stringArrayName,
  306. stringArrayFunctionName,
  307. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa('foo')}'`
  308. });
  309. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  310. atobFunctionName
  311. });
  312. const atobDecodeTemplate: string = format(
  313. StringArrayBase64DecodeTemplate(randomGenerator),
  314. {
  315. atobPolyfill,
  316. atobFunctionName,
  317. selfDefendingCode: '',
  318. stringArrayCacheName,
  319. stringArrayCallsWrapperName
  320. }
  321. );
  322. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  323. decodeCodeHelperTemplate: atobDecodeTemplate,
  324. indexShiftAmount,
  325. stringArrayCacheName,
  326. stringArrayCallsWrapperName,
  327. stringArrayFunctionName
  328. });
  329. decodedValue = Function(`
  330. ${stringArrayTemplate}
  331. ${stringArrayCallsWrapperTemplate}
  332. return ${stringArrayCallsWrapperName}(${index});
  333. `)();
  334. });
  335. it('should return invalid decoded value', () => {
  336. assert.deepEqual(decodedValue, expectedDecodedValue);
  337. });
  338. });
  339. });
  340. });
  341. });
  342. describe('Variant #2: `rc4` encoding', () => {
  343. describe('Variant #1: `selfDefending` option is disabled', () => {
  344. const selfDefendingEnabled: boolean = false;
  345. describe('Variant #1: index shift amount is `0`', () => {
  346. const index: string = '0x0';
  347. const key: string = 'key';
  348. const indexShiftAmount: number = 0;
  349. const expectedDecodedValue: string = 'test1';
  350. let decodedValue: string;
  351. before(() => {
  352. const stringArrayTemplate = format(StringArrayTemplate(), {
  353. stringArrayName,
  354. stringArrayFunctionName,
  355. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'`
  356. });
  357. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  358. atobFunctionName
  359. });
  360. const rc4Polyfill = format(Rc4Template(), {
  361. atobFunctionName,
  362. rc4FunctionName
  363. });
  364. const rc4decodeCodeHelperTemplate: string = format(
  365. StringArrayRC4DecodeTemplate(randomGenerator),
  366. {
  367. atobPolyfill,
  368. rc4Polyfill,
  369. rc4FunctionName,
  370. selfDefendingCode: '',
  371. stringArrayCacheName,
  372. stringArrayCallsWrapperName
  373. }
  374. );
  375. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  376. decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
  377. indexShiftAmount,
  378. stringArrayCacheName,
  379. stringArrayCallsWrapperName,
  380. stringArrayFunctionName
  381. });
  382. decodedValue = Function(`
  383. ${stringArrayTemplate}
  384. ${stringArrayCallsWrapperTemplate}
  385. return ${stringArrayCallsWrapperName}('${index}', '${key}');
  386. `)();
  387. });
  388. it('should correctly return decoded value', () => {
  389. assert.deepEqual(decodedValue, expectedDecodedValue);
  390. });
  391. });
  392. describe('Variant #2: index shift amount is `5`', () => {
  393. const index: string = '0x5';
  394. const key: string = 'key';
  395. const indexShiftAmount: number = 5;
  396. const expectedDecodedValue: string = 'test1';
  397. let decodedValue: string;
  398. before(() => {
  399. const stringArrayTemplate = format(StringArrayTemplate(), {
  400. stringArrayName,
  401. stringArrayFunctionName,
  402. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'`
  403. });
  404. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  405. atobFunctionName
  406. });
  407. const rc4Polyfill = format(Rc4Template(), {
  408. atobFunctionName,
  409. rc4FunctionName
  410. });
  411. const rc4decodeCodeHelperTemplate: string = format(
  412. StringArrayRC4DecodeTemplate(randomGenerator),
  413. {
  414. atobPolyfill,
  415. rc4Polyfill,
  416. rc4FunctionName,
  417. selfDefendingCode: '',
  418. stringArrayCacheName,
  419. stringArrayCallsWrapperName
  420. }
  421. );
  422. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  423. decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
  424. indexShiftAmount,
  425. stringArrayCacheName,
  426. stringArrayCallsWrapperName,
  427. stringArrayFunctionName
  428. });
  429. decodedValue = Function(`
  430. ${stringArrayTemplate}
  431. ${stringArrayCallsWrapperTemplate}
  432. return ${stringArrayCallsWrapperName}('${index}', '${key}');
  433. `)();
  434. });
  435. it('should correctly return decoded value', () => {
  436. assert.deepEqual(decodedValue, expectedDecodedValue);
  437. });
  438. });
  439. });
  440. describe('Variant #2: `selfDefending` option is enabled', () => {
  441. const selfDefendingEnabled: boolean = true;
  442. describe('Variant #1: correct code evaluation for single-line code', () => {
  443. describe('Variant #1: long decoded string', () => {
  444. const index: string = '0x0';
  445. const key: string = 'key';
  446. const indexShiftAmount: number = 0;
  447. const expectedDecodedValue: string = 'test1';
  448. let decodedValue: string;
  449. before(async() => {
  450. const stringArrayTemplate = format(StringArrayTemplate(), {
  451. stringArrayName,
  452. stringArrayFunctionName,
  453. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'`
  454. });
  455. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  456. atobFunctionName
  457. });
  458. const rc4Polyfill = format(Rc4Template(), {
  459. atobFunctionName,
  460. rc4FunctionName
  461. });
  462. const rc4decodeCodeHelperTemplate: string = format(
  463. StringArrayRC4DecodeTemplate(randomGenerator),
  464. {
  465. atobPolyfill,
  466. rc4Polyfill,
  467. rc4FunctionName,
  468. selfDefendingCode: '',
  469. stringArrayCacheName,
  470. stringArrayCallsWrapperName
  471. }
  472. );
  473. const stringArrayCallsWrapperTemplate: string = await minimizeCode(
  474. format(StringArrayCallsWrapperTemplate(), {
  475. decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
  476. indexShiftAmount,
  477. stringArrayCacheName,
  478. stringArrayCallsWrapperName,
  479. stringArrayFunctionName
  480. })
  481. );
  482. console.log(stringArrayCallsWrapperTemplate);
  483. decodedValue = Function(`
  484. ${stringArrayTemplate}
  485. ${stringArrayCallsWrapperTemplate}
  486. return ${stringArrayCallsWrapperName}('${index}', '${key}');
  487. `)();
  488. });
  489. it('should correctly return decoded value', () => {
  490. assert.deepEqual(decodedValue, expectedDecodedValue);
  491. });
  492. });
  493. });
  494. describe('Variant #2: invalid code evaluation for multi-line code', () => {
  495. describe('Variant #1: long decoded string', () => {
  496. const index: string = '0x0';
  497. const key: string = 'key';
  498. const indexShiftAmount: number = 0;
  499. const expectedDecodedValue: string = 'test\u001c';
  500. let decodedValue: string;
  501. before(() => {
  502. const stringArrayTemplate = format(StringArrayTemplate(), {
  503. stringArrayName,
  504. stringArrayFunctionName,
  505. stringArrayStorageItems: `'${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'`
  506. });
  507. const atobPolyfill = format(AtobTemplate(selfDefendingEnabled), {
  508. atobFunctionName
  509. });
  510. const rc4Polyfill = format(Rc4Template(), {
  511. atobFunctionName,
  512. rc4FunctionName
  513. });
  514. const rc4decodeCodeHelperTemplate: string = format(
  515. StringArrayRC4DecodeTemplate(randomGenerator),
  516. {
  517. atobPolyfill,
  518. rc4Polyfill,
  519. rc4FunctionName,
  520. selfDefendingCode: '',
  521. stringArrayCacheName,
  522. stringArrayCallsWrapperName
  523. }
  524. );
  525. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  526. decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
  527. indexShiftAmount,
  528. stringArrayCacheName,
  529. stringArrayCallsWrapperName,
  530. stringArrayFunctionName
  531. });
  532. decodedValue = Function(`
  533. ${stringArrayTemplate}
  534. ${stringArrayCallsWrapperTemplate}
  535. return ${stringArrayCallsWrapperName}('${index}', '${key}');
  536. `)();
  537. });
  538. it('should correctly return decoded value', () => {
  539. assert.deepEqual(decodedValue, expectedDecodedValue);
  540. });
  541. });
  542. });
  543. });
  544. });
  545. describe('Prevailing kind of variables', () => {
  546. describe('`var` kind', () => {
  547. let obfuscatedCode: string,
  548. stringArrayCallsWrapperVariableRegExp: RegExp = /var (_0x(\w){4,6}) *= *(_0x(\w){4,6})\[(_0x(\w){4,6})];/;
  549. beforeEach(() => {
  550. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
  551. const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
  552. code,
  553. {
  554. ...NO_ADDITIONAL_NODES_PRESET,
  555. stringArray: true,
  556. stringArrayThreshold: 1
  557. }
  558. );
  559. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  560. });
  561. it('Should return correct kind of variables for string array calls wrapper code', () => {
  562. assert.match(obfuscatedCode, stringArrayCallsWrapperVariableRegExp);
  563. });
  564. it('Should does not break on obfuscating', () => {
  565. assert.doesNotThrow(() => obfuscatedCode);
  566. });
  567. });
  568. describe('`const` kind', () => {
  569. let obfuscatedCode: string,
  570. stringArrayCallsWrapperVariableRegExp: RegExp = /let (_0x(\w){4,6}) *= *(_0x(\w){4,6})\[(_0x(\w){4,6})];/;
  571. beforeEach(() => {
  572. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
  573. const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
  574. code,
  575. {
  576. ...NO_ADDITIONAL_NODES_PRESET,
  577. stringArray: true,
  578. stringArrayThreshold: 1
  579. }
  580. );
  581. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  582. });
  583. it('Should return correct kind of variables for string array calls wrapper code', () => {
  584. assert.match(obfuscatedCode, stringArrayCallsWrapperVariableRegExp);
  585. });
  586. it('Should does not break on obfuscating', () => {
  587. assert.doesNotThrow(() => obfuscatedCode);
  588. });
  589. });
  590. describe('`let` kind', () => {
  591. let obfuscatedCode: string,
  592. stringArrayCallsWrapperVariableRegExp: RegExp = /let (_0x(\w){4,6}) *= *(_0x(\w){4,6})\[(_0x(\w){4,6})];/;
  593. beforeEach(() => {
  594. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
  595. const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
  596. code,
  597. {
  598. ...NO_ADDITIONAL_NODES_PRESET,
  599. stringArray: true,
  600. stringArrayThreshold: 1
  601. }
  602. );
  603. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  604. });
  605. it('Should return correct kind of variables for string array calls wrapper code', () => {
  606. assert.match(obfuscatedCode, stringArrayCallsWrapperVariableRegExp);
  607. });
  608. it('Should does not break on obfuscating', () => {
  609. assert.doesNotThrow(() => obfuscatedCode);
  610. });
  611. });
  612. });
  613. });