DomainLockNodeTemplate.spec.ts 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  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 { IObfuscatedCode } from '../../../../../src/interfaces/source-code/IObfuscatedCode';
  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 all domains of `domainsString`', () => {
  135. describe('Variant #1', () => {
  136. const domainsString: string = ['example.com', '.example.com'].join(';');
  137. const currentDomain: string = 'example.com';
  138. let testFunc: () => void;
  139. before(() => {
  140. const [
  141. hiddenDomainsString,
  142. diff
  143. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  144. testFunc = () => getFunctionFromTemplate(
  145. {
  146. domainLockFunctionName: 'domainLockFunction',
  147. diff: diff,
  148. domains: hiddenDomainsString,
  149. globalVariableTemplate: GlobalVariableTemplate1(),
  150. singleCallControllerFunctionName
  151. },
  152. singleCallControllerFunctionName,
  153. getDocumentDomainTemplate(currentDomain)
  154. );
  155. });
  156. it('should correctly run code inside template', () => {
  157. assert.doesNotThrow(testFunc);
  158. });
  159. });
  160. describe('Variant #2', () => {
  161. const domainsString: string = ['example.com', '.example.com'].join(';');
  162. const currentDomain: string = 'subdomain.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 #3', () => {
  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 #4', () => {
  211. const domainsString: string = ['sub1.example.com', 'sub2.example.com'].join(';');
  212. const currentDomain: string = 'sub1.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. });
  236. describe('Variant #4: current domain matches with base domain of `domainsString` item', () => {
  237. const domainsString: string = ['www.test.com', '.example.com'].join(';');
  238. const currentDomain: string = 'subdomain.example.com';
  239. let testFunc: () => void;
  240. before(() => {
  241. const [
  242. hiddenDomainsString,
  243. diff
  244. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  245. testFunc = () => getFunctionFromTemplate(
  246. {
  247. domainLockFunctionName: 'domainLockFunction',
  248. diff: diff,
  249. domains: hiddenDomainsString,
  250. globalVariableTemplate: GlobalVariableTemplate1(),
  251. singleCallControllerFunctionName
  252. },
  253. singleCallControllerFunctionName,
  254. getDocumentDomainTemplate(currentDomain)
  255. );
  256. });
  257. it('should correctly run code inside template', () => {
  258. assert.doesNotThrow(testFunc);
  259. });
  260. });
  261. describe('Variant #5: current domain doesn\'t match with `domainsString`', () => {
  262. describe('Variant #1', () => {
  263. const domainsString: string = ['www.example.com'].join(';');
  264. const currentDomain: string = 'www.test.com';
  265. let testFunc: () => void;
  266. before(() => {
  267. const [
  268. hiddenDomainsString,
  269. diff
  270. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  271. testFunc = () => getFunctionFromTemplate(
  272. {
  273. domainLockFunctionName: 'domainLockFunction',
  274. diff: diff,
  275. domains: hiddenDomainsString,
  276. globalVariableTemplate: GlobalVariableTemplate1(),
  277. singleCallControllerFunctionName
  278. },
  279. singleCallControllerFunctionName,
  280. getDocumentDomainTemplate(currentDomain)
  281. );
  282. });
  283. it('should throw an error', () => {
  284. assert.throws(testFunc);
  285. });
  286. });
  287. describe('Variant #2', () => {
  288. const domainsString: string = ['sub1.test.com', 'sub2.test.com'].join(';');
  289. const currentDomain: string = 'sub3.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. domainLockFunctionName: 'domainLockFunction',
  298. diff: diff,
  299. domains: hiddenDomainsString,
  300. globalVariableTemplate: GlobalVariableTemplate1(),
  301. singleCallControllerFunctionName
  302. },
  303. singleCallControllerFunctionName,
  304. getDocumentDomainTemplate(currentDomain)
  305. );
  306. });
  307. it('should throw an error', () => {
  308. assert.throws(testFunc);
  309. });
  310. });
  311. describe('Variant #3', () => {
  312. const domainsString: string = ['www.example.com', '.example.com', 'sub.test.com'].join(';');
  313. const currentDomain: string = 'www.test.com';
  314. let testFunc: () => void;
  315. before(() => {
  316. const [
  317. hiddenDomainsString,
  318. diff
  319. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  320. testFunc = () => getFunctionFromTemplate(
  321. {
  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. });
  337. describe('Variant #6: location.hostname', () => {
  338. describe('Variant #1: current location.hostname matches with `domainsString`', () => {
  339. const domainsString: string = ['www.example.com'].join(';');
  340. const currentHostName: string = 'www.example.com';
  341. let testFunc: () => void;
  342. before(() => {
  343. const [
  344. hiddenDomainsString,
  345. diff
  346. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  347. testFunc = () => getFunctionFromTemplate(
  348. {
  349. domainLockFunctionName: 'domainLockFunction',
  350. diff: diff,
  351. domains: hiddenDomainsString,
  352. globalVariableTemplate: GlobalVariableTemplate1(),
  353. singleCallControllerFunctionName
  354. },
  355. singleCallControllerFunctionName,
  356. getDocumentLocationTemplate(currentHostName)
  357. );
  358. });
  359. it('should correctly run code inside template', () => {
  360. assert.doesNotThrow(testFunc);
  361. });
  362. });
  363. describe('Variant #2: current location.hostname doesn\'t match with `domainsString`', () => {
  364. const domainsString: string = ['www.example.com'].join(';');
  365. const currentHostName: string = 'www.test.com';
  366. let testFunc: () => void;
  367. before(() => {
  368. const [
  369. hiddenDomainsString,
  370. diff
  371. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  372. testFunc = () => getFunctionFromTemplate(
  373. {
  374. domainLockFunctionName: 'domainLockFunction',
  375. diff: diff,
  376. domains: hiddenDomainsString,
  377. globalVariableTemplate: GlobalVariableTemplate1(),
  378. singleCallControllerFunctionName
  379. },
  380. singleCallControllerFunctionName,
  381. getDocumentLocationTemplate(currentHostName)
  382. );
  383. });
  384. it('should throw an error', () => {
  385. assert.throws(testFunc);
  386. });
  387. });
  388. });
  389. describe('Variant #7: domain and location.hostname presented', () => {
  390. describe('Variant #1: current domain matches with `domainsString`', () => {
  391. const domainsString: string = ['www.example.com'].join(';');
  392. const currentHostName: string = 'www.example.com';
  393. let testFunc: () => void;
  394. before(() => {
  395. const [
  396. hiddenDomainsString,
  397. diff
  398. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  399. testFunc = () => getFunctionFromTemplate(
  400. {
  401. domainLockFunctionName: 'domainLockFunction',
  402. diff: diff,
  403. domains: hiddenDomainsString,
  404. globalVariableTemplate: GlobalVariableTemplate1(),
  405. singleCallControllerFunctionName
  406. },
  407. singleCallControllerFunctionName,
  408. getDocumentDomainAndLocationTemplate(currentHostName)
  409. );
  410. });
  411. it('should correctly run code inside template', () => {
  412. assert.doesNotThrow(testFunc);
  413. });
  414. });
  415. describe('Variant #2: current domain doesn\'t match with `domainsString`', () => {
  416. const domainsString: string = ['www.example.com'].join(';');
  417. const currentHostName: string = 'www.test.com';
  418. let testFunc: () => void;
  419. before(() => {
  420. const [
  421. hiddenDomainsString,
  422. diff
  423. ] = cryptUtils.hideString(domainsString, domainsString.length * 3);
  424. testFunc = () => getFunctionFromTemplate(
  425. {
  426. domainLockFunctionName: 'domainLockFunction',
  427. diff: diff,
  428. domains: hiddenDomainsString,
  429. globalVariableTemplate: GlobalVariableTemplate1(),
  430. singleCallControllerFunctionName
  431. },
  432. singleCallControllerFunctionName,
  433. getDocumentDomainAndLocationTemplate(currentHostName)
  434. );
  435. });
  436. it('should throw an error', () => {
  437. assert.throws(testFunc);
  438. });
  439. });
  440. });
  441. describe('Prevailing kind of variables', () => {
  442. const getCodeTemplate = (obfuscatedCode: string) => `
  443. global.document = {
  444. domain: 'obfuscator.io'
  445. };
  446. ${obfuscatedCode}
  447. `;
  448. describe('`var` kind', () => {
  449. let obfuscatedCode: string,
  450. domainLockVariableRegExp: RegExp = /var _0x([a-f0-9]){4,6} *= *new *RegExp/;
  451. beforeEach(() => {
  452. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
  453. const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
  454. code,
  455. {
  456. ...NO_ADDITIONAL_NODES_PRESET,
  457. domainLock: ['obfuscator.io'],
  458. stringArray: true,
  459. stringArrayThreshold: 1
  460. }
  461. );
  462. obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
  463. });
  464. it('Should return correct kind of variables for domain lock code', () => {
  465. assert.match(obfuscatedCode, domainLockVariableRegExp);
  466. });
  467. it('Should does not break on obfuscating', () => {
  468. assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
  469. });
  470. });
  471. describe('`const` kind', () => {
  472. let obfuscatedCode: string,
  473. domainLockVariableRegExp: RegExp = /const _0x([a-f0-9]){4,6} *= *new *RegExp/;
  474. beforeEach(() => {
  475. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
  476. const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
  477. code,
  478. {
  479. ...NO_ADDITIONAL_NODES_PRESET,
  480. domainLock: ['obfuscator.io'],
  481. stringArray: true,
  482. stringArrayThreshold: 1
  483. }
  484. );
  485. obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
  486. });
  487. it('Should return correct kind of variables for domain lock code', () => {
  488. assert.match(obfuscatedCode, domainLockVariableRegExp);
  489. });
  490. it('Should does not break on obfuscating', () => {
  491. assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
  492. });
  493. });
  494. describe('`let` kind', () => {
  495. let obfuscatedCode: string,
  496. domainLockVariableRegExp: RegExp = /const _0x([a-f0-9]){4,6} *= *new *RegExp/;
  497. beforeEach(() => {
  498. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
  499. const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
  500. code,
  501. {
  502. ...NO_ADDITIONAL_NODES_PRESET,
  503. domainLock: ['obfuscator.io'],
  504. stringArray: true,
  505. stringArrayThreshold: 1
  506. }
  507. );
  508. obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
  509. });
  510. it('Should return correct kind of variables for domain lock code', () => {
  511. assert.match(obfuscatedCode, domainLockVariableRegExp);
  512. });
  513. it('Should does not break on obfuscating', () => {
  514. assert.doesNotThrow(() => eval(getCodeTemplate(obfuscatedCode)));
  515. });
  516. });
  517. });
  518. });