├── .gitignore ├── README.md ├── default-obfuscation-options.js ├── package-lock.json ├── package.json ├── stage-1 ├── deobfuscate.js ├── obfuscate.js ├── original-obfuscated.js ├── original.js └── output.js ├── stage-2 ├── deobfuscate.js ├── obfuscate.js ├── original-obfuscated.js ├── original.js └── output.js ├── stage-3 ├── deobfuscate.js ├── index.html ├── obfuscate.js ├── original-obfuscated.js ├── original.js └── output.js ├── stage-4 ├── deobfuscate.js ├── index.html ├── obfuscate.js ├── original-obfuscated.js ├── original.js ├── output.js └── output.ps └── stage-5 ├── deobfuscate.js ├── index.html ├── obfuscate.js ├── original-obfuscated.js ├── original.js ├── output.js └── output.ps /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to deobfuscate JavaScript 2 | 3 | Hacky code used in the reverse engineering streams here : https://www.youtube.com/watch?v=xkoFgPEfFLk&list=PLoZcQiQmH1DX6BEZdTJ6DifssHt9A8zaH 4 | 5 | No guarantees as to the state of code here. This will all be cleaned up at a later date. 6 | 7 | - Stage 1 https://www.youtube.com/watch?v=xkoFgPEfFLk 8 | - Stage 2 https://www.youtube.com/watch?v=YqmmFXVAEkA 9 | - Stage 3 https://www.youtube.com/watch?v=5eXpC6rx06U 10 | - Stage 4 https://www.youtube.com/watch?v=BdfHCOCL8fc 11 | - Stage 5 https://www.youtube.com/watch?v=VxgEwi6LfLc 12 | -------------------------------------------------------------------------------- /default-obfuscation-options.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | seed: 1, 3 | compact: true, 4 | controlFlowFlattening: false, 5 | controlFlowFlatteningThreshold: 0.75, 6 | deadCodeInjection: false, 7 | deadCodeInjectionThreshold: 0.4, 8 | debugProtection: false, 9 | debugProtectionInterval: false, 10 | disableConsoleOutput: false, 11 | domainLock: [], 12 | identifierNamesGenerator: 'hexadecimal', 13 | identifiersPrefix: '', 14 | inputFileName: '', 15 | log: false, 16 | renameGlobals: false, 17 | reservedNames: [], 18 | reservedStrings: [], 19 | rotateStringArray: true, 20 | seed: 0, 21 | selfDefending: false, 22 | sourceMap: false, 23 | sourceMapBaseUrl: '', 24 | sourceMapFileName: '', 25 | sourceMapMode: 'separate', 26 | stringArray: true, 27 | stringArrayEncoding: false, 28 | stringArrayThreshold: 1, 29 | target: 'browser', 30 | transformObjectKeys: false, 31 | unicodeEscapeSequence: false 32 | } -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/runtime": { 8 | "version": "7.0.0-rc.1", 9 | "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.0.0-rc.1.tgz", 10 | "integrity": "sha512-Nifv2kwP/nwR39cAOasNxzjYfpeuf/ZbZNtQz5eYxWTC9yHARU9wItFnAwz1GTZ62MU+AtSjzZPMbLK5Q9hmbg==", 11 | "requires": { 12 | "regenerator-runtime": "^0.12.0" 13 | } 14 | }, 15 | "acorn": { 16 | "version": "5.7.3", 17 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", 18 | "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==" 19 | }, 20 | "acorn-jsx": { 21 | "version": "4.1.1", 22 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", 23 | "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", 24 | "requires": { 25 | "acorn": "^5.0.3" 26 | } 27 | }, 28 | "amdefine": { 29 | "version": "1.0.1", 30 | "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", 31 | "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", 32 | "optional": true 33 | }, 34 | "ansi-escapes": { 35 | "version": "1.4.0", 36 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", 37 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" 38 | }, 39 | "ansi-regex": { 40 | "version": "2.1.1", 41 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 42 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 43 | }, 44 | "ansi-styles": { 45 | "version": "3.2.1", 46 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 47 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 48 | "requires": { 49 | "color-convert": "^1.9.0" 50 | } 51 | }, 52 | "array-differ": { 53 | "version": "1.0.0", 54 | "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", 55 | "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=" 56 | }, 57 | "array-union": { 58 | "version": "1.0.2", 59 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 60 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 61 | "requires": { 62 | "array-uniq": "^1.0.1" 63 | } 64 | }, 65 | "array-uniq": { 66 | "version": "1.0.3", 67 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 68 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=" 69 | }, 70 | "arrify": { 71 | "version": "1.0.1", 72 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 73 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" 74 | }, 75 | "babel-polyfill": { 76 | "version": "6.23.0", 77 | "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.23.0.tgz", 78 | "integrity": "sha1-g2TKYt+Or7gwSZ9pkXdGbDsDSZ0=", 79 | "requires": { 80 | "babel-runtime": "^6.22.0", 81 | "core-js": "^2.4.0", 82 | "regenerator-runtime": "^0.10.0" 83 | }, 84 | "dependencies": { 85 | "regenerator-runtime": { 86 | "version": "0.10.5", 87 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", 88 | "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" 89 | } 90 | } 91 | }, 92 | "babel-runtime": { 93 | "version": "6.26.0", 94 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 95 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", 96 | "requires": { 97 | "core-js": "^2.4.0", 98 | "regenerator-runtime": "^0.11.0" 99 | }, 100 | "dependencies": { 101 | "regenerator-runtime": { 102 | "version": "0.11.1", 103 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 104 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" 105 | } 106 | } 107 | }, 108 | "balanced-match": { 109 | "version": "1.0.0", 110 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 111 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 112 | }, 113 | "brace-expansion": { 114 | "version": "1.1.11", 115 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 116 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 117 | "requires": { 118 | "balanced-match": "^1.0.0", 119 | "concat-map": "0.0.1" 120 | } 121 | }, 122 | "buffer-from": { 123 | "version": "1.1.1", 124 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 125 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" 126 | }, 127 | "chalk": { 128 | "version": "2.4.1", 129 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 130 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 131 | "requires": { 132 | "ansi-styles": "^3.2.1", 133 | "escape-string-regexp": "^1.0.5", 134 | "supports-color": "^5.3.0" 135 | } 136 | }, 137 | "chance": { 138 | "version": "1.0.16", 139 | "resolved": "https://registry.npmjs.org/chance/-/chance-1.0.16.tgz", 140 | "integrity": "sha512-2bgDHH5bVfAXH05SPtjqrsASzZ7h90yCuYT2z4mkYpxxYvJXiIydBFzVieVHZx7wLH1Ag2Azaaej2/zA1XUrNQ==" 141 | }, 142 | "chardet": { 143 | "version": "0.4.2", 144 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", 145 | "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=" 146 | }, 147 | "charenc": { 148 | "version": "0.0.2", 149 | "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", 150 | "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" 151 | }, 152 | "class-validator": { 153 | "version": "0.9.1", 154 | "resolved": "https://registry.npmjs.org/class-validator/-/class-validator-0.9.1.tgz", 155 | "integrity": "sha512-3wApflrd3ywVZyx4jaasGoFt8pmo4aGLPPAEKCKCsTRWVGPilahD88q3jQjRQwja50rl9a7rsP5LAxJYwGK8/Q==", 156 | "requires": { 157 | "google-libphonenumber": "^3.1.6", 158 | "validator": "10.4.0" 159 | } 160 | }, 161 | "cli-cursor": { 162 | "version": "2.1.0", 163 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 164 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 165 | "requires": { 166 | "restore-cursor": "^2.0.0" 167 | } 168 | }, 169 | "cli-width": { 170 | "version": "2.2.0", 171 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 172 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" 173 | }, 174 | "color-convert": { 175 | "version": "1.9.3", 176 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 177 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 178 | "requires": { 179 | "color-name": "1.1.3" 180 | } 181 | }, 182 | "color-name": { 183 | "version": "1.1.3", 184 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 185 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 186 | }, 187 | "commander": { 188 | "version": "2.17.1", 189 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", 190 | "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==" 191 | }, 192 | "concat-map": { 193 | "version": "0.0.1", 194 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 195 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 196 | }, 197 | "core-js": { 198 | "version": "2.6.9", 199 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", 200 | "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==" 201 | }, 202 | "crypt": { 203 | "version": "0.0.2", 204 | "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", 205 | "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" 206 | }, 207 | "deep-is": { 208 | "version": "0.1.3", 209 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 210 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" 211 | }, 212 | "encoding": { 213 | "version": "0.1.12", 214 | "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", 215 | "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", 216 | "requires": { 217 | "iconv-lite": "~0.4.13" 218 | } 219 | }, 220 | "escape-string-regexp": { 221 | "version": "1.0.5", 222 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 223 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 224 | }, 225 | "escodegen-wallaby": { 226 | "version": "1.6.19", 227 | "resolved": "https://registry.npmjs.org/escodegen-wallaby/-/escodegen-wallaby-1.6.19.tgz", 228 | "integrity": "sha512-q+JGvR5+NR+EJBLnGAevCk5PIiIhPkUFCvcm6w9MWYtm8sv4FdGUsgzWsY6At/YHkgMyA366sjphA/JTNC8CeQ==", 229 | "requires": { 230 | "esprima": "^2.7.1", 231 | "estraverse": "^1.9.1", 232 | "esutils": "^2.0.2", 233 | "optionator": "^0.8.1", 234 | "source-map": "~0.2.0" 235 | }, 236 | "dependencies": { 237 | "estraverse": { 238 | "version": "1.9.3", 239 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", 240 | "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=" 241 | } 242 | } 243 | }, 244 | "espree": { 245 | "version": "4.0.0", 246 | "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", 247 | "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", 248 | "requires": { 249 | "acorn": "^5.6.0", 250 | "acorn-jsx": "^4.1.1" 251 | } 252 | }, 253 | "esprima": { 254 | "version": "2.7.3", 255 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", 256 | "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=" 257 | }, 258 | "estraverse": { 259 | "version": "4.2.0", 260 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 261 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" 262 | }, 263 | "esutils": { 264 | "version": "2.0.2", 265 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 266 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" 267 | }, 268 | "external-editor": { 269 | "version": "2.2.0", 270 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", 271 | "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", 272 | "requires": { 273 | "chardet": "^0.4.0", 274 | "iconv-lite": "^0.4.17", 275 | "tmp": "^0.0.33" 276 | } 277 | }, 278 | "fast-levenshtein": { 279 | "version": "2.0.6", 280 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 281 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" 282 | }, 283 | "figures": { 284 | "version": "2.0.0", 285 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 286 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 287 | "requires": { 288 | "escape-string-regexp": "^1.0.5" 289 | } 290 | }, 291 | "google-libphonenumber": { 292 | "version": "3.2.3", 293 | "resolved": "https://registry.npmjs.org/google-libphonenumber/-/google-libphonenumber-3.2.3.tgz", 294 | "integrity": "sha512-8n4JyRptifaIRlHANKRlfqLR8fANm7+Q+1qvDuUsUeStSLtLGTVsZWe1llWDfgWTm1y07cEUyiRuNIv6cs2ovg==" 295 | }, 296 | "has-ansi": { 297 | "version": "2.0.0", 298 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 299 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 300 | "requires": { 301 | "ansi-regex": "^2.0.0" 302 | } 303 | }, 304 | "has-flag": { 305 | "version": "3.0.0", 306 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 307 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 308 | }, 309 | "iconv-lite": { 310 | "version": "0.4.24", 311 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 312 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 313 | "requires": { 314 | "safer-buffer": ">= 2.1.2 < 3" 315 | } 316 | }, 317 | "inquirer": { 318 | "version": "3.0.6", 319 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.0.6.tgz", 320 | "integrity": "sha1-4EqqnQW3o8ubD0B9BDdfBEcZA0c=", 321 | "requires": { 322 | "ansi-escapes": "^1.1.0", 323 | "chalk": "^1.0.0", 324 | "cli-cursor": "^2.1.0", 325 | "cli-width": "^2.0.0", 326 | "external-editor": "^2.0.1", 327 | "figures": "^2.0.0", 328 | "lodash": "^4.3.0", 329 | "mute-stream": "0.0.7", 330 | "run-async": "^2.2.0", 331 | "rx": "^4.1.0", 332 | "string-width": "^2.0.0", 333 | "strip-ansi": "^3.0.0", 334 | "through": "^2.3.6" 335 | }, 336 | "dependencies": { 337 | "ansi-styles": { 338 | "version": "2.2.1", 339 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 340 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 341 | }, 342 | "chalk": { 343 | "version": "1.1.3", 344 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 345 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 346 | "requires": { 347 | "ansi-styles": "^2.2.1", 348 | "escape-string-regexp": "^1.0.2", 349 | "has-ansi": "^2.0.0", 350 | "strip-ansi": "^3.0.0", 351 | "supports-color": "^2.0.0" 352 | } 353 | }, 354 | "supports-color": { 355 | "version": "2.0.0", 356 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 357 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 358 | } 359 | } 360 | }, 361 | "inversify": { 362 | "version": "4.13.0", 363 | "resolved": "https://registry.npmjs.org/inversify/-/inversify-4.13.0.tgz", 364 | "integrity": "sha512-O5d8y7gKtyRwrvTLZzYET3kdFjqUy58sGpBYMARF13mzqDobpfBXVOPLH7HmnD2VR6Q+1HzZtslGvsdQfeb0SA==" 365 | }, 366 | "is-buffer": { 367 | "version": "1.1.6", 368 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 369 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 370 | }, 371 | "is-fullwidth-code-point": { 372 | "version": "2.0.0", 373 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 374 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" 375 | }, 376 | "is-promise": { 377 | "version": "2.1.0", 378 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 379 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 380 | }, 381 | "is-stream": { 382 | "version": "1.1.0", 383 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 384 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 385 | }, 386 | "javascript-obfuscator": { 387 | "version": "0.18.1", 388 | "resolved": "https://registry.npmjs.org/javascript-obfuscator/-/javascript-obfuscator-0.18.1.tgz", 389 | "integrity": "sha512-pQ2DyRV4j0neaWdII1S7iJftCyks9H7afVkQRSE4gslkqpeqyM1DE0eapsZKHR0BnYvw3tPU+Ky+j4yhzcxRZA==", 390 | "requires": { 391 | "@babel/runtime": "7.0.0-rc.1", 392 | "chalk": "2.4.1", 393 | "chance": "1.0.16", 394 | "class-validator": "0.9.1", 395 | "commander": "2.17.1", 396 | "escodegen-wallaby": "1.6.19", 397 | "espree": "4.0.0", 398 | "estraverse": "4.2.0", 399 | "inversify": "4.13.0", 400 | "js-string-escape": "1.0.1", 401 | "md5": "2.2.1", 402 | "mkdirp": "0.5.1", 403 | "multimatch": "2.1.0", 404 | "opencollective": "1.0.3", 405 | "reflect-metadata": "0.1.12", 406 | "source-map-support": "0.5.8", 407 | "string-template": "1.0.0", 408 | "tslib": "1.9.3" 409 | } 410 | }, 411 | "js-string-escape": { 412 | "version": "1.0.1", 413 | "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", 414 | "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=" 415 | }, 416 | "levn": { 417 | "version": "0.3.0", 418 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 419 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 420 | "requires": { 421 | "prelude-ls": "~1.1.2", 422 | "type-check": "~0.3.2" 423 | } 424 | }, 425 | "lodash": { 426 | "version": "4.17.15", 427 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 428 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" 429 | }, 430 | "md5": { 431 | "version": "2.2.1", 432 | "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", 433 | "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", 434 | "requires": { 435 | "charenc": "~0.0.1", 436 | "crypt": "~0.0.1", 437 | "is-buffer": "~1.1.1" 438 | } 439 | }, 440 | "mimic-fn": { 441 | "version": "1.2.0", 442 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 443 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" 444 | }, 445 | "minimatch": { 446 | "version": "3.0.4", 447 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 448 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 449 | "requires": { 450 | "brace-expansion": "^1.1.7" 451 | } 452 | }, 453 | "minimist": { 454 | "version": "0.0.8", 455 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 456 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 457 | }, 458 | "mkdirp": { 459 | "version": "0.5.1", 460 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 461 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 462 | "requires": { 463 | "minimist": "0.0.8" 464 | } 465 | }, 466 | "multimap": { 467 | "version": "1.0.2", 468 | "resolved": "https://registry.npmjs.org/multimap/-/multimap-1.0.2.tgz", 469 | "integrity": "sha1-aqdvwyM5BbqUi75MdNwsOgNW6zY=" 470 | }, 471 | "multimatch": { 472 | "version": "2.1.0", 473 | "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", 474 | "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", 475 | "requires": { 476 | "array-differ": "^1.0.0", 477 | "array-union": "^1.0.1", 478 | "arrify": "^1.0.0", 479 | "minimatch": "^3.0.0" 480 | } 481 | }, 482 | "mute-stream": { 483 | "version": "0.0.7", 484 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 485 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" 486 | }, 487 | "node-fetch": { 488 | "version": "1.6.3", 489 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.6.3.tgz", 490 | "integrity": "sha1-3CNO3WSJmC1Y6PDbT2lQKavNjAQ=", 491 | "requires": { 492 | "encoding": "^0.1.11", 493 | "is-stream": "^1.0.1" 494 | } 495 | }, 496 | "object-assign": { 497 | "version": "4.1.1", 498 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 499 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 500 | }, 501 | "onetime": { 502 | "version": "2.0.1", 503 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 504 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 505 | "requires": { 506 | "mimic-fn": "^1.0.0" 507 | } 508 | }, 509 | "opencollective": { 510 | "version": "1.0.3", 511 | "resolved": "https://registry.npmjs.org/opencollective/-/opencollective-1.0.3.tgz", 512 | "integrity": "sha1-ruY3K8KBRFg2kMPKja7PwSDdDvE=", 513 | "requires": { 514 | "babel-polyfill": "6.23.0", 515 | "chalk": "1.1.3", 516 | "inquirer": "3.0.6", 517 | "minimist": "1.2.0", 518 | "node-fetch": "1.6.3", 519 | "opn": "4.0.2" 520 | }, 521 | "dependencies": { 522 | "ansi-styles": { 523 | "version": "2.2.1", 524 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 525 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 526 | }, 527 | "chalk": { 528 | "version": "1.1.3", 529 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 530 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 531 | "requires": { 532 | "ansi-styles": "^2.2.1", 533 | "escape-string-regexp": "^1.0.2", 534 | "has-ansi": "^2.0.0", 535 | "strip-ansi": "^3.0.0", 536 | "supports-color": "^2.0.0" 537 | } 538 | }, 539 | "minimist": { 540 | "version": "1.2.0", 541 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", 542 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" 543 | }, 544 | "supports-color": { 545 | "version": "2.0.0", 546 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 547 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 548 | } 549 | } 550 | }, 551 | "opn": { 552 | "version": "4.0.2", 553 | "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", 554 | "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", 555 | "requires": { 556 | "object-assign": "^4.0.1", 557 | "pinkie-promise": "^2.0.0" 558 | } 559 | }, 560 | "optionator": { 561 | "version": "0.8.2", 562 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 563 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 564 | "requires": { 565 | "deep-is": "~0.1.3", 566 | "fast-levenshtein": "~2.0.4", 567 | "levn": "~0.3.0", 568 | "prelude-ls": "~1.1.2", 569 | "type-check": "~0.3.2", 570 | "wordwrap": "~1.0.0" 571 | } 572 | }, 573 | "os-tmpdir": { 574 | "version": "1.0.2", 575 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 576 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" 577 | }, 578 | "pinkie": { 579 | "version": "2.0.4", 580 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 581 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" 582 | }, 583 | "pinkie-promise": { 584 | "version": "2.0.1", 585 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 586 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 587 | "requires": { 588 | "pinkie": "^2.0.0" 589 | } 590 | }, 591 | "prelude-ls": { 592 | "version": "1.1.2", 593 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 594 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" 595 | }, 596 | "reflect-metadata": { 597 | "version": "0.1.12", 598 | "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.12.tgz", 599 | "integrity": "sha512-n+IyV+nGz3+0q3/Yf1ra12KpCyi001bi4XFxSjbiWWjfqb52iTTtpGXmCCAOWWIAn9KEuFZKGqBERHmrtScZ3A==" 600 | }, 601 | "regenerator-runtime": { 602 | "version": "0.12.1", 603 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz", 604 | "integrity": "sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==" 605 | }, 606 | "restore-cursor": { 607 | "version": "2.0.0", 608 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 609 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 610 | "requires": { 611 | "onetime": "^2.0.0", 612 | "signal-exit": "^3.0.2" 613 | } 614 | }, 615 | "run-async": { 616 | "version": "2.3.0", 617 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 618 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 619 | "requires": { 620 | "is-promise": "^2.1.0" 621 | } 622 | }, 623 | "rx": { 624 | "version": "4.1.0", 625 | "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", 626 | "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" 627 | }, 628 | "safer-buffer": { 629 | "version": "2.1.2", 630 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 631 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 632 | }, 633 | "shift-ast": { 634 | "version": "6.0.0", 635 | "resolved": "https://registry.npmjs.org/shift-ast/-/shift-ast-6.0.0.tgz", 636 | "integrity": "sha512-XXxDcEBWVBzqWXfNYJlLyJ1/9kMvOXVRXiqPjkOrTCC5qRsBvEMJMRLLFhU3tn8ue56Y7IZyBE6bexFum5QLUw==" 637 | }, 638 | "shift-codegen": { 639 | "version": "6.0.0", 640 | "resolved": "https://registry.npmjs.org/shift-codegen/-/shift-codegen-6.0.0.tgz", 641 | "integrity": "sha512-zETcFzj+ZnaHeqEX23on7cUHzOxLkkkAs55vUGJ3YRCbW0taYJgA7L7YHih5jf+lyGc+b3DnepIMM0qQyEQpgw==", 642 | "requires": { 643 | "esutils": "^2.0.2", 644 | "object-assign": "^4.1.0", 645 | "shift-reducer": "5.0.0" 646 | }, 647 | "dependencies": { 648 | "shift-ast": { 649 | "version": "5.0.0", 650 | "resolved": "https://registry.npmjs.org/shift-ast/-/shift-ast-5.0.0.tgz", 651 | "integrity": "sha512-kMhr/GwgrQ1U2kaa50sD5YxNDQEZHAZigVwrf/NNeezb6oiYnpPMV8v1WVRhCW8sjI7xUdzuPujSQ3gA2IuUAQ==" 652 | }, 653 | "shift-reducer": { 654 | "version": "5.0.0", 655 | "resolved": "https://registry.npmjs.org/shift-reducer/-/shift-reducer-5.0.0.tgz", 656 | "integrity": "sha512-Jgr6kPMZuzsQ63NdeLJT6BZvtJ6IDbYFBVqiid1bZlwxeJYq81Cj2Wc4UUERjO4Q9tz5U4KpWaZhitjcBvfiYA==", 657 | "requires": { 658 | "shift-ast": "5.0.0" 659 | } 660 | } 661 | } 662 | }, 663 | "shift-parser": { 664 | "version": "7.0.0", 665 | "resolved": "https://registry.npmjs.org/shift-parser/-/shift-parser-7.0.0.tgz", 666 | "integrity": "sha512-YYnQdwBEPNiRkDYIPzYIl125ysIYeeDwlUk3lgXxFpJLJhtqrIpZgShacAdoDufSmVOSTDDdxPqfcSfDwVr6dw==", 667 | "requires": { 668 | "multimap": "^1.0.2", 669 | "shift-ast": "6.0.0", 670 | "shift-reducer": "6.0.0", 671 | "shift-regexp-acceptor": "2.0.2" 672 | } 673 | }, 674 | "shift-query": { 675 | "version": "1.0.0", 676 | "resolved": "https://registry.npmjs.org/shift-query/-/shift-query-1.0.0.tgz", 677 | "integrity": "sha512-i/YIfVDPLRljgDj641cUGbvCFTaNE7wM0Ap2fHRzYkUN5a9iQfEySSYEje67eAYu6UzRERLGhSLjrm3PL6++cg==", 678 | "requires": { 679 | "shift-traverser": "^1.0.0" 680 | } 681 | }, 682 | "shift-reducer": { 683 | "version": "6.0.0", 684 | "resolved": "https://registry.npmjs.org/shift-reducer/-/shift-reducer-6.0.0.tgz", 685 | "integrity": "sha512-2rJraRP8drIOjvaE/sALa+0tGJmMVUzlmS3wIJerJbaYuCjpFAiF0WjkTOFVtz1144Nm/ECmqeG+7yRhuMVsMg==", 686 | "requires": { 687 | "shift-ast": "6.0.0" 688 | } 689 | }, 690 | "shift-refactor": { 691 | "version": "0.1.0", 692 | "resolved": "https://registry.npmjs.org/shift-refactor/-/shift-refactor-0.1.0.tgz", 693 | "integrity": "sha512-hWsueAuqBFzvwSd6/YVxZDeMm9RF7jq7Yr9vN9YiwgFW9QppgcRsJFzH4H0D3Yn93LaD6piQ58qq4nezYLOpUg==", 694 | "requires": { 695 | "shift-codegen": "^6.0.0", 696 | "shift-parser": "^7.0.0", 697 | "shift-query": "^1.0.0", 698 | "shift-scope": "^4.0.0", 699 | "shift-traverser": "^1.0.0", 700 | "shift-validator": "^4.0.0" 701 | } 702 | }, 703 | "shift-regexp-acceptor": { 704 | "version": "2.0.2", 705 | "resolved": "https://registry.npmjs.org/shift-regexp-acceptor/-/shift-regexp-acceptor-2.0.2.tgz", 706 | "integrity": "sha512-gW7HMRFZe2mGrVmpv7ENPVIwe4bhJzvHpkT71ZZGQ3d9YaWAZrY3r5sCJ8Hwl/L0/t5n6eWJD+8gJB/r9AvBJQ==", 707 | "requires": { 708 | "unicode-match-property-ecmascript": "1.0.4", 709 | "unicode-match-property-value-ecmascript": "1.0.2", 710 | "unicode-property-aliases-ecmascript": "1.0.4" 711 | } 712 | }, 713 | "shift-scope": { 714 | "version": "4.0.0", 715 | "resolved": "https://registry.npmjs.org/shift-scope/-/shift-scope-4.0.0.tgz", 716 | "integrity": "sha512-b5Ub5m6eP3obI1h6MVmt3Rthh1akLKKjresLtYYqV+V4aNFL1XtdvB+yK6mTROakriKFu4ehwbs6mFMUCenyKA==", 717 | "requires": { 718 | "multimap": "1.0.2", 719 | "shift-reducer": "5.0.0", 720 | "shift-spec": "2017.0.0" 721 | }, 722 | "dependencies": { 723 | "shift-ast": { 724 | "version": "5.0.0", 725 | "resolved": "https://registry.npmjs.org/shift-ast/-/shift-ast-5.0.0.tgz", 726 | "integrity": "sha512-kMhr/GwgrQ1U2kaa50sD5YxNDQEZHAZigVwrf/NNeezb6oiYnpPMV8v1WVRhCW8sjI7xUdzuPujSQ3gA2IuUAQ==" 727 | }, 728 | "shift-reducer": { 729 | "version": "5.0.0", 730 | "resolved": "https://registry.npmjs.org/shift-reducer/-/shift-reducer-5.0.0.tgz", 731 | "integrity": "sha512-Jgr6kPMZuzsQ63NdeLJT6BZvtJ6IDbYFBVqiid1bZlwxeJYq81Cj2Wc4UUERjO4Q9tz5U4KpWaZhitjcBvfiYA==", 732 | "requires": { 733 | "shift-ast": "5.0.0" 734 | } 735 | }, 736 | "shift-spec": { 737 | "version": "2017.0.0", 738 | "resolved": "https://registry.npmjs.org/shift-spec/-/shift-spec-2017.0.0.tgz", 739 | "integrity": "sha512-bJvpDhV0BPI3Qtr0Dztrv9nKjQmeSlRRjMOPe5ojsnzauhwu3fls+iMT6qDUXS+kXloZo71dn15j9D2qWuuQvw==" 740 | } 741 | } 742 | }, 743 | "shift-spec": { 744 | "version": "2018.0.0", 745 | "resolved": "https://registry.npmjs.org/shift-spec/-/shift-spec-2018.0.0.tgz", 746 | "integrity": "sha512-/aiPOkj7dbe+CV2VZhIMTHQToZmgniofpRG7Yr7x2/0sO6CSVC++py1Wzf+s+rWSTDHKcLvziVAxjRRV4i4EoQ==" 747 | }, 748 | "shift-traverser": { 749 | "version": "1.0.0", 750 | "resolved": "https://registry.npmjs.org/shift-traverser/-/shift-traverser-1.0.0.tgz", 751 | "integrity": "sha512-DMY3512wJbdC+IC+nhLH3/Stgr2BbxbNcg7qyZ6+e5qNnNs8TBQJWdMsRgHlX1JXwF4C0ONKS8VUxsPT0Tf7aw==", 752 | "requires": { 753 | "estraverse": "4.2.0", 754 | "shift-spec": "2018.0.0" 755 | } 756 | }, 757 | "shift-validator": { 758 | "version": "4.0.0", 759 | "resolved": "https://registry.npmjs.org/shift-validator/-/shift-validator-4.0.0.tgz", 760 | "integrity": "sha512-4afhnUIoC8RcXzAu7loFNeiTVvIDyb9HwRioxsEtJBcCjTzkRvsKsf0E/w29GIY1HA0H+P0Ujaz3udAhdAX1Tg==", 761 | "requires": { 762 | "esutils": "2.0.2", 763 | "shift-parser": "6.0.0", 764 | "shift-reducer": "5.0.0", 765 | "shift-regexp-acceptor": "1.0.1" 766 | }, 767 | "dependencies": { 768 | "shift-ast": { 769 | "version": "5.0.0", 770 | "resolved": "https://registry.npmjs.org/shift-ast/-/shift-ast-5.0.0.tgz", 771 | "integrity": "sha512-kMhr/GwgrQ1U2kaa50sD5YxNDQEZHAZigVwrf/NNeezb6oiYnpPMV8v1WVRhCW8sjI7xUdzuPujSQ3gA2IuUAQ==" 772 | }, 773 | "shift-parser": { 774 | "version": "6.0.0", 775 | "resolved": "https://registry.npmjs.org/shift-parser/-/shift-parser-6.0.0.tgz", 776 | "integrity": "sha512-tMgXtAnIqlIs3Ngk8bTXz+1hjt+dTWATgWs/y46w+Is3EkoJORjjTCVKvIHabb2h8Ktpu7nhTtBw33mYA8TGUA==", 777 | "requires": { 778 | "multimap": "^1.0.2", 779 | "shift-ast": "^5.0.0", 780 | "shift-reducer": "^5.0.0", 781 | "shift-regexp-acceptor": "^1.0.1" 782 | } 783 | }, 784 | "shift-reducer": { 785 | "version": "5.0.0", 786 | "resolved": "https://registry.npmjs.org/shift-reducer/-/shift-reducer-5.0.0.tgz", 787 | "integrity": "sha512-Jgr6kPMZuzsQ63NdeLJT6BZvtJ6IDbYFBVqiid1bZlwxeJYq81Cj2Wc4UUERjO4Q9tz5U4KpWaZhitjcBvfiYA==", 788 | "requires": { 789 | "shift-ast": "5.0.0" 790 | } 791 | }, 792 | "shift-regexp-acceptor": { 793 | "version": "1.0.1", 794 | "resolved": "https://registry.npmjs.org/shift-regexp-acceptor/-/shift-regexp-acceptor-1.0.1.tgz", 795 | "integrity": "sha512-GresOV14wluN2snjx4GGaRgdS0H7JJ5Ikw+4vLd+QC68pOOXeY/8TbxzEflf8maz/10FmjH/Lq0T9o3EofO4wA==" 796 | } 797 | } 798 | }, 799 | "signal-exit": { 800 | "version": "3.0.2", 801 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 802 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 803 | }, 804 | "source-map": { 805 | "version": "0.2.0", 806 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", 807 | "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", 808 | "optional": true, 809 | "requires": { 810 | "amdefine": ">=0.0.4" 811 | } 812 | }, 813 | "source-map-support": { 814 | "version": "0.5.8", 815 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.8.tgz", 816 | "integrity": "sha512-WqAEWPdb78u25RfKzOF0swBpY0dKrNdjc4GvLwm7ScX/o9bj8Eh/YL8mcMhBHYDGl87UkkSXDOFnW4G7GhWhGg==", 817 | "requires": { 818 | "buffer-from": "^1.0.0", 819 | "source-map": "^0.6.0" 820 | }, 821 | "dependencies": { 822 | "source-map": { 823 | "version": "0.6.1", 824 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 825 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 826 | } 827 | } 828 | }, 829 | "string-template": { 830 | "version": "1.0.0", 831 | "resolved": "https://registry.npmjs.org/string-template/-/string-template-1.0.0.tgz", 832 | "integrity": "sha1-np8iM9wA8hhxjsN5oopWc+zKi5Y=" 833 | }, 834 | "string-width": { 835 | "version": "2.1.1", 836 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 837 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 838 | "requires": { 839 | "is-fullwidth-code-point": "^2.0.0", 840 | "strip-ansi": "^4.0.0" 841 | }, 842 | "dependencies": { 843 | "ansi-regex": { 844 | "version": "3.0.0", 845 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 846 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" 847 | }, 848 | "strip-ansi": { 849 | "version": "4.0.0", 850 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 851 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 852 | "requires": { 853 | "ansi-regex": "^3.0.0" 854 | } 855 | } 856 | } 857 | }, 858 | "strip-ansi": { 859 | "version": "3.0.1", 860 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 861 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 862 | "requires": { 863 | "ansi-regex": "^2.0.0" 864 | } 865 | }, 866 | "supports-color": { 867 | "version": "5.5.0", 868 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 869 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 870 | "requires": { 871 | "has-flag": "^3.0.0" 872 | } 873 | }, 874 | "through": { 875 | "version": "2.3.8", 876 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 877 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 878 | }, 879 | "tmp": { 880 | "version": "0.0.33", 881 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 882 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 883 | "requires": { 884 | "os-tmpdir": "~1.0.2" 885 | } 886 | }, 887 | "tslib": { 888 | "version": "1.9.3", 889 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", 890 | "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" 891 | }, 892 | "type-check": { 893 | "version": "0.3.2", 894 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 895 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 896 | "requires": { 897 | "prelude-ls": "~1.1.2" 898 | } 899 | }, 900 | "unicode-canonical-property-names-ecmascript": { 901 | "version": "1.0.4", 902 | "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", 903 | "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==" 904 | }, 905 | "unicode-match-property-ecmascript": { 906 | "version": "1.0.4", 907 | "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", 908 | "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", 909 | "requires": { 910 | "unicode-canonical-property-names-ecmascript": "^1.0.4", 911 | "unicode-property-aliases-ecmascript": "^1.0.4" 912 | } 913 | }, 914 | "unicode-match-property-value-ecmascript": { 915 | "version": "1.0.2", 916 | "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.2.tgz", 917 | "integrity": "sha512-Rx7yODZC1L/T8XKo/2kNzVAQaRE88AaMvI1EF/Xnj3GW2wzN6fop9DDWuFAKUVFH7vozkz26DzP0qyWLKLIVPQ==" 918 | }, 919 | "unicode-property-aliases-ecmascript": { 920 | "version": "1.0.4", 921 | "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.4.tgz", 922 | "integrity": "sha512-2WSLa6OdYd2ng8oqiGIWnJqyFArvhn+5vgx5GTxMbUYjCYKUcuKS62YLFF0R/BDGlB1yzXjQOLtPAfHsgirEpg==" 923 | }, 924 | "validator": { 925 | "version": "10.4.0", 926 | "resolved": "https://registry.npmjs.org/validator/-/validator-10.4.0.tgz", 927 | "integrity": "sha512-Q/wBy3LB1uOyssgNlXSRmaf22NxjvDNZM2MtIQ4jaEOAB61xsh1TQxsq1CgzUMBV1lDrVMogIh8GjG1DYW0zLg==" 928 | }, 929 | "wordwrap": { 930 | "version": "1.0.0", 931 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 932 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" 933 | } 934 | } 935 | } 936 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "javascript-obfuscator": "^0.18.1", 13 | "shift-ast": "^6.0.0", 14 | "shift-parser": "^7.0.0", 15 | "shift-query": "^1.0.0", 16 | "shift-refactor": "^0.1.0", 17 | "shift-scope": "^4.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /stage-1/deobfuscate.js: -------------------------------------------------------------------------------- 1 | const { RefactorSession } = require('shift-refactor'); 2 | const { parseScript } = require('shift-parser'); 3 | 4 | const Shift = require('shift-ast'); 5 | 6 | const fileContents = require('fs').readFileSync('./original-obfuscated.js', 'utf8'); 7 | 8 | const tree = parseScript(fileContents); 9 | 10 | const refactor = new RefactorSession(tree); 11 | 12 | const strings = refactor.query('Script :first-child ArrayExpression .elements'); 13 | 14 | const destringifyDeclarator = refactor.query('VariableDeclarator[binding.name="b"]'); 15 | 16 | refactor.rename(destringifyDeclarator, 'destringify') 17 | 18 | const destringifyOffset = refactor.queryFrom( 19 | destringifyDeclarator, 20 | 'BinaryExpression > LiteralNumericExpression' 21 | )[0].value; 22 | 23 | refactor.replace( 24 | 'CallExpression[callee.name="destringify"]', 25 | node => { 26 | const rv = new Shift.LiteralStringExpression({ 27 | value : strings[node.arguments[0].value - destringifyOffset].value 28 | }); 29 | return rv; 30 | }); 31 | 32 | refactor.delete('VariableDeclarator[binding.name="destringify"]'); 33 | refactor.delete('VariableDeclarator[binding.name="a"]'); 34 | 35 | refactor.convertComputedToStatic(); 36 | 37 | console.log(refactor.print()); 38 | 39 | -------------------------------------------------------------------------------- /stage-1/obfuscate.js: -------------------------------------------------------------------------------- 1 | const scrambler = require('javascript-obfuscator'); 2 | const defaults = require('../default-obfuscation-options'); 3 | 4 | const fs = require('fs'); 5 | 6 | const contents = fs.readFileSync(__dirname + '/original.js', 'utf8'); 7 | 8 | const options = Object.assign(defaults, { 9 | identifierNamesGenerator: 'mangled', 10 | transformObjectKeys: true, 11 | unicodeEscapeSequence: true, 12 | rotateStringArray: false 13 | }); 14 | 15 | const result = scrambler.obfuscate(contents, options); 16 | 17 | console.log(result.getObfuscatedCode()); -------------------------------------------------------------------------------- /stage-1/original-obfuscated.js: -------------------------------------------------------------------------------- 1 | var a=['\x74\x61\x72\x67\x65\x74','\x67\x72\x65\x65\x74','\x6c\x6f\x67','\x48\x65\x6c\x6c\x6f\x20','\x73\x65\x74\x54\x61\x72\x67\x65\x74','\x77\x6f\x72\x6c\x64','\x72\x65\x61\x64\x65\x72'];var b=function(c,d){c=c-0x0;var e=a[c];return e;};(function(){class c{constructor(d){this[b('0x0')]=d;}[b('0x1')](){console[b('0x2')](b('0x3')+this[b('0x0')]);}[b('0x4')](e){this[b('0x0')]=e;}}const f=new c(b('0x5'));f[b('0x1')]();f[b('0x4')](b('0x6'));f[b('0x1')]();}()); 2 | -------------------------------------------------------------------------------- /stage-1/original.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | class Greeter { 3 | constructor(target) { 4 | this.target = target; 5 | } 6 | greet() { 7 | console.log(`Hello ${this.target}`); 8 | } 9 | setTarget(newTarget) { 10 | this.target = newTarget; 11 | } 12 | } 13 | const greeter = new Greeter("world"); 14 | greeter.greet(); 15 | greeter.setTarget("reader"); 16 | greeter.greet(); 17 | })(); 18 | -------------------------------------------------------------------------------- /stage-1/output.js: -------------------------------------------------------------------------------- 1 | var a=['\x74\x61\x72\x67\x65\x74','\x67\x72\x65\x65\x74','\x6c\x6f\x67','\x48\x65\x6c\x6c\x6f\x20','\x73\x65\x74\x54\x61\x72\x67\x65\x74','\x77\x6f\x72\x6c\x64','\x72\x65\x61\x64\x65\x72'];var b=function(c,d){c=c-0x0;var e=a[c];return e;};(function(){class c{constructor(d){this[b('0x0')]=d;}[b('0x1')](){console[b('0x2')](b('0x3')+this[b('0x0')]);}[b('0x4')](e){this[b('0x0')]=e;}}const f=new c(b('0x5'));f[b('0x1')]();f[b('0x4')](b('0x6'));f[b('0x1')]();}()); 2 | -------------------------------------------------------------------------------- /stage-2/deobfuscate.js: -------------------------------------------------------------------------------- 1 | const { RefactorSession } = require('shift-refactor'); 2 | const { parseScript } = require('shift-parser'); 3 | 4 | const Shift = require('shift-ast'); 5 | 6 | const fileContents = require('fs').readFileSync('./original-obfuscated.js', 'utf8'); 7 | 8 | const tree = parseScript(fileContents); 9 | 10 | const refactor = new RefactorSession(tree); 11 | 12 | const strings = refactor.query('Script :first-child ArrayExpression .elements'); 13 | 14 | const offset = refactor.query('Script > :nth-child(2) .expression LiteralNumericExpression')[0]; 15 | 16 | function rotate(offset) { 17 | while (--offset) { 18 | strings.push(strings.shift()); 19 | } 20 | }; 21 | 22 | rotate(offset.value + 1); 23 | 24 | const destringifyDeclarator = refactor.query('Script > :nth-child(3)')[0].declaration.declarators[0]; 25 | 26 | refactor.rename(destringifyDeclarator, 'destringify') 27 | 28 | const destringifyOffset = refactor.queryFrom( 29 | destringifyDeclarator, 30 | 'BinaryExpression > LiteralNumericExpression' 31 | )[0].value; 32 | 33 | refactor.replace( 34 | 'CallExpression[callee.name="destringify"]', 35 | node => { 36 | const rv = new Shift.LiteralStringExpression({ 37 | value : strings[node.arguments[0].value - destringifyOffset].value 38 | }); 39 | return rv; 40 | }); 41 | 42 | refactor.delete('VariableDeclarator[binding.name="destringify"]'); 43 | refactor.delete('Script > :first-child'); 44 | refactor.delete('Script > :first-child'); 45 | 46 | refactor.convertComputedToStatic(); 47 | 48 | console.log(refactor.print()); 49 | 50 | -------------------------------------------------------------------------------- /stage-2/obfuscate.js: -------------------------------------------------------------------------------- 1 | const scrambler = require('javascript-obfuscator'); 2 | const defaults = require('../default-obfuscation-options'); 3 | 4 | const fs = require('fs'); 5 | 6 | const contents = fs.readFileSync(__dirname + '/original.js', 'utf8'); 7 | 8 | const options = Object.assign(defaults, { 9 | // identifierNamesGenerator: 'mangled', 10 | transformObjectKeys: true, 11 | unicodeEscapeSequence: true, 12 | rotateStringArray: true 13 | }); 14 | 15 | const result = scrambler.obfuscate(contents, options); 16 | 17 | fs.writeFileSync('./original-obfuscated.js', result.getObfuscatedCode()); 18 | 19 | -------------------------------------------------------------------------------- /stage-2/original-obfuscated.js: -------------------------------------------------------------------------------- 1 | var _0xf0a2 = [ 2 | "\x73\x65\x74\x54\x61\x72\x67\x65\x74", 3 | "\x77\x6f\x72\x6c\x64", 4 | "\x72\x65\x61\x64\x65\x72", 5 | "\x74\x61\x72\x67\x65\x74", 6 | "\x67\x72\x65\x65\x74", 7 | "\x6c\x6f\x67", 8 | "\x48\x65\x6c\x6c\x6f\x20" 9 | ]; 10 | (function(_0x26911f, _0x42ef24) { 11 | var _0x3703e8 = function(_0x2fab33) { 12 | while (--_0x2fab33) { 13 | _0x26911f["push"](_0x26911f["shift"]()); 14 | } 15 | }; 16 | _0x3703e8(++_0x42ef24); 17 | })(_0xf0a2, 0x14c); 18 | var _0x53d2 = function(_0x5614ea, _0x461bef) { 19 | _0x5614ea = _0x5614ea - 0x0; 20 | var _0x288db7 = _0xf0a2[_0x5614ea]; 21 | return _0x288db7; 22 | }; 23 | (function() { 24 | class _0x42fe35 { 25 | constructor(_0x44f84b) { 26 | this[_0x53d2("0x0")] = _0x44f84b; 27 | } 28 | [_0x53d2("0x1")]() { 29 | console[_0x53d2("0x2")](_0x53d2("0x3") + this[_0x53d2("0x0")]); 30 | } 31 | [_0x53d2("0x4")](_0x4c30b6) { 32 | this[_0x53d2("0x0")] = _0x4c30b6; 33 | } 34 | } 35 | const _0x237464 = new _0x42fe35(_0x53d2("0x5")); 36 | _0x237464[_0x53d2("0x1")](); 37 | _0x237464[_0x53d2("0x4")](_0x53d2("0x6")); 38 | _0x237464[_0x53d2("0x1")](); 39 | })(); 40 | -------------------------------------------------------------------------------- /stage-2/original.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | class Greeter { 3 | constructor(target) { 4 | this.target = target; 5 | } 6 | greet() { 7 | console.log(`Hello ${this.target}`); 8 | } 9 | setTarget(newTarget) { 10 | this.target = newTarget; 11 | } 12 | } 13 | const greeter = new Greeter("world"); 14 | greeter.greet(); 15 | greeter.setTarget("reader"); 16 | greeter.greet(); 17 | })(); -------------------------------------------------------------------------------- /stage-2/output.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | class _0x42fe35 { 3 | constructor(_0x44f84b) { 4 | this.target = _0x44f84b; 5 | } 6 | greet() { 7 | console.log("Hello " + this.target); 8 | } 9 | setTarget(_0x4c30b6) { 10 | this.target = _0x4c30b6; 11 | } 12 | } 13 | const _0x237464 = new _0x42fe35("world"); 14 | _0x237464.greet(); 15 | _0x237464.setTarget("reader"); 16 | _0x237464.greet(); 17 | }()); 18 | 19 | -------------------------------------------------------------------------------- /stage-3/deobfuscate.js: -------------------------------------------------------------------------------- 1 | const { RefactorSession } = require('shift-refactor'); 2 | const { parseScript } = require('shift-parser'); 3 | 4 | const Shift = require('shift-ast'); 5 | 6 | const fileContents = require('fs').readFileSync('./original-obfuscated.js', 'utf8'); 7 | 8 | const tree = parseScript(fileContents); 9 | 10 | const refactor = new RefactorSession(tree); 11 | 12 | const strings = refactor.query('Script :first-child ArrayExpression')[0].elements; 13 | 14 | const offset = refactor.query('.expression[arguments.length=2][arguments.0.name="a"]')[0].arguments[1]; 15 | 16 | function rotate(offset) { 17 | while (--offset) { 18 | strings.push(strings.shift()); 19 | } 20 | }; 21 | 22 | rotate(offset.value + 1); 23 | 24 | const destringifyDeclarator = refactor.query('Script > :nth-child(3)')[0].declaration.declarators[0]; 25 | 26 | refactor.rename(destringifyDeclarator, 'destringify') 27 | 28 | const destringifyOffset = refactor.queryFrom( 29 | destringifyDeclarator, 30 | 'BinaryExpression > LiteralNumericExpression' 31 | )[0].value; 32 | 33 | refactor.query('CallExpression[callee.name="destringify"]'); 34 | 35 | refactor.replace( 36 | 'CallExpression[callee.name="destringify"]', 37 | node => { 38 | const rv = new Shift.LiteralStringExpression({ 39 | value : strings[node.arguments[0].value - destringifyOffset].value 40 | }); 41 | return rv; 42 | }); 43 | 44 | refactor._queueDeletion(tree.statements[0]); 45 | refactor._queueDeletion(tree.statements[1]); 46 | refactor._queueDeletion(tree.statements[2]); 47 | refactor.cleanup(); 48 | const internalStatements = tree.statements[0].expression.callee.body.statements; 49 | refactor._queueDeletion(internalStatements[0]); 50 | refactor._queueDeletion(internalStatements[1]); 51 | refactor._queueDeletion(internalStatements[2]); 52 | refactor._queueDeletion(internalStatements[3]); 53 | refactor._queueDeletion(internalStatements[4]); 54 | refactor._queueDeletion(tree.statements[1]); 55 | refactor.cleanup(); 56 | 57 | refactor.convertComputedToStatic(); 58 | 59 | console.log(refactor.print()); -------------------------------------------------------------------------------- /stage-3/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /stage-3/obfuscate.js: -------------------------------------------------------------------------------- 1 | const scrambler = require('javascript-obfuscator'); 2 | const defaults = require('../default-obfuscation-options'); 3 | 4 | const fs = require('fs'); 5 | 6 | const contents = fs.readFileSync(__dirname + '/original.js', 'utf8'); 7 | 8 | const options = Object.assign(defaults, { 9 | identifierNamesGenerator: 'mangled', 10 | transformObjectKeys: true, 11 | unicodeEscapeSequence: true, 12 | rotateStringArray: true, 13 | stringArray: true, 14 | selfDefending: true, 15 | debugProtection: true 16 | }); 17 | 18 | const result = scrambler.obfuscate(contents, options); 19 | 20 | fs.writeFileSync('./original-obfuscated.js', result.getObfuscatedCode()); 21 | 22 | -------------------------------------------------------------------------------- /stage-3/original-obfuscated.js: -------------------------------------------------------------------------------- 1 | var a = [ 2 | "\x69\x6e\x70\x75\x74", 3 | "\x74\x61\x72\x67\x65\x74", 4 | "\x67\x72\x65\x65\x74", 5 | "\x6c\x6f\x67", 6 | "\x48\x65\x6c\x6c\x6f\x20", 7 | "\x73\x65\x74\x54\x61\x72\x67\x65\x74", 8 | "\x77\x6f\x72\x6c\x64", 9 | "\x72\x65\x61\x64\x65\x72", 10 | "\x73\x74\x72\x69\x6e\x67", 11 | "\x63\x6f\x6e\x73\x74\x72\x75\x63\x74\x6f\x72", 12 | "\x77\x68\x69\x6c\x65\x20\x28\x74\x72\x75\x65\x29\x20\x7b\x7d", 13 | "\x63\x6f\x75\x6e\x74\x65\x72", 14 | "\x6c\x65\x6e\x67\x74\x68", 15 | "\x64\x65\x62\x75", 16 | "\x67\x67\x65\x72", 17 | "\x63\x61\x6c\x6c", 18 | "\x61\x63\x74\x69\x6f\x6e", 19 | "\x73\x74\x61\x74\x65\x4f\x62\x6a\x65\x63\x74", 20 | "\x61\x70\x70\x6c\x79", 21 | "\x66\x75\x6e\x63\x74\x69\x6f\x6e\x20\x2a\x5c\x28\x20\x2a\x5c\x29", 22 | "\x5c\x2b\x5c\x2b\x20\x2a\x28\x3f\x3a\x5f\x30\x78\x28\x3f\x3a\x5b\x61\x2d\x66\x30\x2d\x39\x5d\x29\x7b\x34\x2c\x36\x7d\x7c\x28\x3f\x3a\x5c\x62\x7c\x5c\x64\x29\x5b\x61\x2d\x7a\x30\x2d\x39\x5d\x7b\x31\x2c\x34\x7d\x28\x3f\x3a\x5c\x62\x7c\x5c\x64\x29\x29", 23 | "\x69\x6e\x69\x74", 24 | "\x74\x65\x73\x74", 25 | "\x63\x68\x61\x69\x6e" 26 | ]; 27 | (function(c, d) { 28 | var e = function(f) { 29 | while (--f) { 30 | c["push"](c["shift"]()); 31 | } 32 | }; 33 | var g = function() { 34 | var h = { 35 | data: { key: "cookie", value: "timeout" }, 36 | setCookie: function(i, j, k, l) { 37 | l = l || {}; 38 | var m = j + "=" + k; 39 | var n = 0x0; 40 | for (var n = 0x0, p = i["length"]; n < p; n++) { 41 | var q = i[n]; 42 | m += ";\x20" + q; 43 | var r = i[q]; 44 | i["push"](r); 45 | p = i["length"]; 46 | if (r !== !![]) { 47 | m += "=" + r; 48 | } 49 | } 50 | l["cookie"] = m; 51 | }, 52 | removeCookie: function() { 53 | return "dev"; 54 | }, 55 | getCookie: function(s, t) { 56 | s = 57 | s || 58 | function(u) { 59 | return u; 60 | }; 61 | var v = s( 62 | new RegExp( 63 | "(?:^|;\x20)" + 64 | t["replace"](/([.$?*|{}()[]\/+^])/g, "$1") + 65 | "=([^;]*)" 66 | ) 67 | ); 68 | var w = function(x, y) { 69 | x(++y); 70 | }; 71 | w(e, d); 72 | return v ? decodeURIComponent(v[0x1]) : undefined; 73 | } 74 | }; 75 | var z = function() { 76 | var A = new RegExp( 77 | "\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*[\x27|\x22].+[\x27|\x22];?\x20*}" 78 | ); 79 | return A["test"](h["removeCookie"]["toString"]()); 80 | }; 81 | h["updateCookie"] = z; 82 | var B = ""; 83 | var C = h["updateCookie"](); 84 | if (!C) { 85 | h["setCookie"](["*"], "counter", 0x1); 86 | } else if (C) { 87 | B = h["getCookie"](null, "counter"); 88 | } else { 89 | h["removeCookie"](); 90 | } 91 | }; 92 | g(); 93 | })(a, 0x1aa); 94 | var b = function(c, d) { 95 | c = c - 0x0; 96 | var e = a[c]; 97 | return e; 98 | }; 99 | (function() { 100 | var e = (function() { 101 | var c = !![]; 102 | return function(d, e) { 103 | var f = c 104 | ? function() { 105 | if (e) { 106 | var g = e["apply"](d, arguments); 107 | e = null; 108 | return g; 109 | } 110 | } 111 | : function() {}; 112 | c = ![]; 113 | return f; 114 | }; 115 | })(); 116 | var x = e(this, function() { 117 | var c = function() { 118 | return "\x64\x65\x76"; 119 | }, 120 | d = function() { 121 | return "\x77\x69\x6e\x64\x6f\x77"; 122 | }; 123 | var e = function() { 124 | var f = new RegExp( 125 | "\x5c\x77\x2b\x20\x2a\x5c\x28\x5c\x29\x20\x2a\x7b\x5c\x77\x2b\x20\x2a\x5b\x27\x7c\x22\x5d\x2e\x2b\x5b\x27\x7c\x22\x5d\x3b\x3f\x20\x2a\x7d" 126 | ); 127 | return !f["\x74\x65\x73\x74"](c["\x74\x6f\x53\x74\x72\x69\x6e\x67"]()); 128 | }; 129 | var g = function() { 130 | var h = new RegExp( 131 | "\x28\x5c\x5c\x5b\x78\x7c\x75\x5d\x28\x5c\x77\x29\x7b\x32\x2c\x34\x7d\x29\x2b" 132 | ); 133 | return h["\x74\x65\x73\x74"](d["\x74\x6f\x53\x74\x72\x69\x6e\x67"]()); 134 | }; 135 | var i = function(j) { 136 | var k = ~-0x1 >> (0x1 + (0xff % 0x0)); 137 | if (j["\x69\x6e\x64\x65\x78\x4f\x66"]("\x69" === k)) { 138 | l(j); 139 | } 140 | }; 141 | var l = function(m) { 142 | var n = ~-0x4 >> (0x1 + (0xff % 0x0)); 143 | if (m["\x69\x6e\x64\x65\x78\x4f\x66"]((!![] + "")[0x3]) !== n) { 144 | i(m); 145 | } 146 | }; 147 | if (!e()) { 148 | if (!g()) { 149 | i("\x69\x6e\x64\u0435\x78\x4f\x66"); 150 | } else { 151 | i("\x69\x6e\x64\x65\x78\x4f\x66"); 152 | } 153 | } else { 154 | i("\x69\x6e\x64\u0435\x78\x4f\x66"); 155 | } 156 | }); 157 | x(); 158 | var f = (function() { 159 | var g = !![]; 160 | return function(h, i) { 161 | var j = g 162 | ? function() { 163 | if (i) { 164 | var k = i[b("0x0")](h, arguments); 165 | i = null; 166 | return k; 167 | } 168 | } 169 | : function() {}; 170 | g = ![]; 171 | return j; 172 | }; 173 | })(); 174 | (function() { 175 | f(this, function() { 176 | var l = new RegExp(b("0x1")); 177 | var m = new RegExp(b("0x2"), "\x69"); 178 | var n = c(b("0x3")); 179 | if (!l[b("0x4")](n + b("0x5")) || !m[b("0x4")](n + b("0x6"))) { 180 | n("\x30"); 181 | } else { 182 | c(); 183 | } 184 | })(); 185 | })(); 186 | class o { 187 | constructor(p) { 188 | this[b("0x7")] = p; 189 | } 190 | [b("0x8")]() { 191 | console[b("0x9")](b("0xa") + this[b("0x7")]); 192 | } 193 | [b("0xb")](q) { 194 | this[b("0x7")] = q; 195 | } 196 | } 197 | const r = new o(b("0xc")); 198 | r[b("0x8")](); 199 | r[b("0xb")](b("0xd")); 200 | r[b("0x8")](); 201 | })(); 202 | function c(s) { 203 | function t(u) { 204 | if (typeof u === b("0xe")) { 205 | return function(v) {}[b("0xf")](b("0x10"))[b("0x0")](b("0x11")); 206 | } else { 207 | if (("" + u / u)[b("0x12")] !== 0x1 || u % 0x14 === 0x0) { 208 | (function() { 209 | return !![]; 210 | } 211 | [b("0xf")](b("0x13") + b("0x14")) 212 | [b("0x15")](b("0x16"))); 213 | } else { 214 | (function() { 215 | return ![]; 216 | } 217 | [b("0xf")](b("0x13") + b("0x14")) 218 | [b("0x0")](b("0x17"))); 219 | } 220 | } 221 | t(++u); 222 | } 223 | try { 224 | if (s) { 225 | return t; 226 | } else { 227 | t(0x0); 228 | } 229 | } catch (w) {} 230 | } 231 | -------------------------------------------------------------------------------- /stage-3/original.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | class Greeter { 3 | constructor(target) { 4 | this.target = target; 5 | } 6 | greet() { 7 | console.log(`Hello ${this.target}`); 8 | } 9 | setTarget(newTarget) { 10 | this.target = newTarget; 11 | } 12 | } 13 | const greeter = new Greeter("world"); 14 | greeter.greet(); 15 | greeter.setTarget("reader"); 16 | greeter.greet(); 17 | })(); -------------------------------------------------------------------------------- /stage-3/output.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | class o { 3 | constructor(p) { 4 | this.target = p; 5 | } 6 | greet() { 7 | console.log("Hello " + this.target); 8 | } 9 | setTarget(q) { 10 | this.target = q; 11 | } 12 | } 13 | const r = new o("world"); 14 | r.greet(); 15 | r.setTarget("reader"); 16 | r.greet(); 17 | }()); 18 | 19 | -------------------------------------------------------------------------------- /stage-4/deobfuscate.js: -------------------------------------------------------------------------------- 1 | const { RefactorSession } = require('shift-refactor'); 2 | const { parseScript } = require('shift-parser'); 3 | 4 | const { traverse } = require('shift-traverser'); 5 | 6 | const Shift = require('shift-ast'); 7 | 8 | const fileContents = require('fs').readFileSync('./original-obfuscated.js', 'utf8'); 9 | 10 | const ast = parseScript(fileContents); 11 | 12 | const refactor = new RefactorSession(ast); 13 | 14 | const whileNodes = refactor.query('WhileStatement[test.operand.type="UnaryExpression"]'); 15 | 16 | const parentFunctions = []; 17 | 18 | traverse(ast, { 19 | enter(node, parent){ 20 | if (whileNodes.indexOf(node) > -1) { 21 | parentFunctions.push(parent); 22 | } 23 | } 24 | }) 25 | 26 | const dataObject = ast.statements[0].expression.callee.body.statements[0].declaration.declarators[0]; 27 | 28 | function unflatten(functionBody) { 29 | const keyStringPropertyName = functionBody.statements[0].declaration.declarators[0].init.callee.object.expression.value; 30 | const keyString = dataObject.init.properties.find(_ => _.name.value === keyStringPropertyName); 31 | 32 | const order = keyString.expression.value.split('|'); 33 | 34 | const switchCases = functionBody.statements[1].body.block.statements[0].cases; 35 | 36 | const reorderedSwitchCases = order.map(_ => switchCases[_]); 37 | 38 | return reorderedSwitchCases.map(_ => _.consequent[0]); 39 | } 40 | 41 | parentFunctions.forEach(fn => { 42 | fn.statements = unflatten(fn); 43 | }) 44 | 45 | refactor.convertComputedToStatic(); 46 | 47 | console.log(refactor.print()); -------------------------------------------------------------------------------- /stage-4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /stage-4/obfuscate.js: -------------------------------------------------------------------------------- 1 | const scrambler = require('javascript-obfuscator'); 2 | const defaults = require('../default-obfuscation-options'); 3 | 4 | const fs = require('fs'); 5 | 6 | const contents = fs.readFileSync(__dirname + '/original.js', 'utf8'); 7 | 8 | const options = Object.assign(defaults, { 9 | identifierNamesGenerator: 'mangled', 10 | transformObjectKeys: false, 11 | unicodeEscapeSequence: false, 12 | rotateStringArray: false, 13 | stringArray: false, 14 | selfDefending: false, 15 | debugProtection: false, 16 | controlFlowFlattening: true, 17 | controlFlowFlatteningThreshold: 1, 18 | }); 19 | 20 | const result = scrambler.obfuscate(contents, options); 21 | 22 | fs.writeFileSync('./original-obfuscated.js', result.getObfuscatedCode()); 23 | 24 | -------------------------------------------------------------------------------- /stage-4/original-obfuscated.js: -------------------------------------------------------------------------------- 1 | (function(){var c={'hsakO':'3|4|2|1|0','tPkAq':function(d,e){return d===e;},'YhcXR':'reader','PFwHf':'world'};class f{constructor(g){this['target']=g;}['greet'](){var h=c['hsakO']['split']('|'),i=0x0;while(!![]){switch(h[i++]){case'0':console['log']('I\x20have\x20run\x20out\x20of\x20things\x20to\x20say.');continue;case'1':console['log']('I\x20hope\x20you\x20have\x20a\x20good\x20day!');continue;case'2':if(c['tPkAq'](this['target'],c['YhcXR'])){console['log']('I\x20like\x20your\x20hair!');}continue;case'3':console['log']('Hello\x20'+this['target']);continue;case'4':if(c['tPkAq'](this['target'],c['PFwHf'])){console['log']('It\x27s\x20beautiful\x20out,\x20isn\x27t\x20it?');}continue;}break;}}['setTarget'](j){this['target']=j;}}const k=new f(c['PFwHf']);k['greet']();k['setTarget'](c['YhcXR']);k['greet']();}()); -------------------------------------------------------------------------------- /stage-4/original.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | class Greeter { 3 | constructor(target) { 4 | this.target = target; 5 | } 6 | greet() { 7 | console.log(`Hello ${this.target}`); 8 | 9 | if (this.target === 'world') { 10 | console.log(`It's beautiful out, isn't it?`) 11 | } 12 | 13 | if (this.target === 'reader') { 14 | console.log(`I like your hair!`); 15 | } 16 | 17 | console.log(`I hope you have a good day!`); 18 | console.log(`I have run out of things to say.`); 19 | } 20 | setTarget(newTarget) { 21 | this.target = newTarget; 22 | } 23 | } 24 | const greeter = new Greeter("world"); 25 | greeter.greet(); 26 | greeter.setTarget("reader"); 27 | greeter.greet(); 28 | })(); -------------------------------------------------------------------------------- /stage-4/output.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var c = {hsakO: "3|4|2|1|0", tPkAq: function (d, e) { 3 | return d === e; 4 | }, YhcXR: "reader", PFwHf: "world"}; 5 | class f { 6 | constructor(g) { 7 | this.target = g; 8 | } 9 | greet() { 10 | console.log("Hello " + this.target); 11 | if (c.tPkAq(this.target, c.PFwHf)) { 12 | console.log("It's beautiful out, isn't it?"); 13 | } 14 | if (c.tPkAq(this.target, c.YhcXR)) { 15 | console.log("I like your hair!"); 16 | } 17 | console.log("I hope you have a good day!"); 18 | console.log("I have run out of things to say."); 19 | } 20 | setTarget(j) { 21 | this.target = j; 22 | } 23 | } 24 | const k = new f(c.PFwHf); 25 | k.greet(); 26 | k.setTarget(c.YhcXR); 27 | k.greet(); 28 | }()); 29 | 30 | -------------------------------------------------------------------------------- /stage-4/output.ps: -------------------------------------------------------------------------------- 1 | (function () { 2 | var c = {aiHas: "4|2|0|3|1", dphWW: function (d, e) { 3 | return d === e; 4 | }, FMldB: "reader", zVloB: "world"}; 5 | class f { 6 | constructor(g) { 7 | this.target = g; 8 | } 9 | greet() { 10 | console.log("Hello " + this.target); 11 | if (c.dphWW(this.target, c.zVloB)) { 12 | console.log("It's beautiful out, isn't it?"); 13 | } 14 | if (c.dphWW(this.target, c.FMldB)) { 15 | console.log("I like your hair!"); 16 | } 17 | console.log("I hope you have a good day!"); 18 | console.log("I have run out of things to say."); 19 | } 20 | setTarget(j) { 21 | this.target = j; 22 | } 23 | } 24 | const k = new f(c.zVloB); 25 | k.greet(); 26 | k.setTarget(c.FMldB); 27 | k.greet(); 28 | }()); 29 | 30 | -------------------------------------------------------------------------------- /stage-5/deobfuscate.js: -------------------------------------------------------------------------------- 1 | const { RefactorSession } = require("shift-refactor"); 2 | const { parseScript } = require("shift-parser"); 3 | const Shift = require("shift-ast"); 4 | 5 | const fileContents = require("fs").readFileSync( 6 | "./original-obfuscated.js", 7 | "utf8" 8 | ); 9 | 10 | const ast = parseScript(fileContents); 11 | 12 | const refactor = new RefactorSession(ast); 13 | 14 | const strings = refactor.query("Script :first-child ArrayExpression .elements"); 15 | 16 | const destringifyDeclarator = refactor.query( 17 | 'VariableDeclarator[binding.name="b"]' 18 | ); 19 | 20 | refactor.rename(destringifyDeclarator, "destringify"); 21 | 22 | const destringifyOffset = refactor.queryFrom( 23 | destringifyDeclarator, 24 | "BinaryExpression > LiteralNumericExpression" 25 | )[0].value; 26 | 27 | refactor.replace('CallExpression[callee.name="destringify"]', node => { 28 | const rv = new Shift.LiteralStringExpression({ 29 | value: strings[node.arguments[0].value - destringifyOffset].value 30 | }); 31 | return rv; 32 | }); 33 | 34 | refactor.delete(ast.statements[0]); 35 | refactor.delete(ast.statements[0]); 36 | refactor.convertComputedToStatic(); 37 | 38 | 39 | refactor.replace("IfStatement > .test", node => { 40 | if (node.left.type.match(/^Literal/) && node.right.type.match(/^Literal/)) { 41 | if (node.operator === "===") { 42 | return new Shift.LiteralBooleanExpression({ 43 | value: node.left.value === node.right.value 44 | }); 45 | } else if (node.operator === "!==") { 46 | return new Shift.LiteralBooleanExpression({ 47 | value: node.left.value !== node.right.value 48 | }); 49 | } 50 | } 51 | return node; 52 | }); 53 | 54 | refactor.replace("IfStatement", node => { 55 | if (node.test.type === 'LiteralBooleanExpression') { 56 | if (node.test.value) { 57 | return node.consequent; 58 | } else { 59 | return node.alternate; 60 | } 61 | } 62 | return node; 63 | }); 64 | 65 | const dumbBodies = refactor.query("FunctionBody").filter(body => body.statements.length === 1 && body.statements[0].type === 'BlockStatement'); 66 | 67 | dumbBodies.forEach(node => { 68 | node.statements = node.statements[0].block.statements; 69 | }) 70 | 71 | console.log(refactor.print()); 72 | -------------------------------------------------------------------------------- /stage-5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /stage-5/obfuscate.js: -------------------------------------------------------------------------------- 1 | const scrambler = require('javascript-obfuscator'); 2 | const defaults = require('../default-obfuscation-options'); 3 | 4 | const fs = require('fs'); 5 | 6 | const contents = fs.readFileSync(__dirname + '/original.js', 'utf8'); 7 | 8 | const options = Object.assign(defaults, { 9 | identifierNamesGenerator: 'mangled', 10 | transformObjectKeys: false, 11 | unicodeEscapeSequence: false, 12 | rotateStringArray: false, 13 | stringArrayThreshold: 0, 14 | stringArray: false, 15 | selfDefending: false, 16 | debugProtection: false, 17 | deadCodeInjection: true, 18 | deadCodeInjectionThreshold: 1, 19 | }); 20 | 21 | const result = scrambler.obfuscate(contents, options); 22 | 23 | fs.writeFileSync('./original-obfuscated.js', result.getObfuscatedCode()); 24 | 25 | -------------------------------------------------------------------------------- /stage-5/original-obfuscated.js: -------------------------------------------------------------------------------- 1 | var a = [ 2 | "opKyd", 3 | "log", 4 | "Hello\x20", 5 | "target", 6 | "world", 7 | "It\x27s\x20beautiful\x20out,\x20isn\x27t\x20it?", 8 | "reader", 9 | "I\x20like\x20your\x20hair!", 10 | "I\x20have\x20run\x20out\x20of\x20things\x20to\x20say.", 11 | "greet", 12 | "uXPpI", 13 | "BBRiF", 14 | "kxpqP", 15 | "MIGiO", 16 | "PQXfs", 17 | "I\x20hope\x20you\x20have\x20a\x20good\x20day!", 18 | "setTarget", 19 | "mYfPc" 20 | ]; 21 | var b = function(c, d) { 22 | c = c - 0x0; 23 | var e = a[c]; 24 | return e; 25 | }; 26 | (function() { 27 | class c { 28 | constructor(d) { 29 | if (b("0x0") !== b("0x0")) { 30 | console[b("0x1")](b("0x2") + this["target"]); 31 | if (this[b("0x3")] === b("0x4")) { 32 | console["log"](b("0x5")); 33 | } 34 | if (this[b("0x3")] === b("0x6")) { 35 | console[b("0x1")](b("0x7")); 36 | } 37 | console[b("0x1")]("I\x20hope\x20you\x20have\x20a\x20good\x20day!"); 38 | console["log"](b("0x8")); 39 | } else { 40 | this[b("0x3")] = d; 41 | } 42 | } 43 | [b("0x9")]() { 44 | if (b("0xa") === b("0xb")) { 45 | console[b("0x1")](b("0x7")); 46 | } else { 47 | console["log"]("Hello\x20" + this["target"]); 48 | if (this[b("0x3")] === b("0x4")) { 49 | if (b("0xc") === b("0xd")) { 50 | console[b("0x1")](b("0x5")); 51 | } else { 52 | console[b("0x1")](b("0x5")); 53 | } 54 | } 55 | if (this["target"] === b("0x6")) { 56 | if ("PQXfs" !== b("0xe")) { 57 | this["target"] = target; 58 | } else { 59 | console[b("0x1")](b("0x7")); 60 | } 61 | } 62 | console["log"](b("0xf")); 63 | console["log"](b("0x8")); 64 | } 65 | } 66 | [b("0x10")](i) { 67 | if (b("0x11") !== "YjRWy") { 68 | this[b("0x3")] = i; 69 | } else { 70 | this[b("0x3")] = i; 71 | } 72 | } 73 | } 74 | const k = new c(b("0x4")); 75 | k["greet"](); 76 | k[b("0x10")](b("0x6")); 77 | k[b("0x9")](); 78 | })(); 79 | -------------------------------------------------------------------------------- /stage-5/original.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | class Greeter { 3 | constructor(target) { 4 | this.target = target; 5 | } 6 | greet() { 7 | console.log(`Hello ${this.target}`); 8 | 9 | if (this.target === 'world') { 10 | console.log(`It's beautiful out, isn't it?`) 11 | } 12 | 13 | if (this.target === 'reader') { 14 | console.log(`I like your hair!`); 15 | } 16 | 17 | console.log(`I hope you have a good day!`); 18 | console.log(`I have run out of things to say.`); 19 | } 20 | setTarget(newTarget) { 21 | this.target = newTarget; 22 | } 23 | } 24 | const greeter = new Greeter("world"); 25 | greeter.greet(); 26 | greeter.setTarget("reader"); 27 | greeter.greet(); 28 | })(); -------------------------------------------------------------------------------- /stage-5/output.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | class c { 3 | constructor(d) { 4 | this.target = d; 5 | } 6 | greet() { 7 | console.log("Hello " + this.target); 8 | if (this.target === "world") { 9 | { 10 | console.log("It's beautiful out, isn't it?"); 11 | } 12 | } 13 | if (this.target === "reader") { 14 | { 15 | console.log("I like your hair!"); 16 | } 17 | } 18 | console.log("I hope you have a good day!"); 19 | console.log("I have run out of things to say."); 20 | } 21 | setTarget(i) { 22 | this.target = i; 23 | } 24 | } 25 | const k = new c("world"); 26 | k.greet(); 27 | k.setTarget("reader"); 28 | k.greet(); 29 | }()); 30 | 31 | -------------------------------------------------------------------------------- /stage-5/output.ps: -------------------------------------------------------------------------------- 1 | (function () { 2 | var c = {aiHas: "4|2|0|3|1", dphWW: function (d, e) { 3 | return d === e; 4 | }, FMldB: "reader", zVloB: "world"}; 5 | class f { 6 | constructor(g) { 7 | this.target = g; 8 | } 9 | greet() { 10 | console.log("Hello " + this.target); 11 | if (c.dphWW(this.target, c.zVloB)) { 12 | console.log("It's beautiful out, isn't it?"); 13 | } 14 | if (c.dphWW(this.target, c.FMldB)) { 15 | console.log("I like your hair!"); 16 | } 17 | console.log("I hope you have a good day!"); 18 | console.log("I have run out of things to say."); 19 | } 20 | setTarget(j) { 21 | this.target = j; 22 | } 23 | } 24 | const k = new f(c.zVloB); 25 | k.greet(); 26 | k.setTarget(c.FMldB); 27 | k.greet(); 28 | }()); 29 | 30 | --------------------------------------------------------------------------------