JavaScriptObfuscatorRuntime.spec.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. import { assert } from 'chai';
  2. import { TInputOptions } from '../../src/types/options/TInputOptions';
  3. import { StringArrayEncoding } from '../../src/enums/StringArrayEncoding';
  4. import { IdentifierNamesGenerator } from '../../src/enums/generators/identifier-names-generators/IdentifierNamesGenerator';
  5. import { evaluateInWorker } from '../helpers/evaluateInWorker';
  6. import { readFileAsString } from '../helpers/readFileAsString';
  7. import { JavaScriptObfuscator } from '../../src/JavaScriptObfuscatorFacade';
  8. const getEnvironmentCode = () => `
  9. global.document = {
  10. domain: 'obfuscator.io'
  11. };
  12. `;
  13. describe('JavaScriptObfuscator runtime eval', function () {
  14. const baseOptions: TInputOptions = {
  15. controlFlowFlattening: true,
  16. controlFlowFlatteningThreshold: 1,
  17. deadCodeInjection: true,
  18. deadCodeInjectionThreshold: 1,
  19. debugProtection: true,
  20. disableConsoleOutput: true,
  21. domainLock: ['obfuscator.io'],
  22. numbersToExpressions: true,
  23. simplify: true,
  24. renameProperties: true,
  25. reservedNames: ['generate', 'sha256'],
  26. rotateStringArray: true,
  27. selfDefending: true,
  28. splitStrings: true,
  29. splitStringsChunkLength: 5,
  30. stringArray: true,
  31. stringArrayEncoding: [
  32. StringArrayEncoding.None,
  33. StringArrayEncoding.Base64,
  34. StringArrayEncoding.Rc4
  35. ],
  36. stringArrayThreshold: 1,
  37. transformObjectKeys: true,
  38. unicodeEscapeSequence: true
  39. };
  40. this.timeout(200000);
  41. [
  42. {
  43. identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
  44. renameGlobals: false
  45. },
  46. {
  47. identifierNamesGenerator: IdentifierNamesGenerator.HexadecimalIdentifierNamesGenerator,
  48. renameGlobals: true
  49. },
  50. {
  51. identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
  52. renameGlobals: false
  53. },
  54. {
  55. identifierNamesGenerator: IdentifierNamesGenerator.MangledIdentifierNamesGenerator,
  56. renameGlobals: true
  57. },
  58. {
  59. identifierNamesGenerator: IdentifierNamesGenerator.MangledShuffledIdentifierNamesGenerator,
  60. renameGlobals: false
  61. },
  62. {
  63. identifierNamesGenerator: IdentifierNamesGenerator.MangledShuffledIdentifierNamesGenerator,
  64. renameGlobals: true
  65. }
  66. ].forEach((options: Partial<TInputOptions>) => {
  67. const detailedDescription: string = `Identifier names generator: ${options.identifierNamesGenerator}, rename globals: ${options.renameGlobals?.toString()}`;
  68. describe(`Astring. ${detailedDescription}`, () => {
  69. it('should obfuscate code without any runtime errors after obfuscation: Variant #1 astring', () => {
  70. const code: string = readFileAsString(__dirname + '/fixtures/astring.js');
  71. const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
  72. code,
  73. {
  74. ...baseOptions,
  75. ...options,
  76. renameProperties: false
  77. }
  78. ).getObfuscatedCode();
  79. let evaluationResult: string;
  80. try {
  81. evaluationResult = eval(`
  82. ${getEnvironmentCode()}
  83. ${obfuscatedCode}
  84. const code = generate({
  85. "type": "Program",
  86. "body": [
  87. {
  88. "type": "FunctionDeclaration",
  89. "id": {
  90. "type": "Identifier",
  91. "name": "test",
  92. "range": [
  93. 9,
  94. 13
  95. ]
  96. },
  97. "params": [],
  98. "body": {
  99. "type": "BlockStatement",
  100. "body": [
  101. {
  102. "type": "ReturnStatement",
  103. "argument": {
  104. "type": "Literal",
  105. "value": "foo",
  106. "raw": "'foo'",
  107. "range": [
  108. 30,
  109. 35
  110. ]
  111. },
  112. "range": [
  113. 23,
  114. 36
  115. ]
  116. }
  117. ],
  118. "range": [
  119. 17,
  120. 38
  121. ]
  122. },
  123. "generator": false,
  124. "expression": false,
  125. "async": false,
  126. "range": [
  127. 0,
  128. 38
  129. ]
  130. }
  131. ],
  132. "sourceType": "module",
  133. "range": [
  134. 0,
  135. 38
  136. ],
  137. "comments": []
  138. });
  139. eval(\`\${code} test();\`);
  140. `)
  141. } catch (e) {
  142. throw new Error(`Evaluation error: ${e.message}. Code: ${obfuscatedCode}`);
  143. }
  144. assert.equal(evaluationResult, 'foo');
  145. });
  146. });
  147. describe(`Sha256. ${detailedDescription}`, () => {
  148. it('should obfuscate code without any runtime errors after obfuscation: Variant #2 sha256', () => {
  149. const code: string = readFileAsString(__dirname + '/fixtures/sha256.js');
  150. const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
  151. code,
  152. {
  153. ...baseOptions,
  154. ...options
  155. }
  156. ).getObfuscatedCode();
  157. assert.equal(
  158. eval(`
  159. ${getEnvironmentCode()}
  160. ${obfuscatedCode}
  161. sha256('test');
  162. `),
  163. '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08'
  164. );
  165. });
  166. });
  167. describe(`Obfuscator. ${detailedDescription}`, () => {
  168. const evaluationTimeout: number = 50000;
  169. let evaluationResult: string;
  170. beforeEach(() => {
  171. const code: string = readFileAsString(process.cwd() + '/dist/index.js');
  172. const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
  173. code,
  174. {
  175. ...baseOptions,
  176. ...options,
  177. renameProperties: false
  178. }
  179. ).getObfuscatedCode();
  180. return evaluateInWorker(
  181. `
  182. ${getEnvironmentCode()}
  183. ${obfuscatedCode}
  184. module.exports.obfuscate('var foo = 1;').getObfuscatedCode();
  185. `,
  186. evaluationTimeout
  187. )
  188. .then((result: string | null) => {
  189. if (!result) {
  190. return;
  191. }
  192. evaluationResult = result;
  193. })
  194. .catch((error: Error) => {
  195. evaluationResult = `${error.message}. ${error.stack}. Code: ${obfuscatedCode}`;
  196. });
  197. });
  198. it('should obfuscate code without any runtime errors after obfuscation: Variant #3 obfuscator', () => {
  199. assert.equal(
  200. evaluationResult,
  201. 'var foo=0x1;'
  202. );
  203. });
  204. });
  205. [
  206. {
  207. debugProtection: false,
  208. selfDefending: false,
  209. stringArray: true
  210. },
  211. {
  212. debugProtection: false,
  213. selfDefending: true,
  214. stringArray: false
  215. },
  216. {
  217. debugProtection: true,
  218. selfDefending: false,
  219. stringArray: false
  220. },
  221. {
  222. debugProtection: true,
  223. selfDefending: true,
  224. stringArray: false
  225. },
  226. {
  227. debugProtection: true,
  228. selfDefending: true,
  229. stringArray: true
  230. }
  231. ].forEach((webpackBootstrapOptions: Partial<TInputOptions>) => {
  232. describe(`Webpack bootstrap code. ${detailedDescription}. ${JSON.stringify(webpackBootstrapOptions)}`, () => {
  233. let evaluationResult: string;
  234. beforeEach(() => {
  235. const code: string = readFileAsString(__dirname + '/fixtures/webpack-bootstrap.js');
  236. const obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
  237. code,
  238. {
  239. ...baseOptions,
  240. ...options,
  241. ...webpackBootstrapOptions,
  242. reservedNames: ['^foo$']
  243. }
  244. ).getObfuscatedCode();
  245. try {
  246. evaluationResult = eval(`
  247. ${getEnvironmentCode()}
  248. ${obfuscatedCode}
  249. `);
  250. } catch (e) {
  251. throw new Error(`Evaluation error: ${e.message}. Code: ${obfuscatedCode}`);
  252. }
  253. });
  254. it('should obfuscate code without any runtime errors after obfuscation: Variant #4 webpack bootstrap', () => {
  255. assert.equal(evaluationResult, 'foo');
  256. });
  257. });
  258. });
  259. });
  260. });