DomainLockNodeTemplate.spec.ts 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712
  1. import 'reflect-metadata';
  2. import format from 'string-template';
  3. import { assert } from 'chai';
  4. import { ServiceIdentifiers } from '../../../../../src/container/ServiceIdentifiers';
  5. import { ICryptUtils } from '../../../../../src/interfaces/utils/ICryptUtils';
  6. import { IInversifyContainerFacade } from '../../../../../src/interfaces/container/IInversifyContainerFacade';
  7. import { IObfuscationResult } from '../../../../../src/interfaces/source-code/IObfuscationResult';
  8. import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../src/options/presets/NoCustomNodes';
  9. import { DomainLockTemplate } from '../../../../../src/custom-code-helpers/domain-lock/templates/DomainLockTemplate';
  10. import { GlobalVariableTemplate1 } from '../../../../../src/custom-code-helpers/common/templates/GlobalVariableTemplate1';
  11. import { InversifyContainerFacade } from '../../../../../src/container/InversifyContainerFacade';
  12. import { JavaScriptObfuscator } from '../../../../../src/JavaScriptObfuscatorFacade';
  13. import { readFileAsString } from '../../../../helpers/readFileAsString';
  14. /**
  15. * @param {string} currentDomain
  16. * @returns {string}
  17. */
  18. function getDocumentDomainTemplate (currentDomain: string): string {
  19. return `
  20. document = {
  21. domain: '${currentDomain}'
  22. };
  23. `
  24. }
  25. /**
  26. * @param {string} currentDomain
  27. * @returns {string}
  28. */
  29. function getDocumentLocationTemplate (currentDomain: string): string {
  30. return `
  31. document = {
  32. location: {
  33. hostname: '${currentDomain}'
  34. }
  35. };
  36. `
  37. }
  38. /**
  39. * @param {string} currentDomain
  40. * @returns {string}
  41. */
  42. function getDocumentDomainAndLocationTemplate (currentDomain: string): string {
  43. return `
  44. document = {
  45. domain: '${currentDomain}',
  46. location: {
  47. hostname: '${currentDomain}'
  48. }
  49. };
  50. `
  51. }
  52. /**
  53. * @param templateData
  54. * @param {string} callsControllerFunctionName
  55. * @param {string} documentTemplate
  56. * @returns {Function}
  57. */
  58. function getFunctionFromTemplate (
  59. templateData: any,
  60. callsControllerFunctionName: string,
  61. documentTemplate: string
  62. ): Function {
  63. const domainLockTemplate: string = format(DomainLockTemplate(), templateData);
  64. return Function(`
  65. ${documentTemplate}
  66. var ${callsControllerFunctionName} = (function(){
  67. return function (context, fn){
  68. return function () {
  69. return fn.apply(context, arguments);
  70. };
  71. }
  72. })();
  73. ${domainLockTemplate}
  74. `)();
  75. }
  76. describe('DomainLockTemplate', () => {
  77. const singleCallControllerFunctionName: string = 'callsController';
  78. let cryptUtils: ICryptUtils;
  79. before(() => {
  80. const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
  81. inversifyContainerFacade.load('', '', {});
  82. cryptUtils = inversifyContainerFacade.get<ICryptUtils>(ServiceIdentifiers.ICryptUtils);
  83. });
  84. describe('Variant #1: current domain matches with `domainsString`', () => {
  85. const domainsString: string = ['www.example.com'].join(';');
  86. const currentDomain: string = 'www.example.com';
  87. let testFunc: () => void;
  88. before(() => {
  89. const [
  90. hiddenDomainsString,
  91. diff
  92. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  93. testFunc = () => getFunctionFromTemplate(
  94. {
  95. domainLockFunctionName: 'domainLockFunction',
  96. diff: diff,
  97. domains: hiddenDomainsString,
  98. globalVariableTemplate: GlobalVariableTemplate1(),
  99. singleCallControllerFunctionName
  100. },
  101. singleCallControllerFunctionName,
  102. getDocumentDomainTemplate(currentDomain)
  103. );
  104. });
  105. it('should correctly run code inside template', () => {
  106. assert.doesNotThrow(testFunc);
  107. });
  108. });
  109. describe('Variant #2: current domain matches with base domain of `domainsString`', () => {
  110. const domainsString: string = ['.example.com'].join(';');
  111. const currentDomain: string = 'www.example.com';
  112. let testFunc: () => void;
  113. before(() => {
  114. const [
  115. hiddenDomainsString,
  116. diff
  117. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  118. testFunc = () => getFunctionFromTemplate(
  119. {
  120. domainLockFunctionName: 'domainLockFunction',
  121. diff: diff,
  122. domains: hiddenDomainsString,
  123. globalVariableTemplate: GlobalVariableTemplate1(),
  124. singleCallControllerFunctionName
  125. },
  126. singleCallControllerFunctionName,
  127. getDocumentDomainTemplate(currentDomain)
  128. );
  129. });
  130. it('should correctly run code inside template', () => {
  131. assert.doesNotThrow(testFunc);
  132. });
  133. });
  134. describe('Variant #3: current domain matches with root domain of `domainsString`', () => {
  135. const domainsString: string = ['.example.com'].join(';');
  136. const currentDomain: string = 'example.com';
  137. let testFunc: () => void;
  138. before(() => {
  139. const [
  140. hiddenDomainsString,
  141. diff
  142. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  143. testFunc = () => getFunctionFromTemplate(
  144. {
  145. domainLockFunctionName: 'domainLockFunction',
  146. diff: diff,
  147. domains: hiddenDomainsString,
  148. globalVariableTemplate: GlobalVariableTemplate1(),
  149. singleCallControllerFunctionName
  150. },
  151. singleCallControllerFunctionName,
  152. getDocumentDomainTemplate(currentDomain)
  153. );
  154. });
  155. it('should correctly run code inside template', () => {
  156. assert.doesNotThrow(testFunc);
  157. });
  158. });
  159. describe('Variant #4: current root domain matches with `domainsString`', () => {
  160. describe('Variant #1', () => {
  161. const domainsString: string = ['example.com'].join(';');
  162. const currentDomain: string = 'example.com';
  163. let testFunc: () => void;
  164. before(() => {
  165. const [
  166. hiddenDomainsString,
  167. diff
  168. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  169. testFunc = () => getFunctionFromTemplate(
  170. {
  171. domainLockFunctionName: 'domainLockFunction',
  172. diff: diff,
  173. domains: hiddenDomainsString,
  174. globalVariableTemplate: GlobalVariableTemplate1(),
  175. singleCallControllerFunctionName
  176. },
  177. singleCallControllerFunctionName,
  178. getDocumentDomainTemplate(currentDomain)
  179. );
  180. });
  181. it('should correctly run code inside template', () => {
  182. assert.doesNotThrow(testFunc);
  183. });
  184. });
  185. describe('Variant #2', () => {
  186. const domainsString: string = ['example.com', '.example.com'].join(';');
  187. const currentDomain: string = 'subdomain.example.com';
  188. let testFunc: () => void;
  189. before(() => {
  190. const [
  191. hiddenDomainsString,
  192. diff
  193. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  194. testFunc = () => getFunctionFromTemplate(
  195. {
  196. domainLockFunctionName: 'domainLockFunction',
  197. diff: diff,
  198. domains: hiddenDomainsString,
  199. globalVariableTemplate: GlobalVariableTemplate1(),
  200. singleCallControllerFunctionName
  201. },
  202. singleCallControllerFunctionName,
  203. getDocumentDomainTemplate(currentDomain)
  204. );
  205. });
  206. it('should correctly run code inside template', () => {
  207. assert.doesNotThrow(testFunc);
  208. });
  209. });
  210. describe('Variant #3', () => {
  211. const domainsString: string = ['.example.com', 'example.com'].join(';');
  212. const currentDomain: string = 'subdomain.example.com';
  213. let testFunc: () => void;
  214. before(() => {
  215. const [
  216. hiddenDomainsString,
  217. diff
  218. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  219. testFunc = () => getFunctionFromTemplate(
  220. {
  221. domainLockFunctionName: 'domainLockFunction',
  222. diff: diff,
  223. domains: hiddenDomainsString,
  224. globalVariableTemplate: GlobalVariableTemplate1(),
  225. singleCallControllerFunctionName
  226. },
  227. singleCallControllerFunctionName,
  228. getDocumentDomainTemplate(currentDomain)
  229. );
  230. });
  231. it('should correctly run code inside template', () => {
  232. assert.doesNotThrow(testFunc);
  233. });
  234. });
  235. describe('Variant #4', () => {
  236. const domainsString: string = ['sub1.example.com', 'sub2.example.com'].join(';');
  237. const currentDomain: string = 'sub1.example.com';
  238. let testFunc: () => void;
  239. before(() => {
  240. const [
  241. hiddenDomainsString,
  242. diff
  243. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  244. testFunc = () => getFunctionFromTemplate(
  245. {
  246. domainLockFunctionName: 'domainLockFunction',
  247. diff: diff,
  248. domains: hiddenDomainsString,
  249. globalVariableTemplate: GlobalVariableTemplate1(),
  250. singleCallControllerFunctionName
  251. },
  252. singleCallControllerFunctionName,
  253. getDocumentDomainTemplate(currentDomain)
  254. );
  255. });
  256. it('should correctly run code inside template', () => {
  257. assert.doesNotThrow(testFunc);
  258. });
  259. });
  260. });
  261. describe('Variant #5: current domain matches with base domain of `domainsString` item', () => {
  262. const domainsString: string = ['www.test.com', '.example.com'].join(';');
  263. const currentDomain: string = 'subdomain.example.com';
  264. let testFunc: () => void;
  265. before(() => {
  266. const [
  267. hiddenDomainsString,
  268. diff
  269. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  270. testFunc = () => getFunctionFromTemplate(
  271. {
  272. domainLockFunctionName: 'domainLockFunction',
  273. diff: diff,
  274. domains: hiddenDomainsString,
  275. globalVariableTemplate: GlobalVariableTemplate1(),
  276. singleCallControllerFunctionName
  277. },
  278. singleCallControllerFunctionName,
  279. getDocumentDomainTemplate(currentDomain)
  280. );
  281. });
  282. it('should correctly run code inside template', () => {
  283. assert.doesNotThrow(testFunc);
  284. });
  285. });
  286. describe('Variant #6: current domain doesn\'t match with `domainsString`', () => {
  287. describe('Variant #1', () => {
  288. const domainsString: string = ['www.example.com'].join(';');
  289. const currentDomain: string = 'www.test.com';
  290. let testFunc: () => void;
  291. before(() => {
  292. const [
  293. hiddenDomainsString,
  294. diff
  295. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  296. testFunc = () => getFunctionFromTemplate(
  297. {
  298. domainLockFunctionName: 'domainLockFunction',
  299. diff: diff,
  300. domains: hiddenDomainsString,
  301. globalVariableTemplate: GlobalVariableTemplate1(),
  302. singleCallControllerFunctionName
  303. },
  304. singleCallControllerFunctionName,
  305. getDocumentDomainTemplate(currentDomain)
  306. );
  307. });
  308. it('should throw an error', () => {
  309. assert.throws(testFunc);
  310. });
  311. });
  312. describe('Variant #2', () => {
  313. const domainsString: string = ['sub1.test.com', 'sub2.test.com'].join(';');
  314. const currentDomain: string = 'sub3.test.com';
  315. let testFunc: () => void;
  316. before(() => {
  317. const [
  318. hiddenDomainsString,
  319. diff
  320. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  321. testFunc = () => getFunctionFromTemplate({
  322. domainLockFunctionName: 'domainLockFunction',
  323. diff: diff,
  324. domains: hiddenDomainsString,
  325. globalVariableTemplate: GlobalVariableTemplate1(),
  326. singleCallControllerFunctionName
  327. },
  328. singleCallControllerFunctionName,
  329. getDocumentDomainTemplate(currentDomain)
  330. );
  331. });
  332. it('should throw an error', () => {
  333. assert.throws(testFunc);
  334. });
  335. });
  336. describe('Variant #3', () => {
  337. const domainsString: string = ['www.example.com', '.example.com', 'sub.test.com'].join(';');
  338. const currentDomain: string = 'www.test.com';
  339. let testFunc: () => void;
  340. before(() => {
  341. const [
  342. hiddenDomainsString,
  343. diff
  344. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  345. testFunc = () => getFunctionFromTemplate(
  346. {
  347. domainLockFunctionName: 'domainLockFunction',
  348. diff: diff,
  349. domains: hiddenDomainsString,
  350. globalVariableTemplate: GlobalVariableTemplate1(),
  351. singleCallControllerFunctionName
  352. },
  353. singleCallControllerFunctionName,
  354. getDocumentDomainTemplate(currentDomain)
  355. );
  356. });
  357. it('should throw an error', () => {
  358. assert.throws(testFunc);
  359. });
  360. });
  361. describe('Variant #4', () => {
  362. const domainsString: string = ['.example.com'].join(';');
  363. const currentDomain: string = 'example1.com';
  364. let testFunc: () => void;
  365. before(() => {
  366. const [
  367. hiddenDomainsString,
  368. diff
  369. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  370. testFunc = () => getFunctionFromTemplate(
  371. {
  372. domainLockFunctionName: 'domainLockFunction',
  373. diff: diff,
  374. domains: hiddenDomainsString,
  375. globalVariableTemplate: GlobalVariableTemplate1(),
  376. singleCallControllerFunctionName
  377. },
  378. singleCallControllerFunctionName,
  379. getDocumentDomainTemplate(currentDomain)
  380. );
  381. });
  382. it('should throw an error', () => {
  383. assert.throws(testFunc);
  384. });
  385. });
  386. describe('Variant #4', () => {
  387. const domainsString: string = ['example.com'].join(';');
  388. const currentDomain: string = 'sub.example.com';
  389. let testFunc: () => void;
  390. before(() => {
  391. const [
  392. hiddenDomainsString,
  393. diff
  394. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  395. testFunc = () => getFunctionFromTemplate(
  396. {
  397. domainLockFunctionName: 'domainLockFunction',
  398. diff: diff,
  399. domains: hiddenDomainsString,
  400. globalVariableTemplate: GlobalVariableTemplate1(),
  401. singleCallControllerFunctionName
  402. },
  403. singleCallControllerFunctionName,
  404. getDocumentDomainTemplate(currentDomain)
  405. );
  406. });
  407. it('should throw an error', () => {
  408. assert.throws(testFunc);
  409. });
  410. });
  411. });
  412. describe('Variant #7: location.hostname', () => {
  413. describe('Variant #1: current location.hostname matches with `domainsString`', () => {
  414. const domainsString: string = ['www.example.com'].join(';');
  415. const currentHostName: string = 'www.example.com';
  416. let testFunc: () => void;
  417. before(() => {
  418. const [
  419. hiddenDomainsString,
  420. diff
  421. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  422. testFunc = () => getFunctionFromTemplate(
  423. {
  424. domainLockFunctionName: 'domainLockFunction',
  425. diff: diff,
  426. domains: hiddenDomainsString,
  427. globalVariableTemplate: GlobalVariableTemplate1(),
  428. singleCallControllerFunctionName
  429. },
  430. singleCallControllerFunctionName,
  431. getDocumentLocationTemplate(currentHostName)
  432. );
  433. });
  434. it('should correctly run code inside template', () => {
  435. assert.doesNotThrow(testFunc);
  436. });
  437. });
  438. describe('Variant #2: current location.hostname doesn\'t match with `domainsString`', () => {
  439. const domainsString: string = ['www.example.com'].join(';');
  440. const currentHostName: string = 'www.test.com';
  441. let testFunc: () => void;
  442. before(() => {
  443. const [
  444. hiddenDomainsString,
  445. diff
  446. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  447. testFunc = () => getFunctionFromTemplate(
  448. {
  449. domainLockFunctionName: 'domainLockFunction',
  450. diff: diff,
  451. domains: hiddenDomainsString,
  452. globalVariableTemplate: GlobalVariableTemplate1(),
  453. singleCallControllerFunctionName
  454. },
  455. singleCallControllerFunctionName,
  456. getDocumentLocationTemplate(currentHostName)
  457. );
  458. });
  459. it('should throw an error', () => {
  460. assert.throws(testFunc);
  461. });
  462. });
  463. });
  464. describe('Variant #8: domain and location.hostname presented', () => {
  465. describe('Variant #1: current domain matches with `domainsString`', () => {
  466. const domainsString: string = ['www.example.com'].join(';');
  467. const currentHostName: string = 'www.example.com';
  468. let testFunc: () => void;
  469. before(() => {
  470. const [
  471. hiddenDomainsString,
  472. diff
  473. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  474. testFunc = () => getFunctionFromTemplate(
  475. {
  476. domainLockFunctionName: 'domainLockFunction',
  477. diff: diff,
  478. domains: hiddenDomainsString,
  479. globalVariableTemplate: GlobalVariableTemplate1(),
  480. singleCallControllerFunctionName
  481. },
  482. singleCallControllerFunctionName,
  483. getDocumentDomainAndLocationTemplate(currentHostName)
  484. );
  485. });
  486. it('should correctly run code inside template', () => {
  487. assert.doesNotThrow(testFunc);
  488. });
  489. });
  490. describe('Variant #2: current domain doesn\'t match with `domainsString`', () => {
  491. const domainsString: string = ['www.example.com'].join(';');
  492. const currentHostName: string = 'www.test.com';
  493. let testFunc: () => void;
  494. before(() => {
  495. const [
  496. hiddenDomainsString,
  497. diff
  498. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  499. testFunc = () => getFunctionFromTemplate(
  500. {
  501. domainLockFunctionName: 'domainLockFunction',
  502. diff: diff,
  503. domains: hiddenDomainsString,
  504. globalVariableTemplate: GlobalVariableTemplate1(),
  505. singleCallControllerFunctionName
  506. },
  507. singleCallControllerFunctionName,
  508. getDocumentDomainAndLocationTemplate(currentHostName)
  509. );
  510. });
  511. it('should throw an error', () => {
  512. assert.throws(testFunc);
  513. });
  514. });
  515. });
  516. describe('Prevailing kind of variables', () => {
  517. const getCodeTemplate = (obfuscatedCode: string) => `
  518. global.document = {
  519. domain: 'obfuscator.io'
  520. };
  521. ${obfuscatedCode}
  522. `;
  523. describe('`var` kind', () => {
  524. let obfuscatedCode: string,
  525. domainLockVariableRegExp: RegExp = /var _0x([a-f0-9]){4,6} *= *new *RegExp/;
  526. beforeEach(() => {
  527. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
  528. const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
  529. code,
  530. {
  531. ...NO_ADDITIONAL_NODES_PRESET,
  532. domainLock: ['obfuscator.io'],
  533. stringArray: true,
  534. stringArrayThreshold: 1
  535. }
  536. );
  537. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  538. });
  539. it('Should return correct kind of variables for domain lock code', () => {
  540. assert.match(obfuscatedCode, domainLockVariableRegExp);
  541. });
  542. it('Should does not break on obfuscating', () => {
  543. assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
  544. });
  545. });
  546. describe('`const` kind', () => {
  547. let obfuscatedCode: string,
  548. domainLockVariableRegExp: RegExp = /const _0x([a-f0-9]){4,6} *= *new *RegExp/;
  549. beforeEach(() => {
  550. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
  551. const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
  552. code,
  553. {
  554. ...NO_ADDITIONAL_NODES_PRESET,
  555. domainLock: ['obfuscator.io'],
  556. stringArray: true,
  557. stringArrayThreshold: 1
  558. }
  559. );
  560. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  561. });
  562. it('Should return correct kind of variables for domain lock code', () => {
  563. assert.match(obfuscatedCode, domainLockVariableRegExp);
  564. });
  565. it('Should does not break on obfuscating', () => {
  566. assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
  567. });
  568. });
  569. describe('`let` kind', () => {
  570. let obfuscatedCode: string,
  571. domainLockVariableRegExp: RegExp = /const _0x([a-f0-9]){4,6} *= *new *RegExp/;
  572. beforeEach(() => {
  573. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
  574. const obfuscationResult: IObfuscationResult = JavaScriptObfuscator.obfuscate(
  575. code,
  576. {
  577. ...NO_ADDITIONAL_NODES_PRESET,
  578. domainLock: ['obfuscator.io'],
  579. stringArray: true,
  580. stringArrayThreshold: 1
  581. }
  582. );
  583. obfuscatedCode = obfuscationResult.getObfuscatedCode();
  584. });
  585. it('Should return correct kind of variables for domain lock code', () => {
  586. assert.match(obfuscatedCode, domainLockVariableRegExp);
  587. });
  588. it('Should does not break on obfuscating', () => {
  589. assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
  590. });
  591. });
  592. });
  593. });