ConditionalCommentObfuscatingGuard.spec.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import { assert } from 'chai';
  2. import { JavaScriptObfuscator } from '../../../../../../src/JavaScriptObfuscatorFacade';
  3. import { NO_ADDITIONAL_NODES_PRESET } from '../../../../../../src/options/presets/NoCustomNodes';
  4. import { readFileAsString } from '../../../../../helpers/readFileAsString';
  5. describe('ConditionalCommentObfuscatingGuard', () => {
  6. describe('check', () => {
  7. describe('Variant #1: `disable` conditional comment', () => {
  8. const disableConditionalCommentRegExp: RegExp = /\/\/ *javascript-obfuscator:disable/;
  9. const obfuscatedVariableDeclarationRegExp: RegExp = /var _0x([a-f0-9]){5,6} *= *0x1;/;
  10. const ignoredVariableDeclarationRegExp: RegExp = /var bar *= *2;/;
  11. const consoleLogRegExp: RegExp = /console.log\(_0x([a-f0-9]){5,6}\);/;
  12. let obfuscatedCode: string;
  13. beforeEach(() => {
  14. const code: string = readFileAsString(__dirname + '/fixtures/simple.js');
  15. obfuscatedCode = JavaScriptObfuscator.obfuscate(
  16. code,
  17. {
  18. ...NO_ADDITIONAL_NODES_PRESET
  19. }
  20. ).getObfuscatedCode();
  21. });
  22. it('match #1: should remove `disable` conditional comment from the code', () => {
  23. assert.notMatch(obfuscatedCode, disableConditionalCommentRegExp);
  24. });
  25. it('match #2: should obfuscate variable declaration before `disable` conditional comment', () => {
  26. assert.match(obfuscatedCode, obfuscatedVariableDeclarationRegExp);
  27. });
  28. it('match #3: should ignore variable declaration after `disable` conditional comment', () => {
  29. assert.match(obfuscatedCode, ignoredVariableDeclarationRegExp);
  30. });
  31. it('match #4: should obfuscate variable name in `console.log`', () => {
  32. assert.match(obfuscatedCode, consoleLogRegExp);
  33. });
  34. });
  35. describe('Variant #2: `disable` and `enable` conditional comments #1', () => {
  36. const disableConditionalCommentRegExp: RegExp = /\/\/ *javascript-obfuscator:disable/;
  37. const enableConditionalCommentRegExp: RegExp = /\/\/ *javascript-obfuscator:enable/;
  38. const obfuscatedVariableDeclaration1RegExp: RegExp = /var _0x([a-f0-9]){5,6} *= *0x1;/;
  39. const obfuscatedVariableDeclaration2RegExp: RegExp = /var _0x([a-f0-9]){5,6} *= *0x3;/;
  40. const ignoredVariableDeclarationRegExp: RegExp = /var bar *= *2;/;
  41. let obfuscatedCode: string;
  42. beforeEach(() => {
  43. const code: string = readFileAsString(__dirname + '/fixtures/disable-and-enable-comments-1.js');
  44. obfuscatedCode = JavaScriptObfuscator.obfuscate(
  45. code,
  46. {
  47. ...NO_ADDITIONAL_NODES_PRESET
  48. }
  49. ).getObfuscatedCode();
  50. });
  51. it('match #1: should remove `disable` conditional comment from the code', () => {
  52. assert.notMatch(obfuscatedCode, disableConditionalCommentRegExp);
  53. });
  54. it('match #2: should remove `enable` conditional comment from the code', () => {
  55. assert.notMatch(obfuscatedCode, enableConditionalCommentRegExp);
  56. });
  57. it('match #3: should obfuscate variable declaration before `disable` conditional comment', () => {
  58. assert.match(obfuscatedCode, obfuscatedVariableDeclaration1RegExp);
  59. });
  60. it('match #4: should ignore variable declaration after `disable` conditional comment', () => {
  61. assert.match(obfuscatedCode, ignoredVariableDeclarationRegExp);
  62. });
  63. it('match #5: should obfuscate variable declaration after `enable` conditional comment', () => {
  64. assert.match(obfuscatedCode, obfuscatedVariableDeclaration2RegExp);
  65. });
  66. });
  67. describe('Variant #3: `disable` and `enable` conditional comments #2', () => {
  68. const ignoredVariableDeclarationRegExp: RegExp = /var foo *= *1;/;
  69. const obfuscatedVariableDeclarationRegExp: RegExp = /var _0x([a-f0-9]){5,6} *= *0x2;/;
  70. let obfuscatedCode: string;
  71. beforeEach(() => {
  72. const code: string = readFileAsString(__dirname + '/fixtures/disable-and-enable-comments-2.js');
  73. obfuscatedCode = JavaScriptObfuscator.obfuscate(
  74. code,
  75. {
  76. ...NO_ADDITIONAL_NODES_PRESET,
  77. renameGlobals: true
  78. }
  79. ).getObfuscatedCode();
  80. });
  81. it('match #1: should ignore variable declaration after `disable` conditional comment', () => {
  82. assert.match(obfuscatedCode, ignoredVariableDeclarationRegExp);
  83. });
  84. it('match #2: should obfuscate variable declaration before `disable` conditional comment', () => {
  85. assert.match(obfuscatedCode, obfuscatedVariableDeclarationRegExp);
  86. });
  87. });
  88. describe('Variant #4: `disable` conditional comment from beginning of the code', () => {
  89. const ignoredVariableDeclaration1RegExp: RegExp = /var foo *= *1;/;
  90. const ignoredVariableDeclaration2RegExp: RegExp = /var bar *= *2;/;
  91. let obfuscatedCode: string;
  92. beforeEach(() => {
  93. const code: string = readFileAsString(__dirname + '/fixtures/disable-from-beginning.js');
  94. obfuscatedCode = JavaScriptObfuscator.obfuscate(
  95. code,
  96. {
  97. ...NO_ADDITIONAL_NODES_PRESET
  98. }
  99. ).getObfuscatedCode();
  100. });
  101. it('match #1: should ignore variable declaration after `disable` conditional comment', () => {
  102. assert.match(obfuscatedCode, ignoredVariableDeclaration1RegExp);
  103. });
  104. it('match #2: should ignore variable declaration after `disable` conditional comment', () => {
  105. assert.match(obfuscatedCode, ignoredVariableDeclaration2RegExp);
  106. });
  107. });
  108. describe('Variant #5: `disable` and `enable` conditional comments with dead code injection', () => {
  109. const obfuscatedFunctionExpressionRegExp: RegExp = /var _0x([a-f0-9]){5,6} *= *function *\(_0x([a-f0-9]){5,6}, *_0x([a-f0-9]){5,6}, *_0x([a-f0-9]){5,6}\) *{/g;
  110. const expectedObfuscatedFunctionExpressionLength: number = 3;
  111. const ignoredFunctionExpression1RegExp: RegExp = /var bar *= *function *\(a, *b, *c\) *{/;
  112. const ignoredFunctionExpression2RegExp: RegExp = /var baz *= *function *\(a, *b, *c\) *{/;
  113. const obfuscatedFunctionCallRegExp: RegExp = /_0x([a-f0-9]){5,6}\( *\);/g;
  114. const expectedObfuscatedFunctionCallsLength: number = 3;
  115. const ignoredFunctionCall1RegExp: RegExp = /bar\( *\);/;
  116. const ignoredFunctionCall2RegExp: RegExp = /baz\( *\);/;
  117. let obfuscatedCode: string,
  118. obfuscatedFunctionExpressionMatchesLength: number,
  119. obfuscatedFunctionCallMatchesLength: number;
  120. beforeEach(() => {
  121. const code: string = readFileAsString(__dirname + '/fixtures/dead-code-injection.js');
  122. obfuscatedCode = JavaScriptObfuscator.obfuscate(
  123. code,
  124. {
  125. ...NO_ADDITIONAL_NODES_PRESET,
  126. deadCodeInjection: true,
  127. deadCodeInjectionThreshold: 1
  128. }
  129. ).getObfuscatedCode();
  130. const obfuscatedFunctionExpressionMatches: RegExpMatchArray | null = obfuscatedCode.match(
  131. obfuscatedFunctionExpressionRegExp
  132. );
  133. const obfuscatedFunctionCallMatches: RegExpMatchArray | null = obfuscatedCode.match(
  134. obfuscatedFunctionCallRegExp
  135. );
  136. obfuscatedFunctionExpressionMatchesLength = obfuscatedFunctionExpressionMatches
  137. ? obfuscatedFunctionExpressionMatches.length
  138. : 0;
  139. obfuscatedFunctionCallMatchesLength = obfuscatedFunctionCallMatches
  140. ? obfuscatedFunctionCallMatches.length
  141. : 0;
  142. });
  143. it('match #1: should ignore function expression after `disable` conditional comment', () => {
  144. assert.match(obfuscatedCode, ignoredFunctionExpression1RegExp);
  145. });
  146. it('match #2: should ignore function expression after `disable` conditional comment', () => {
  147. assert.match(obfuscatedCode, ignoredFunctionExpression2RegExp);
  148. });
  149. it('match #3: should ignore function expression call', () => {
  150. assert.match(obfuscatedCode, ignoredFunctionCall1RegExp);
  151. });
  152. it('match #4: should ignore function expression call', () => {
  153. assert.match(obfuscatedCode, ignoredFunctionCall2RegExp);
  154. });
  155. it('should obfuscate 3 function expressions', () => {
  156. assert.equal(obfuscatedFunctionExpressionMatchesLength, expectedObfuscatedFunctionExpressionLength);
  157. });
  158. it('should obfuscate 3 function expression calls', () => {
  159. assert.equal(obfuscatedFunctionCallMatchesLength, expectedObfuscatedFunctionCallsLength);
  160. });
  161. });
  162. describe('Variant #6: `disable` and `enable` conditional comments with control flow flattening', () => {
  163. const obfuscatedVariableDeclarationRegExp: RegExp = /var _0x([a-f0-9]){5,6} *= *_0x([a-f0-9]){5,6}\['\w{5}'];/;
  164. const ignoredVariableDeclarationRegExp: RegExp = /var bar *= *'bar';/;
  165. let obfuscatedCode: string;
  166. beforeEach(() => {
  167. const code: string = readFileAsString(__dirname + '/fixtures/control-flow-flattening.js');
  168. obfuscatedCode = JavaScriptObfuscator.obfuscate(
  169. code,
  170. {
  171. ...NO_ADDITIONAL_NODES_PRESET,
  172. controlFlowFlattening: true,
  173. controlFlowFlatteningThreshold: 1
  174. }
  175. ).getObfuscatedCode();
  176. });
  177. it('match #1: should obfuscate variable declaration before `disable` conditional comment', () => {
  178. assert.match(obfuscatedCode, obfuscatedVariableDeclarationRegExp);
  179. });
  180. it('match #2: should ignore variable declaration after `disable` conditional comment', () => {
  181. assert.match(obfuscatedCode, ignoredVariableDeclarationRegExp);
  182. });
  183. });
  184. });
  185. });