StringArrayCallsWrapperTemplate.spec.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. import 'reflect-metadata';
  2. import format from 'string-template';
  3. import { assert } from 'chai';
  4. import { ServiceIdentifiers } from '../../../../../../src/container/ServiceIdentifiers';
  5. import { ICryptUtilsSwappedAlphabet } from '../../../../../../src/interfaces/utils/ICryptUtilsSwappedAlphabet';
  6. import { IInversifyContainerFacade } from '../../../../../../src/interfaces/container/IInversifyContainerFacade';
  7. import { IObfuscatedCode } from '../../../../../../src/interfaces/source-code/IObfuscatedCode';
  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 { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
  15. import { InversifyContainerFacade } from '../../../../../../src/container/InversifyContainerFacade';
  16. import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscatorFacade';
  17. import { readFileAsString } from '../../../../../helpers/readFileAsString';
  18. describe('StringArrayCallsWrapperTemplate', () => {
  19. const stringArrayName: string = 'stringArrayName';
  20. const stringArrayCallsWrapperName: string = 'stringArrayCallsWrapperName';
  21. const atobFunctionName: string = 'atob';
  22. let cryptUtilsSwappedAlphabet: ICryptUtilsSwappedAlphabet,
  23. randomGenerator: IRandomGenerator;
  24. before(() => {
  25. const inversifyContainerFacade: IInversifyContainerFacade = new InversifyContainerFacade();
  26. inversifyContainerFacade.load('', '', {});
  27. cryptUtilsSwappedAlphabet = inversifyContainerFacade
  28. .get<ICryptUtilsSwappedAlphabet>(ServiceIdentifiers.ICryptUtilsSwappedAlphabet);
  29. randomGenerator = inversifyContainerFacade
  30. .get<IRandomGenerator>(ServiceIdentifiers.IRandomGenerator);
  31. });
  32. describe('Variant #1: `base64` encoding', () => {
  33. describe('Variant #1: index shift amount is `0`', () => {
  34. const index: string = '0x0';
  35. const indexShiftAmount: number = 0;
  36. const expectedDecodedValue: string = 'test1';
  37. let decodedValue: string;
  38. before(() => {
  39. const atobPolyfill = format(AtobTemplate(), {
  40. atobFunctionName
  41. });
  42. const atobDecodeTemplate: string = format(
  43. StringArrayBase64DecodeTemplate(randomGenerator),
  44. {
  45. atobPolyfill,
  46. atobFunctionName,
  47. selfDefendingCode: '',
  48. stringArrayCallsWrapperName
  49. }
  50. );
  51. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  52. decodeCodeHelperTemplate: atobDecodeTemplate,
  53. indexShiftAmount,
  54. stringArrayCallsWrapperName,
  55. stringArrayName
  56. });
  57. decodedValue = Function(`
  58. var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa('test1')}'];
  59. ${stringArrayCallsWrapperTemplate}
  60. return ${stringArrayCallsWrapperName}(${index});
  61. `)();
  62. });
  63. it('should correctly return decoded value', () => {
  64. assert.deepEqual(decodedValue, expectedDecodedValue);
  65. });
  66. });
  67. describe('Variant #2: index shift amount is `5`', () => {
  68. const index: string = '0x5';
  69. const indexShiftAmount: number = 5;
  70. const expectedDecodedValue: string = 'test1';
  71. let decodedValue: string;
  72. before(() => {
  73. const atobPolyfill = format(AtobTemplate(), {
  74. atobFunctionName
  75. });
  76. const atobDecodeTemplate: string = format(
  77. StringArrayBase64DecodeTemplate(randomGenerator),
  78. {
  79. atobPolyfill,
  80. atobFunctionName,
  81. selfDefendingCode: '',
  82. stringArrayCallsWrapperName
  83. }
  84. );
  85. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  86. decodeCodeHelperTemplate: atobDecodeTemplate,
  87. indexShiftAmount,
  88. stringArrayCallsWrapperName,
  89. stringArrayName
  90. });
  91. decodedValue = Function(`
  92. var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa('test1')}'];
  93. ${stringArrayCallsWrapperTemplate}
  94. return ${stringArrayCallsWrapperName}(${index});
  95. `)();
  96. });
  97. it('should correctly return decoded value', () => {
  98. assert.deepEqual(decodedValue, expectedDecodedValue);
  99. });
  100. });
  101. });
  102. describe('Variant #2: `rc4` encoding', () => {
  103. describe('Variant #1: index shift amount is `0`', () => {
  104. const index: string = '0x0';
  105. const key: string = 'key';
  106. const indexShiftAmount: number = 0;
  107. const expectedDecodedValue: string = 'test1';
  108. let decodedValue: string;
  109. before(() => {
  110. const atobPolyfill = format(AtobTemplate(), {
  111. atobFunctionName
  112. });
  113. const rc4Polyfill = format(Rc4Template(), {
  114. atobFunctionName
  115. });
  116. const rc4decodeCodeHelperTemplate: string = format(
  117. StringArrayRC4DecodeTemplate(randomGenerator),
  118. {
  119. atobPolyfill,
  120. rc4Polyfill,
  121. selfDefendingCode: '',
  122. stringArrayCallsWrapperName
  123. }
  124. );
  125. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  126. decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
  127. indexShiftAmount,
  128. stringArrayCallsWrapperName,
  129. stringArrayName
  130. });
  131. decodedValue = Function(`
  132. var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'];
  133. ${stringArrayCallsWrapperTemplate}
  134. return ${stringArrayCallsWrapperName}('${index}', '${key}');
  135. `)();
  136. });
  137. it('should correctly return decoded value', () => {
  138. assert.deepEqual(decodedValue, expectedDecodedValue);
  139. });
  140. });
  141. describe('Variant #2: index shift amount is `5`', () => {
  142. const index: string = '0x5';
  143. const key: string = 'key';
  144. const indexShiftAmount: number = 5;
  145. const expectedDecodedValue: string = 'test1';
  146. let decodedValue: string;
  147. before(() => {
  148. const atobPolyfill = format(AtobTemplate(), {
  149. atobFunctionName
  150. });
  151. const rc4Polyfill = format(Rc4Template(), {
  152. atobFunctionName
  153. });
  154. const rc4decodeCodeHelperTemplate: string = format(
  155. StringArrayRC4DecodeTemplate(randomGenerator),
  156. {
  157. atobPolyfill,
  158. rc4Polyfill,
  159. selfDefendingCode: '',
  160. stringArrayCallsWrapperName
  161. }
  162. );
  163. const stringArrayCallsWrapperTemplate: string = format(StringArrayCallsWrapperTemplate(), {
  164. decodeCodeHelperTemplate: rc4decodeCodeHelperTemplate,
  165. indexShiftAmount,
  166. stringArrayCallsWrapperName,
  167. stringArrayName
  168. });
  169. decodedValue = Function(`
  170. var ${stringArrayName} = ['${cryptUtilsSwappedAlphabet.btoa(cryptUtilsSwappedAlphabet.rc4('test1', key))}'];
  171. ${stringArrayCallsWrapperTemplate}
  172. return ${stringArrayCallsWrapperName}('${index}', '${key}');
  173. `)();
  174. });
  175. it('should correctly return decoded value', () => {
  176. assert.deepEqual(decodedValue, expectedDecodedValue);
  177. });
  178. });
  179. });
  180. describe('Prevailing kind of variables', () => {
  181. describe('`var` kind', () => {
  182. let obfuscatedCode: string,
  183. stringArrayCallsWrapperRegExp: RegExp = /var (_0x(\w){4}) *= *function/;
  184. beforeEach(() => {
  185. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-var.js');
  186. const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
  187. code,
  188. {
  189. ...NO_ADDITIONAL_NODES_PRESET,
  190. stringArray: true,
  191. stringArrayThreshold: 1
  192. }
  193. );
  194. obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
  195. });
  196. it('Should return correct kind of variables for string array calls wrapper', () => {
  197. assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
  198. });
  199. it('Should does not break on obfuscating', () => {
  200. assert.doesNotThrow(() => obfuscatedCode);
  201. });
  202. });
  203. describe('`const` kind', () => {
  204. let obfuscatedCode: string,
  205. stringArrayCallsWrapperRegExp: RegExp = /const (_0x(\w){4}) *= *function/;
  206. beforeEach(() => {
  207. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-const.js');
  208. const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
  209. code,
  210. {
  211. ...NO_ADDITIONAL_NODES_PRESET,
  212. stringArray: true,
  213. stringArrayThreshold: 1
  214. }
  215. );
  216. obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
  217. });
  218. it('Should return correct kind of variables for string array calls wrapper', () => {
  219. assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
  220. });
  221. it('Should does not break on obfuscating', () => {
  222. assert.doesNotThrow(() => obfuscatedCode);
  223. });
  224. });
  225. describe('`let` kind', () => {
  226. let obfuscatedCode: string,
  227. stringArrayCallsWrapperRegExp: RegExp = /const (_0x(\w){4}) *= *function/;
  228. beforeEach(() => {
  229. const code: string = readFileAsString(__dirname + '/fixtures/prevailing-kind-of-variables-let.js');
  230. const obfuscatedCodeObject: IObfuscatedCode = JavaScriptObfuscator.obfuscate(
  231. code,
  232. {
  233. ...NO_ADDITIONAL_NODES_PRESET,
  234. stringArray: true,
  235. stringArrayThreshold: 1
  236. }
  237. );
  238. obfuscatedCode = obfuscatedCodeObject.getObfuscatedCode();
  239. });
  240. it('Should return correct kind of variables for string array calls wrapper', () => {
  241. assert.match(obfuscatedCode, stringArrayCallsWrapperRegExp);
  242. });
  243. it('Should does not break on obfuscating', () => {
  244. assert.doesNotThrow(() => obfuscatedCode);
  245. });
  246. });
  247. });
  248. });