JavaScriptObfuscatorRuntime.spec.ts 11 KB

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