├── Examples ├── LICENSE_1.txt ├── LICENSE_2.txt ├── case_01__original.txt ├── case_01_input_stringarraywithoutwrappers.txt ├── case_01_output.txt ├── case_01_output_with_stringarray_input.txt ├── case_01_stringarray.txt ├── case_01_stringarrayrotate.txt ├── case_01_stringarraywrappers.txt ├── case_01_z_commandline.txt ├── case_02__original.txt ├── case_02_input_newestoptionandeval.txt ├── case_02_output.txt ├── case_02_output_with_stringarray_input.txt ├── case_02_stringarray.txt ├── case_02_stringarrayrotate.txt ├── case_02_stringarraywrappers.txt ├── case_02_z_commandline.txt ├── case_03__original.txt ├── case_03_input_compact.txt ├── case_03_output.txt ├── case_03_output_with_stringarray_input.txt ├── case_03_stringarray.txt ├── case_03_stringarrayrotate.txt ├── case_03_stringarraywrappers.txt ├── case_03_z_commandline.txt ├── case_04__original.txt ├── case_04_input.txt ├── case_04_input_v2.txt ├── case_04_output.txt ├── case_04_stringarray.txt ├── case_04_stringarrayrotate.txt ├── case_04_stringarraywrappers.txt ├── case_04_z_commandline.txt ├── case_05__original.txt ├── case_05_input_helloworld_default.txt ├── case_05_output.txt ├── case_06__original.txt ├── case_06_input_helloworld_low.txt ├── case_06_output.txt ├── case_07__original.txt ├── case_07_input_helloworld_medium.txt ├── case_07_output.txt ├── case_08__original.txt ├── case_08_input_helloworld_high.txt ├── case_08_output.txt ├── case_09__original.txt ├── case_09_input_helloworld_domainlock.txt ├── case_09_output.txt ├── case_10__original.txt ├── case_10_map_default.txt ├── case_10_output.txt ├── case_11__original.txt ├── case_11_map_low.txt ├── case_11_output.txt ├── case_12__original.txt ├── case_12_map_medium.txt ├── case_12_output.txt ├── case_13__original.txt ├── case_13_map_high.txt ├── case_13_output.txt ├── case_14__original.txt ├── case_14_map_domainlock.txt ├── case_14_output.txt ├── case_15__original.txt ├── case_15_linkedlist_default.txt ├── case_15_output.txt ├── case_16__original.txt ├── case_16_linkedlist_medium.txt ├── case_16_output.txt ├── case_17__original.txt ├── case_17_linkedlist_high.txt └── case_17_output.txt ├── LICENSE ├── README.md ├── Stages ├── stage_01_finalizing.js ├── stage_02_simplifying.js ├── stage_03_stringarray.js ├── stage_04_renameidentifiers.js ├── stage_05_converting.js ├── stage_06_renameproperties.js ├── stage_07_controlflowflattening.js ├── stage_08_deadcodeinjection.js ├── stage_09_preparing.js ├── stage_10_initializing.js ├── stage_11_finishing.js └── stage_deobfuscator.js ├── ast_operations.js ├── deobfuscator.js ├── index.js ├── package.json └── useful.js /Examples/LICENSE_1.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2016-2022 Timofey Kachalov. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 4 | 5 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 6 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 7 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Examples/LICENSE_2.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Oleksii Trekhleb 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /Examples/case_01__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | 12 | (function(){ 13 | var variable1 = '5' - 3; 14 | var variable2 = '5' + 3; 15 | var variable3 = '5' + - '2'; 16 | var variable4 = ['10','10','10','10','10'].map(parseInt); 17 | var variable5 = 'foo ' + 1 + 1; 18 | console.log(variable1); 19 | console.log(variable2); 20 | console.log(variable3); 21 | console.log(variable4); 22 | console.log(variable5); 23 | })(); -------------------------------------------------------------------------------- /Examples/case_01_input_stringarraywithoutwrappers.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | var _0x9947 = [ 11 | 'map', 12 | 'log', 13 | 'foo\x20', 14 | 'bvmqO', 15 | '133039ViRMWR', 16 | 'xPfLC', 17 | 'ytpdx', 18 | '1243717qSZCyh', 19 | '2|7|4|6|9|', 20 | '1ErtbCr', 21 | '1608314VKvthn', 22 | '1ZRaFKN', 23 | 'XBoAA', 24 | '423266kQOYHV', 25 | '3|0|5|8|1', 26 | '235064xPNdKe', 27 | '13RUDZfG', 28 | '157gNPQGm', 29 | '1639212MvnHZL', 30 | 'rDjOa', 31 | 'iBHph', 32 | '9926iRHoRl', 33 | 'split' 34 | ]; 35 | function _0x33e4(_0x1809b5, _0x37ef6e) { 36 | return _0x33e4 = function (_0x338a69, _0x39ad79) { 37 | _0x338a69 = _0x338a69 - (0x1939 + -0xf * 0x1f3 + 0x1 * 0x469); 38 | var _0x2b223a = _0x9947[_0x338a69]; 39 | return _0x2b223a; 40 | }, _0x33e4(_0x1809b5, _0x37ef6e); 41 | } 42 | (function (_0x431d87, _0x156c7f) { 43 | var _0x10cf6e = _0x33e4; 44 | while (!![]) { 45 | try { 46 | var _0x330ad1 = -parseInt(_0x10cf6e(0x6c)) * -parseInt(_0x10cf6e(0x6d)) + -parseInt(_0x10cf6e(0x74)) * -parseInt(_0x10cf6e(0x78)) + parseInt(_0x10cf6e(0x6a)) + -parseInt(_0x10cf6e(0x70)) + parseInt(_0x10cf6e(0x6e)) * -parseInt(_0x10cf6e(0x75)) + parseInt(_0x10cf6e(0x72)) + -parseInt(_0x10cf6e(0x67)) * parseInt(_0x10cf6e(0x73)); 47 | if (_0x330ad1 === _0x156c7f) 48 | break; 49 | else 50 | _0x431d87['push'](_0x431d87['shift']()); 51 | } catch (_0x9f878) { 52 | _0x431d87['push'](_0x431d87['shift']()); 53 | } 54 | } 55 | }(_0x9947, -0xb6270 + 0x4dfd2 * 0x2 + 0x75460 * 0x2), function () { 56 | var _0x1f346d = _0x33e4, _0x860db8 = { 57 | 'ytpdx': _0x1f346d(0x6b) + _0x1f346d(0x71), 58 | 'bvmqO': function (_0x560787, _0x519b9e) { 59 | return _0x560787 - _0x519b9e; 60 | }, 61 | 'rDjOa': function (_0x4501fe, _0x2b07a3) { 62 | return _0x4501fe + _0x2b07a3; 63 | }, 64 | 'xPfLC': function (_0x5f3c9b, _0x434936) { 65 | return _0x5f3c9b + _0x434936; 66 | }, 67 | 'XBoAA': function (_0x535b8a, _0x42eef4) { 68 | return _0x535b8a + _0x42eef4; 69 | }, 70 | 'iBHph': _0x1f346d(0x65) 71 | }, _0x346c55 = _0x860db8[_0x1f346d(0x69)][_0x1f346d(0x79)]('|'), _0x3bf817 = 0x4bb * 0x1 + 0x801 + -0xcbc; 72 | while (!![]) { 73 | switch (_0x346c55[_0x3bf817++]) { 74 | case '0': 75 | console[_0x1f346d(0x7b)](_0x4c96d8); 76 | continue; 77 | case '1': 78 | console[_0x1f346d(0x7b)](_0x101028); 79 | continue; 80 | case '2': 81 | var _0x65977d = _0x860db8[_0x1f346d(0x66)]('5', -0x586 + -0x2195 + -0x6 * -0x685); 82 | continue; 83 | case '3': 84 | console[_0x1f346d(0x7b)](_0x65977d); 85 | continue; 86 | case '4': 87 | var _0x56d39b = _0x860db8[_0x1f346d(0x76)]('5', -'2'); 88 | continue; 89 | case '5': 90 | console[_0x1f346d(0x7b)](_0x56d39b); 91 | continue; 92 | case '6': 93 | var _0x544285 = [ 94 | '10', 95 | '10', 96 | '10', 97 | '10', 98 | '10' 99 | ][_0x1f346d(0x7a)](parseInt); 100 | continue; 101 | case '7': 102 | var _0x4c96d8 = _0x860db8[_0x1f346d(0x68)]('5', 0x622 * -0x6 + 0x4a * 0x3 + 0x1 * 0x23f1); 103 | continue; 104 | case '8': 105 | console[_0x1f346d(0x7b)](_0x544285); 106 | continue; 107 | case '9': 108 | var _0x101028 = _0x860db8[_0x1f346d(0x6f)](_0x860db8[_0x1f346d(0x6f)](_0x860db8[_0x1f346d(0x77)], 0x6fb * 0x5 + 0x1ebf * 0x1 + -0x41a5), 0x209 * 0xa + 0x1314 + -0x276d); 109 | continue; 110 | } 111 | break; 112 | } 113 | }()); -------------------------------------------------------------------------------- /Examples/case_01_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | var _0x65977d = 2; 3 | var _0x4c96d8 = '53'; 4 | var _0x56d39b = '5-2'; 5 | var _0x544285 = [ 6 | '10', 7 | '10', 8 | '10', 9 | '10', 10 | '10' 11 | ].map(parseInt); 12 | var _0x101028 = 'foo 11'; 13 | console.log(_0x65977d); 14 | console.log(_0x4c96d8); 15 | console.log(_0x56d39b); 16 | console.log(_0x544285); 17 | console.log(_0x101028); 18 | }()); -------------------------------------------------------------------------------- /Examples/case_01_output_with_stringarray_input.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | var _0x9947 = [ 11 | 'map', 12 | 'log', 13 | 'foo ', 14 | 'bvmqO', 15 | '133039ViRMWR', 16 | 'xPfLC', 17 | 'ytpdx', 18 | '1243717qSZCyh', 19 | '2|7|4|6|9|', 20 | '1ErtbCr', 21 | '1608314VKvthn', 22 | '1ZRaFKN', 23 | 'XBoAA', 24 | '423266kQOYHV', 25 | '3|0|5|8|1', 26 | '235064xPNdKe', 27 | '13RUDZfG', 28 | '157gNPQGm', 29 | '1639212MvnHZL', 30 | 'rDjOa', 31 | 'iBHph', 32 | '9926iRHoRl', 33 | 'split' 34 | ]; 35 | function _0x33e4(_0x1809b5, _0x37ef6e) { 36 | _0x33e4 = function (_0x338a69, _0x39ad79) { 37 | _0x338a69 = _0x338a69 - 101; 38 | var _0x2b223a = _0x9947[_0x338a69]; 39 | return _0x2b223a; 40 | }; 41 | return _0x33e4(_0x1809b5, _0x37ef6e); 42 | } 43 | (function (_0x431d87, _0x156c7f) { 44 | while (true) { 45 | try { 46 | var _0x330ad1 = -parseInt('1ErtbCr') * -parseInt('1608314VKvthn') + -parseInt('157gNPQGm') * -parseInt('9926iRHoRl') + parseInt('1243717qSZCyh') + -parseInt('423266kQOYHV') + parseInt('1ZRaFKN') * -parseInt('1639212MvnHZL') + parseInt('235064xPNdKe') + -parseInt('133039ViRMWR') * parseInt('13RUDZfG'); 47 | if (_0x330ad1 === _0x156c7f) { 48 | break; 49 | } else { 50 | _0x431d87.push(_0x431d87.shift()); 51 | } 52 | } catch (_0x9f878) { 53 | _0x431d87.push(_0x431d87.shift()); 54 | } 55 | } 56 | }(_0x9947, 853492)); 57 | (function () { 58 | var _0x65977d = 2; 59 | var _0x4c96d8 = '53'; 60 | var _0x56d39b = '5-2'; 61 | var _0x544285 = [ 62 | '10', 63 | '10', 64 | '10', 65 | '10', 66 | '10' 67 | ].map(parseInt); 68 | var _0x101028 = 'foo 11'; 69 | console.log(_0x65977d); 70 | console.log(_0x4c96d8); 71 | console.log(_0x56d39b); 72 | console.log(_0x544285); 73 | console.log(_0x101028); 74 | }()); -------------------------------------------------------------------------------- /Examples/case_01_stringarray.txt: -------------------------------------------------------------------------------- 1 | var _0x9947 = [ 2 | 'map', 3 | 'log', 4 | 'foo\x20', 5 | 'bvmqO', 6 | '133039ViRMWR', 7 | 'xPfLC', 8 | 'ytpdx', 9 | '1243717qSZCyh', 10 | '2|7|4|6|9|', 11 | '1ErtbCr', 12 | '1608314VKvthn', 13 | '1ZRaFKN', 14 | 'XBoAA', 15 | '423266kQOYHV', 16 | '3|0|5|8|1', 17 | '235064xPNdKe', 18 | '13RUDZfG', 19 | '157gNPQGm', 20 | '1639212MvnHZL', 21 | 'rDjOa', 22 | 'iBHph', 23 | '9926iRHoRl', 24 | 'split' 25 | ]; -------------------------------------------------------------------------------- /Examples/case_01_stringarrayrotate.txt: -------------------------------------------------------------------------------- 1 | (function (_0x431d87, _0x156c7f) { 2 | var _0x10cf6e = _0x33e4; 3 | while (!![]) { 4 | try { 5 | var _0x330ad1 = -parseInt(_0x10cf6e(0x6c)) * -parseInt(_0x10cf6e(0x6d)) + -parseInt(_0x10cf6e(0x74)) * -parseInt(_0x10cf6e(0x78)) + parseInt(_0x10cf6e(0x6a)) + -parseInt(_0x10cf6e(0x70)) + parseInt(_0x10cf6e(0x6e)) * -parseInt(_0x10cf6e(0x75)) + parseInt(_0x10cf6e(0x72)) + -parseInt(_0x10cf6e(0x67)) * parseInt(_0x10cf6e(0x73)); 6 | if (_0x330ad1 === _0x156c7f) 7 | break; 8 | else 9 | _0x431d87['push'](_0x431d87['shift']()); 10 | } catch (_0x9f878) { 11 | _0x431d87['push'](_0x431d87['shift']()); 12 | } 13 | } 14 | }(_0x9947, -0xb6270 + 0x4dfd2 * 0x2 + 0x75460 * 0x2)); -------------------------------------------------------------------------------- /Examples/case_01_stringarraywrappers.txt: -------------------------------------------------------------------------------- 1 | function _0x33e4(_0x1809b5, _0x37ef6e) { 2 | return _0x33e4 = function (_0x338a69, _0x39ad79) { 3 | _0x338a69 = _0x338a69 - (0x1939 + -0xf * 0x1f3 + 0x1 * 0x469); 4 | var _0x2b223a = _0x9947[_0x338a69]; 5 | return _0x2b223a; 6 | }, _0x33e4(_0x1809b5, _0x37ef6e); 7 | } -------------------------------------------------------------------------------- /Examples/case_01_z_commandline.txt: -------------------------------------------------------------------------------- 1 | stringarray auto detection: node index.js -i case_01_input_stringarraywithoutwrappers.txt -o case_01_output.txt 2 | With stringarray input: node index.js -i case_01_input_stringarraywithoutwrappers.txt -o case_01_output_with_stringarray_input.txt -s case_01_stringarray.txt -w case_01_stringarraywrappers.txt -n _0x33e4 -r case_01_stringarrayrotate.txt -------------------------------------------------------------------------------- /Examples/case_02__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | 12 | eval('console.log(5);'); 13 | eval('console.log(5);'); 14 | eval('console.log(5);'); 15 | console.log(6); 16 | (function(){ 17 | var variable1 = '5' - 3; 18 | var variable2 = '5' + 3; 19 | var variable3 = '5' + - '2'; 20 | var variable4 = ['10','10','10','10','10'].map(parseInt); 21 | var variable5 = 'foo ' + 1 + 1; 22 | console.log(variable1); 23 | console.log(variable2); 24 | console.log(variable3); 25 | console.log(variable4); 26 | console.log(variable5); 27 | })(); -------------------------------------------------------------------------------- /Examples/case_02_output.txt: -------------------------------------------------------------------------------- 1 | eval('console.log(5);'); 2 | eval('console.log(5);'); 3 | eval('console.log(5);'); 4 | console.log(6); 5 | (function () { 6 | var _0x1581e1 = 2; 7 | var _0x299c37 = '53'; 8 | var _0x576e1a = '5-2'; 9 | var _0x5ea38c = [ 10 | '10', 11 | '10', 12 | '10', 13 | '10', 14 | '10' 15 | ].map(parseInt); 16 | var _0x45b774 = 'foo 11'; 17 | console.log(_0x1581e1); 18 | console.log(_0x299c37); 19 | console.log(_0x576e1a); 20 | console.log(_0x5ea38c); 21 | console.log(_0x45b774); 22 | }()); -------------------------------------------------------------------------------- /Examples/case_02_output_with_stringarray_input.txt: -------------------------------------------------------------------------------- 1 | eval('console.log(5);'); 2 | eval('console.log(5);'); 3 | eval('console.log(5);'); 4 | console.log(6); 5 | function _0x471d(_0x45e7ff, _0x1eb4cb) { 6 | var _0x192adc = _0x5838(); 7 | _0x471d = function (_0x408193, _0x54b3d3) { 8 | _0x408193 = _0x408193 - 355; 9 | var _0x5401ef = _0x192adc[_0x408193]; 10 | if (_0x471d.vrYqVX === undefined) { 11 | var _0x230a5e = function (_0x547f0c) { 12 | var _0x117381 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 13 | var _0x33d83e = ''; 14 | var _0x397103 = ''; 15 | for (var _0x14fdd7 = 0; _0x24bfc5 = _0x547f0c.charAt(_0x57c896++); ~_0x24bfc5 && (_0x829bd4 = _0x14fdd7 % 4 ? _0x829bd4 * 64 + _0x24bfc5 : _0x24bfc5, _0x14fdd7++ % 4) ? _0x33d83e += String.fromCharCode(255 & _0x829bd4 >> (-2 * _0x14fdd7 & 6)) : 0) { 16 | _0x24bfc5 = _0x117381.indexOf(_0x24bfc5); 17 | } 18 | for (var _0x2d991a = 0; _0x2d991a < _0x49d606; _0x2d991a++) { 19 | _0x397103 += '%' + ('00' + _0x33d83e.charCodeAt(_0x2d991a).toString(16)).slice(-2); 20 | } 21 | return decodeURIComponent(_0x397103); 22 | }; 23 | _0x471d.MKunPw = _0x230a5e; 24 | _0x45e7ff = arguments; 25 | _0x471d.vrYqVX = true; 26 | } 27 | var _0x1398bb = _0x192adc[0]; 28 | var _0x143de4 = _0x408193 + _0x1398bb; 29 | var _0x10d5d4 = _0x45e7ff[_0x143de4]; 30 | if (!_0x10d5d4) { 31 | _0x5401ef = _0x471d.MKunPw(_0x5401ef); 32 | _0x45e7ff[_0x143de4] = _0x5401ef; 33 | } else { 34 | _0x5401ef = _0x10d5d4; 35 | } 36 | return _0x5401ef; 37 | }; 38 | return _0x471d(_0x45e7ff, _0x1eb4cb); 39 | } 40 | function _0x9cad(_0x3c12b3, _0x45f2c7) { 41 | var _0x5f57c1 = _0x5838(); 42 | _0x9cad = function (_0x1f14da, _0x471d03) { 43 | _0x1f14da = _0x1f14da - 355; 44 | var _0x58ad91 = _0x5f57c1[_0x1f14da]; 45 | return _0x58ad91; 46 | }; 47 | return _0x9cad(_0x3c12b3, _0x45f2c7); 48 | } 49 | function _0x4cd9(_0x49cc9c, _0x66e089) { 50 | var _0x3301b3 = _0x5838(); 51 | _0x4cd9 = function (_0x57f4a9, _0x1581e1) { 52 | _0x57f4a9 = _0x57f4a9 - 355; 53 | var _0x299c37 = _0x3301b3[_0x57f4a9]; 54 | if (_0x4cd9.bkrCVb === undefined) { 55 | var _0x576e1a = function (_0x14fe9c) { 56 | var _0x15b0ec = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 57 | var _0x536910 = ''; 58 | var _0x2e6bdd = ''; 59 | for (var _0x51290e = 0; _0x22fa61 = _0x14fe9c.charAt(_0x20fa98++); ~_0x22fa61 && (_0x393f6b = _0x51290e % 4 ? _0x393f6b * 64 + _0x22fa61 : _0x22fa61, _0x51290e++ % 4) ? _0x536910 += String.fromCharCode(255 & _0x393f6b >> (-2 * _0x51290e & 6)) : 0) { 60 | _0x22fa61 = _0x15b0ec.indexOf(_0x22fa61); 61 | } 62 | for (var _0x35d576 = 0; _0x35d576 < _0x3d9ecd; _0x35d576++) { 63 | _0x2e6bdd += '%' + ('00' + _0x536910.charCodeAt(_0x35d576).toString(16)).slice(-2); 64 | } 65 | return decodeURIComponent(_0x2e6bdd); 66 | }; 67 | var _0x1439f2 = function (_0x15e8b1, _0x291855) { 68 | var _0x11a2cf = []; 69 | var _0x3a4f89 = 0; 70 | var _0xc9fd0; 71 | var _0x25739b = ''; 72 | _0x15e8b1 = _0x576e1a(_0x15e8b1); 73 | var _0x1ddd2a; 74 | for (_0x1ddd2a = 0; _0x1ddd2a < 256; _0x1ddd2a++) { 75 | _0x11a2cf[_0x1ddd2a] = _0x1ddd2a; 76 | } 77 | for (_0x1ddd2a = 0; _0x1ddd2a < 256; _0x1ddd2a++) { 78 | _0x3a4f89 = (_0x3a4f89 + _0x11a2cf[_0x1ddd2a] + _0x291855.charCodeAt(_0x1ddd2a % _0x291855.length)) % 256; 79 | _0xc9fd0 = _0x11a2cf[_0x1ddd2a]; 80 | _0x11a2cf[_0x1ddd2a] = _0x11a2cf[_0x3a4f89]; 81 | _0x11a2cf[_0x3a4f89] = _0xc9fd0; 82 | } 83 | _0x1ddd2a = 0; 84 | _0x3a4f89 = 0; 85 | for (var _0x56797d = 0; _0x56797d < _0x15e8b1.length; _0x56797d++) { 86 | _0x1ddd2a = (_0x1ddd2a + 1) % 256; 87 | _0x3a4f89 = (_0x3a4f89 + _0x11a2cf[_0x1ddd2a]) % 256; 88 | _0xc9fd0 = _0x11a2cf[_0x1ddd2a]; 89 | _0x11a2cf[_0x1ddd2a] = _0x11a2cf[_0x3a4f89]; 90 | _0x11a2cf[_0x3a4f89] = _0xc9fd0; 91 | _0x25739b += String.fromCharCode(_0x15e8b1.charCodeAt(_0x56797d) ^ _0x11a2cf[(_0x11a2cf[_0x1ddd2a] + _0x11a2cf[_0x3a4f89]) % 256]); 92 | } 93 | return _0x25739b; 94 | }; 95 | _0x4cd9.NhPWbX = _0x1439f2; 96 | _0x49cc9c = arguments; 97 | _0x4cd9.bkrCVb = true; 98 | } 99 | var _0x5ea38c = _0x3301b3[0]; 100 | var _0x45b774 = _0x57f4a9 + _0x5ea38c; 101 | var _0x19ea5b = _0x49cc9c[_0x45b774]; 102 | if (!_0x19ea5b) { 103 | if (_0x4cd9.NAvBjY === undefined) { 104 | _0x4cd9.NAvBjY = true; 105 | } 106 | _0x299c37 = _0x4cd9.NhPWbX(_0x299c37, _0x1581e1); 107 | _0x49cc9c[_0x45b774] = _0x299c37; 108 | } else { 109 | _0x299c37 = _0x19ea5b; 110 | } 111 | return _0x299c37; 112 | }; 113 | return _0x4cd9(_0x49cc9c, _0x66e089); 114 | } 115 | function _0x5838() { 116 | var _0x4b401c = [ 117 | '1602873ZZzntI', 118 | 'jUjCF', 119 | 'BwfW', 120 | '1116075EVywnD', 121 | 'cPQiY', 122 | 'W5tcQdm/Dq', 123 | 'iAYBG', 124 | 'ax7cRJH4wSoCWRNdV0j5WRO', 125 | 'W7ldLh3dKMFdVSogW4brWQyLWQe', 126 | 'zM9Via', 127 | 'vCoGWRhcHSoz', 128 | 'ufbNzeK', 129 | 'WRGnamkadwhcMCksW4jhWQOX', 130 | 'amowWQ17aq', 131 | 'Bg9N', 132 | 'W5Phja', 133 | 'mJHxwxLwC00', 134 | 'mtG3mJC2mhLtAhbIuW', 135 | 'mZq3mJe3wfrNwNzM', 136 | 'log', 137 | 'W5D9W4NcQmkgpCoAfCkjD8kjW4j+', 138 | 'C3bSAxq', 139 | '38201110KStAJj', 140 | 'zSo3aSkOWRpdJCk5lGpcLmoVWOJdS8oQ', 141 | 'ouLOzuHqAq', 142 | '9553698TGVBgP', 143 | '4EoVXSj', 144 | '28WYyVsM', 145 | 'nevVvLHtAG', 146 | 'mNW1Fdz8n3W5Fdb8mxWZFdr8oa', 147 | 'v0VcVZu1qmoE', 148 | 'PPgdI', 149 | 'ALvQq0y' 150 | ]; 151 | _0x5838 = function () { 152 | return _0x4b401c; 153 | }; 154 | return _0x5838(); 155 | } 156 | (function (_0x4b2b1a, _0x45ec8c) { 157 | var _0x2401fe = _0x4b2b1a(); 158 | while (true) { 159 | try { 160 | var _0x38a635 = parseInt('347217XTgZvf') / 1 + -parseInt('923354MvpvhL') / 2 + -parseInt('1602873ZZzntI') / 3 * (parseInt('4EoVXSj') / 4) + parseInt('1116075EVywnD') / 5 + -parseInt('9553698TGVBgP') / 6 + -parseInt('28WYyVsM') / 7 * (parseInt('1872760yShpbS') / 8) + parseInt('9IheHPi') / 9 * (parseInt('38201110KStAJj') / 10); 161 | if (_0x38a635 === _0x45ec8c) { 162 | break; 163 | } else { 164 | _0x2401fe.push(_0x2401fe.shift()); 165 | } 166 | } catch (_0x3216ad) { 167 | _0x2401fe.push(_0x2401fe.shift()); 168 | } 169 | } 170 | }(_0x5838, 865912)); 171 | (function () { 172 | var _0x1581e1 = 2; 173 | var _0x299c37 = '53'; 174 | var _0x576e1a = '5-2'; 175 | var _0x5ea38c = [ 176 | '10', 177 | '10', 178 | '10', 179 | '10', 180 | '10' 181 | ].map(parseInt); 182 | var _0x45b774 = 'foo 11'; 183 | console.log(_0x1581e1); 184 | console.log(_0x299c37); 185 | console.log(_0x576e1a); 186 | console.log(_0x5ea38c); 187 | console.log(_0x45b774); 188 | }()); -------------------------------------------------------------------------------- /Examples/case_02_stringarray.txt: -------------------------------------------------------------------------------- 1 | function _0x5838() { 2 | var _0x4b401c = [ 3 | '1602873ZZzntI', 4 | 'jUjCF', 5 | 'BwfW', 6 | '1116075EVywnD', 7 | 'cPQiY', 8 | 'W5tcQdm/Dq', 9 | 'iAYBG', 10 | 'ax7cRJH4wSoCWRNdV0j5WRO', 11 | 'W7ldLh3dKMFdVSogW4brWQyLWQe', 12 | 'zM9Via', 13 | 'vCoGWRhcHSoz', 14 | 'ufbNzeK', 15 | 'WRGnamkadwhcMCksW4jhWQOX', 16 | 'amowWQ17aq', 17 | 'Bg9N', 18 | 'W5Phja', 19 | 'mJHxwxLwC00', 20 | 'mtG3mJC2mhLtAhbIuW', 21 | 'mZq3mJe3wfrNwNzM', 22 | 'log', 23 | 'W5D9W4NcQmkgpCoAfCkjD8kjW4j+', 24 | 'C3bSAxq', 25 | '38201110KStAJj', 26 | 'zSo3aSkOWRpdJCk5lGpcLmoVWOJdS8oQ', 27 | 'ouLOzuHqAq', 28 | '9553698TGVBgP', 29 | '4EoVXSj', 30 | '28WYyVsM', 31 | 'nevVvLHtAG', 32 | 'mNW1Fdz8n3W5Fdb8mxWZFdr8oa', 33 | 'v0VcVZu1qmoE', 34 | 'PPgdI', 35 | 'ALvQq0y' 36 | ]; 37 | _0x5838 = function () { 38 | return _0x4b401c; 39 | }; 40 | return _0x5838(); 41 | } 42 | -------------------------------------------------------------------------------- /Examples/case_02_stringarrayrotate.txt: -------------------------------------------------------------------------------- 1 | (function (_0x4b2b1a, _0x45ec8c) { 2 | var _0x2bfa1b = { 3 | _0x3b9030: 0x3b0, 4 | _0x2dddb5: 0x101, 5 | _0x53463a: 0x1d5, 6 | _0x3d36c7: 0x1db, 7 | _0x5998bc: 0x55e, 8 | _0x5f5de1: 0x554, 9 | _0x2fefb8: 0x561, 10 | _0x2629b5: 0x562, 11 | _0x3f93f4: 0x202, 12 | _0x29e0d6: 0x20e, 13 | _0x15f309: 0x1f0, 14 | _0xd0bb12: 0x1f1, 15 | _0x44ccf1: 0x1f4, 16 | _0x467078: 0x3b8, 17 | _0x3a0502: 0x3ac, 18 | _0x301526: 0x3b4, 19 | _0xb8c9d0: 0x3c4, 20 | _0x176fe1: 0x2fc, 21 | _0x5b56ec: 0x2f6, 22 | _0x5cbbbd: 0xd5, 23 | _0x1766eb: 0xc6, 24 | _0x526a2a: 0xd7, 25 | _0x19507c: 0xd0, 26 | _0x33c55e: 0x56b, 27 | _0x2c48be: 0x55e 28 | }, _0x2017c7 = { _0x39b629: 0x186 }, _0x4f42ae = { _0x212634: 0x3e5 }; 29 | function _0x35f3c5(_0x415657, _0x26bf88, _0x3c60df, _0x4401fc, _0x32dfbd) { 30 | return _0x4cd9(_0x26bf88 - -0x68, _0x4401fc); 31 | } 32 | function _0x127697(_0x2323a1, _0x7939c8, _0x2c41b9, _0x403960, _0x314b5a) { 33 | return _0x9cad(_0x2c41b9 - 0x237, _0x314b5a); 34 | } 35 | function _0x3205a5(_0x18f537, _0x9e8f13, _0x4ccbfe, _0x2d5065, _0xe7536d) { 36 | return _0x471d(_0xe7536d - 0x239, _0x18f537); 37 | } 38 | function _0x11a04a(_0x3bea95, _0x2ca55d, _0x2fa47a, _0x5a8fa8, _0xc60c3d) { 39 | return _0x9cad(_0x2fa47a - _0x4f42ae._0x212634, _0x3bea95); 40 | } 41 | function _0x49d8d1(_0x480bd7, _0x5e8a34, _0x5f1fca, _0x435c3e, _0x2e741f) { 42 | return _0x9cad(_0x480bd7 - -0x367, _0x435c3e); 43 | } 44 | function _0x294877(_0x206557, _0x527b52, _0x262807, _0x217fc7, _0x4375f4) { 45 | return _0x471d(_0x206557 - -0xa4, _0x262807); 46 | } 47 | var _0x2401fe = _0x4b2b1a(); 48 | function _0x6da0a9(_0x5247f0, _0x497ba9, _0x8b36a5, _0x155ae4, _0xcac12) { 49 | return _0x4cd9(_0x5247f0 - _0x2017c7._0x39b629, _0x8b36a5); 50 | } 51 | while (!![]) { 52 | try { 53 | var _0x38a635 = parseInt(_0x3205a5(0x3bb, 0x3a9, _0x2bfa1b._0x3b9030, 0x39c, 0x3ad)) / (0x19e + -0x33f * -0x7 + -0x1856) + -parseInt(_0x35f3c5(0x10a, _0x2bfa1b._0x2dddb5, 0x100, 'FSlj', 0xfc)) / (0xad0 * -0x2 + -0x23f1 + 0x11 * 0x363) + -parseInt(_0x49d8d1(-0x1e4, -0x1da, -0x1d7, -_0x2bfa1b._0x53463a, -_0x2bfa1b._0x3d36c7)) / (0x1bf9 + -0x215b + 0x565) * (parseInt(_0x11a04a(_0x2bfa1b._0x5998bc, _0x2bfa1b._0x5f5de1, _0x2bfa1b._0x2fefb8, 0x55a, _0x2bfa1b._0x2629b5)) / (0x1b3 * 0x9 + 0xe * -0x82 + 0x29 * -0x33)) + parseInt(_0x49d8d1(-_0x2bfa1b._0x3f93f4, -0x1fd, -_0x2bfa1b._0x3f93f4, -0x20e, -_0x2bfa1b._0x29e0d6)) / (-0x1189 + 0x1 * 0xf76 + 0x1 * 0x218) + -parseInt(_0x49d8d1(-0x1ec, -0x1dc, -_0x2bfa1b._0x15f309, -_0x2bfa1b._0xd0bb12, -_0x2bfa1b._0x44ccf1)) / (-0x1 * -0xaf8 + -0x1476 + 0x1c * 0x57) + -parseInt(_0x127697(_0x2bfa1b._0x467078, _0x2bfa1b._0x3a0502, _0x2bfa1b._0x301526, _0x2bfa1b._0xb8c9d0, 0x3ad)) / (0x4f * -0x31 + -0x1e19 + 0x75 * 0x63) * (parseInt(_0x6da0a9(_0x2bfa1b._0x176fe1, 0x2fc, 'K]j#', _0x2bfa1b._0x5b56ec, 0x30a)) / (0x1502 + -0x44 * 0x93 + 0x1212)) + parseInt(_0x294877(0xd6, _0x2bfa1b._0x5cbbbd, _0x2bfa1b._0x1766eb, _0x2bfa1b._0x526a2a, _0x2bfa1b._0x19507c)) / (-0x2392 + -0xc88 + -0x3023 * -0x1) * (parseInt(_0x11a04a(0x553, _0x2bfa1b._0x33c55e, 0x55d, _0x2bfa1b._0x2c48be, 0x563)) / (0x7be + 0x1cff + -0x757 * 0x5)); 54 | if (_0x38a635 === _0x45ec8c) 55 | break; 56 | else 57 | _0x2401fe['push'](_0x2401fe['shift']()); 58 | } catch (_0x3216ad) { 59 | _0x2401fe['push'](_0x2401fe['shift']()); 60 | } 61 | } 62 | }(_0x5838, -0xf38f7 + 0xc8aac + 0xfe4c3)) -------------------------------------------------------------------------------- /Examples/case_02_stringarraywrappers.txt: -------------------------------------------------------------------------------- 1 | 2 | function _0x471d(_0x45e7ff, _0x1eb4cb) { 3 | var _0x192adc = _0x5838(); 4 | return _0x471d = function (_0x408193, _0x54b3d3) { 5 | _0x408193 = _0x408193 - (0x65 * 0x3d + 0x1727 + -0x2dd5); 6 | var _0x5401ef = _0x192adc[_0x408193]; 7 | if (_0x471d['vrYqVX'] === undefined) { 8 | var _0x230a5e = function (_0x547f0c) { 9 | var _0x117381 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 10 | var _0x33d83e = '', _0x397103 = ''; 11 | for (var _0x14fdd7 = -0xa26 * -0x1 + 0x29b * 0x7 + -0x1c63, _0x829bd4, _0x24bfc5, _0x57c896 = 0x3f7 + -0x4cd * 0x1 + -0xd6 * -0x1; _0x24bfc5 = _0x547f0c['charAt'](_0x57c896++); ~_0x24bfc5 && (_0x829bd4 = _0x14fdd7 % (0x1693 + -0x4bb + -0x2 * 0x8ea) ? _0x829bd4 * (0x230 + 0x19 * -0x44 + 0x2 * 0x25a) + _0x24bfc5 : _0x24bfc5, _0x14fdd7++ % (0x14ad * -0x1 + -0x874 * 0x3 + -0x2e0d * -0x1)) ? _0x33d83e += String['fromCharCode'](0x2505 + -0x643 + -0x1dc3 & _0x829bd4 >> (-(-0x576 * 0x3 + 0x2638 + -0x15d4) * _0x14fdd7 & -0x1d * -0xec + 0xa6e + 0x1 * -0x2524)) : 0x4 * -0x745 + 0x1a + 0xe7d * 0x2) { 12 | _0x24bfc5 = _0x117381['indexOf'](_0x24bfc5); 13 | } 14 | for (var _0x2d991a = -0x264c + 0x8b9 + 0x1d93, _0x49d606 = _0x33d83e['length']; _0x2d991a < _0x49d606; _0x2d991a++) { 15 | _0x397103 += '%' + ('00' + _0x33d83e['charCodeAt'](_0x2d991a)['toString'](0xfed + 0x9dc * -0x1 + 0x1 * -0x601))['slice'](-(-0x8 * -0x16 + -0x1 * 0x11b7 + 0x59 * 0x31)); 16 | } 17 | return decodeURIComponent(_0x397103); 18 | }; 19 | _0x471d['MKunPw'] = _0x230a5e, _0x45e7ff = arguments, _0x471d['vrYqVX'] = !![]; 20 | } 21 | var _0x1398bb = _0x192adc[-0x71 + -0xf5f * 0x1 + 0x8 * 0x1fa], _0x143de4 = _0x408193 + _0x1398bb, _0x10d5d4 = _0x45e7ff[_0x143de4]; 22 | return !_0x10d5d4 ? (_0x5401ef = _0x471d['MKunPw'](_0x5401ef), _0x45e7ff[_0x143de4] = _0x5401ef) : _0x5401ef = _0x10d5d4, _0x5401ef; 23 | }, _0x471d(_0x45e7ff, _0x1eb4cb); 24 | } 25 | function _0x9cad(_0x3c12b3, _0x45f2c7) { 26 | var _0x5f57c1 = _0x5838(); 27 | return _0x9cad = function (_0x1f14da, _0x471d03) { 28 | _0x1f14da = _0x1f14da - (0x65 * 0x3d + 0x1727 + -0x2dd5); 29 | var _0x58ad91 = _0x5f57c1[_0x1f14da]; 30 | return _0x58ad91; 31 | }, _0x9cad(_0x3c12b3, _0x45f2c7); 32 | } 33 | function _0x4cd9(_0x49cc9c, _0x66e089) { 34 | var _0x3301b3 = _0x5838(); 35 | return _0x4cd9 = function (_0x57f4a9, _0x1581e1) { 36 | _0x57f4a9 = _0x57f4a9 - (0x65 * 0x3d + 0x1727 + -0x2dd5); 37 | var _0x299c37 = _0x3301b3[_0x57f4a9]; 38 | if (_0x4cd9['bkrCVb'] === undefined) { 39 | var _0x576e1a = function (_0x14fe9c) { 40 | var _0x15b0ec = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 41 | var _0x536910 = '', _0x2e6bdd = ''; 42 | for (var _0x51290e = -0xa26 * -0x1 + 0x29b * 0x7 + -0x1c63, _0x393f6b, _0x22fa61, _0x20fa98 = 0x3f7 + -0x4cd * 0x1 + -0xd6 * -0x1; _0x22fa61 = _0x14fe9c['charAt'](_0x20fa98++); ~_0x22fa61 && (_0x393f6b = _0x51290e % (0x1693 + -0x4bb + -0x2 * 0x8ea) ? _0x393f6b * (0x230 + 0x19 * -0x44 + 0x2 * 0x25a) + _0x22fa61 : _0x22fa61, _0x51290e++ % (0x14ad * -0x1 + -0x874 * 0x3 + -0x2e0d * -0x1)) ? _0x536910 += String['fromCharCode'](0x2505 + -0x643 + -0x1dc3 & _0x393f6b >> (-(-0x576 * 0x3 + 0x2638 + -0x15d4) * _0x51290e & -0x1d * -0xec + 0xa6e + 0x1 * -0x2524)) : 0x4 * -0x745 + 0x1a + 0xe7d * 0x2) { 43 | _0x22fa61 = _0x15b0ec['indexOf'](_0x22fa61); 44 | } 45 | for (var _0x35d576 = -0x264c + 0x8b9 + 0x1d93, _0x3d9ecd = _0x536910['length']; _0x35d576 < _0x3d9ecd; _0x35d576++) { 46 | _0x2e6bdd += '%' + ('00' + _0x536910['charCodeAt'](_0x35d576)['toString'](0xfed + 0x9dc * -0x1 + 0x1 * -0x601))['slice'](-(-0x8 * -0x16 + -0x1 * 0x11b7 + 0x59 * 0x31)); 47 | } 48 | return decodeURIComponent(_0x2e6bdd); 49 | }; 50 | var _0x1439f2 = function (_0x15e8b1, _0x291855) { 51 | var _0x11a2cf = [], _0x3a4f89 = -0x71 + -0xf5f * 0x1 + 0x8 * 0x1fa, _0xc9fd0, _0x25739b = ''; 52 | _0x15e8b1 = _0x576e1a(_0x15e8b1); 53 | var _0x1ddd2a; 54 | for (_0x1ddd2a = 0x1234 + 0x6f5 * -0x2 + -0x6 * 0xb7; _0x1ddd2a < -0x1704 + -0x12f * 0x13 + 0x1 * 0x2e81; _0x1ddd2a++) { 55 | _0x11a2cf[_0x1ddd2a] = _0x1ddd2a; 56 | } 57 | for (_0x1ddd2a = -0x25ff + -0x1 * 0x2062 + 0x2b * 0x1a3; _0x1ddd2a < -0x2 * -0x136e + -0x1650 + 0x1 * -0xf8c; _0x1ddd2a++) { 58 | _0x3a4f89 = (_0x3a4f89 + _0x11a2cf[_0x1ddd2a] + _0x291855['charCodeAt'](_0x1ddd2a % _0x291855['length'])) % (0x1a1b * -0x1 + 0x85 * 0x43 + 0x44 * -0x1d), _0xc9fd0 = _0x11a2cf[_0x1ddd2a], _0x11a2cf[_0x1ddd2a] = _0x11a2cf[_0x3a4f89], _0x11a2cf[_0x3a4f89] = _0xc9fd0; 59 | } 60 | _0x1ddd2a = -0x1c96 * 0x1 + -0x2155 + 0x3deb, _0x3a4f89 = 0xc51 + 0xbf6 * 0x3 + -0x3033; 61 | for (var _0x56797d = 0x24bd + -0x137b + 0x1 * -0x1142; _0x56797d < _0x15e8b1['length']; _0x56797d++) { 62 | _0x1ddd2a = (_0x1ddd2a + (-0x1 * 0x707 + -0x1 * -0x1163 + -0xa5b)) % (0x1656 + 0xb2e + 0x2 * -0x1042), _0x3a4f89 = (_0x3a4f89 + _0x11a2cf[_0x1ddd2a]) % (0x1d85 + -0x259 * -0x1 + -0x1ede), _0xc9fd0 = _0x11a2cf[_0x1ddd2a], _0x11a2cf[_0x1ddd2a] = _0x11a2cf[_0x3a4f89], _0x11a2cf[_0x3a4f89] = _0xc9fd0, _0x25739b += String['fromCharCode'](_0x15e8b1['charCodeAt'](_0x56797d) ^ _0x11a2cf[(_0x11a2cf[_0x1ddd2a] + _0x11a2cf[_0x3a4f89]) % (0x1eac + 0x1f24 + -0x3cd0)]); 63 | } 64 | return _0x25739b; 65 | }; 66 | _0x4cd9['NhPWbX'] = _0x1439f2, _0x49cc9c = arguments, _0x4cd9['bkrCVb'] = !![]; 67 | } 68 | var _0x5ea38c = _0x3301b3[-0xd13 + 0x392 * 0x2 + -0xd9 * -0x7], _0x45b774 = _0x57f4a9 + _0x5ea38c, _0x19ea5b = _0x49cc9c[_0x45b774]; 69 | return !_0x19ea5b ? (_0x4cd9['NAvBjY'] === undefined && (_0x4cd9['NAvBjY'] = !![]), _0x299c37 = _0x4cd9['NhPWbX'](_0x299c37, _0x1581e1), _0x49cc9c[_0x45b774] = _0x299c37) : _0x299c37 = _0x19ea5b, _0x299c37; 70 | }, _0x4cd9(_0x49cc9c, _0x66e089); 71 | } -------------------------------------------------------------------------------- /Examples/case_02_z_commandline.txt: -------------------------------------------------------------------------------- 1 | stringarray auto detection: node index.js -i case_02_input_newestoptionandeval.txt -o case_02_output.txt 2 | With stringarray input: node index.js -i case_02_input_newestoptionandeval.txt -o case_02_output_with_stringarray_input.txt -s case_02_stringarray.txt -w case_02_stringarraywrappers.txt -n _0x471d,_0x9cad,_0x4cd9 -r case_02_stringarrayrotate.txt -------------------------------------------------------------------------------- /Examples/case_03__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | 12 | (function(){ 13 | var variable1 = '5' - 3; 14 | var variable2 = '5' + 3; 15 | var variable3 = '5' + - '2'; 16 | var variable4 = ['10','10','10','10','10'].map(parseInt); 17 | var variable5 = 'foo ' + 1 + 1; 18 | console.log(variable1); 19 | console.log(variable2); 20 | console.log(variable3); 21 | console.log(variable4); 22 | console.log(variable5); 23 | })(); 24 | 25 | eval('console.log(5);'); 26 | eval('console.log(5);'); -------------------------------------------------------------------------------- /Examples/case_03_input_compact.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | function _0x4b3d(_0x3c12b3,_0x45f2c7){var _0x5f57c1=_0x1bd8();_0x4b3d=function(_0x1f14da,_0x471d03){_0x1f14da=_0x1f14da-(0x65*0x3d+0x1727+-0x2dd5);var _0x58ad91=_0x5f57c1[_0x1f14da];return _0x58ad91;};return _0x4b3d(_0x3c12b3,_0x45f2c7);}function _0x1bd8(){var _0x32fbf0=['nSkGxSoRW7BcJSo9FtZcQmoP','C2vHCMnO','gM3cHcqpECozWO8','4635084DclwjF','zM9Via','yxbWBhK','162dBVlwV','BwfW','oda3otjQt1jlzK8','x8kudmk9EbfrDXCZ','log','W61dW4PyW69UDG','muLLCgHjwa','kcGOlISPkYKRksSK','sSkIW5KDBuRcTw1nW74','mti4ode5ognquwLzBG','4755519mrLAvL','odmZmLz3vhbZtW','ndyZnta4nerJBhDQrG','891942BiEfjU','nZG1mfPnywXSBa','WRLsjmopeM15g1K','W4SrWP1vdSoYW6y','kCklW44','1288198cPQiYn','mJe4nuH5DvPjva','mtq0mvr6u0z0CG','Bg9N','1441TzSFtr'];_0x1bd8=function(){return _0x32fbf0;};return _0x1bd8();}function _0x3487(_0x53b786,_0x328d51){var _0xfde531=_0x1bd8();_0x3487=function(_0x3795a2,_0x93800d){_0x3795a2=_0x3795a2-(0x65*0x3d+0x1727+-0x2dd5);var _0x11838d=_0xfde531[_0x3795a2];if(_0x3487['mXhRfe']===undefined){var _0x551fe7=function(_0x100e3b){var _0x1fbaf1='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x386774='';var _0x10ae8d='';var _0x4a8f4c=_0x386774+_0x551fe7;for(var _0x4fbcab=-0xa26*-0x1+0x29b*0x7+-0x1c63,_0x438f13,_0xa142e8,_0x49cc9c=0x3f7+-0x4cd*0x1+-0xd6*-0x1;_0xa142e8=_0x100e3b['charAt'](_0x49cc9c++);~_0xa142e8&&(_0x438f13=_0x4fbcab%(0x1693+-0x4bb+-0x2*0x8ea)?_0x438f13*(0x230+0x19*-0x44+0x2*0x25a)+_0xa142e8:_0xa142e8,_0x4fbcab++%(0x14ad*-0x1+-0x874*0x3+-0x2e0d*-0x1))?_0x386774+=_0x4a8f4c['charCodeAt'](_0x49cc9c+(0x2505+-0x643+-0x1eb8))-(-0x576*0x3+0x2638+-0x15cc)!==-0x1d*-0xec+0xa6e+0x2*-0x1295?String['fromCharCode'](0x4*-0x745+0x1a+0x1df9*0x1&_0x438f13>>(-(-0x264c+0x8b9+0x1d95)*_0x4fbcab&0xfed+0x9dc*-0x1+0x7*-0xdd)):_0x4fbcab:-0x8*-0x16+-0x1*0x11b7+0x5ad*0x3){_0xa142e8=_0x1fbaf1['indexOf'](_0xa142e8);}for(var _0x66e089=-0x71+-0xf5f*0x1+0x8*0x1fa,_0x3301b3=_0x386774['length'];_0x66e089<_0x3301b3;_0x66e089++){_0x10ae8d+='%'+('00'+_0x386774['charCodeAt'](_0x66e089)['toString'](0x1234+0x6f5*-0x2+-0x2*0x21d))['slice'](-(-0x1704+-0x12f*0x13+0x1*0x2d83));}return decodeURIComponent(_0x10ae8d);};_0x3487['SAZVpZ']=_0x551fe7;_0x53b786=arguments;_0x3487['mXhRfe']=!![];}var _0x55b2b1=_0xfde531[-0x25ff+-0x1*0x2062+0x2b*0x1a3];var _0x4f8681=_0x3795a2+_0x55b2b1;var _0x9f66fc=_0x53b786[_0x4f8681];if(!_0x9f66fc){var _0x57f4a9=function(_0x1581e1){this['TivuVN']=_0x1581e1;this['vYGybm']=[-0x2*-0x136e+-0x1650+0x1*-0x108b,0x1a1b*-0x1+0x85*0x43+0x22d*-0x4,-0x1c96*0x1+-0x2155+0x3deb];this['kOTaoR']=function(){return'newState';};this['vQkpkc']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';this['qTfJUY']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x57f4a9['prototype']['OteyJA']=function(){var _0x299c37=new RegExp(this['vQkpkc']+this['qTfJUY']);var _0x576e1a=_0x299c37['test'](this['kOTaoR']['toString']())?--this['vYGybm'][0xc51+0xbf6*0x3+-0x3032]:--this['vYGybm'][0x24bd+-0x137b+0x1*-0x1142];return this['DCZPCi'](_0x576e1a);};_0x57f4a9['prototype']['DCZPCi']=function(_0x5ea38c){if(!Boolean(~_0x5ea38c)){return _0x5ea38c;}return this['IedQYl'](this['TivuVN']);};_0x57f4a9['prototype']['IedQYl']=function(_0x45b774){for(var _0x19ea5b=-0x1*0x707+-0x1*-0x1163+-0xa5c,_0x1439f2=this['vYGybm']['length'];_0x19ea5b<_0x1439f2;_0x19ea5b++){this['vYGybm']['push'](Math['round'](Math['random']()));_0x1439f2=this['vYGybm']['length'];}return _0x45b774(this['vYGybm'][0x1656+0xb2e+0x21*-0x104]);};new _0x57f4a9(_0x3487)['OteyJA']();_0x11838d=_0x3487['SAZVpZ'](_0x11838d);_0x53b786[_0x4f8681]=_0x11838d;}else{_0x11838d=_0x9f66fc;}return _0x11838d;};return _0x3487(_0x53b786,_0x328d51);}(function(_0x22990b,_0xb25385){var _0x8a4557={_0x223161:0x16c,_0x3638a6:'rrDy',_0x2850e7:0x165,_0x12d557:0x166,_0x1568df:'8#Xu',_0x361335:0x17e,_0x512cbc:'Mafe',_0xf4c6e4:0x16b,_0x22fd72:'&T4o',_0x3cce40:0x164,_0x297f3c:0x170};var _0x12e604=_0x4b3d;var _0x5d69e1=_0x4b3d;var _0x1f2a82=_0x4b3d;var _0x2e07ef=_0x3487;var _0x1c7651=_0x3487;var _0x3878b1=_0x3487;var _0x16dd08=_0x3c12;var _0x580267=_0x3c12;var _0x13eb14=_0x3c12;var _0x1893d7=_0x22990b();while(!![]){try{var _0x425a5b=parseInt(_0x16dd08(_0x8a4557._0x223161,_0x8a4557._0x3638a6))/(-0x266d+-0x1*0x863+0x11*0x2c1)*(parseInt(_0x2e07ef(_0x8a4557._0x2850e7))/(0x2407+-0x9*-0x341+-0x414e))+parseInt(_0x12e604(_0x8a4557._0x12d557))/(0x1334+-0x713+-0xc1e)+parseInt(_0x16dd08(0x17c,_0x8a4557._0x1568df))/(-0x1*-0x1175+0x26bd+-0x382e)*(-parseInt(_0x1c7651(0x16f))/(0xd32+0x1b0*0x4+-0x13ed*0x1))+parseInt(_0x5d69e1(0x169))/(0x722+0x20da+-0x27f6)*(parseInt(_0x580267(_0x8a4557._0x361335,_0x8a4557._0x512cbc))/(0x542*0x1+-0x1d0*-0x10+0x223b*-0x1))+parseInt(_0x1c7651(0x17b))/(-0xb*-0x34f+-0x1*0x272+-0x1c9*0x13)*(-parseInt(_0x580267(_0x8a4557._0xf4c6e4,_0x8a4557._0x22fd72))/(0x25*-0x6d+-0x24e7+0x34b1))+-parseInt(_0x16dd08(_0x8a4557._0x3cce40,'QHJZ'))/(0xbfb+0x131*0x13+-0x2294)*(parseInt(_0x3878b1(_0x8a4557._0x297f3c))/(0xb5+0x2ef*0x5+-0xf55))+-parseInt(_0x5d69e1(0x176))/(0x1d37+-0x19d5+-0x356);if(_0x425a5b===_0xb25385){break;}else{_0x1893d7['push'](_0x1893d7['shift']());}}catch(_0x2702eb){_0x1893d7['push'](_0x1893d7['shift']());}}}(_0x1bd8,0x180c57+0x2c*0x7a87+-0x20f31b*0x1));function _0x3c12(_0x361b18,_0x5314f6){var _0x3c7ffb=_0x1bd8();_0x3c12=function(_0x56c0e7,_0x324f7d){_0x56c0e7=_0x56c0e7-(0x65*0x3d+0x1727+-0x2dd5);var _0xc9ac2e=_0x3c7ffb[_0x56c0e7];if(_0x3c12['iPwJvG']===undefined){var _0x4c9746=function(_0x21204c){var _0x475545='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';var _0x2cd6be='';var _0x523cfc='';var _0xe2368d=_0x2cd6be+_0x4c9746;for(var _0x1c756a=-0xa26*-0x1+0x29b*0x7+-0x1c63,_0x2a5e1a,_0x528323,_0x3f67bc=0x3f7+-0x4cd*0x1+-0xd6*-0x1;_0x528323=_0x21204c['charAt'](_0x3f67bc++);~_0x528323&&(_0x2a5e1a=_0x1c756a%(0x1693+-0x4bb+-0x2*0x8ea)?_0x2a5e1a*(0x230+0x19*-0x44+0x2*0x25a)+_0x528323:_0x528323,_0x1c756a++%(0x14ad*-0x1+-0x874*0x3+-0x2e0d*-0x1))?_0x2cd6be+=_0xe2368d['charCodeAt'](_0x3f67bc+(0x2505+-0x643+-0x1eb8))-(-0x576*0x3+0x2638+-0x15cc)!==-0x1d*-0xec+0xa6e+0x2*-0x1295?String['fromCharCode'](0x4*-0x745+0x1a+0x1df9*0x1&_0x2a5e1a>>(-(-0x264c+0x8b9+0x1d95)*_0x1c756a&0xfed+0x9dc*-0x1+0x7*-0xdd)):_0x1c756a:-0x8*-0x16+-0x1*0x11b7+0x5ad*0x3){_0x528323=_0x475545['indexOf'](_0x528323);}for(var _0xd9183a=-0x71+-0xf5f*0x1+0x8*0x1fa,_0x8770e0=_0x2cd6be['length'];_0xd9183a<_0x8770e0;_0xd9183a++){_0x523cfc+='%'+('00'+_0x2cd6be['charCodeAt'](_0xd9183a)['toString'](0x1234+0x6f5*-0x2+-0x2*0x21d))['slice'](-(-0x1704+-0x12f*0x13+0x1*0x2d83));}return decodeURIComponent(_0x523cfc);};var _0x56e612=function(_0x3e4f6d,_0x4b51a5){var _0x106441=[],_0x42afb1=-0x25ff+-0x1*0x2062+0x2b*0x1a3,_0x50c1c4,_0x22f16a='';_0x3e4f6d=_0x4c9746(_0x3e4f6d);var _0x308c9f;for(_0x308c9f=-0x2*-0x136e+-0x1650+0x1*-0x108c;_0x308c9f<0x1a1b*-0x1+0x85*0x43+0x44*-0x1d;_0x308c9f++){_0x106441[_0x308c9f]=_0x308c9f;}for(_0x308c9f=-0x1c96*0x1+-0x2155+0x3deb;_0x308c9f<0xc51+0xbf6*0x3+-0x2f33;_0x308c9f++){_0x42afb1=(_0x42afb1+_0x106441[_0x308c9f]+_0x4b51a5['charCodeAt'](_0x308c9f%_0x4b51a5['length']))%(0x24bd+-0x137b+0x1*-0x1042);_0x50c1c4=_0x106441[_0x308c9f];_0x106441[_0x308c9f]=_0x106441[_0x42afb1];_0x106441[_0x42afb1]=_0x50c1c4;}_0x308c9f=-0x1*0x707+-0x1*-0x1163+-0xa5c;_0x42afb1=0x1656+0xb2e+0x21*-0x104;for(var _0x41974c=0x1d85+-0x259*-0x1+-0x1fde;_0x41974c<_0x3e4f6d['length'];_0x41974c++){_0x308c9f=(_0x308c9f+(0x1eac+0x1f24+-0x3dcf))%(-0xd13+0x392*0x2+-0x163*-0x5);_0x42afb1=(_0x42afb1+_0x106441[_0x308c9f])%(0x1565*0x1+-0x21ce+0xd69);_0x50c1c4=_0x106441[_0x308c9f];_0x106441[_0x308c9f]=_0x106441[_0x42afb1];_0x106441[_0x42afb1]=_0x50c1c4;_0x22f16a+=String['fromCharCode'](_0x3e4f6d['charCodeAt'](_0x41974c)^_0x106441[(_0x106441[_0x308c9f]+_0x106441[_0x42afb1])%(-0x2090*-0x1+0x2678+-0x4608)]);}return _0x22f16a;};_0x3c12['LBjHpr']=_0x56e612;_0x361b18=arguments;_0x3c12['iPwJvG']=!![];}var _0x59bf7c=_0x3c7ffb[-0x154d+0x1*0x1d45+-0x7f8];var _0x5c1c2d=_0x56c0e7+_0x59bf7c;var _0x2cb39a=_0x361b18[_0x5c1c2d];if(!_0x2cb39a){if(_0x3c12['RdnhOX']===undefined){var _0x11e9a2=function(_0x31a9d1){this['xXwZSO']=_0x31a9d1;this['elaeFj']=[-0xc0d+0x509+0x705,-0x189f+0x8b4+0xfeb,0x5*0x65b+0x755*-0x1+-0x1872];this['hPxTGL']=function(){return'newState';};this['YRndvy']='\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*';this['DCScBy']='[\x27|\x22].+[\x27|\x22];?\x20*}';};_0x11e9a2['prototype']['URDnSr']=function(){var _0x4b6bf7=new RegExp(this['YRndvy']+this['DCScBy']);var _0x70e4c8=_0x4b6bf7['test'](this['hPxTGL']['toString']())?--this['elaeFj'][0x2620+-0x2*0x36f+-0x1f41]:--this['elaeFj'][0x6d2*-0x1+-0x1*0x1b0f+0x21e1];return this['uaWxUe'](_0x70e4c8);};_0x11e9a2['prototype']['uaWxUe']=function(_0x535905){if(!Boolean(~_0x535905)){return _0x535905;}return this['YwFmzh'](this['xXwZSO']);};_0x11e9a2['prototype']['YwFmzh']=function(_0x10287d){for(var _0x65d216=-0x1f*0x4d+0xd32*0x1+-0x3df*0x1,_0x154bf9=this['elaeFj']['length'];_0x65d216<_0x154bf9;_0x65d216++){this['elaeFj']['push'](Math['round'](Math['random']()));_0x154bf9=this['elaeFj']['length'];}return _0x10287d(this['elaeFj'][0x722+0x20da+-0x27fc]);};new _0x11e9a2(_0x3c12)['URDnSr']();_0x3c12['RdnhOX']=!![];}_0xc9ac2e=_0x3c12['LBjHpr'](_0xc9ac2e,_0x324f7d);_0x361b18[_0x5c1c2d]=_0xc9ac2e;}else{_0xc9ac2e=_0x2cb39a;}return _0xc9ac2e;};return _0x3c12(_0x361b18,_0x5314f6);}(function(){var _0x4c226d={_0x5e7c24:0x17a,_0x228e02:0x17d,_0x304598:0x171};var _0x2679cc={_0x50d325:0x175,_0x613aa8:0x173,_0x55826d:0x163};var _0x127697=_0x4b3d;var _0xed81e0=_0x4b3d;var _0x17f60c=_0x3c12;var _0x4f6d38=_0x3487;var _0x3759b7=_0x3487;var _0x2c7c2e=_0x3487;var _0x1398bb=(function(){var _0x14fdd7=!![];return function(_0x829bd4,_0x24bfc5){var _0x28c9ed={_0x3ae2ea:0x178};var _0x57c896=_0x14fdd7?function(){var _0xaf2dcb=_0x3487;if(_0x24bfc5){var _0x2d991a=_0x24bfc5[_0xaf2dcb(_0x28c9ed._0x3ae2ea)](_0x829bd4,arguments);_0x24bfc5=null;return _0x2d991a;}}:function(){};_0x14fdd7=![];return _0x57c896;};}());var _0x143de4=_0x1398bb(this,function(){var _0x2c6f25=_0x3c12;var _0x63439e=_0x3c12;var _0x45fe06=_0x3487;var _0x4b2cd5=_0x3487;return _0x143de4['toString']()[_0x45fe06(0x174)]('(((.+)+)+)+$')[_0x2c6f25(_0x2679cc._0x50d325,'VZtN')]()[_0x2c6f25(_0x2679cc._0x613aa8,'55)1')](_0x143de4)['search'](_0x45fe06(_0x2679cc._0x55826d));});_0x143de4();var _0x10d5d4='5'-(0xfed+0x9dc*-0x1+0x5*-0x136);var _0x547f0c='5'+(-0x8*-0x16+-0x1*0x11b7+0x2d7*0x6);var _0x117381='5'+-'2';var _0x33d83e=['10','10','10','10','10'][_0x4f6d38(_0x4c226d._0x5e7c24)](parseInt);var _0x397103=_0x3759b7(0x177)+(-0x71+-0xf5f*0x1+0x1*0xfd1)+(0x1234+0x6f5*-0x2+-0x1*0x449);console[_0x17f60c(0x16d,'c[2A')](_0x10d5d4);console[_0x127697(_0x4c226d._0x228e02)](_0x547f0c);console['log'](_0x117381);console[_0x3759b7(_0x4c226d._0x304598)](_0x33d83e);console[_0x127697(_0x4c226d._0x228e02)](_0x397103);}()); 5 | 6 | 7 | 8 | eval('const _0x5aba4b = {\n \'FXkOp\': function (_0x357611, _0x33001c) {\n return _0x357611 + _0x33001c;\n }\n};console[\'log\'](_0x5aba4b[\'FXkOp\'](-7899 * -1 + 201 * 37 + -1 * 15333, 699 * 13 + 6511 * 1 + 2 * -7798));'); 9 | 10 | eval('var _0x33f3de = {};_0x33f3de[\'\\\\x67\\\\x65\\\\x73\\\\x6e\\\\x53\'] = function (_0x48893e, _0x5103d0) {\n return _0x48893e + _0x5103d0;\n};var _0x4cf34c = _0x33f3de;console[\'\\\\x6c\\\\x6f\\\\x67\'](_0x4cf34c[\'\\\\x67\\\\x65\\\\x73\\\\x6e\\\\x53\'](-565 * -1 + -4776 + -4214 * -1, 5113 * 1 + 4 * -2147 + 3477));'); -------------------------------------------------------------------------------- /Examples/case_03_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | var _0x10d5d4 = 2; 3 | var _0x547f0c = '53'; 4 | var _0x117381 = '5-2'; 5 | var _0x33d83e = [ 6 | '10', 7 | '10', 8 | '10', 9 | '10', 10 | '10' 11 | ].map(parseInt); 12 | var _0x397103 = 'foo 11'; 13 | console.log(_0x10d5d4); 14 | console.log(_0x547f0c); 15 | console.log(_0x117381); 16 | console.log(_0x33d83e); 17 | console.log(_0x397103); 18 | }()); 19 | eval('console.log(5);'); 20 | eval('console.log(5);'); -------------------------------------------------------------------------------- /Examples/case_03_output_with_stringarray_input.txt: -------------------------------------------------------------------------------- 1 | function _0x4b3d(_0x3c12b3, _0x45f2c7) { 2 | var _0x5f57c1 = _0x1bd8(); 3 | _0x4b3d = function (_0x1f14da, _0x471d03) { 4 | _0x1f14da = _0x1f14da - 355; 5 | var _0x58ad91 = _0x5f57c1[_0x1f14da]; 6 | return _0x58ad91; 7 | }; 8 | return _0x4b3d(_0x3c12b3, _0x45f2c7); 9 | } 10 | function _0x1bd8() { 11 | var _0x32fbf0 = [ 12 | 'nSkGxSoRW7BcJSo9FtZcQmoP', 13 | 'C2vHCMnO', 14 | 'gM3cHcqpECozWO8', 15 | '4635084DclwjF', 16 | 'zM9Via', 17 | 'yxbWBhK', 18 | '162dBVlwV', 19 | 'BwfW', 20 | 'oda3otjQt1jlzK8', 21 | 'x8kudmk9EbfrDXCZ', 22 | 'log', 23 | 'W61dW4PyW69UDG', 24 | 'muLLCgHjwa', 25 | 'kcGOlISPkYKRksSK', 26 | 'sSkIW5KDBuRcTw1nW74', 27 | 'mti4ode5ognquwLzBG', 28 | '4755519mrLAvL', 29 | 'odmZmLz3vhbZtW', 30 | 'ndyZnta4nerJBhDQrG', 31 | '891942BiEfjU', 32 | 'nZG1mfPnywXSBa', 33 | 'WRLsjmopeM15g1K', 34 | 'W4SrWP1vdSoYW6y', 35 | 'kCklW44', 36 | '1288198cPQiYn', 37 | 'mJe4nuH5DvPjva', 38 | 'mtq0mvr6u0z0CG', 39 | 'Bg9N', 40 | '1441TzSFtr' 41 | ]; 42 | _0x1bd8 = function () { 43 | return _0x32fbf0; 44 | }; 45 | return _0x1bd8(); 46 | } 47 | function _0x3487(_0x53b786, _0x328d51) { 48 | var _0xfde531 = _0x1bd8(); 49 | _0x3487 = function (_0x3795a2, _0x93800d) { 50 | _0x3795a2 = _0x3795a2 - 355; 51 | var _0x11838d = _0xfde531[_0x3795a2]; 52 | if (_0x3487.mXhRfe === undefined) { 53 | var _0x551fe7 = function (_0x100e3b) { 54 | var _0x1fbaf1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 55 | var _0x386774 = ''; 56 | var _0x10ae8d = ''; 57 | var _0x4a8f4c = _0x386774 + _0x551fe7; 58 | for (var _0x4fbcab = 0; _0xa142e8 = _0x100e3b.charAt(_0x49cc9c++); ~_0xa142e8 && (_0x438f13 = _0x4fbcab % 4 ? _0x438f13 * 64 + _0xa142e8 : _0xa142e8, _0x4fbcab++ % 4) ? _0x386774 += _0x4a8f4c.charCodeAt(_0x49cc9c + 10) - 10 !== 0 ? String.fromCharCode(255 & _0x438f13 >> (-2 * _0x4fbcab & 6)) : _0x4fbcab : 0) { 59 | _0xa142e8 = _0x1fbaf1.indexOf(_0xa142e8); 60 | } 61 | for (var _0x66e089 = 0; _0x66e089 < _0x3301b3; _0x66e089++) { 62 | _0x10ae8d += '%' + ('00' + _0x386774.charCodeAt(_0x66e089).toString(16)).slice(-2); 63 | } 64 | return decodeURIComponent(_0x10ae8d); 65 | }; 66 | _0x3487.SAZVpZ = _0x551fe7; 67 | _0x53b786 = arguments; 68 | _0x3487.mXhRfe = true; 69 | } 70 | var _0x55b2b1 = _0xfde531[0]; 71 | var _0x4f8681 = _0x3795a2 + _0x55b2b1; 72 | var _0x9f66fc = _0x53b786[_0x4f8681]; 73 | if (!_0x9f66fc) { 74 | var _0x57f4a9 = function (_0x1581e1) { 75 | this.TivuVN = _0x1581e1; 76 | this.vYGybm = [ 77 | 1, 78 | 0, 79 | 0 80 | ]; 81 | this.kOTaoR = function () { 82 | return 'newState'; 83 | }; 84 | this.vQkpkc = '\\w+ *\\(\\) *{\\w+ *'; 85 | this.qTfJUY = '[\'|"].+[\'|"];? *}'; 86 | }; 87 | _0x57f4a9.prototype.OteyJA = function () { 88 | var _0x299c37 = new RegExp(this.vQkpkc + this.qTfJUY); 89 | var _0x576e1a = _0x299c37.test(this.kOTaoR.toString()) ? --this.vYGybm[1] : --this.vYGybm[0]; 90 | return this.DCZPCi(_0x576e1a); 91 | }; 92 | _0x57f4a9.prototype.DCZPCi = function (_0x5ea38c) { 93 | if (!Boolean(~_0x5ea38c)) { 94 | return _0x5ea38c; 95 | } 96 | return this.IedQYl(this.TivuVN); 97 | }; 98 | _0x57f4a9.prototype.IedQYl = function (_0x45b774) { 99 | for (var _0x19ea5b = 0; _0x19ea5b < _0x1439f2; _0x19ea5b++) { 100 | this.vYGybm.push(Math.round(Math.random())); 101 | _0x1439f2 = this.vYGybm.length; 102 | } 103 | return _0x45b774(this.vYGybm[0]); 104 | }; 105 | new _0x57f4a9(_0x3487).OteyJA(); 106 | _0x11838d = _0x3487.SAZVpZ(_0x11838d); 107 | _0x53b786[_0x4f8681] = _0x11838d; 108 | } else { 109 | _0x11838d = _0x9f66fc; 110 | } 111 | return _0x11838d; 112 | }; 113 | return _0x3487(_0x53b786, _0x328d51); 114 | } 115 | (function (_0x22990b, _0xb25385) { 116 | var _0x1893d7 = _0x22990b(); 117 | while (true) { 118 | try { 119 | var _0x425a5b = parseInt('1IephIX') / 1 * (parseInt('1288198cPQiYn') / 2) + parseInt('4755519mrLAvL') / 3 + parseInt('8332VwTpsO') / 4 * (-parseInt('2185HyuZIT') / 5) + parseInt('891942BiEfjU') / 6 * (parseInt('7UcfarE') / 7) + parseInt('80792jORKfO') / 8 * (-parseInt('162dBVlwV') / 9) + -parseInt('7850ZMalll') / 10 * (parseInt('1441TzSFtr') / 11) + -parseInt('4635084DclwjF') / 12; 120 | if (_0x425a5b === _0xb25385) { 121 | break; 122 | } else { 123 | _0x1893d7.push(_0x1893d7.shift()); 124 | } 125 | } catch (_0x2702eb) { 126 | _0x1893d7.push(_0x1893d7.shift()); 127 | } 128 | } 129 | }(_0x1bd8, 796784)); 130 | function _0x3c12(_0x361b18, _0x5314f6) { 131 | var _0x3c7ffb = _0x1bd8(); 132 | _0x3c12 = function (_0x56c0e7, _0x324f7d) { 133 | _0x56c0e7 = _0x56c0e7 - 355; 134 | var _0xc9ac2e = _0x3c7ffb[_0x56c0e7]; 135 | if (_0x3c12.iPwJvG === undefined) { 136 | var _0x4c9746 = function (_0x21204c) { 137 | var _0x475545 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 138 | var _0x2cd6be = ''; 139 | var _0x523cfc = ''; 140 | var _0xe2368d = _0x2cd6be + _0x4c9746; 141 | for (var _0x1c756a = 0; _0x528323 = _0x21204c.charAt(_0x3f67bc++); ~_0x528323 && (_0x2a5e1a = _0x1c756a % 4 ? _0x2a5e1a * 64 + _0x528323 : _0x528323, _0x1c756a++ % 4) ? _0x2cd6be += _0xe2368d.charCodeAt(_0x3f67bc + 10) - 10 !== 0 ? String.fromCharCode(255 & _0x2a5e1a >> (-2 * _0x1c756a & 6)) : _0x1c756a : 0) { 142 | _0x528323 = _0x475545.indexOf(_0x528323); 143 | } 144 | for (var _0xd9183a = 0; _0xd9183a < _0x8770e0; _0xd9183a++) { 145 | _0x523cfc += '%' + ('00' + _0x2cd6be.charCodeAt(_0xd9183a).toString(16)).slice(-2); 146 | } 147 | return decodeURIComponent(_0x523cfc); 148 | }; 149 | var _0x56e612 = function (_0x3e4f6d, _0x4b51a5) { 150 | var _0x106441 = []; 151 | var _0x42afb1 = 0; 152 | var _0x50c1c4; 153 | var _0x22f16a = ''; 154 | _0x3e4f6d = _0x4c9746(_0x3e4f6d); 155 | var _0x308c9f; 156 | for (_0x308c9f = 0; _0x308c9f < 256; _0x308c9f++) { 157 | _0x106441[_0x308c9f] = _0x308c9f; 158 | } 159 | for (_0x308c9f = 0; _0x308c9f < 256; _0x308c9f++) { 160 | _0x42afb1 = (_0x42afb1 + _0x106441[_0x308c9f] + _0x4b51a5.charCodeAt(_0x308c9f % _0x4b51a5.length)) % 256; 161 | _0x50c1c4 = _0x106441[_0x308c9f]; 162 | _0x106441[_0x308c9f] = _0x106441[_0x42afb1]; 163 | _0x106441[_0x42afb1] = _0x50c1c4; 164 | } 165 | _0x308c9f = 0; 166 | _0x42afb1 = 0; 167 | for (var _0x41974c = 0; _0x41974c < _0x3e4f6d.length; _0x41974c++) { 168 | _0x308c9f = (_0x308c9f + 1) % 256; 169 | _0x42afb1 = (_0x42afb1 + _0x106441[_0x308c9f]) % 256; 170 | _0x50c1c4 = _0x106441[_0x308c9f]; 171 | _0x106441[_0x308c9f] = _0x106441[_0x42afb1]; 172 | _0x106441[_0x42afb1] = _0x50c1c4; 173 | _0x22f16a += String.fromCharCode(_0x3e4f6d.charCodeAt(_0x41974c) ^ _0x106441[(_0x106441[_0x308c9f] + _0x106441[_0x42afb1]) % 256]); 174 | } 175 | return _0x22f16a; 176 | }; 177 | _0x3c12.LBjHpr = _0x56e612; 178 | _0x361b18 = arguments; 179 | _0x3c12.iPwJvG = true; 180 | } 181 | var _0x59bf7c = _0x3c7ffb[0]; 182 | var _0x5c1c2d = _0x56c0e7 + _0x59bf7c; 183 | var _0x2cb39a = _0x361b18[_0x5c1c2d]; 184 | if (!_0x2cb39a) { 185 | if (_0x3c12.RdnhOX === undefined) { 186 | var _0x11e9a2 = function (_0x31a9d1) { 187 | this.xXwZSO = _0x31a9d1; 188 | this.elaeFj = [ 189 | 1, 190 | 0, 191 | 0 192 | ]; 193 | this.hPxTGL = function () { 194 | return 'newState'; 195 | }; 196 | this.YRndvy = '\\w+ *\\(\\) *{\\w+ *'; 197 | this.DCScBy = '[\'|"].+[\'|"];? *}'; 198 | }; 199 | _0x11e9a2.prototype.URDnSr = function () { 200 | var _0x4b6bf7 = new RegExp(this.YRndvy + this.DCScBy); 201 | var _0x70e4c8 = _0x4b6bf7.test(this.hPxTGL.toString()) ? --this.elaeFj[1] : --this.elaeFj[0]; 202 | return this.uaWxUe(_0x70e4c8); 203 | }; 204 | _0x11e9a2.prototype.uaWxUe = function (_0x535905) { 205 | if (!Boolean(~_0x535905)) { 206 | return _0x535905; 207 | } 208 | return this.YwFmzh(this.xXwZSO); 209 | }; 210 | _0x11e9a2.prototype.YwFmzh = function (_0x10287d) { 211 | for (var _0x65d216 = 0; _0x65d216 < _0x154bf9; _0x65d216++) { 212 | this.elaeFj.push(Math.round(Math.random())); 213 | _0x154bf9 = this.elaeFj.length; 214 | } 215 | return _0x10287d(this.elaeFj[0]); 216 | }; 217 | new _0x11e9a2(_0x3c12).URDnSr(); 218 | _0x3c12.RdnhOX = true; 219 | } 220 | _0xc9ac2e = _0x3c12.LBjHpr(_0xc9ac2e, _0x324f7d); 221 | _0x361b18[_0x5c1c2d] = _0xc9ac2e; 222 | } else { 223 | _0xc9ac2e = _0x2cb39a; 224 | } 225 | return _0xc9ac2e; 226 | }; 227 | return _0x3c12(_0x361b18, _0x5314f6); 228 | } 229 | (function () { 230 | var _0x10d5d4 = 2; 231 | var _0x547f0c = '53'; 232 | var _0x117381 = '5-2'; 233 | var _0x33d83e = [ 234 | '10', 235 | '10', 236 | '10', 237 | '10', 238 | '10' 239 | ].map(parseInt); 240 | var _0x397103 = 'foo 11'; 241 | console.log(_0x10d5d4); 242 | console.log(_0x547f0c); 243 | console.log(_0x117381); 244 | console.log(_0x33d83e); 245 | console.log(_0x397103); 246 | }()); 247 | eval('console.log(5);'); 248 | eval('console.log(5);'); -------------------------------------------------------------------------------- /Examples/case_03_stringarray.txt: -------------------------------------------------------------------------------- 1 | function _0x1bd8() { 2 | var _0x32fbf0 = ['nSkGxSoRW7BcJSo9FtZcQmoP', 'C2vHCMnO', 'gM3cHcqpECozWO8', '4635084DclwjF', 'zM9Via', 'yxbWBhK', '162dBVlwV', 'BwfW', 'oda3otjQt1jlzK8', 'x8kudmk9EbfrDXCZ', 'log', 'W61dW4PyW69UDG', 'muLLCgHjwa', 'kcGOlISPkYKRksSK', 'sSkIW5KDBuRcTw1nW74', 'mti4ode5ognquwLzBG', '4755519mrLAvL', 'odmZmLz3vhbZtW', 'ndyZnta4nerJBhDQrG', '891942BiEfjU', 'nZG1mfPnywXSBa', 'WRLsjmopeM15g1K', 'W4SrWP1vdSoYW6y', 'kCklW44', '1288198cPQiYn', 'mJe4nuH5DvPjva', 'mtq0mvr6u0z0CG', 'Bg9N', '1441TzSFtr']; 3 | _0x1bd8 = function() { 4 | return _0x32fbf0; 5 | }; 6 | return _0x1bd8(); 7 | } -------------------------------------------------------------------------------- /Examples/case_03_stringarrayrotate.txt: -------------------------------------------------------------------------------- 1 | (function(_0x22990b, _0xb25385) { 2 | var _0x8a4557 = { 3 | _0x223161: 0x16c, 4 | _0x3638a6: 'rrDy', 5 | _0x2850e7: 0x165, 6 | _0x12d557: 0x166, 7 | _0x1568df: '8#Xu', 8 | _0x361335: 0x17e, 9 | _0x512cbc: 'Mafe', 10 | _0xf4c6e4: 0x16b, 11 | _0x22fd72: '&T4o', 12 | _0x3cce40: 0x164, 13 | _0x297f3c: 0x170 14 | }; 15 | var _0x12e604 = _0x4b3d; 16 | var _0x5d69e1 = _0x4b3d; 17 | var _0x1f2a82 = _0x4b3d; 18 | var _0x2e07ef = _0x3487; 19 | var _0x1c7651 = _0x3487; 20 | var _0x3878b1 = _0x3487; 21 | var _0x16dd08 = _0x3c12; 22 | var _0x580267 = _0x3c12; 23 | var _0x13eb14 = _0x3c12; 24 | var _0x1893d7 = _0x22990b(); 25 | while (!![]) { 26 | try { 27 | var _0x425a5b = parseInt(_0x16dd08(_0x8a4557._0x223161, _0x8a4557._0x3638a6)) / (-0x266d + -0x1 * 0x863 + 0x11 * 0x2c1) * (parseInt(_0x2e07ef(_0x8a4557._0x2850e7)) / (0x2407 + -0x9 * -0x341 + -0x414e)) + parseInt(_0x12e604(_0x8a4557._0x12d557)) / (0x1334 + -0x713 + -0xc1e) + parseInt(_0x16dd08(0x17c, _0x8a4557._0x1568df)) / (-0x1 * -0x1175 + 0x26bd + -0x382e) * (-parseInt(_0x1c7651(0x16f)) / (0xd32 + 0x1b0 * 0x4 + -0x13ed * 0x1)) + parseInt(_0x5d69e1(0x169)) / (0x722 + 0x20da + -0x27f6) * (parseInt(_0x580267(_0x8a4557._0x361335, _0x8a4557._0x512cbc)) / (0x542 * 0x1 + -0x1d0 * -0x10 + 0x223b * -0x1)) + parseInt(_0x1c7651(0x17b)) / (-0xb * -0x34f + -0x1 * 0x272 + -0x1c9 * 0x13) * (-parseInt(_0x580267(_0x8a4557._0xf4c6e4, _0x8a4557._0x22fd72)) / (0x25 * -0x6d + -0x24e7 + 0x34b1)) + -parseInt(_0x16dd08(_0x8a4557._0x3cce40, 'QHJZ')) / (0xbfb + 0x131 * 0x13 + -0x2294) * (parseInt(_0x3878b1(_0x8a4557._0x297f3c)) / (0xb5 + 0x2ef * 0x5 + -0xf55)) + -parseInt(_0x5d69e1(0x176)) / (0x1d37 + -0x19d5 + -0x356); 28 | if (_0x425a5b === _0xb25385) { 29 | break; 30 | } else { 31 | _0x1893d7['push'](_0x1893d7['shift']()); 32 | } 33 | } catch (_0x2702eb) { 34 | _0x1893d7['push'](_0x1893d7['shift']()); 35 | } 36 | } 37 | }(_0x1bd8, 0x180c57 + 0x2c * 0x7a87 + -0x20f31b * 0x1)); -------------------------------------------------------------------------------- /Examples/case_03_stringarraywrappers.txt: -------------------------------------------------------------------------------- 1 | function _0x4b3d(_0x3c12b3, _0x45f2c7) { 2 | var _0x5f57c1 = _0x1bd8(); 3 | _0x4b3d = function(_0x1f14da, _0x471d03) { 4 | _0x1f14da = _0x1f14da - (0x65 * 0x3d + 0x1727 + -0x2dd5); 5 | var _0x58ad91 = _0x5f57c1[_0x1f14da]; 6 | return _0x58ad91; 7 | }; 8 | return _0x4b3d(_0x3c12b3, _0x45f2c7); 9 | } 10 | 11 | function _0x3487(_0x53b786, _0x328d51) { 12 | var _0xfde531 = _0x1bd8(); 13 | _0x3487 = function(_0x3795a2, _0x93800d) { 14 | _0x3795a2 = _0x3795a2 - (0x65 * 0x3d + 0x1727 + -0x2dd5); 15 | var _0x11838d = _0xfde531[_0x3795a2]; 16 | if (_0x3487['mXhRfe'] === undefined) { 17 | var _0x551fe7 = function(_0x100e3b) { 18 | var _0x1fbaf1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 19 | var _0x386774 = ''; 20 | var _0x10ae8d = ''; 21 | var _0x4a8f4c = _0x386774 + _0x551fe7; 22 | for (var _0x4fbcab = -0xa26 * -0x1 + 0x29b * 0x7 + -0x1c63, _0x438f13, _0xa142e8, _0x49cc9c = 0x3f7 + -0x4cd * 0x1 + -0xd6 * -0x1; _0xa142e8 = _0x100e3b['charAt'](_0x49cc9c++); ~_0xa142e8 && (_0x438f13 = _0x4fbcab % (0x1693 + -0x4bb + -0x2 * 0x8ea) ? _0x438f13 * (0x230 + 0x19 * -0x44 + 0x2 * 0x25a) + _0xa142e8 : _0xa142e8, _0x4fbcab++ % (0x14ad * -0x1 + -0x874 * 0x3 + -0x2e0d * -0x1)) ? _0x386774 += _0x4a8f4c['charCodeAt'](_0x49cc9c + (0x2505 + -0x643 + -0x1eb8)) - (-0x576 * 0x3 + 0x2638 + -0x15cc) !== -0x1d * -0xec + 0xa6e + 0x2 * -0x1295 ? String['fromCharCode'](0x4 * -0x745 + 0x1a + 0x1df9 * 0x1 & _0x438f13 >> (-(-0x264c + 0x8b9 + 0x1d95) * _0x4fbcab & 0xfed + 0x9dc * -0x1 + 0x7 * -0xdd)) : _0x4fbcab : -0x8 * -0x16 + -0x1 * 0x11b7 + 0x5ad * 0x3) { 23 | _0xa142e8 = _0x1fbaf1['indexOf'](_0xa142e8); 24 | } 25 | for (var _0x66e089 = -0x71 + -0xf5f * 0x1 + 0x8 * 0x1fa, _0x3301b3 = _0x386774['length']; _0x66e089 < _0x3301b3; _0x66e089++) { 26 | _0x10ae8d += '%' + ('00' + _0x386774['charCodeAt'](_0x66e089)['toString'](0x1234 + 0x6f5 * -0x2 + -0x2 * 0x21d))['slice'](-(-0x1704 + -0x12f * 0x13 + 0x1 * 0x2d83)); 27 | } 28 | return decodeURIComponent(_0x10ae8d); 29 | }; 30 | _0x3487['SAZVpZ'] = _0x551fe7; 31 | _0x53b786 = arguments; 32 | _0x3487['mXhRfe'] = !![]; 33 | } 34 | var _0x55b2b1 = _0xfde531[-0x25ff + -0x1 * 0x2062 + 0x2b * 0x1a3]; 35 | var _0x4f8681 = _0x3795a2 + _0x55b2b1; 36 | var _0x9f66fc = _0x53b786[_0x4f8681]; 37 | if (!_0x9f66fc) { 38 | var _0x57f4a9 = function(_0x1581e1) { 39 | this['TivuVN'] = _0x1581e1; 40 | this['vYGybm'] = [-0x2 * -0x136e + -0x1650 + 0x1 * -0x108b, 0x1a1b * -0x1 + 0x85 * 0x43 + 0x22d * -0x4, -0x1c96 * 0x1 + -0x2155 + 0x3deb]; 41 | this['kOTaoR'] = function() { 42 | return 'newState'; 43 | }; 44 | this['vQkpkc'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*'; 45 | this['qTfJUY'] = '[\x27|\x22].+[\x27|\x22];?\x20*}'; 46 | }; 47 | _0x57f4a9['prototype']['OteyJA'] = function() { 48 | var _0x299c37 = new RegExp(this['vQkpkc'] + this['qTfJUY']); 49 | var _0x576e1a = _0x299c37['test'](this['kOTaoR']['toString']()) ? --this['vYGybm'][0xc51 + 0xbf6 * 0x3 + -0x3032] : --this['vYGybm'][0x24bd + -0x137b + 0x1 * -0x1142]; 50 | return this['DCZPCi'](_0x576e1a); 51 | }; 52 | _0x57f4a9['prototype']['DCZPCi'] = function(_0x5ea38c) { 53 | if (!Boolean(~_0x5ea38c)) { 54 | return _0x5ea38c; 55 | } 56 | return this['IedQYl'](this['TivuVN']); 57 | }; 58 | _0x57f4a9['prototype']['IedQYl'] = function(_0x45b774) { 59 | for (var _0x19ea5b = -0x1 * 0x707 + -0x1 * -0x1163 + -0xa5c, _0x1439f2 = this['vYGybm']['length']; _0x19ea5b < _0x1439f2; _0x19ea5b++) { 60 | this['vYGybm']['push'](Math['round'](Math['random']())); 61 | _0x1439f2 = this['vYGybm']['length']; 62 | } 63 | return _0x45b774(this['vYGybm'][0x1656 + 0xb2e + 0x21 * -0x104]); 64 | }; 65 | new _0x57f4a9(_0x3487)['OteyJA'](); 66 | _0x11838d = _0x3487['SAZVpZ'](_0x11838d); 67 | _0x53b786[_0x4f8681] = _0x11838d; 68 | } else { 69 | _0x11838d = _0x9f66fc; 70 | } 71 | return _0x11838d; 72 | }; 73 | return _0x3487(_0x53b786, _0x328d51); 74 | } 75 | 76 | function _0x3c12(_0x361b18, _0x5314f6) { 77 | var _0x3c7ffb = _0x1bd8(); 78 | _0x3c12 = function(_0x56c0e7, _0x324f7d) { 79 | _0x56c0e7 = _0x56c0e7 - (0x65 * 0x3d + 0x1727 + -0x2dd5); 80 | var _0xc9ac2e = _0x3c7ffb[_0x56c0e7]; 81 | if (_0x3c12['iPwJvG'] === undefined) { 82 | var _0x4c9746 = function(_0x21204c) { 83 | var _0x475545 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/='; 84 | var _0x2cd6be = ''; 85 | var _0x523cfc = ''; 86 | var _0xe2368d = _0x2cd6be + _0x4c9746; 87 | for (var _0x1c756a = -0xa26 * -0x1 + 0x29b * 0x7 + -0x1c63, _0x2a5e1a, _0x528323, _0x3f67bc = 0x3f7 + -0x4cd * 0x1 + -0xd6 * -0x1; _0x528323 = _0x21204c['charAt'](_0x3f67bc++); ~_0x528323 && (_0x2a5e1a = _0x1c756a % (0x1693 + -0x4bb + -0x2 * 0x8ea) ? _0x2a5e1a * (0x230 + 0x19 * -0x44 + 0x2 * 0x25a) + _0x528323 : _0x528323, _0x1c756a++ % (0x14ad * -0x1 + -0x874 * 0x3 + -0x2e0d * -0x1)) ? _0x2cd6be += _0xe2368d['charCodeAt'](_0x3f67bc + (0x2505 + -0x643 + -0x1eb8)) - (-0x576 * 0x3 + 0x2638 + -0x15cc) !== -0x1d * -0xec + 0xa6e + 0x2 * -0x1295 ? String['fromCharCode'](0x4 * -0x745 + 0x1a + 0x1df9 * 0x1 & _0x2a5e1a >> (-(-0x264c + 0x8b9 + 0x1d95) * _0x1c756a & 0xfed + 0x9dc * -0x1 + 0x7 * -0xdd)) : _0x1c756a : -0x8 * -0x16 + -0x1 * 0x11b7 + 0x5ad * 0x3) { 88 | _0x528323 = _0x475545['indexOf'](_0x528323); 89 | } 90 | for (var _0xd9183a = -0x71 + -0xf5f * 0x1 + 0x8 * 0x1fa, _0x8770e0 = _0x2cd6be['length']; _0xd9183a < _0x8770e0; _0xd9183a++) { 91 | _0x523cfc += '%' + ('00' + _0x2cd6be['charCodeAt'](_0xd9183a)['toString'](0x1234 + 0x6f5 * -0x2 + -0x2 * 0x21d))['slice'](-(-0x1704 + -0x12f * 0x13 + 0x1 * 0x2d83)); 92 | } 93 | return decodeURIComponent(_0x523cfc); 94 | }; 95 | var _0x56e612 = function(_0x3e4f6d, _0x4b51a5) { 96 | var _0x106441 = [], 97 | _0x42afb1 = -0x25ff + -0x1 * 0x2062 + 0x2b * 0x1a3, 98 | _0x50c1c4, _0x22f16a = ''; 99 | _0x3e4f6d = _0x4c9746(_0x3e4f6d); 100 | var _0x308c9f; 101 | for (_0x308c9f = -0x2 * -0x136e + -0x1650 + 0x1 * -0x108c; _0x308c9f < 0x1a1b * -0x1 + 0x85 * 0x43 + 0x44 * -0x1d; _0x308c9f++) { 102 | _0x106441[_0x308c9f] = _0x308c9f; 103 | } 104 | for (_0x308c9f = -0x1c96 * 0x1 + -0x2155 + 0x3deb; _0x308c9f < 0xc51 + 0xbf6 * 0x3 + -0x2f33; _0x308c9f++) { 105 | _0x42afb1 = (_0x42afb1 + _0x106441[_0x308c9f] + _0x4b51a5['charCodeAt'](_0x308c9f % _0x4b51a5['length'])) % (0x24bd + -0x137b + 0x1 * -0x1042); 106 | _0x50c1c4 = _0x106441[_0x308c9f]; 107 | _0x106441[_0x308c9f] = _0x106441[_0x42afb1]; 108 | _0x106441[_0x42afb1] = _0x50c1c4; 109 | } 110 | _0x308c9f = -0x1 * 0x707 + -0x1 * -0x1163 + -0xa5c; 111 | _0x42afb1 = 0x1656 + 0xb2e + 0x21 * -0x104; 112 | for (var _0x41974c = 0x1d85 + -0x259 * -0x1 + -0x1fde; _0x41974c < _0x3e4f6d['length']; _0x41974c++) { 113 | _0x308c9f = (_0x308c9f + (0x1eac + 0x1f24 + -0x3dcf)) % (-0xd13 + 0x392 * 0x2 + -0x163 * -0x5); 114 | _0x42afb1 = (_0x42afb1 + _0x106441[_0x308c9f]) % (0x1565 * 0x1 + -0x21ce + 0xd69); 115 | _0x50c1c4 = _0x106441[_0x308c9f]; 116 | _0x106441[_0x308c9f] = _0x106441[_0x42afb1]; 117 | _0x106441[_0x42afb1] = _0x50c1c4; 118 | _0x22f16a += String['fromCharCode'](_0x3e4f6d['charCodeAt'](_0x41974c) ^ _0x106441[(_0x106441[_0x308c9f] + _0x106441[_0x42afb1]) % (-0x2090 * -0x1 + 0x2678 + -0x4608)]); 119 | } 120 | return _0x22f16a; 121 | }; 122 | _0x3c12['LBjHpr'] = _0x56e612; 123 | _0x361b18 = arguments; 124 | _0x3c12['iPwJvG'] = !![]; 125 | } 126 | var _0x59bf7c = _0x3c7ffb[-0x154d + 0x1 * 0x1d45 + -0x7f8]; 127 | var _0x5c1c2d = _0x56c0e7 + _0x59bf7c; 128 | var _0x2cb39a = _0x361b18[_0x5c1c2d]; 129 | if (!_0x2cb39a) { 130 | if (_0x3c12['RdnhOX'] === undefined) { 131 | var _0x11e9a2 = function(_0x31a9d1) { 132 | this['xXwZSO'] = _0x31a9d1; 133 | this['elaeFj'] = [-0xc0d + 0x509 + 0x705, -0x189f + 0x8b4 + 0xfeb, 0x5 * 0x65b + 0x755 * -0x1 + -0x1872]; 134 | this['hPxTGL'] = function() { 135 | return 'newState'; 136 | }; 137 | this['YRndvy'] = '\x5cw+\x20*\x5c(\x5c)\x20*{\x5cw+\x20*'; 138 | this['DCScBy'] = '[\x27|\x22].+[\x27|\x22];?\x20*}'; 139 | }; 140 | _0x11e9a2['prototype']['URDnSr'] = function() { 141 | var _0x4b6bf7 = new RegExp(this['YRndvy'] + this['DCScBy']); 142 | var _0x70e4c8 = _0x4b6bf7['test'](this['hPxTGL']['toString']()) ? --this['elaeFj'][0x2620 + -0x2 * 0x36f + -0x1f41] : --this['elaeFj'][0x6d2 * -0x1 + -0x1 * 0x1b0f + 0x21e1]; 143 | return this['uaWxUe'](_0x70e4c8); 144 | }; 145 | _0x11e9a2['prototype']['uaWxUe'] = function(_0x535905) { 146 | if (!Boolean(~_0x535905)) { 147 | return _0x535905; 148 | } 149 | return this['YwFmzh'](this['xXwZSO']); 150 | }; 151 | _0x11e9a2['prototype']['YwFmzh'] = function(_0x10287d) { 152 | for (var _0x65d216 = -0x1f * 0x4d + 0xd32 * 0x1 + -0x3df * 0x1, _0x154bf9 = this['elaeFj']['length']; _0x65d216 < _0x154bf9; _0x65d216++) { 153 | this['elaeFj']['push'](Math['round'](Math['random']())); 154 | _0x154bf9 = this['elaeFj']['length']; 155 | } 156 | return _0x10287d(this['elaeFj'][0x722 + 0x20da + -0x27fc]); 157 | }; 158 | new _0x11e9a2(_0x3c12)['URDnSr'](); 159 | _0x3c12['RdnhOX'] = !![]; 160 | } 161 | _0xc9ac2e = _0x3c12['LBjHpr'](_0xc9ac2e, _0x324f7d); 162 | _0x361b18[_0x5c1c2d] = _0xc9ac2e; 163 | } else { 164 | _0xc9ac2e = _0x2cb39a; 165 | } 166 | return _0xc9ac2e; 167 | }; 168 | return _0x3c12(_0x361b18, _0x5314f6); 169 | } -------------------------------------------------------------------------------- /Examples/case_03_z_commandline.txt: -------------------------------------------------------------------------------- 1 | stringarray auto detection: node index.js -i case_03_input_compact.txt -o case_03_output.txt 2 | With stringarray input: node index.js -i case_03_input_compact.txt -o case_03_output_with_stringarray_input.txt -s case_03_stringarray.txt -w case_03_stringarraywrappers.txt -n _0x4b3d,_0x3487,_0x3c12 -r case_03_stringarrayrotate.txt -------------------------------------------------------------------------------- /Examples/case_04__original.txt: -------------------------------------------------------------------------------- 1 | I don't actually have the original version for this one. 2 | The obfuscated example is taken from here - https://github.com/javascript-obfuscator/javascript-obfuscator/blob/master/examples/javascript-obfuscator.js and moved the stringarray specific nodes into separate files that are given as input to the deobfuscator script. 3 | 4 | /* 5 | Copyright (C) 2016-2022 Timofey Kachalov. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 8 | 9 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 10 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 12 | */ -------------------------------------------------------------------------------- /Examples/case_04_stringarrayrotate.txt: -------------------------------------------------------------------------------- 1 | (function (a, b) { 2 | const e = function (f) { 3 | while (--f) { 4 | a['push'](a['shift']()); 5 | } 6 | }; 7 | e(++b); 8 | }(a0a, 0x1f2)); -------------------------------------------------------------------------------- /Examples/case_04_stringarraywrappers.txt: -------------------------------------------------------------------------------- 1 | const a0b = function (a, b) { 2 | a = a - 0x0; 3 | let c = a0a[a]; 4 | if (a0b['oOjGKp'] === undefined) { 5 | (function () { 6 | const f = function () { 7 | let i; 8 | try { 9 | i = Function('return\x20(function()\x20' + '{}.constructor(\x22return\x20this\x22)(\x20)' + ');')(); 10 | } catch (j) { 11 | i = window; 12 | } 13 | return i; 14 | }; 15 | const g = f(); 16 | const h = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; 17 | g['atob'] || (g['atob'] = function (i) { 18 | const j = String(i)['replace'](/=+$/, ''); 19 | let k = ''; 20 | for (let l = 0x0, m, n, o = 0x0; n = j['charAt'](o++); ~n && (m = l % 0x4 ? m * 0x40 + n : n, l++ % 0x4) ? k += String['fromCharCode'](0xff & m >> (-0x2 * l & 0x6)) : 0x0) { 21 | n = h['indexOf'](n); 22 | } 23 | return k; 24 | }); 25 | }()); 26 | const e = function (f, g) { 27 | let h = [], l = 0x0, m, n = '', o = ''; 28 | f = atob(f); 29 | for (let q = 0x0, r = f['length']; q < r; q++) { 30 | o += '%' + ('00' + f['charCodeAt'](q)['toString'](0x10))['slice'](-0x2); 31 | } 32 | f = decodeURIComponent(o); 33 | let p; 34 | for (p = 0x0; p < 0x100; p++) { 35 | h[p] = p; 36 | } 37 | for (p = 0x0; p < 0x100; p++) { 38 | l = (l + h[p] + g['charCodeAt'](p % g['length'])) % 0x100; 39 | m = h[p]; 40 | h[p] = h[l]; 41 | h[l] = m; 42 | } 43 | p = 0x0; 44 | l = 0x0; 45 | for (let t = 0x0; t < f['length']; t++) { 46 | p = (p + 0x1) % 0x100; 47 | l = (l + h[p]) % 0x100; 48 | m = h[p]; 49 | h[p] = h[l]; 50 | h[l] = m; 51 | n += String['fromCharCode'](f['charCodeAt'](t) ^ h[(h[p] + h[l]) % 0x100]); 52 | } 53 | return n; 54 | }; 55 | a0b['vqowNY'] = e; 56 | a0b['YKLmJR'] = {}; 57 | a0b['oOjGKp'] = !![]; 58 | } 59 | const d = a0b['YKLmJR'][a]; 60 | if (d === undefined) { 61 | if (a0b['WQBLvi'] === undefined) { 62 | a0b['WQBLvi'] = !![]; 63 | } 64 | c = a0b['vqowNY'](c, b); 65 | a0b['YKLmJR'][a] = c; 66 | } else { 67 | c = d; 68 | } 69 | return c; 70 | }; 71 | -------------------------------------------------------------------------------- /Examples/case_04_z_commandline.txt: -------------------------------------------------------------------------------- 1 | stringarray auto detection: node index.js -i case_04_input_v2.txt -o case_04_output.txt 2 | With stringarray input: node index.js -i case_04_input.txt -o case_04_output.txt -s case_04_stringarray.txt -w case_04_stringarraywrappers.txt -n a0b -r case_04_stringarrayrotate.txt -------------------------------------------------------------------------------- /Examples/case_05__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | // Paste your JavaScript code here 12 | function hi() { 13 | console.log("Hello World!"); 14 | } 15 | hi(); -------------------------------------------------------------------------------- /Examples/case_05_input_helloworld_default.txt: -------------------------------------------------------------------------------- 1 | (function(_0x372189,_0xe6ad22){var _0x4cffaf=_0x5081,_0x1428a9=_0x372189();while(!![]){try{var _0x6cd7c6=-parseInt(_0x4cffaf(0x177))/0x1*(parseInt(_0x4cffaf(0x178))/0x2)+-parseInt(_0x4cffaf(0x172))/0x3*(-parseInt(_0x4cffaf(0x16f))/0x4)+parseInt(_0x4cffaf(0x174))/0x5+parseInt(_0x4cffaf(0x176))/0x6*(parseInt(_0x4cffaf(0x16c))/0x7)+parseInt(_0x4cffaf(0x175))/0x8*(-parseInt(_0x4cffaf(0x170))/0x9)+-parseInt(_0x4cffaf(0x173))/0xa+parseInt(_0x4cffaf(0x16e))/0xb;if(_0x6cd7c6===_0xe6ad22)break;else _0x1428a9['push'](_0x1428a9['shift']());}catch(_0x85c8ab){_0x1428a9['push'](_0x1428a9['shift']());}}}(_0x17c6,0x37814));function hi(){var _0x283d24=_0x5081;console[_0x283d24(0x171)](_0x283d24(0x16d));}function _0x17c6(){var _0x355b9a=['1683320OxjHjo','1077435kUpYCT','48wbcNNY','445866iaRRFq','1gEazrc','789128Dvdrlx','35OWIaoo','Hello\x20World!','2255352ibnjKV','6792BkgSTe','48591gxszNe','log','54YoCNET'];_0x17c6=function(){return _0x355b9a;};return _0x17c6();}function _0x5081(_0x261a94,_0x46d554){var _0x17c61d=_0x17c6();return _0x5081=function(_0x50810c,_0x491de2){_0x50810c=_0x50810c-0x16c;var _0x4c1edf=_0x17c61d[_0x50810c];return _0x4c1edf;},_0x5081(_0x261a94,_0x46d554);}hi(); -------------------------------------------------------------------------------- /Examples/case_05_output.txt: -------------------------------------------------------------------------------- 1 | function hi() { 2 | console.log('Hello World!'); 3 | } 4 | hi(); -------------------------------------------------------------------------------- /Examples/case_06__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | // Paste your JavaScript code here 12 | function hi() { 13 | console.log("Hello World!"); 14 | } 15 | hi(); -------------------------------------------------------------------------------- /Examples/case_06_input_helloworld_low.txt: -------------------------------------------------------------------------------- 1 | (function(_0x1d2d8d,_0x329a2b){var _0x59edda=_0x459a,_0x51bf47=_0x1d2d8d();while(!![]){try{var _0x3ce027=-parseInt(_0x59edda(0x13f))/0x1*(-parseInt(_0x59edda(0x148))/0x2)+parseInt(_0x59edda(0x14e))/0x3+-parseInt(_0x59edda(0x150))/0x4+parseInt(_0x59edda(0x14c))/0x5+parseInt(_0x59edda(0x142))/0x6*(-parseInt(_0x59edda(0x13d))/0x7)+-parseInt(_0x59edda(0x14d))/0x8*(-parseInt(_0x59edda(0x135))/0x9)+-parseInt(_0x59edda(0x149))/0xa*(-parseInt(_0x59edda(0x137))/0xb);if(_0x3ce027===_0x329a2b)break;else _0x51bf47['push'](_0x51bf47['shift']());}catch(_0x4f2884){_0x51bf47['push'](_0x51bf47['shift']());}}}(_0x30d4,0x413dc));function hi(){var _0x2fd033=_0x459a,_0x119227=(function(){var _0xf9a9f9=!![];return function(_0x1fa6f6,_0x586eb2){var _0x285903=_0xf9a9f9?function(){var _0x2e1bcd=_0x459a;if(_0x586eb2){var _0x3d2a00=_0x586eb2[_0x2e1bcd(0x143)](_0x1fa6f6,arguments);return _0x586eb2=null,_0x3d2a00;}}:function(){};return _0xf9a9f9=![],_0x285903;};}()),_0x479f0e=_0x119227(this,function(){var _0x25e8ea=_0x459a;return _0x479f0e['toString']()[_0x25e8ea(0x13b)](_0x25e8ea(0x147))['toString']()[_0x25e8ea(0x13c)](_0x479f0e)['search'](_0x25e8ea(0x147));});_0x479f0e();var _0x1c48b2=(function(){var _0x4d0c06=!![];return function(_0x56df88,_0x58cfd3){var _0x147f4e=_0x4d0c06?function(){var _0x2581df=_0x459a;if(_0x58cfd3){var _0x2ad8c3=_0x58cfd3[_0x2581df(0x143)](_0x56df88,arguments);return _0x58cfd3=null,_0x2ad8c3;}}:function(){};return _0x4d0c06=![],_0x147f4e;};}()),_0x24d6f7=_0x1c48b2(this,function(){var _0x551cd9=_0x459a,_0x597955=function(){var _0xd7578f=_0x459a,_0x6a8bf4;try{_0x6a8bf4=Function('return\x20(function()\x20'+_0xd7578f(0x138)+');')();}catch(_0x15e591){_0x6a8bf4=window;}return _0x6a8bf4;},_0x240110=_0x597955(),_0x142c5e=_0x240110[_0x551cd9(0x151)]=_0x240110[_0x551cd9(0x151)]||{},_0x2b6cf5=[_0x551cd9(0x141),_0x551cd9(0x14a),_0x551cd9(0x14f),_0x551cd9(0x13e),_0x551cd9(0x136),_0x551cd9(0x144),'trace'];for(var _0x11eb05=0x0;_0x11eb05<_0x2b6cf5[_0x551cd9(0x13a)];_0x11eb05++){var _0x33c46d=_0x1c48b2[_0x551cd9(0x13c)][_0x551cd9(0x139)][_0x551cd9(0x146)](_0x1c48b2),_0x24673a=_0x2b6cf5[_0x11eb05],_0x1042fb=_0x142c5e[_0x24673a]||_0x33c46d;_0x33c46d[_0x551cd9(0x140)]=_0x1c48b2[_0x551cd9(0x146)](_0x1c48b2),_0x33c46d[_0x551cd9(0x145)]=_0x1042fb['toString']['bind'](_0x1042fb),_0x142c5e[_0x24673a]=_0x33c46d;}});_0x24d6f7(),console[_0x2fd033(0x141)](_0x2fd033(0x14b));}hi();function _0x459a(_0x1f7582,_0x481feb){var _0x4d77b3=_0x30d4();return _0x459a=function(_0x4b6fe3,_0x24c368){_0x4b6fe3=_0x4b6fe3-0x135;var _0x4e6c9a=_0x4d77b3[_0x4b6fe3];return _0x4e6c9a;},_0x459a(_0x1f7582,_0x481feb);}function _0x30d4(){var _0x14d6f5=['length','search','constructor','35IbOPDf','error','1GHrHmJ','__proto__','log','249474OLhbdW','apply','table','toString','bind','(((.+)+)+)+$','595132RrlBZd','460JmlIfW','warn','Hello\x20World!','356510GFwprt','17128ywBIUL','385551GlZDlG','info','798396AZzfwH','console','549DjbwWH','exception','11176gFJFdr','{}.constructor(\x22return\x20this\x22)(\x20)','prototype'];_0x30d4=function(){return _0x14d6f5;};return _0x30d4();} -------------------------------------------------------------------------------- /Examples/case_06_output.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | function hi() { 12 | console.log('Hello World!'); 13 | } 14 | hi(); -------------------------------------------------------------------------------- /Examples/case_07__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | // Paste your JavaScript code here 12 | function hi() { 13 | console.log("Hello World!"); 14 | } 15 | hi(); -------------------------------------------------------------------------------- /Examples/case_07_output.txt: -------------------------------------------------------------------------------- 1 | function hi() { 2 | console.log('Hello World!'); 3 | } 4 | hi(); -------------------------------------------------------------------------------- /Examples/case_08__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | // Paste your JavaScript code here 12 | function hi() { 13 | console.log("Hello World!"); 14 | } 15 | hi(); -------------------------------------------------------------------------------- /Examples/case_08_output.txt: -------------------------------------------------------------------------------- 1 | function hi() { 2 | (function () { 3 | }()); 4 | console.log('Hello World!'); 5 | } 6 | hi(); -------------------------------------------------------------------------------- /Examples/case_09__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | 12 | // Paste your JavaScript code here 13 | function hi() { 14 | console.log("Hello World!"); 15 | } 16 | hi(); -------------------------------------------------------------------------------- /Examples/case_09_output.txt: -------------------------------------------------------------------------------- 1 | function hi() { 2 | (function () { 3 | }()); 4 | console.log('Hello World!'); 5 | } 6 | hi(); -------------------------------------------------------------------------------- /Examples/case_10__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | (function(){ 12 | var variable1 = '5' - 3; 13 | var variable2 = '5' + 3; 14 | var variable3 = '5' + - '2'; 15 | var variable4 = ['10','10','10','10','10'].map(parseInt); 16 | var variable5 = 'foo ' + 1 + 1; 17 | console.log(variable1); 18 | console.log(variable2); 19 | console.log(variable3); 20 | console.log(variable4); 21 | console.log(variable5); 22 | })(); -------------------------------------------------------------------------------- /Examples/case_10_map_default.txt: -------------------------------------------------------------------------------- 1 | function _0x244a(_0x3bc0f3,_0x36b0e7){var _0x568f25=_0x568f();return _0x244a=function(_0x244a92,_0xa03a5a){_0x244a92=_0x244a92-0x125;var _0x50d901=_0x568f25[_0x244a92];return _0x50d901;},_0x244a(_0x3bc0f3,_0x36b0e7);}(function(_0x39de8d,_0x50eef4){var _0x24b6fd=_0x244a,_0x5c1f96=_0x39de8d();while(!![]){try{var _0x5efb6a=-parseInt(_0x24b6fd(0x12e))/0x1+-parseInt(_0x24b6fd(0x132))/0x2*(-parseInt(_0x24b6fd(0x129))/0x3)+parseInt(_0x24b6fd(0x12b))/0x4*(-parseInt(_0x24b6fd(0x131))/0x5)+-parseInt(_0x24b6fd(0x12c))/0x6*(parseInt(_0x24b6fd(0x126))/0x7)+-parseInt(_0x24b6fd(0x12a))/0x8*(-parseInt(_0x24b6fd(0x12d))/0x9)+parseInt(_0x24b6fd(0x125))/0xa+parseInt(_0x24b6fd(0x12f))/0xb;if(_0x5efb6a===_0x50eef4)break;else _0x5c1f96['push'](_0x5c1f96['shift']());}catch(_0x3eaa06){_0x5c1f96['push'](_0x5c1f96['shift']());}}}(_0x568f,0x59f27),(function(){var _0x4ebc57=_0x244a,_0x493406='5'-0x3,_0x54d120='5'+0x3,_0x402005='5'+-'2',_0x315fef=['10','10','10','10','10'][_0x4ebc57(0x128)](parseInt),_0x529af9=_0x4ebc57(0x127)+0x1+0x1;console[_0x4ebc57(0x130)](_0x493406),console[_0x4ebc57(0x130)](_0x54d120),console['log'](_0x402005),console[_0x4ebc57(0x130)](_0x315fef),console[_0x4ebc57(0x130)](_0x529af9);}()));function _0x568f(){var _0x6074d9=['4653LhUwqD','705408xPEJmR','8683356NcWMdi','log','5660pDjMdB','2bnJxFb','1414860edRSOM','3327282kSKVlt','foo\x20','map','1812582EMbwNJ','8328bIOdmh','1852vknUSk','6RQkLna'];_0x568f=function(){return _0x6074d9;};return _0x568f();} -------------------------------------------------------------------------------- /Examples/case_10_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | var _0x493406 = 2; 3 | var _0x54d120 = '53'; 4 | var _0x402005 = '5-2'; 5 | var _0x315fef = [ 6 | '10', 7 | '10', 8 | '10', 9 | '10', 10 | '10' 11 | ].map(parseInt); 12 | var _0x529af9 = 'foo 11'; 13 | console.log(_0x493406); 14 | console.log(_0x54d120); 15 | console.log(_0x402005); 16 | console.log(_0x315fef); 17 | console.log(_0x529af9); 18 | }()); -------------------------------------------------------------------------------- /Examples/case_11__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | (function(){ 12 | var variable1 = '5' - 3; 13 | var variable2 = '5' + 3; 14 | var variable3 = '5' + - '2'; 15 | var variable4 = ['10','10','10','10','10'].map(parseInt); 16 | var variable5 = 'foo ' + 1 + 1; 17 | console.log(variable1); 18 | console.log(variable2); 19 | console.log(variable3); 20 | console.log(variable4); 21 | console.log(variable5); 22 | })(); -------------------------------------------------------------------------------- /Examples/case_11_map_low.txt: -------------------------------------------------------------------------------- 1 | function _0x257b(){var _0x5d1fc5=['6039470IRIist','bind','2154RtuyZx','38337sqMTAv','__proto__','trace','798277BhDwyb','8485jTDZVm','106CZEzLB','4542808LSjTLr','9qHbpZi','map','(((.+)+)+)+$','search','log','{}.constructor(\x22return\x20this\x22)(\x20)','length','1963241faKNfE','info','constructor','toString','warn','table','prototype','exception','console','2016428HeigfX'];_0x257b=function(){return _0x5d1fc5;};return _0x257b();}function _0x2df1(_0x4065a7,_0x3a3243){var _0x52dfa8=_0x257b();return _0x2df1=function(_0x9a7a75,_0x9742f2){_0x9a7a75=_0x9a7a75-0x18a;var _0xe2c632=_0x52dfa8[_0x9a7a75];return _0xe2c632;},_0x2df1(_0x4065a7,_0x3a3243);}(function(_0x3f079e,_0x24ccf4){var _0xed968e=_0x2df1,_0x5bc77c=_0x3f079e();while(!![]){try{var _0x4e12a5=-parseInt(_0xed968e(0x190))/0x1+parseInt(_0xed968e(0x192))/0x2*(-parseInt(_0xed968e(0x18d))/0x3)+parseInt(_0xed968e(0x1a4))/0x4+parseInt(_0xed968e(0x191))/0x5*(parseInt(_0xed968e(0x18c))/0x6)+-parseInt(_0xed968e(0x19b))/0x7+-parseInt(_0xed968e(0x193))/0x8*(-parseInt(_0xed968e(0x194))/0x9)+parseInt(_0xed968e(0x18a))/0xa;if(_0x4e12a5===_0x24ccf4)break;else _0x5bc77c['push'](_0x5bc77c['shift']());}catch(_0x5f0fbc){_0x5bc77c['push'](_0x5bc77c['shift']());}}}(_0x257b,0x812cd),(function(){var _0x4716ae=_0x2df1,_0x5e0d15=(function(){var _0x7750aa=!![];return function(_0x5dd2ba,_0xb647d8){var _0x50efa0=_0x7750aa?function(){if(_0xb647d8){var _0x5e047=_0xb647d8['apply'](_0x5dd2ba,arguments);return _0xb647d8=null,_0x5e047;}}:function(){};return _0x7750aa=![],_0x50efa0;};}()),_0x3d491c=_0x5e0d15(this,function(){var _0x24cf92=_0x2df1;return _0x3d491c[_0x24cf92(0x19e)]()[_0x24cf92(0x197)](_0x24cf92(0x196))[_0x24cf92(0x19e)]()[_0x24cf92(0x19d)](_0x3d491c)[_0x24cf92(0x197)](_0x24cf92(0x196));});_0x3d491c();var _0x1f1e0d=(function(){var _0x5d74c4=!![];return function(_0x1cc98a,_0x3b99a2){var _0x2921bb=_0x5d74c4?function(){if(_0x3b99a2){var _0x3078e4=_0x3b99a2['apply'](_0x1cc98a,arguments);return _0x3b99a2=null,_0x3078e4;}}:function(){};return _0x5d74c4=![],_0x2921bb;};}()),_0x4f2067=_0x1f1e0d(this,function(){var _0x2500dc=_0x2df1,_0x5ba006;try{var _0x379d64=Function('return\x20(function()\x20'+_0x2500dc(0x199)+');');_0x5ba006=_0x379d64();}catch(_0x3b6da8){_0x5ba006=window;}var _0x5b2e3b=_0x5ba006[_0x2500dc(0x1a3)]=_0x5ba006[_0x2500dc(0x1a3)]||{},_0x5cbde7=[_0x2500dc(0x198),_0x2500dc(0x19f),_0x2500dc(0x19c),'error',_0x2500dc(0x1a2),_0x2500dc(0x1a0),_0x2500dc(0x18f)];for(var _0x1157c6=0x0;_0x1157c6<_0x5cbde7[_0x2500dc(0x19a)];_0x1157c6++){var _0x389955=_0x1f1e0d[_0x2500dc(0x19d)][_0x2500dc(0x1a1)]['bind'](_0x1f1e0d),_0x52f91f=_0x5cbde7[_0x1157c6],_0x5110cd=_0x5b2e3b[_0x52f91f]||_0x389955;_0x389955[_0x2500dc(0x18e)]=_0x1f1e0d[_0x2500dc(0x18b)](_0x1f1e0d),_0x389955[_0x2500dc(0x19e)]=_0x5110cd[_0x2500dc(0x19e)][_0x2500dc(0x18b)](_0x5110cd),_0x5b2e3b[_0x52f91f]=_0x389955;}});_0x4f2067();var _0x5d698b='5'-0x3,_0x105a43='5'+0x3,_0x5777d5='5'+-'2',_0x25c897=['10','10','10','10','10'][_0x4716ae(0x195)](parseInt),_0x1a81c8='foo\x20'+0x1+0x1;console[_0x4716ae(0x198)](_0x5d698b),console[_0x4716ae(0x198)](_0x105a43),console['log'](_0x5777d5),console[_0x4716ae(0x198)](_0x25c897),console[_0x4716ae(0x198)](_0x1a81c8);}())); -------------------------------------------------------------------------------- /Examples/case_11_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | var _0x5d698b = 2; 3 | var _0x105a43 = '53'; 4 | var _0x5777d5 = '5-2'; 5 | var _0x25c897 = [ 6 | '10', 7 | '10', 8 | '10', 9 | '10', 10 | '10' 11 | ].map(parseInt); 12 | var _0x1a81c8 = 'foo 11'; 13 | console.log(_0x5d698b); 14 | console.log(_0x105a43); 15 | console.log(_0x5777d5); 16 | console.log(_0x25c897); 17 | console.log(_0x1a81c8); 18 | }()); -------------------------------------------------------------------------------- /Examples/case_12__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | (function(){ 12 | var variable1 = '5' - 3; 13 | var variable2 = '5' + 3; 14 | var variable3 = '5' + - '2'; 15 | var variable4 = ['10','10','10','10','10'].map(parseInt); 16 | var variable5 = 'foo ' + 1 + 1; 17 | console.log(variable1); 18 | console.log(variable2); 19 | console.log(variable3); 20 | console.log(variable4); 21 | console.log(variable5); 22 | })(); -------------------------------------------------------------------------------- /Examples/case_12_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | var _0x47bfb9 = 2; 3 | var _0x4a5f7f = '53'; 4 | var _0x1d56e8 = '5-2'; 5 | var _0x44aaa0 = [ 6 | '10', 7 | '10', 8 | '10', 9 | '10', 10 | '10' 11 | ].map(parseInt); 12 | var _0x5768cc = 'foo 11'; 13 | console.log(_0x47bfb9); 14 | console.log(_0x4a5f7f); 15 | console.log(_0x1d56e8); 16 | console.log(_0x44aaa0); 17 | console.log(_0x5768cc); 18 | }()); -------------------------------------------------------------------------------- /Examples/case_13__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | 12 | (function(){ 13 | var variable1 = '5' - 3; 14 | var variable2 = '5' + 3; 15 | var variable3 = '5' + - '2'; 16 | var variable4 = ['10','10','10','10','10'].map(parseInt); 17 | var variable5 = 'foo ' + 1 + 1; 18 | console.log(variable1); 19 | console.log(variable2); 20 | console.log(variable3); 21 | console.log(variable4); 22 | console.log(variable5); 23 | })(); -------------------------------------------------------------------------------- /Examples/case_13_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | (function () { 3 | }()); 4 | var _0x29b1a3 = 2; 5 | var _0x27a46d = '53'; 6 | var _0xca1752 = '5-2'; 7 | var _0x412db5 = [ 8 | '10', 9 | '10', 10 | '10', 11 | '10', 12 | '10' 13 | ].map(parseInt); 14 | var _0x4d1e25 = 'foo 11'; 15 | console.log(_0x29b1a3); 16 | console.log(_0x27a46d); 17 | console.log(_0xca1752); 18 | console.log(_0x412db5); 19 | console.log(_0x4d1e25); 20 | }()); -------------------------------------------------------------------------------- /Examples/case_14__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2016-2022 Timofey Kachalov. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 9 | */ 10 | 11 | 12 | (function(){ 13 | var variable1 = '5' - 3; 14 | var variable2 = '5' + 3; 15 | var variable3 = '5' + - '2'; 16 | var variable4 = ['10','10','10','10','10'].map(parseInt); 17 | var variable5 = 'foo ' + 1 + 1; 18 | console.log(variable1); 19 | console.log(variable2); 20 | console.log(variable3); 21 | console.log(variable4); 22 | console.log(variable5); 23 | })(); -------------------------------------------------------------------------------- /Examples/case_14_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | (function () { 3 | }()); 4 | var _0x1a79e3 = 2; 5 | var _0x3bf2b6 = '53'; 6 | var _0x38ff90 = '5-2'; 7 | var _0x45eaa5 = [ 8 | '10', 9 | '10', 10 | '10', 11 | '10', 12 | '10' 13 | ].map(parseInt); 14 | var _0x5cbc39 = 'foo 11'; 15 | console.log(_0x1a79e3); 16 | console.log(_0x3bf2b6); 17 | console.log(_0x38ff90); 18 | console.log(_0x45eaa5); 19 | console.log(_0x5cbc39); 20 | }()); -------------------------------------------------------------------------------- /Examples/case_15__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2018 Oleksii Trekhleb 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | // Example from https://github.com/trekhleb/javascript-algorithms/blob/master/src/data-structures/linked-list/LinkedList.js 26 | 27 | import LinkedListNode from './LinkedListNode'; 28 | import Comparator from '../../utils/comparator/Comparator'; 29 | 30 | export default class LinkedList { 31 | /** 32 | * @param {Function} [comparatorFunction] 33 | */ 34 | constructor(comparatorFunction) { 35 | /** @var LinkedListNode */ 36 | this.head = null; 37 | 38 | /** @var LinkedListNode */ 39 | this.tail = null; 40 | 41 | this.compare = new Comparator(comparatorFunction); 42 | } 43 | 44 | /** 45 | * @param {*} value 46 | * @return {LinkedList} 47 | */ 48 | prepend(value) { 49 | // Make new node to be a head. 50 | const newNode = new LinkedListNode(value, this.head); 51 | this.head = newNode; 52 | 53 | // If there is no tail yet let's make new node a tail. 54 | if (!this.tail) { 55 | this.tail = newNode; 56 | } 57 | 58 | return this; 59 | } 60 | 61 | /** 62 | * @param {*} value 63 | * @return {LinkedList} 64 | */ 65 | append(value) { 66 | const newNode = new LinkedListNode(value); 67 | 68 | // If there is no head yet let's make new node a head. 69 | if (!this.head) { 70 | this.head = newNode; 71 | this.tail = newNode; 72 | 73 | return this; 74 | } 75 | 76 | // Attach new node to the end of linked list. 77 | this.tail.next = newNode; 78 | this.tail = newNode; 79 | 80 | return this; 81 | } 82 | 83 | /** 84 | * @param {*} value 85 | * @param {number} index 86 | * @return {LinkedList} 87 | */ 88 | insert(value, rawIndex) { 89 | const index = rawIndex < 0 ? 0 : rawIndex; 90 | if (index === 0) { 91 | this.prepend(value); 92 | } else { 93 | let count = 1; 94 | let currentNode = this.head; 95 | const newNode = new LinkedListNode(value); 96 | while (currentNode) { 97 | if (count === index) break; 98 | currentNode = currentNode.next; 99 | count += 1; 100 | } 101 | if (currentNode) { 102 | newNode.next = currentNode.next; 103 | currentNode.next = newNode; 104 | } else { 105 | if (this.tail) { 106 | this.tail.next = newNode; 107 | this.tail = newNode; 108 | } else { 109 | this.head = newNode; 110 | this.tail = newNode; 111 | } 112 | } 113 | } 114 | return this; 115 | } 116 | 117 | /** 118 | * @param {*} value 119 | * @return {LinkedListNode} 120 | */ 121 | delete(value) { 122 | if (!this.head) { 123 | return null; 124 | } 125 | 126 | let deletedNode = null; 127 | 128 | // If the head must be deleted then make next node that is different 129 | // from the head to be a new head. 130 | while (this.head && this.compare.equal(this.head.value, value)) { 131 | deletedNode = this.head; 132 | this.head = this.head.next; 133 | } 134 | 135 | let currentNode = this.head; 136 | 137 | if (currentNode !== null) { 138 | // If next node must be deleted then make next node to be a next next one. 139 | while (currentNode.next) { 140 | if (this.compare.equal(currentNode.next.value, value)) { 141 | deletedNode = currentNode.next; 142 | currentNode.next = currentNode.next.next; 143 | } else { 144 | currentNode = currentNode.next; 145 | } 146 | } 147 | } 148 | 149 | // Check if tail must be deleted. 150 | if (this.compare.equal(this.tail.value, value)) { 151 | this.tail = currentNode; 152 | } 153 | 154 | return deletedNode; 155 | } 156 | 157 | /** 158 | * @param {Object} findParams 159 | * @param {*} findParams.value 160 | * @param {function} [findParams.callback] 161 | * @return {LinkedListNode} 162 | */ 163 | find({ value = undefined, callback = undefined }) { 164 | if (!this.head) { 165 | return null; 166 | } 167 | 168 | let currentNode = this.head; 169 | 170 | while (currentNode) { 171 | // If callback is specified then try to find node by callback. 172 | if (callback && callback(currentNode.value)) { 173 | return currentNode; 174 | } 175 | 176 | // If value is specified then try to compare by value.. 177 | if (value !== undefined && this.compare.equal(currentNode.value, value)) { 178 | return currentNode; 179 | } 180 | 181 | currentNode = currentNode.next; 182 | } 183 | 184 | return null; 185 | } 186 | 187 | /** 188 | * @return {LinkedListNode} 189 | */ 190 | deleteTail() { 191 | const deletedTail = this.tail; 192 | 193 | if (this.head === this.tail) { 194 | // There is only one node in linked list. 195 | this.head = null; 196 | this.tail = null; 197 | 198 | return deletedTail; 199 | } 200 | 201 | // If there are many nodes in linked list... 202 | 203 | // Rewind to the last node and delete "next" link for the node before the last one. 204 | let currentNode = this.head; 205 | while (currentNode.next) { 206 | if (!currentNode.next.next) { 207 | currentNode.next = null; 208 | } else { 209 | currentNode = currentNode.next; 210 | } 211 | } 212 | 213 | this.tail = currentNode; 214 | 215 | return deletedTail; 216 | } 217 | 218 | /** 219 | * @return {LinkedListNode} 220 | */ 221 | deleteHead() { 222 | if (!this.head) { 223 | return null; 224 | } 225 | 226 | const deletedHead = this.head; 227 | 228 | if (this.head.next) { 229 | this.head = this.head.next; 230 | } else { 231 | this.head = null; 232 | this.tail = null; 233 | } 234 | 235 | return deletedHead; 236 | } 237 | 238 | /** 239 | * @param {*[]} values - Array of values that need to be converted to linked list. 240 | * @return {LinkedList} 241 | */ 242 | fromArray(values) { 243 | values.forEach((value) => this.append(value)); 244 | 245 | return this; 246 | } 247 | 248 | /** 249 | * @return {LinkedListNode[]} 250 | */ 251 | toArray() { 252 | const nodes = []; 253 | 254 | let currentNode = this.head; 255 | while (currentNode) { 256 | nodes.push(currentNode); 257 | currentNode = currentNode.next; 258 | } 259 | 260 | return nodes; 261 | } 262 | 263 | /** 264 | * @param {function} [callback] 265 | * @return {string} 266 | */ 267 | toString(callback) { 268 | return this.toArray().map((node) => node.toString(callback)).toString(); 269 | } 270 | 271 | /** 272 | * Reverse a linked list. 273 | * @returns {LinkedList} 274 | */ 275 | reverse() { 276 | let currNode = this.head; 277 | let prevNode = null; 278 | let nextNode = null; 279 | 280 | while (currNode) { 281 | // Store next node. 282 | nextNode = currNode.next; 283 | 284 | // Change next node of the current node so it would link to previous node. 285 | currNode.next = prevNode; 286 | 287 | // Move prevNode and currNode nodes one step forward. 288 | prevNode = currNode; 289 | currNode = nextNode; 290 | } 291 | 292 | // Reset head and tail. 293 | this.tail = this.head; 294 | this.head = prevNode; 295 | 296 | return this; 297 | } 298 | } -------------------------------------------------------------------------------- /Examples/case_15_linkedlist_default.txt: -------------------------------------------------------------------------------- 1 | function _0x297d(){const _0xae714=['deleteHead','toArray','next','752096hHVDay','7803530FnbkhZ','deleteTail','push','map','append','delete','forEach','5087880ogGnLH','910935BkHZAt','46CKKtwp','5820690MRdtzM','prepend','504XtrchA','reverse','toString','value','compare','equal','head','insert','tail','2111880BMJptZ','9315uYTfHP'];_0x297d=function(){return _0xae714;};return _0x297d();}function _0x5ae8(_0x140cb8,_0x430342){const _0x297dab=_0x297d();return _0x5ae8=function(_0x5ae8f4,_0x83eb00){_0x5ae8f4=_0x5ae8f4-0x131;let _0x5c53ef=_0x297dab[_0x5ae8f4];return _0x5c53ef;},_0x5ae8(_0x140cb8,_0x430342);}const _0x3eef96=_0x5ae8;(function(_0x2afcea,_0x2f2f22){const _0x489a65=_0x5ae8,_0x240500=_0x2afcea();while(!![]){try{const _0x592e30=-parseInt(_0x489a65(0x13d))/0x1+parseInt(_0x489a65(0x13e))/0x2*(-parseInt(_0x489a65(0x14b))/0x3)+-parseInt(_0x489a65(0x14a))/0x4+-parseInt(_0x489a65(0x13c))/0x5+-parseInt(_0x489a65(0x13f))/0x6+-parseInt(_0x489a65(0x135))/0x7+-parseInt(_0x489a65(0x134))/0x8*(-parseInt(_0x489a65(0x141))/0x9);if(_0x592e30===_0x2f2f22)break;else _0x240500['push'](_0x240500['shift']());}catch(_0x57f588){_0x240500['push'](_0x240500['shift']());}}}(_0x297d,0x9f25f));import _0x50486c from'./LinkedListNode';import _0x43d572 from'../../utils/comparator/Comparator';export default class LinkedList{constructor(_0x4614c9){const _0x2b5a19=_0x5ae8;this[_0x2b5a19(0x147)]=null,this['tail']=null,this['compare']=new _0x43d572(_0x4614c9);}['prepend'](_0x233a96){const _0x282b6b=_0x5ae8,_0x1bfd9e=new _0x50486c(_0x233a96,this[_0x282b6b(0x147)]);return this[_0x282b6b(0x147)]=_0x1bfd9e,!this[_0x282b6b(0x149)]&&(this[_0x282b6b(0x149)]=_0x1bfd9e),this;}[_0x3eef96(0x139)](_0x1fea95){const _0x3533cb=_0x3eef96,_0xd676ea=new _0x50486c(_0x1fea95);if(!this['head'])return this['head']=_0xd676ea,this[_0x3533cb(0x149)]=_0xd676ea,this;return this[_0x3533cb(0x149)][_0x3533cb(0x133)]=_0xd676ea,this['tail']=_0xd676ea,this;}[_0x3eef96(0x148)](_0x27afcb,_0x3a8de5){const _0x55ed2f=_0x3eef96,_0x278cc0=_0x3a8de5<0x0?0x0:_0x3a8de5;if(_0x278cc0===0x0)this[_0x55ed2f(0x140)](_0x27afcb);else{let _0x1d7e31=0x1,_0x1a940c=this[_0x55ed2f(0x147)];const _0x4cda03=new _0x50486c(_0x27afcb);while(_0x1a940c){if(_0x1d7e31===_0x278cc0)break;_0x1a940c=_0x1a940c[_0x55ed2f(0x133)],_0x1d7e31+=0x1;}_0x1a940c?(_0x4cda03[_0x55ed2f(0x133)]=_0x1a940c[_0x55ed2f(0x133)],_0x1a940c[_0x55ed2f(0x133)]=_0x4cda03):this[_0x55ed2f(0x149)]?(this[_0x55ed2f(0x149)][_0x55ed2f(0x133)]=_0x4cda03,this[_0x55ed2f(0x149)]=_0x4cda03):(this[_0x55ed2f(0x147)]=_0x4cda03,this[_0x55ed2f(0x149)]=_0x4cda03);}return this;}[_0x3eef96(0x13a)](_0x1a12e2){const _0xbd3fac=_0x3eef96;if(!this['head'])return null;let _0x242636=null;while(this[_0xbd3fac(0x147)]&&this[_0xbd3fac(0x145)][_0xbd3fac(0x146)](this['head'][_0xbd3fac(0x144)],_0x1a12e2)){_0x242636=this[_0xbd3fac(0x147)],this['head']=this[_0xbd3fac(0x147)][_0xbd3fac(0x133)];}let _0x22f019=this[_0xbd3fac(0x147)];if(_0x22f019!==null)while(_0x22f019[_0xbd3fac(0x133)]){this[_0xbd3fac(0x145)][_0xbd3fac(0x146)](_0x22f019[_0xbd3fac(0x133)][_0xbd3fac(0x144)],_0x1a12e2)?(_0x242636=_0x22f019[_0xbd3fac(0x133)],_0x22f019[_0xbd3fac(0x133)]=_0x22f019[_0xbd3fac(0x133)][_0xbd3fac(0x133)]):_0x22f019=_0x22f019[_0xbd3fac(0x133)];}return this[_0xbd3fac(0x145)][_0xbd3fac(0x146)](this['tail'][_0xbd3fac(0x144)],_0x1a12e2)&&(this['tail']=_0x22f019),_0x242636;}['find']({value:value=undefined,callback:callback=undefined}){const _0x17fdf7=_0x3eef96;if(!this[_0x17fdf7(0x147)])return null;let _0x131c41=this[_0x17fdf7(0x147)];while(_0x131c41){if(callback&&callback(_0x131c41[_0x17fdf7(0x144)]))return _0x131c41;if(value!==undefined&&this[_0x17fdf7(0x145)][_0x17fdf7(0x146)](_0x131c41[_0x17fdf7(0x144)],value))return _0x131c41;_0x131c41=_0x131c41[_0x17fdf7(0x133)];}return null;}[_0x3eef96(0x136)](){const _0x3243b4=_0x3eef96,_0x4117ce=this[_0x3243b4(0x149)];if(this['head']===this[_0x3243b4(0x149)])return this[_0x3243b4(0x147)]=null,this['tail']=null,_0x4117ce;let _0x35adf3=this[_0x3243b4(0x147)];while(_0x35adf3[_0x3243b4(0x133)]){!_0x35adf3[_0x3243b4(0x133)][_0x3243b4(0x133)]?_0x35adf3[_0x3243b4(0x133)]=null:_0x35adf3=_0x35adf3[_0x3243b4(0x133)];}return this[_0x3243b4(0x149)]=_0x35adf3,_0x4117ce;}[_0x3eef96(0x131)](){const _0xc190a2=_0x3eef96;if(!this[_0xc190a2(0x147)])return null;const _0x124235=this[_0xc190a2(0x147)];return this[_0xc190a2(0x147)][_0xc190a2(0x133)]?this[_0xc190a2(0x147)]=this[_0xc190a2(0x147)]['next']:(this[_0xc190a2(0x147)]=null,this[_0xc190a2(0x149)]=null),_0x124235;}['fromArray'](_0x4ce9d9){const _0x333d41=_0x3eef96;return _0x4ce9d9[_0x333d41(0x13b)](_0xbd3431=>this[_0x333d41(0x139)](_0xbd3431)),this;}[_0x3eef96(0x132)](){const _0x66af62=_0x3eef96,_0x3a48de=[];let _0x407e3a=this[_0x66af62(0x147)];while(_0x407e3a){_0x3a48de[_0x66af62(0x137)](_0x407e3a),_0x407e3a=_0x407e3a[_0x66af62(0x133)];}return _0x3a48de;}[_0x3eef96(0x143)](_0x11855f){const _0x12c638=_0x3eef96;return this[_0x12c638(0x132)]()[_0x12c638(0x138)](_0x25c100=>_0x25c100[_0x12c638(0x143)](_0x11855f))['toString']();}[_0x3eef96(0x142)](){const _0x43bb1e=_0x3eef96;let _0x47fd97=this[_0x43bb1e(0x147)],_0x47f614=null,_0x59d20d=null;while(_0x47fd97){_0x59d20d=_0x47fd97[_0x43bb1e(0x133)],_0x47fd97[_0x43bb1e(0x133)]=_0x47f614,_0x47f614=_0x47fd97,_0x47fd97=_0x59d20d;}return this['tail']=this[_0x43bb1e(0x147)],this[_0x43bb1e(0x147)]=_0x47f614,this;}} -------------------------------------------------------------------------------- /Examples/case_15_output.txt: -------------------------------------------------------------------------------- 1 | import _0x50486c from './LinkedListNode'; 2 | import _0x43d572 from '../../utils/comparator/Comparator'; 3 | export default class LinkedList { 4 | constructor(_0x4614c9) { 5 | this.head = null; 6 | this.tail = null; 7 | this.compare = new _0x43d572(_0x4614c9); 8 | } 9 | prepend(_0x233a96) { 10 | const _0x1bfd9e = new _0x50486c(_0x233a96, this.head); 11 | this.head = _0x1bfd9e; 12 | if (!this.tail) { 13 | this.tail = _0x1bfd9e; 14 | } 15 | return this; 16 | } 17 | append(_0x1fea95) { 18 | const _0xd676ea = new _0x50486c(_0x1fea95); 19 | if (!this.head) { 20 | this.head = _0xd676ea; 21 | this.tail = _0xd676ea; 22 | return this; 23 | } 24 | this.tail.next = _0xd676ea; 25 | this.tail = _0xd676ea; 26 | return this; 27 | } 28 | insert(_0x27afcb, _0x3a8de5) { 29 | const _0x278cc0 = _0x3a8de5 < 0 ? 0 : _0x3a8de5; 30 | if (_0x278cc0 === 0) { 31 | this.prepend(_0x27afcb); 32 | } else { 33 | let _0x1d7e31 = 1; 34 | let _0x1a940c = this.head; 35 | const _0x4cda03 = new _0x50486c(_0x27afcb); 36 | while (_0x1a940c) { 37 | if (_0x1d7e31 === _0x278cc0) { 38 | break; 39 | } 40 | _0x1a940c = _0x1a940c.next; 41 | _0x1d7e31 += 1; 42 | } 43 | if (_0x1a940c) { 44 | _0x4cda03.next = _0x1a940c.next; 45 | _0x1a940c.next = _0x4cda03; 46 | } else { 47 | if (this.tail) { 48 | this.tail.next = _0x4cda03; 49 | this.tail = _0x4cda03; 50 | } else { 51 | this.head = _0x4cda03; 52 | this.tail = _0x4cda03; 53 | } 54 | } 55 | } 56 | return this; 57 | } 58 | delete(_0x1a12e2) { 59 | if (!this.head) { 60 | return null; 61 | } 62 | let _0x242636 = null; 63 | while (this.head && this.compare.equal(this.head.value, _0x1a12e2)) { 64 | _0x242636 = this.head; 65 | this.head = this.head.next; 66 | } 67 | let _0x22f019 = this.head; 68 | if (_0x22f019 !== null) { 69 | while (_0x22f019.next) { 70 | if (this.compare.equal(_0x22f019.next.value, _0x1a12e2)) { 71 | _0x242636 = _0x22f019.next; 72 | _0x22f019.next = _0x22f019.next.next; 73 | } else { 74 | _0x22f019 = _0x22f019.next; 75 | } 76 | } 77 | } 78 | if (this.compare.equal(this.tail.value, _0x1a12e2)) { 79 | this.tail = _0x22f019; 80 | } 81 | return _0x242636; 82 | } 83 | find({ 84 | value: value = undefined, 85 | callback: callback = undefined 86 | }) { 87 | if (!this.head) { 88 | return null; 89 | } 90 | let _0x131c41 = this.head; 91 | while (_0x131c41) { 92 | if (callback && callback(_0x131c41.value)) { 93 | return _0x131c41; 94 | } 95 | if (value !== undefined && this.compare.equal(_0x131c41.value, value)) { 96 | return _0x131c41; 97 | } 98 | _0x131c41 = _0x131c41.next; 99 | } 100 | return null; 101 | } 102 | deleteTail() { 103 | const _0x4117ce = this.tail; 104 | if (this.head === this.tail) { 105 | this.head = null; 106 | this.tail = null; 107 | return _0x4117ce; 108 | } 109 | let _0x35adf3 = this.head; 110 | while (_0x35adf3.next) { 111 | if (!_0x35adf3.next.next) { 112 | _0x35adf3.next = null; 113 | } else { 114 | _0x35adf3 = _0x35adf3.next; 115 | } 116 | } 117 | this.tail = _0x35adf3; 118 | return _0x4117ce; 119 | } 120 | deleteHead() { 121 | if (!this.head) { 122 | return null; 123 | } 124 | const _0x124235 = this.head; 125 | if (this.head.next) { 126 | this.head = this.head.next; 127 | } else { 128 | this.head = null; 129 | this.tail = null; 130 | } 131 | return _0x124235; 132 | } 133 | fromArray(_0x4ce9d9) { 134 | _0x4ce9d9.forEach(_0xbd3431 => this.append(_0xbd3431)); 135 | return this; 136 | } 137 | toArray() { 138 | const _0x3a48de = []; 139 | let _0x407e3a = this.head; 140 | while (_0x407e3a) { 141 | _0x3a48de.push(_0x407e3a); 142 | _0x407e3a = _0x407e3a.next; 143 | } 144 | return _0x3a48de; 145 | } 146 | toString(_0x11855f) { 147 | return this.toArray().map(_0x25c100 => _0x25c100.toString(_0x11855f)).toString(); 148 | } 149 | reverse() { 150 | let _0x47fd97 = this.head; 151 | let _0x47f614 = null; 152 | let _0x59d20d = null; 153 | while (_0x47fd97) { 154 | _0x59d20d = _0x47fd97.next; 155 | _0x47fd97.next = _0x47f614; 156 | _0x47f614 = _0x47fd97; 157 | _0x47fd97 = _0x59d20d; 158 | } 159 | this.tail = this.head; 160 | this.head = _0x47f614; 161 | return this; 162 | } 163 | } -------------------------------------------------------------------------------- /Examples/case_16__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2018 Oleksii Trekhleb 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | // Example from https://github.com/trekhleb/javascript-algorithms/blob/master/src/data-structures/linked-list/LinkedList.js 26 | 27 | import LinkedListNode from './LinkedListNode'; 28 | import Comparator from '../../utils/comparator/Comparator'; 29 | 30 | export default class LinkedList { 31 | /** 32 | * @param {Function} [comparatorFunction] 33 | */ 34 | constructor(comparatorFunction) { 35 | /** @var LinkedListNode */ 36 | this.head = null; 37 | 38 | /** @var LinkedListNode */ 39 | this.tail = null; 40 | 41 | this.compare = new Comparator(comparatorFunction); 42 | } 43 | 44 | /** 45 | * @param {*} value 46 | * @return {LinkedList} 47 | */ 48 | prepend(value) { 49 | // Make new node to be a head. 50 | const newNode = new LinkedListNode(value, this.head); 51 | this.head = newNode; 52 | 53 | // If there is no tail yet let's make new node a tail. 54 | if (!this.tail) { 55 | this.tail = newNode; 56 | } 57 | 58 | return this; 59 | } 60 | 61 | /** 62 | * @param {*} value 63 | * @return {LinkedList} 64 | */ 65 | append(value) { 66 | const newNode = new LinkedListNode(value); 67 | 68 | // If there is no head yet let's make new node a head. 69 | if (!this.head) { 70 | this.head = newNode; 71 | this.tail = newNode; 72 | 73 | return this; 74 | } 75 | 76 | // Attach new node to the end of linked list. 77 | this.tail.next = newNode; 78 | this.tail = newNode; 79 | 80 | return this; 81 | } 82 | 83 | /** 84 | * @param {*} value 85 | * @param {number} index 86 | * @return {LinkedList} 87 | */ 88 | insert(value, rawIndex) { 89 | const index = rawIndex < 0 ? 0 : rawIndex; 90 | if (index === 0) { 91 | this.prepend(value); 92 | } else { 93 | let count = 1; 94 | let currentNode = this.head; 95 | const newNode = new LinkedListNode(value); 96 | while (currentNode) { 97 | if (count === index) break; 98 | currentNode = currentNode.next; 99 | count += 1; 100 | } 101 | if (currentNode) { 102 | newNode.next = currentNode.next; 103 | currentNode.next = newNode; 104 | } else { 105 | if (this.tail) { 106 | this.tail.next = newNode; 107 | this.tail = newNode; 108 | } else { 109 | this.head = newNode; 110 | this.tail = newNode; 111 | } 112 | } 113 | } 114 | return this; 115 | } 116 | 117 | /** 118 | * @param {*} value 119 | * @return {LinkedListNode} 120 | */ 121 | delete(value) { 122 | if (!this.head) { 123 | return null; 124 | } 125 | 126 | let deletedNode = null; 127 | 128 | // If the head must be deleted then make next node that is different 129 | // from the head to be a new head. 130 | while (this.head && this.compare.equal(this.head.value, value)) { 131 | deletedNode = this.head; 132 | this.head = this.head.next; 133 | } 134 | 135 | let currentNode = this.head; 136 | 137 | if (currentNode !== null) { 138 | // If next node must be deleted then make next node to be a next next one. 139 | while (currentNode.next) { 140 | if (this.compare.equal(currentNode.next.value, value)) { 141 | deletedNode = currentNode.next; 142 | currentNode.next = currentNode.next.next; 143 | } else { 144 | currentNode = currentNode.next; 145 | } 146 | } 147 | } 148 | 149 | // Check if tail must be deleted. 150 | if (this.compare.equal(this.tail.value, value)) { 151 | this.tail = currentNode; 152 | } 153 | 154 | return deletedNode; 155 | } 156 | 157 | /** 158 | * @param {Object} findParams 159 | * @param {*} findParams.value 160 | * @param {function} [findParams.callback] 161 | * @return {LinkedListNode} 162 | */ 163 | find({ value = undefined, callback = undefined }) { 164 | if (!this.head) { 165 | return null; 166 | } 167 | 168 | let currentNode = this.head; 169 | 170 | while (currentNode) { 171 | // If callback is specified then try to find node by callback. 172 | if (callback && callback(currentNode.value)) { 173 | return currentNode; 174 | } 175 | 176 | // If value is specified then try to compare by value.. 177 | if (value !== undefined && this.compare.equal(currentNode.value, value)) { 178 | return currentNode; 179 | } 180 | 181 | currentNode = currentNode.next; 182 | } 183 | 184 | return null; 185 | } 186 | 187 | /** 188 | * @return {LinkedListNode} 189 | */ 190 | deleteTail() { 191 | const deletedTail = this.tail; 192 | 193 | if (this.head === this.tail) { 194 | // There is only one node in linked list. 195 | this.head = null; 196 | this.tail = null; 197 | 198 | return deletedTail; 199 | } 200 | 201 | // If there are many nodes in linked list... 202 | 203 | // Rewind to the last node and delete "next" link for the node before the last one. 204 | let currentNode = this.head; 205 | while (currentNode.next) { 206 | if (!currentNode.next.next) { 207 | currentNode.next = null; 208 | } else { 209 | currentNode = currentNode.next; 210 | } 211 | } 212 | 213 | this.tail = currentNode; 214 | 215 | return deletedTail; 216 | } 217 | 218 | /** 219 | * @return {LinkedListNode} 220 | */ 221 | deleteHead() { 222 | if (!this.head) { 223 | return null; 224 | } 225 | 226 | const deletedHead = this.head; 227 | 228 | if (this.head.next) { 229 | this.head = this.head.next; 230 | } else { 231 | this.head = null; 232 | this.tail = null; 233 | } 234 | 235 | return deletedHead; 236 | } 237 | 238 | /** 239 | * @param {*[]} values - Array of values that need to be converted to linked list. 240 | * @return {LinkedList} 241 | */ 242 | fromArray(values) { 243 | values.forEach((value) => this.append(value)); 244 | 245 | return this; 246 | } 247 | 248 | /** 249 | * @return {LinkedListNode[]} 250 | */ 251 | toArray() { 252 | const nodes = []; 253 | 254 | let currentNode = this.head; 255 | while (currentNode) { 256 | nodes.push(currentNode); 257 | currentNode = currentNode.next; 258 | } 259 | 260 | return nodes; 261 | } 262 | 263 | /** 264 | * @param {function} [callback] 265 | * @return {string} 266 | */ 267 | toString(callback) { 268 | return this.toArray().map((node) => node.toString(callback)).toString(); 269 | } 270 | 271 | /** 272 | * Reverse a linked list. 273 | * @returns {LinkedList} 274 | */ 275 | reverse() { 276 | let currNode = this.head; 277 | let prevNode = null; 278 | let nextNode = null; 279 | 280 | while (currNode) { 281 | // Store next node. 282 | nextNode = currNode.next; 283 | 284 | // Change next node of the current node so it would link to previous node. 285 | currNode.next = prevNode; 286 | 287 | // Move prevNode and currNode nodes one step forward. 288 | prevNode = currNode; 289 | currNode = nextNode; 290 | } 291 | 292 | // Reset head and tail. 293 | this.tail = this.head; 294 | this.head = prevNode; 295 | 296 | return this; 297 | } 298 | } -------------------------------------------------------------------------------- /Examples/case_16_output.txt: -------------------------------------------------------------------------------- 1 | import _0x59dd84 from './LinkedListNode'; 2 | import _0x1dcfeb from '../../utils/comparator/Comparator'; 3 | export default class LinkedList { 4 | constructor(_0xcce2bc) { 5 | this.head = null; 6 | this.tail = null; 7 | this.compare = new _0x1dcfeb(_0xcce2bc); 8 | } 9 | prepend(_0x223f39) { 10 | const _0x101c76 = new _0x59dd84(_0x223f39, this.head); 11 | this.head = _0x101c76; 12 | if (!this.tail) { 13 | this.tail = _0x101c76; 14 | } 15 | return this; 16 | } 17 | append(_0x739dd9) { 18 | const _0x3ebb42 = new _0x59dd84(_0x739dd9); 19 | if (!this.head) { 20 | this.head = _0x3ebb42; 21 | this.tail = _0x3ebb42; 22 | return this; 23 | } 24 | this.tail.next = _0x3ebb42; 25 | this.tail = _0x3ebb42; 26 | return this; 27 | } 28 | insert(_0x74fb72, _0xf34a) { 29 | const _0x1f98c4 = _0xf34a < 0 ? 0 : _0xf34a; 30 | if (_0x1f98c4 === 0) { 31 | this.prepend(_0x74fb72); 32 | } else { 33 | let _0x11faee = 1; 34 | let _0x521623 = this.head; 35 | const _0x368b27 = new _0x59dd84(_0x74fb72); 36 | while (_0x521623) { 37 | if (_0x11faee === _0x1f98c4) { 38 | break; 39 | } 40 | _0x521623 = _0x521623.next; 41 | _0x11faee += 1; 42 | } 43 | if (_0x521623) { 44 | _0x368b27.next = _0x521623.next; 45 | _0x521623.next = _0x368b27; 46 | } else { 47 | if (this.tail) { 48 | this.tail.next = _0x368b27; 49 | this.tail = _0x368b27; 50 | } else { 51 | this.head = _0x368b27; 52 | this.tail = _0x368b27; 53 | } 54 | } 55 | } 56 | return this; 57 | } 58 | delete(_0x44364d) { 59 | if (!this.head) { 60 | return null; 61 | } 62 | let _0x4f6d63 = null; 63 | while (this.head && this.compare.equal(this.head.value, _0x44364d)) { 64 | _0x4f6d63 = this.head; 65 | this.head = this.head.next; 66 | } 67 | let _0x4db2eb = this.head; 68 | if (_0x4db2eb !== null) { 69 | while (_0x4db2eb.next) { 70 | if (this.compare.equal(_0x4db2eb.next.value, _0x44364d)) { 71 | _0x4f6d63 = _0x4db2eb.next; 72 | _0x4db2eb.next = _0x4db2eb.next.next; 73 | } else { 74 | _0x4db2eb = _0x4db2eb.next; 75 | } 76 | } 77 | } 78 | if (this.compare.equal(this.tail.value, _0x44364d)) { 79 | this.tail = _0x4db2eb; 80 | } 81 | return _0x4f6d63; 82 | } 83 | find({ 84 | value: value = undefined, 85 | callback: callback = undefined 86 | }) { 87 | if (!this.head) { 88 | return null; 89 | } 90 | let _0x331b47 = this.head; 91 | while (_0x331b47) { 92 | if (callback && callback(_0x331b47.value)) { 93 | return _0x331b47; 94 | } 95 | if (value !== undefined && this.compare.equal(_0x331b47.value, value)) { 96 | return _0x331b47; 97 | } 98 | _0x331b47 = _0x331b47.next; 99 | } 100 | return null; 101 | } 102 | deleteTail() { 103 | const _0x55be35 = this.tail; 104 | if (this.head === this.tail) { 105 | this.head = null; 106 | this.tail = null; 107 | return _0x55be35; 108 | } 109 | let _0x4fa99e = this.head; 110 | while (_0x4fa99e.next) { 111 | if (!_0x4fa99e.next.next) { 112 | _0x4fa99e.next = null; 113 | } else { 114 | _0x4fa99e = _0x4fa99e.next; 115 | } 116 | } 117 | this.tail = _0x4fa99e; 118 | return _0x55be35; 119 | } 120 | deleteHead() { 121 | if (!this.head) { 122 | return null; 123 | } 124 | const _0x42a834 = this.head; 125 | if (this.head.next) { 126 | this.head = this.head.next; 127 | } else { 128 | this.head = null; 129 | this.tail = null; 130 | } 131 | return _0x42a834; 132 | } 133 | fromArray(_0x158a58) { 134 | _0x158a58.forEach(_0x1a5c3c => this.append(_0x1a5c3c)); 135 | return this; 136 | } 137 | toArray() { 138 | const _0x31b06e = []; 139 | let _0xae1b6e = this.head; 140 | while (_0xae1b6e) { 141 | _0x31b06e.push(_0xae1b6e); 142 | _0xae1b6e = _0xae1b6e.next; 143 | } 144 | return _0x31b06e; 145 | } 146 | toString(_0x31f306) { 147 | return this.toArray().map(_0x21d6df => _0x21d6df.toString(_0x31f306)).toString(); 148 | } 149 | reverse() { 150 | let _0x49df9d = this.head; 151 | let _0x580ace = null; 152 | let _0x833014 = null; 153 | while (_0x49df9d) { 154 | _0x833014 = _0x49df9d.next; 155 | _0x49df9d.next = _0x580ace; 156 | _0x580ace = _0x49df9d; 157 | _0x49df9d = _0x833014; 158 | } 159 | this.tail = this.head; 160 | this.head = _0x580ace; 161 | return this; 162 | } 163 | } -------------------------------------------------------------------------------- /Examples/case_17__original.txt: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2018 Oleksii Trekhleb 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | 26 | // Example from https://github.com/trekhleb/javascript-algorithms/blob/master/src/data-structures/linked-list/LinkedList.js 27 | 28 | import LinkedListNode from './LinkedListNode'; 29 | import Comparator from '../../utils/comparator/Comparator'; 30 | 31 | export default class LinkedList { 32 | /** 33 | * @param {Function} [comparatorFunction] 34 | */ 35 | constructor(comparatorFunction) { 36 | /** @var LinkedListNode */ 37 | this.head = null; 38 | 39 | /** @var LinkedListNode */ 40 | this.tail = null; 41 | 42 | this.compare = new Comparator(comparatorFunction); 43 | } 44 | 45 | /** 46 | * @param {*} value 47 | * @return {LinkedList} 48 | */ 49 | prepend(value) { 50 | // Make new node to be a head. 51 | const newNode = new LinkedListNode(value, this.head); 52 | this.head = newNode; 53 | 54 | // If there is no tail yet let's make new node a tail. 55 | if (!this.tail) { 56 | this.tail = newNode; 57 | } 58 | 59 | return this; 60 | } 61 | 62 | /** 63 | * @param {*} value 64 | * @return {LinkedList} 65 | */ 66 | append(value) { 67 | const newNode = new LinkedListNode(value); 68 | 69 | // If there is no head yet let's make new node a head. 70 | if (!this.head) { 71 | this.head = newNode; 72 | this.tail = newNode; 73 | 74 | return this; 75 | } 76 | 77 | // Attach new node to the end of linked list. 78 | this.tail.next = newNode; 79 | this.tail = newNode; 80 | 81 | return this; 82 | } 83 | 84 | /** 85 | * @param {*} value 86 | * @param {number} index 87 | * @return {LinkedList} 88 | */ 89 | insert(value, rawIndex) { 90 | const index = rawIndex < 0 ? 0 : rawIndex; 91 | if (index === 0) { 92 | this.prepend(value); 93 | } else { 94 | let count = 1; 95 | let currentNode = this.head; 96 | const newNode = new LinkedListNode(value); 97 | while (currentNode) { 98 | if (count === index) break; 99 | currentNode = currentNode.next; 100 | count += 1; 101 | } 102 | if (currentNode) { 103 | newNode.next = currentNode.next; 104 | currentNode.next = newNode; 105 | } else { 106 | if (this.tail) { 107 | this.tail.next = newNode; 108 | this.tail = newNode; 109 | } else { 110 | this.head = newNode; 111 | this.tail = newNode; 112 | } 113 | } 114 | } 115 | return this; 116 | } 117 | 118 | /** 119 | * @param {*} value 120 | * @return {LinkedListNode} 121 | */ 122 | delete(value) { 123 | if (!this.head) { 124 | return null; 125 | } 126 | 127 | let deletedNode = null; 128 | 129 | // If the head must be deleted then make next node that is different 130 | // from the head to be a new head. 131 | while (this.head && this.compare.equal(this.head.value, value)) { 132 | deletedNode = this.head; 133 | this.head = this.head.next; 134 | } 135 | 136 | let currentNode = this.head; 137 | 138 | if (currentNode !== null) { 139 | // If next node must be deleted then make next node to be a next next one. 140 | while (currentNode.next) { 141 | if (this.compare.equal(currentNode.next.value, value)) { 142 | deletedNode = currentNode.next; 143 | currentNode.next = currentNode.next.next; 144 | } else { 145 | currentNode = currentNode.next; 146 | } 147 | } 148 | } 149 | 150 | // Check if tail must be deleted. 151 | if (this.compare.equal(this.tail.value, value)) { 152 | this.tail = currentNode; 153 | } 154 | 155 | return deletedNode; 156 | } 157 | 158 | /** 159 | * @param {Object} findParams 160 | * @param {*} findParams.value 161 | * @param {function} [findParams.callback] 162 | * @return {LinkedListNode} 163 | */ 164 | find({ value = undefined, callback = undefined }) { 165 | if (!this.head) { 166 | return null; 167 | } 168 | 169 | let currentNode = this.head; 170 | 171 | while (currentNode) { 172 | // If callback is specified then try to find node by callback. 173 | if (callback && callback(currentNode.value)) { 174 | return currentNode; 175 | } 176 | 177 | // If value is specified then try to compare by value.. 178 | if (value !== undefined && this.compare.equal(currentNode.value, value)) { 179 | return currentNode; 180 | } 181 | 182 | currentNode = currentNode.next; 183 | } 184 | 185 | return null; 186 | } 187 | 188 | /** 189 | * @return {LinkedListNode} 190 | */ 191 | deleteTail() { 192 | const deletedTail = this.tail; 193 | 194 | if (this.head === this.tail) { 195 | // There is only one node in linked list. 196 | this.head = null; 197 | this.tail = null; 198 | 199 | return deletedTail; 200 | } 201 | 202 | // If there are many nodes in linked list... 203 | 204 | // Rewind to the last node and delete "next" link for the node before the last one. 205 | let currentNode = this.head; 206 | while (currentNode.next) { 207 | if (!currentNode.next.next) { 208 | currentNode.next = null; 209 | } else { 210 | currentNode = currentNode.next; 211 | } 212 | } 213 | 214 | this.tail = currentNode; 215 | 216 | return deletedTail; 217 | } 218 | 219 | /** 220 | * @return {LinkedListNode} 221 | */ 222 | deleteHead() { 223 | if (!this.head) { 224 | return null; 225 | } 226 | 227 | const deletedHead = this.head; 228 | 229 | if (this.head.next) { 230 | this.head = this.head.next; 231 | } else { 232 | this.head = null; 233 | this.tail = null; 234 | } 235 | 236 | return deletedHead; 237 | } 238 | 239 | /** 240 | * @param {*[]} values - Array of values that need to be converted to linked list. 241 | * @return {LinkedList} 242 | */ 243 | fromArray(values) { 244 | values.forEach((value) => this.append(value)); 245 | 246 | return this; 247 | } 248 | 249 | /** 250 | * @return {LinkedListNode[]} 251 | */ 252 | toArray() { 253 | const nodes = []; 254 | 255 | let currentNode = this.head; 256 | while (currentNode) { 257 | nodes.push(currentNode); 258 | currentNode = currentNode.next; 259 | } 260 | 261 | return nodes; 262 | } 263 | 264 | /** 265 | * @param {function} [callback] 266 | * @return {string} 267 | */ 268 | toString(callback) { 269 | return this.toArray().map((node) => node.toString(callback)).toString(); 270 | } 271 | 272 | /** 273 | * Reverse a linked list. 274 | * @returns {LinkedList} 275 | */ 276 | reverse() { 277 | let currNode = this.head; 278 | let prevNode = null; 279 | let nextNode = null; 280 | 281 | while (currNode) { 282 | // Store next node. 283 | nextNode = currNode.next; 284 | 285 | // Change next node of the current node so it would link to previous node. 286 | currNode.next = prevNode; 287 | 288 | // Move prevNode and currNode nodes one step forward. 289 | prevNode = currNode; 290 | currNode = nextNode; 291 | } 292 | 293 | // Reset head and tail. 294 | this.tail = this.head; 295 | this.head = prevNode; 296 | 297 | return this; 298 | } 299 | } -------------------------------------------------------------------------------- /Examples/case_17_output.txt: -------------------------------------------------------------------------------- 1 | (function () { 2 | }()); 3 | import _0x50b3d4 from './LinkedListNode'; 4 | import _0x2c139c from '../../utils/comparator/Comparator'; 5 | export default class LinkedList { 6 | constructor(_0x1e9260) { 7 | this.head = null; 8 | this.tail = null; 9 | this.compare = new _0x2c139c(_0x1e9260); 10 | } 11 | prepend(_0x16805c) { 12 | const _0x22f81e = new _0x50b3d4(_0x16805c, this.head); 13 | this.head = _0x22f81e; 14 | if (!this.tail) { 15 | this.tail = _0x22f81e; 16 | } 17 | return this; 18 | } 19 | append(_0x2ff615) { 20 | const _0x28e621 = new _0x50b3d4(_0x2ff615); 21 | if (!this.head) { 22 | this.head = _0x28e621; 23 | this.tail = _0x28e621; 24 | return this; 25 | } 26 | this.tail.next = _0x28e621; 27 | this.tail = _0x28e621; 28 | return this; 29 | } 30 | insert(_0x589b3c, _0x159227) { 31 | const _0x33d6b2 = _0x159227 < 0 ? 0 : _0x159227; 32 | if (_0x33d6b2 === 0) { 33 | this.prepend(_0x589b3c); 34 | } else { 35 | let _0x2f2ffc = 1; 36 | let _0x324033 = this.head; 37 | const _0x304c16 = new _0x50b3d4(_0x589b3c); 38 | while (_0x324033) { 39 | if (_0x2f2ffc === _0x33d6b2) { 40 | break; 41 | } 42 | _0x324033 = _0x324033.next; 43 | _0x2f2ffc += 1; 44 | } 45 | if (_0x324033) { 46 | _0x304c16.next = _0x324033.next; 47 | _0x324033.next = _0x304c16; 48 | } else { 49 | if (this.tail) { 50 | this.tail.next = _0x304c16; 51 | this.tail = _0x304c16; 52 | } else { 53 | this.head = _0x304c16; 54 | this.tail = _0x304c16; 55 | } 56 | } 57 | } 58 | return this; 59 | } 60 | delete(_0x2fa700) { 61 | if (!this.head) { 62 | return null; 63 | } 64 | let _0xfcfa8b = null; 65 | while (this.head && this.compare.equal(this.head.value, _0x2fa700)) { 66 | _0xfcfa8b = this.head; 67 | this.head = this.head.next; 68 | } 69 | let _0x5bc736 = this.head; 70 | if (_0x5bc736 !== null) { 71 | while (_0x5bc736.next) { 72 | if (this.compare.equal(_0x5bc736.next.value, _0x2fa700)) { 73 | _0xfcfa8b = _0x5bc736.next; 74 | _0x5bc736.next = _0x5bc736.next.next; 75 | } else { 76 | _0x5bc736 = _0x5bc736.next; 77 | } 78 | } 79 | } 80 | if (this.compare.equal(this.tail.value, _0x2fa700)) { 81 | this.tail = _0x5bc736; 82 | } 83 | return _0xfcfa8b; 84 | } 85 | find({ 86 | value: value = undefined, 87 | callback: callback = undefined 88 | }) { 89 | if (!this.head) { 90 | return null; 91 | } 92 | let _0x39fe87 = this.head; 93 | while (_0x39fe87) { 94 | if (callback && callback(_0x39fe87.value)) { 95 | return _0x39fe87; 96 | } 97 | if (value !== undefined && this.compare.equal(_0x39fe87.value, value)) { 98 | return _0x39fe87; 99 | } 100 | _0x39fe87 = _0x39fe87.next; 101 | } 102 | return null; 103 | } 104 | deleteTail() { 105 | const _0x419246 = this.tail; 106 | if (this.head === this.tail) { 107 | this.head = null; 108 | this.tail = null; 109 | return _0x419246; 110 | } 111 | let _0x2f695e = this.head; 112 | while (_0x2f695e.next) { 113 | if (!_0x2f695e.next.next) { 114 | _0x2f695e.next = null; 115 | } else { 116 | _0x2f695e = _0x2f695e.next; 117 | } 118 | } 119 | this.tail = _0x2f695e; 120 | return _0x419246; 121 | } 122 | deleteHead() { 123 | if (!this.head) { 124 | return null; 125 | } 126 | const _0x3897c2 = this.head; 127 | if (this.head.next) { 128 | this.head = this.head.next; 129 | } else { 130 | this.head = null; 131 | this.tail = null; 132 | } 133 | return _0x3897c2; 134 | } 135 | fromArray(_0x4edb3c) { 136 | _0x4edb3c.forEach(_0x44145a => this.append(_0x44145a)); 137 | return this; 138 | } 139 | toArray() { 140 | const _0x2e07f7 = []; 141 | let _0x41deb7 = this.head; 142 | while (_0x41deb7) { 143 | _0x2e07f7.push(_0x41deb7); 144 | _0x41deb7 = _0x41deb7.next; 145 | } 146 | return _0x2e07f7; 147 | } 148 | toString(_0x438a4d) { 149 | return this.toArray().map(_0x14518e => _0x14518e.toString(_0x438a4d)).toString(); 150 | } 151 | reverse() { 152 | let _0x2092f8 = this.head; 153 | let _0x5dfce9 = null; 154 | let _0x1b73bc = null; 155 | while (_0x2092f8) { 156 | _0x1b73bc = _0x2092f8.next; 157 | _0x2092f8.next = _0x5dfce9; 158 | _0x5dfce9 = _0x2092f8; 159 | _0x2092f8 = _0x1b73bc; 160 | } 161 | this.tail = this.head; 162 | this.head = _0x5dfce9; 163 | return this; 164 | } 165 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 0x1Avram 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JS-Deobfuscator 2 | Deobfuscator for [Timofey Kachalov's](https://github.com/sanex3339) [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator) - also available at [obfuscator.io](https://obfuscator.io/). 3 | 4 | # :warning: !!! WARNING !!! 5 | The code here is not secure. It uses 'eval' for convenience purposes and could easily be exploited by someone with malicious intent. That is why this should only be used in secure and isolated environments. Under no circumstances should anyone run this on a real environment - at least, use a virtual machine or something to protect your system !!! 6 | 7 | 8 | ## Setup 9 | 1) Clone this project: 10 | ``` 11 | git clone https://github.com/0x1Avram/js-deobfuscator.git 12 | ``` 13 | 2) Install node.js (I used version 16.15) 14 | 3) Install dependencies by running this command in the folder root: 15 | ``` 16 | npm install 17 | ``` 18 | 4) Enjoy 19 | 20 | 21 | 22 | ## Binaries 23 | I included binaries built for Windows/Linux in the release section (for the windows one, you will need to add the proper '.exe' extension in order to use it). Those binaries where built using pkg and can be run on a system standalone, without the need to install node.js or any other dependencies. 24 | Their respective SHA256 hashes can be found in the release section as well. 25 | 26 | 27 | For those wanting to build this into an executable themselves, install [pkg](https://www.npmjs.com/package/pkg) and then run this command in the folder root 28 | ``` 29 | pkg index.js 30 | ``` 31 | 32 | 33 | ## Examples 34 | To showcase the deobfuscator capabilities, I included some sets of original + obfuscated + deobfuscated samples in the 'Examples' folder. 35 | Some of those use examples from [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator) or [javascript-algorithms](https://github.com/trekhleb/javascript-algorithms/). 36 | Here are their respective copyright licenses: 37 | 38 | [javascript-obfuscator](https://github.com/javascript-obfuscator/javascript-obfuscator) 39 | 40 | ``` 41 | Copyright (C) 2016-2022 Timofey Kachalov. 42 | 43 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 44 | 45 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 46 | Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 48 | ``` 49 | 50 | [javascript-algorithms](https://github.com/trekhleb/javascript-algorithms/) 51 | 52 | ``` 53 | The MIT License (MIT) 54 | 55 | Copyright (c) 2018 Oleksii Trekhleb 56 | 57 | Permission is hereby granted, free of charge, to any person obtaining a copy 58 | of this software and associated documentation files (the "Software"), to deal 59 | in the Software without restriction, including without limitation the rights 60 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 61 | copies of the Software, and to permit persons to whom the Software is 62 | furnished to do so, subject to the following conditions: 63 | 64 | The above copyright notice and this permission notice shall be included in all 65 | copies or substantial portions of the Software. 66 | 67 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 68 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 69 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 70 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 71 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 72 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 73 | SOFTWARE. 74 | ``` 75 | 76 | ## Usage 77 | The "main" script is index.js. Calling it with a '-h' argument should display the command line options. 78 | The deobfuscator tries to automatically detect the stringarray related code. If it manages to do so correctly, it can be run by just specifying the input and output path. 79 | ``` 80 | node ./index.js -i obfuscated.txt -o deobfuscated.txt 81 | ``` 82 | Otherwise, the code for the stringarray needs to be placed in separate files and given as input. Example: 83 | ``` 84 | node ./index.js -s stringarray.txt -w stringarraywrappers.txt -n _0x471d,_0x9cad,_0x4cd9 85 | -r stringarrayrotate.txt -i obfuscated.txt -o output.txt 86 | ``` 87 | More examples regarding how the stringarray related code looks like along with command lines can be found in the 'Examples' folder. 88 | 89 | Detailed information about the command line options: 90 | ``` 91 | node .\index.js -h 92 | Usage: program [options] 93 | 94 | Options: 95 | --version Show version number [boolean] 96 | -i, --inputPath Path of input (obfuscated) file. 97 | [string] [default: "input.txt"] 98 | -o, --outputPath Path where the output (deobfuscated) file is 99 | stored. [string] [default: "output.txt"] 100 | -d, --debug Display debug log messages (for large input 101 | files, debug log might be large). 102 | [boolean] [default: false] 103 | -a, --debugall Display all AST operations for debugging. The 104 | 'debug' option needs to be set for this to 105 | work. [boolean] [default: false] 106 | -l, --separateloggers Use a separate logger for each deobfuscation 107 | stage. This will lead to the creation of a 108 | debug log file for each deobfuscation stage (11 109 | stages). This is useful so that instead of a 110 | single huge debug log file, several smaller 111 | ones are created (one per each stage). The 112 | 'debug' option needs to be set for this to 113 | work. [boolean] [default: false] 114 | -f, --writedifffiles Write before&after files for each 115 | transformation modifying the source code(used 116 | for debugging). The files are written in the 117 | working directory of the script. 118 | [boolean] [default: false] 119 | -s, --stringarray [StringArray] The path at which the code for 120 | the string array is found(can be just an array 121 | or a function containing the array). 122 | [string] [default: ""] 123 | -w, --stringarraywrappers [StringArray] The path at which the code for 124 | the string wrappers is found(there can be 125 | multiple wrappers depending on the 126 | 'string-array-encoding' obfuscation option) 127 | (the wrappers can contain the self defending 128 | code). [string] [default: ""] 129 | -n, --stringarraywrappernames [StringArray] The names of the string array 130 | wrapper functions in a comma separated string 131 | without spaces. (these are the functions from 132 | the code indicated by the 'stringarraywrappers' 133 | path). [string] [default: ""] 134 | -r, --stringarrayrotate [string] [default: ""] 135 | -c, --cleanuplog [boolean] [default: false] 136 | -h, --help Show help [boolean] 137 | 138 | Examples: 139 | -s stringarray.txt -w stringarraywrappers.txt -n _0x471d,_0x9cad,_0x4cd9 -r 140 | stringarrayrotate.txt -i obfuscated.txt -o output.txt 141 | -i obfuscated.txt -o deobfuscated.txt 142 | ``` 143 | 144 | ## Notes 145 | From my testing, this seems to work fine with current versions of the obfuscator. 146 | However, older versions of the obfuscator may output a different AST and that might complicate things. If you happen to stumble across a case where this should work but it doesn't, open an issue and I'll look into it. 147 | 148 | There are some scenarios where the deobfuscator might crash because an AST cannot be generated from the input. This is a limitation from the esprima parser used by the deobfuscator which does not support all new JavaScript features. If this error is encountered, a message suggesting that the code needs to be transpiled before deobfuscation will be displayed. The transpilation to an older JavaScript version for which esprima correctly parses the script can be done using [Babel](https://babeljs.io/) and the parsing of the script can be checked with tools such as [astexplorer](https://astexplorer.net/). 149 | 150 | ### Easy transpilation with babel: 151 | 1) Create directory with the file you are trying to deobfuscate inside directory 152 | 2) Initialize node project with default configuration: 153 | ``` 154 | npm init -y 155 | ``` 156 | 3) Install babel: 157 | ``` 158 | npm install --save-dev @babel/core @babel/cli @babel/preset-env 159 | ``` 160 | 4) Create '.babelrc' file inside directory with the following content 161 | ``` 162 | { 163 | "presets": ["@babel/preset-env"], 164 | "compact": false 165 | } 166 | ``` 167 | 5) Run babel via CLI for transpilation 168 | 169 | Example for transpiling 'a.txt' file to 'output.js' file. ('a.txt' is the input file, not parsed by espirma; 'output.js' is the output file, successfully parsed by esprima): 170 | ``` 171 | npx babel a.txt -o output.js 172 | ``` 173 | 174 | ## License 175 | 176 | The MIT License (MIT) 177 | 178 | Copyright (c) 2022 [0x1Avram](https://github.com/0x1Avram) 179 | 180 | Permission is hereby granted, free of charge, to any person obtaining a copy of this 181 | software and associated documentation files (the "Software"), to deal in the Software 182 | without restriction, including without limitation the rights to use, copy, modify, 183 | merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 184 | permit persons to whom the Software is furnished to do so, subject to the following 185 | conditions: 186 | 187 | The above copyright notice and this permission notice shall be included in all copies 188 | or substantial portions of the Software. 189 | 190 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 191 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 192 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 193 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 194 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 195 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 196 | 197 | -------------------------------------------------------------------------------- /Stages/stage_01_finalizing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const stageDeobfuscator = require('./stage_deobfuscator'); 5 | 6 | 7 | class StageFinalizing extends stageDeobfuscator.StageDeobfuscator{ 8 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 9 | super(logger, obfuscatedSourceCode, ast, argv, stageName); 10 | } 11 | 12 | _initiateTransformers(){ 13 | this.transformers = { 14 | 'FinalizingDirectivePlacementTransformer': FinalizingDirectivePlacementTransformer, 15 | 'FinalizingCustomCodeHelpersTransformer': FinalizingCustomCodeHelpersTransformer, 16 | 'FinalizingCommentsTransformer': FinalizingCommentsTransformer 17 | } 18 | } 19 | } 20 | 21 | 22 | class FinalizingDirectivePlacementTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 23 | constructor(logger, obfuscatedSourceCode, ast, argv){ 24 | super(logger, obfuscatedSourceCode, ast, argv); 25 | } 26 | 27 | deobfuscate(){ 28 | ; 29 | } 30 | } 31 | 32 | 33 | class FinalizingCustomCodeHelpersTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 34 | constructor(logger, obfuscatedSourceCode, ast, argv){ 35 | super(logger, obfuscatedSourceCode, ast, argv); 36 | } 37 | 38 | deobfuscate(){ 39 | ; 40 | } 41 | } 42 | 43 | 44 | class FinalizingCommentsTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 45 | constructor(logger, obfuscatedSourceCode, ast, argv){ 46 | super(logger, obfuscatedSourceCode, ast, argv); 47 | } 48 | 49 | deobfuscate(){ 50 | ; 51 | } 52 | } 53 | 54 | 55 | module.exports = {StageFinalizing}; 56 | -------------------------------------------------------------------------------- /Stages/stage_04_renameidentifiers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const stageDeobfuscator = require('./stage_deobfuscator'); 5 | 6 | 7 | class StageRenameIdentifiers extends stageDeobfuscator.StageDeobfuscator{ 8 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 9 | super(logger, obfuscatedSourceCode, ast, argv, stageName); 10 | } 11 | 12 | _initiateTransformers(){ 13 | this.transformers = { 14 | 'RenameIdentifiersCustomCodeHelpersTransformer': RenameIdentifiersCustomCodeHelpersTransformer, 15 | 'RenameIdentifiersScopeThroughIdentifiersTransformer': RenameIdentifiersScopeThroughIdentifiersTransformer, 16 | 'RenameIdentifiersScopeIdentifiersTransformer': RenameIdentifiersScopeIdentifiersTransformer, 17 | 'RenameIdentifiersLabeledStatementTransformer': RenameIdentifiersLabeledStatementTransformer, 18 | 'RenameIdentifiersVariablePreserveTransformer': RenameIdentifiersVariablePreserveTransformer, 19 | } 20 | } 21 | } 22 | 23 | 24 | class RenameIdentifiersCustomCodeHelpersTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 25 | constructor(logger, obfuscatedSourceCode, ast, argv){ 26 | super(logger, obfuscatedSourceCode, ast, argv); 27 | } 28 | 29 | deobfuscate(){ 30 | ; 31 | } 32 | } 33 | 34 | 35 | class RenameIdentifiersScopeThroughIdentifiersTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 36 | constructor(logger, obfuscatedSourceCode, ast, argv){ 37 | super(logger, obfuscatedSourceCode, ast, argv); 38 | } 39 | 40 | deobfuscate(){ 41 | ; 42 | } 43 | } 44 | 45 | 46 | class RenameIdentifiersScopeIdentifiersTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 47 | constructor(logger, obfuscatedSourceCode, ast, argv){ 48 | super(logger, obfuscatedSourceCode, ast, argv); 49 | } 50 | 51 | deobfuscate(){ 52 | ; 53 | } 54 | } 55 | 56 | 57 | class RenameIdentifiersLabeledStatementTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 58 | constructor(logger, obfuscatedSourceCode, ast, argv){ 59 | super(logger, obfuscatedSourceCode, ast, argv); 60 | } 61 | 62 | deobfuscate(){ 63 | ; 64 | } 65 | } 66 | 67 | 68 | class RenameIdentifiersVariablePreserveTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 69 | constructor(logger, obfuscatedSourceCode, ast, argv){ 70 | super(logger, obfuscatedSourceCode, ast, argv); 71 | } 72 | 73 | deobfuscate(){ 74 | ; 75 | } 76 | } 77 | 78 | 79 | module.exports = {StageRenameIdentifiers}; 80 | -------------------------------------------------------------------------------- /Stages/stage_06_renameproperties.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | "use strict"; 4 | 5 | 6 | const stageDeobfuscator = require('./stage_deobfuscator'); 7 | 8 | 9 | class StageRenameProperties extends stageDeobfuscator.StageDeobfuscator{ 10 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 11 | super(logger, obfuscatedSourceCode, ast, argv, stageName); 12 | } 13 | 14 | _initiateTransformers(){ 15 | this.transformers = { 16 | 'RenamePropertiesRenamePropertiesTransformer': RenamePropertiesRenamePropertiesTransformer, 17 | } 18 | } 19 | } 20 | 21 | 22 | class RenamePropertiesRenamePropertiesTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 23 | constructor(logger, obfuscatedSourceCode, ast, argv){ 24 | super(logger, obfuscatedSourceCode, ast, argv); 25 | } 26 | 27 | deobfuscate(){ 28 | ; 29 | } 30 | } 31 | 32 | 33 | module.exports = {StageRenameProperties}; 34 | -------------------------------------------------------------------------------- /Stages/stage_08_deadcodeinjection.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const esquery = require('esquery'); 5 | const estraverse = require('estraverse'); 6 | const stageDeobfuscator = require('./stage_deobfuscator'); 7 | const astOperations = require('../ast_operations'); 8 | 9 | 10 | class StageDeadCodeInjection extends stageDeobfuscator.StageDeobfuscator{ 11 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 12 | super(logger, obfuscatedSourceCode, ast, argv, stageName); 13 | } 14 | 15 | _initiateTransformers(){ 16 | this.transformers = { 17 | 'DeadCodeInjectionDeadCodeInjectionTransformer': DeadCodeInjectionDeadCodeInjectionTransformer 18 | } 19 | } 20 | } 21 | 22 | 23 | class DeadCodeInjectionDeadCodeInjectionTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 24 | constructor(logger, obfuscatedSourceCode, ast, argv){ 25 | super(logger, obfuscatedSourceCode, ast, argv); 26 | this.nrBlockStatements = 0; 27 | } 28 | 29 | deobfuscate(){ 30 | this.deadCodePropertiesNames = []; 31 | this._deobfuscateNodes(this.ast); 32 | this._removeDeadCodeDanglingDictionaries(); 33 | } 34 | 35 | _deobfuscateNodes(astNodes){ 36 | var thisObj = this; 37 | 38 | if(!Array.isArray(astNodes)){ 39 | astNodes = [astNodes]; 40 | } 41 | 42 | 43 | const totalNr = astNodes.length; 44 | for(let i = 0; i < astNodes.length; i++){ 45 | estraverse.traverse(astNodes[i], { 46 | enter: function(node){ 47 | thisObj.nrBlockStatements++; 48 | if(thisObj.nrBlockStatements % 1000 == 0){ 49 | console.log(`[stage_08][DeadCodeInjectionDeadCodeInjectionTransformer] Deobfuscate nrBlockStatements = ${thisObj.nrBlockStatements}.`); 50 | } 51 | 52 | if(node.type == 'BlockStatement'){ 53 | thisObj._deobfuscateBlockStatementWithDeadCodeInjected(node); 54 | } 55 | }, 56 | }) 57 | } 58 | } 59 | 60 | _deobfuscateBlockStatementWithDeadCodeInjected(node){ 61 | if(!node || (node.type != 'BlockStatement')){ 62 | return; 63 | } 64 | if(!node.body || (node.body.length == 0)){ 65 | return; 66 | } 67 | 68 | for(let i = 0; i < node.body.length; i++){ 69 | let ifStatement = node.body[i]; 70 | 71 | if(!ifStatement || !ifStatement.type || (ifStatement.type != 'IfStatement')){ 72 | continue; 73 | } 74 | if(!ifStatement.test || !ifStatement.consequent || !ifStatement.alternate){ 75 | continue; 76 | } 77 | if(!ifStatement.consequent.body || !ifStatement.alternate.body || 78 | (ifStatement.consequent.body.length == 0) || (ifStatement.alternate.body.length == 0)){ 79 | continue; 80 | } 81 | 82 | if(!this._isTestConditionFoundInIfStatementOfInjectedDeadCode(ifStatement.test)){ 83 | continue; 84 | } 85 | 86 | var bodyWithoutDeadCode = null; 87 | var bodyWithDeadCode = null; 88 | let partRemoved = ''; 89 | if(this._isTestConditionTrue(ifStatement.test)){ 90 | bodyWithoutDeadCode = ifStatement.consequent.body; 91 | bodyWithDeadCode = ifStatement.alternate.body; 92 | partRemoved = 'alternate'; 93 | } 94 | else{ 95 | bodyWithoutDeadCode = ifStatement.alternate.body; 96 | bodyWithDeadCode = ifStatement.consequent.body; 97 | partRemoved = 'consequent'; 98 | } 99 | bodyWithoutDeadCode.parent = node; 100 | this._getDeadCodePropertiesFromMemberExpressions(bodyWithDeadCode); 101 | 102 | astOperations.ASTModifier.insertNodesAfter(ifStatement, bodyWithoutDeadCode, this.logger, this.obfuscatedSourceCode); 103 | this._deobfuscateNodes(bodyWithoutDeadCode); 104 | astOperations.ASTModifier.removeSingleNode(ifStatement, this.logger, this.obfuscatedSourceCode) 105 | } 106 | 107 | } 108 | 109 | _isTestConditionFoundInIfStatementOfInjectedDeadCode(node){ 110 | if(!node || (node.type != 'BinaryExpression')){ 111 | return false; 112 | } 113 | 114 | if(!node.operator || ((node.operator != '===') && (node.operator != '!=='))){ 115 | return false; 116 | } 117 | 118 | if(!node.left || !node.right){ 119 | return false; 120 | } 121 | const left = node.left; 122 | const right = node.right; 123 | if(!left.type || (left.type != 'Literal') || (typeof left.value != 'string')){ 124 | return false; 125 | } 126 | if(!right.type || (right.type != 'Literal') || (typeof right.value != 'string')){ 127 | return false; 128 | } 129 | 130 | return true; 131 | } 132 | 133 | _isTestConditionTrue(node){ 134 | const operator = node.operator; 135 | const leftStr = node.left.value; 136 | const rightStr = node.right.value; 137 | 138 | if(operator == '==='){ 139 | return leftStr == rightStr; 140 | } 141 | else{ 142 | return leftStr != rightStr; 143 | } 144 | } 145 | 146 | _getDeadCodePropertiesFromMemberExpressions(body){ 147 | for(let i = 0; i < body.length; i++){ 148 | const statement = body[i]; 149 | 150 | const memberExpressionNodes = esquery(statement, ` MemberExpression[object.type='Identifier']` 151 | + `[property.type='Identifier']`); 152 | 153 | for(let j = 0; j < memberExpressionNodes.length; j++){ 154 | const memberExpression = memberExpressionNodes[j]; 155 | const propertyName = memberExpression.property.name; 156 | if(!propertyName){ 157 | continue; 158 | } 159 | if(!this.deadCodePropertiesNames.includes(propertyName)){ 160 | this.deadCodePropertiesNames.push(propertyName); 161 | } 162 | } 163 | } 164 | } 165 | 166 | _removeDeadCodeDanglingDictionaries(){ 167 | console.log(`[stage_08][DeadCodeInjectionDeadCodeInjectionTransformer] Dangling remove-START.`); 168 | 169 | let objectExpressionNodes = esquery(this.ast, `VariableDeclaration[declarations.length=1] > VariableDeclarator` 170 | + `[id.type='Identifier'] > ObjectExpression`); 171 | 172 | const totalNrObjectExprNodes = objectExpressionNodes.length; 173 | let nrObjExprNodes = 0; 174 | for(let i = 0; i < objectExpressionNodes.length; i++){ 175 | nrObjExprNodes++; 176 | if((nrObjExprNodes == 1) && (nrObjExprNodes % 100 == 0)){ 177 | console.log(`[stage_08][DeadCodeInjectionDeadCodeInjectionTransformer] Dangling remove ` + 178 | `nrObjExprNodes = ${nrObjExprNodes}/${totalNrObjectExprNodes}.`); 179 | } 180 | 181 | const objectExpression = objectExpressionNodes[i]; 182 | if(!objectExpression.properties){ 183 | continue; 184 | } 185 | 186 | const nrProperties = objectExpression.properties.length; 187 | let propertiesToRemove = []; 188 | 189 | for(let j = 0; j < objectExpression.properties.length; j++){ 190 | let property = objectExpression.properties[j]; 191 | 192 | if(!property || (property.type != 'Property')){ 193 | continue; 194 | } 195 | 196 | if(!property.key || (property.key.type != 'Identifier')){ 197 | continue; 198 | } 199 | 200 | const propertyName = property.key.name; 201 | if(!propertyName){ 202 | continue; 203 | } 204 | if(!this.deadCodePropertiesNames.includes(propertyName)){ 205 | continue; 206 | } 207 | 208 | const objectExpressionLexicalScope = astOperations.ASTRelations.getParentNodeWithLexicalScope( 209 | objectExpression); 210 | const identifiersWithProperty = esquery(objectExpressionLexicalScope, `Identifier[name=${propertyName}]`); 211 | if(identifiersWithProperty.length == 1){ 212 | propertiesToRemove.push(property); 213 | } 214 | } 215 | 216 | if(nrProperties == propertiesToRemove.length){ 217 | const variableDeclaration = objectExpression.parent.parent; 218 | astOperations.ASTModifier.removeSingleNode(variableDeclaration, this.logger, this.obfuscatedSourceCode); 219 | } 220 | else if(propertiesToRemove.length > 0){ 221 | astOperations.ASTModifier.removeMultipleNodesWithSameParent(propertiesToRemove, this.logger, this.obfuscatedSourceCode); 222 | } 223 | } 224 | } 225 | } 226 | 227 | 228 | module.exports = {StageDeadCodeInjection}; 229 | -------------------------------------------------------------------------------- /Stages/stage_10_initializing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const stageDeobfuscator = require('./stage_deobfuscator'); 5 | 6 | 7 | class StageInitializing extends stageDeobfuscator.StageDeobfuscator{ 8 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 9 | super(logger, obfuscatedSourceCode, ast, argv, stageName); 10 | } 11 | 12 | _initiateTransformers(){ 13 | this.transformers = { 14 | 'InitializingCommentsTransformer': InitializingCommentsTransformer, 15 | 'InitializingCustomCodeHelpersTransformer': InitializingCustomCodeHelpersTransformer 16 | } 17 | } 18 | } 19 | 20 | 21 | class InitializingCommentsTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 22 | constructor(logger, obfuscatedSourceCode, ast, argv){ 23 | super(logger, obfuscatedSourceCode, ast, argv); 24 | } 25 | 26 | deobfuscate(){ 27 | ; 28 | } 29 | } 30 | 31 | 32 | class InitializingCustomCodeHelpersTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 33 | constructor(logger, obfuscatedSourceCode, ast, argv){ 34 | super(logger, obfuscatedSourceCode, ast, argv); 35 | } 36 | 37 | deobfuscate(){ 38 | ; 39 | } 40 | } 41 | 42 | 43 | module.exports = {StageInitializing}; 44 | -------------------------------------------------------------------------------- /Stages/stage_11_finishing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const stageDeobfuscator = require('./stage_deobfuscator'); 5 | const stageConverting = require('./stage_05_converting'); 6 | 7 | 8 | class StageFinishing extends stageDeobfuscator.StageDeobfuscator{ 9 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 10 | super(logger, obfuscatedSourceCode, ast, argv, stageName); 11 | } 12 | 13 | _initiateTransformers(){ 14 | this.transformers = { 15 | 'FinishingConvertingNumberToNumericalExpressionTransformer': stageConverting.ConvertingNumberToNumericalExpressionTransformer, 16 | } 17 | } 18 | } 19 | 20 | 21 | module.exports = {StageFinishing}; 22 | -------------------------------------------------------------------------------- /Stages/stage_deobfuscator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const estraverse = require('estraverse'); 5 | const winston = require('winston'); 6 | const astOperations = require('../ast_operations'); 7 | const usefulModule = require('../useful'); 8 | 9 | 10 | class StageDeobfuscator{ 11 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 12 | this.obfuscatedSourceCode = obfuscatedSourceCode; 13 | this.ast = ast; 14 | this.argv = argv; 15 | this.stageName = stageName; 16 | 17 | if(argv.separateloggers){ 18 | this._createSeparateLogger(); 19 | } 20 | else{ 21 | this.logger = logger; 22 | } 23 | 24 | this._initiateTransformers(); 25 | } 26 | 27 | _createSeparateLogger(){ 28 | this.logger = winston.createLogger({ 29 | level: 'info', 30 | format: winston.format.combine( 31 | winston.format.timestamp({format: 'HH:mm:ss'}), 32 | winston.format.simple() 33 | ), 34 | transports: [ 35 | new winston.transports.File({ filename: `debug_${this.stageName}.log`, level: 'debug', options: {flags: 'a'}}), 36 | new winston.transports.Console({ 37 | level: 'info', 38 | format: winston.format.combine( 39 | winston.format.colorize(), 40 | winston.format.simple() 41 | ) 42 | }) 43 | ] 44 | }); 45 | } 46 | 47 | _initiateTransformers(){ 48 | throw `Method '_initiateTransformers' from 'StageDeobfuscator' needs to be overriden.`; 49 | } 50 | 51 | deobfuscate(){ 52 | this._getSourceCodeBeforeDeobfuscation(); 53 | 54 | let i = 0; 55 | const nrTransformers = Object.keys(this.transformers).length; 56 | for (const transformerName in this.transformers){ 57 | const transformerDeobfuscatorObject = this._instantiateTransformerObject(transformerName); 58 | this.logger.info(`[stage_deobfuscator.js] ${i + 1}/${nrTransformers}) Transform '${transformerName}'.`); 59 | console.log(`[stage_deobfuscator.js] ${i + 1}/${nrTransformers}) Transform '${transformerName}'.`); 60 | try{ 61 | this._callDeobfuscationForTransformerObject(transformerDeobfuscatorObject, transformerName); 62 | } 63 | catch(e){ 64 | this.logger.error(`[stage_deobfuscator.js] Deobfuscation error for transform '${transformerName}'. ` + 65 | `error = ${e}. Stack = ${e.stack}`); 66 | console.log(`[stage_deobfuscator.js] Deobfuscation error for transform '${transformerName}'. ` + 67 | `error = ${e}. Stack = ${e.stack}`); 68 | } 69 | i++; 70 | } 71 | 72 | this._displaySourceCodeBeforeAndAfterDeobfuscation(); 73 | } 74 | 75 | _getSourceCodeBeforeDeobfuscation(){ 76 | this.sourceCodeBeforeStage = astOperations.ASTSourceCodeOperations.generateSourceCodeFromAST(this.ast); 77 | } 78 | 79 | _instantiateTransformerObject(transformerName){ 80 | const transformerClass = this.transformers[transformerName]; 81 | return new transformerClass(this.logger, this.obfuscatedSourceCode, this.ast, this.argv); 82 | } 83 | 84 | _callDeobfuscationForTransformerObject(transformerDeobfuscatorObject, transformerName){ 85 | transformerDeobfuscatorObject.deobfuscate(); 86 | transformerDeobfuscatorObject.displaySourceCodeBeforeAndAfterTransformation(transformerName); 87 | } 88 | 89 | _displaySourceCodeBeforeAndAfterDeobfuscation(){ 90 | const sourceCodeAfterStage = astOperations.ASTSourceCodeOperations.generateSourceCodeFromAST(this.ast); 91 | if(sourceCodeAfterStage == this.sourceCodeBeforeStage){ 92 | this.logger.debug(`Stage ${this.stageName} does not modify contents.`); 93 | return; 94 | } 95 | this.logger.debug(`${'-'.repeat(100)}\nStage ${this.stageName}:\n` 96 | + `Before stage (${this.stageName}):\n${this.sourceCodeBeforeStage}\n` 97 | + `After stage (${this.stageName}):\n${sourceCodeAfterStage}\n` 98 | + `${'-'.repeat(100)}`); 99 | } 100 | } 101 | 102 | 103 | class TransformerDeobfuscator{ 104 | constructor(logger, obfuscatedSourceCode, ast, argv){ 105 | this.logger = logger; 106 | this.obfuscatedSourceCode = obfuscatedSourceCode; 107 | this.ast = ast; 108 | this.argv = argv; 109 | this._getSourceCodeBeforeTransformation(); 110 | } 111 | 112 | static transformNamesToSkipFromDisplaying = [ 113 | 'FinalizingDirectivePlacementTransformer', 114 | 'FinalizingCustomCodeHelpersTransformer', 115 | 'FinalizingCommentsTransformer', 116 | 'SimplifyingCustomCodeHelpersTransformer', 117 | 'RenameIdentifiersCustomCodeHelpersTransformer', 118 | 'RenameIdentifiersScopeThroughIdentifiersTransformer', 119 | 'RenameIdentifiersScopeIdentifiersTransformer', 120 | 'RenameIdentifiersLabeledStatementTransformer', 121 | 'RenameIdentifiersVariablePreserveTransformer', 122 | 'ConvertingNumberLiteralTransformer', 123 | 'ConvertingCustomCodeHelpersTransformer', 124 | 'ConvertingTemplateLiteralTransformer', 125 | 'ConvertingExportSpecifierTransformer', 126 | 'ConvertingVariablePreserveTransformer', 127 | 'RenamePropertiesRenamePropertiesTransformer', 128 | 'ControlFlowFlatteningCustomCodeHelpersTransformer', 129 | 'PreparingParentificationTransformer', 130 | 'PreparingRenamePropertiesTransformer', 131 | 'PreparingVariablePreserveTransformer', 132 | //'PreparingCustomCodeHelpersTransformer', 133 | 'PreparingEvalCallExpressionTransformer', 134 | 'PreparingMetadataTransformer', 135 | 'PreparingObfuscatingGuardsTransformer', 136 | 'PreparingDirectivePlacementTransformer', 137 | 'InitializingCommentsTransformer', 138 | 'InitializingCustomCodeHelpersTransformer' 139 | ]; 140 | 141 | _getSourceCodeBeforeTransformation(){ 142 | this.sourceCodeBeforeTransformation = astOperations.ASTSourceCodeOperations.generateSourceCodeFromAST(this.ast); 143 | } 144 | 145 | deobfuscate(){ 146 | throw `Method 'deobfuscate' from 'TransformerDeobfuscator' needs to be overriden.`; 147 | } 148 | 149 | displaySourceCodeBeforeAndAfterTransformation(transformName){ 150 | if(this.argv.debug){ 151 | this._checkForMissingParentsInAST(transformName); 152 | } 153 | 154 | if(TransformerDeobfuscator.transformNamesToSkipFromDisplaying.includes(transformName)){ 155 | this.logger.debug(`Not displaying before&after transformation for ${transformName} because ` 156 | + `this transform does not modify the ast.`); 157 | return; 158 | } 159 | 160 | const sourceCodeAfterTransformation = astOperations.ASTSourceCodeOperations.generateSourceCodeFromAST(this.ast); 161 | if(sourceCodeAfterTransformation == this.sourceCodeBeforeTransformation){ 162 | this.logger.debug(`Transformation ${transformName} does not modify contents.`); 163 | return; 164 | } 165 | 166 | this._writeTransformationDiffFiles(transformName, sourceCodeAfterTransformation); 167 | } 168 | 169 | _checkForMissingParentsInAST(transformName){ 170 | let foundMissingParent = false; 171 | 172 | estraverse.traverse(this.ast, { 173 | enter: function(node, parent){ 174 | if(!node.parent){ 175 | foundMissingParent = true; 176 | this.break(); 177 | } 178 | } 179 | }); 180 | 181 | if(foundMissingParent){ 182 | this.logger.warn(`Missing parent after transformation '${transformName}.'`); 183 | } 184 | else{ 185 | this.logger.debug(`All parents are present for transformation '${transformName}.'`); 186 | } 187 | } 188 | 189 | _writeTransformationDiffFiles(transformName, sourceCodeAfterTransformation){ 190 | this.logger.debug(`${'&'.repeat(100)}\nTransformation ${transformName}:\n` + 191 | `Before transformation (${transformName}):\n${this.sourceCodeBeforeTransformation}\n` + 192 | `After transformation (${transformName}):\n${sourceCodeAfterTransformation}\n` + 193 | `${'&'.repeat(100)}`); 194 | 195 | if(this.argv.writedifffiles){ 196 | const fileName = `transform_${("0" + this.argv.transformNumber).slice(-2)}_${transformName}`; 197 | usefulModule.writeTextFile(`${fileName}.in`, this.sourceCodeBeforeTransformation); 198 | usefulModule.writeTextFile(`${fileName}.out`, sourceCodeAfterTransformation); 199 | this.argv.transformNumber++; 200 | } 201 | } 202 | } 203 | 204 | 205 | module.exports = {StageDeobfuscator, TransformerDeobfuscator}; -------------------------------------------------------------------------------- /deobfuscator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const estraverse = require('estraverse'); 5 | const astOperations = require('./ast_operations'); 6 | const usefulModule = require('./useful'); 7 | const stageDeobfuscator = require('./Stages/stage_deobfuscator'); 8 | const stageFinalizing = require('./Stages/stage_01_finalizing'); 9 | const stageSimplifying = require('./Stages/stage_02_simplifying'); 10 | const stageStringArray = require('./Stages/stage_03_stringarray'); 11 | const stageRenameIdentifiers = require('./Stages/stage_04_renameidentifiers'); 12 | const stageConverting = require('./Stages/stage_05_converting'); 13 | const stageRenameProperties = require('./Stages/stage_06_renameproperties'); 14 | const stageControlFlowFlattening = require('./Stages/stage_07_controlflowflattening'); 15 | const stageDeadCodeInjection = require('./Stages/stage_08_deadcodeinjection'); 16 | const stagePreparing = require('./Stages/stage_09_preparing'); 17 | const stageInitializing = require('./Stages/stage_10_initializing'); 18 | const stageFinishing = require('./Stages/stage_11_finishing'); 19 | 20 | 21 | class SourceCodeDeobfuscator{ 22 | constructor(logger, obfuscatedSourceCode, argv, currentCallIsFromEmbeddedEval=false){ 23 | this.logger = logger; 24 | this.obfuscatedSourceCode = obfuscatedSourceCode; 25 | this.argv = argv; 26 | this.currentCallIsFromEmbeddedEval = currentCallIsFromEmbeddedEval; 27 | } 28 | 29 | deobfuscate(){ 30 | try{ 31 | this._generateASTFromObfuscatedSourceCode(); 32 | } 33 | catch(e){ 34 | this.logger.error(`[deobfuscator.js] Error when transforming the input source code to AST.` 35 | + ` This is an 'esprima' parser limitation and the code needs to be` 36 | + ` transpiled to an esprima compatible version before passing it to` 37 | + ` the deobfuscator. error = ${e}. Stack = ${e.stack}`); 38 | return ''; 39 | } 40 | this._deobfuscateAST(); 41 | this._generateSourceCodeFromDeobfuscatedAST(); 42 | return this.deobfuscatedSourceCode; 43 | } 44 | 45 | _generateASTFromObfuscatedSourceCode(){ 46 | this.logger.info('[deobfuscator.js] Generating AST from obfuscated source code.'); 47 | this.ast = astOperations.ASTSourceCodeOperations.generateASTFromSourceCode(this.obfuscatedSourceCode); 48 | } 49 | 50 | _deobfuscateAST(){ 51 | this.logger.info('[deobfuscator.js] Deobfuscating AST.'); 52 | const astDeobfuscator = new ASTDeobfuscator(this.logger, this.obfuscatedSourceCode, this.ast, 53 | this.argv, this.currentCallIsFromEmbeddedEval); 54 | astDeobfuscator.deobfuscate(); 55 | } 56 | 57 | _generateSourceCodeFromDeobfuscatedAST(){ 58 | this.logger.info('[deobfuscator.js] Generating source code from deobfuscated AST.'); 59 | this.deobfuscatedSourceCode = astOperations.ASTSourceCodeOperations.generateSourceCodeFromAST(this.ast); 60 | } 61 | } 62 | 63 | 64 | class StageFinalizingEmbeddedEval extends stageDeobfuscator.StageDeobfuscator{ 65 | constructor(logger, obfuscatedSourceCode, ast, argv, stageName){ 66 | super(logger, obfuscatedSourceCode, ast, argv, stageName); 67 | } 68 | 69 | _initiateTransformers(){ 70 | this.transformers = { 71 | 'FinalizingEvalCallExpressionTransformer': FinalizingEvalCallExpressionTransformer, 72 | 'FinalizingEscapeSequenceTransformer': FinalizingEscapeSequenceTransformer, 73 | } 74 | } 75 | 76 | deobfuscate(currentCallIsFromEmbeddedEval=false){ 77 | this._getSourceCodeBeforeDeobfuscation(); 78 | 79 | let i = 0; 80 | const nrTransformers = Object.keys(this.transformers).length; 81 | for (const transformerName in this.transformers){ 82 | const transformerDeobfuscatorObject = this._instantiateTransformerObject(transformerName); 83 | this.logger.info(`[deobfuscator.js] ${i + 1}/${nrTransformers}) Transform '${transformerName}'.`); 84 | try{ 85 | this._callDeobfuscationForTransformerObject(transformerDeobfuscatorObject, transformerName, 86 | currentCallIsFromEmbeddedEval); 87 | } 88 | catch(e){ 89 | this.logger.error(`[deobfuscator.js] Deobfuscation error for eval-transform '${transformerName}'. ` + 90 | `error = ${e}. Stack = ${e.stack}`); 91 | } 92 | } 93 | 94 | this._displaySourceCodeBeforeAndAfterDeobfuscation(); 95 | } 96 | 97 | _callDeobfuscationForTransformerObject(transformerDeobfuscatorObject, transformerName, currentCallIsFromEmbeddedEval){ 98 | transformerDeobfuscatorObject.deobfuscate(currentCallIsFromEmbeddedEval); 99 | transformerDeobfuscatorObject.displaySourceCodeBeforeAndAfterTransformation(transformerName); 100 | } 101 | } 102 | 103 | 104 | class FinalizingEvalCallExpressionTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 105 | constructor(logger, obfuscatedSourceCode, ast, argv){ 106 | super(logger, obfuscatedSourceCode, ast, argv); 107 | } 108 | 109 | deobfuscate(currentCallIsFromEmbeddedEval=false){ 110 | if(currentCallIsFromEmbeddedEval){ 111 | return; 112 | } 113 | var thisObj = this; 114 | estraverse.replace(this.ast, { 115 | enter: function (node) { 116 | if(thisObj._nodeIsEvalWithString(node)){ 117 | return thisObj._deobfuscateEvalledString(node); 118 | } 119 | } 120 | }); 121 | } 122 | 123 | _nodeIsEvalWithString(node){ 124 | if(node && node.type == 'CallExpression' && (node.callee.type == 'Identifier') 125 | && (node.callee.name == 'eval') && (node.arguments.length == 1) 126 | && (node.arguments[0].type == 'Literal') && (typeof node.arguments[0].value == 'string')){ 127 | return true; 128 | } 129 | return false; 130 | } 131 | 132 | _deobfuscateEvalledString(node){ 133 | const evalledString = node.arguments[0].value; 134 | const evalContentsDeobfuscator = new SourceCodeDeobfuscator(this.logger, evalledString, this.argv, true); 135 | 136 | this.logger.info(`${'$'.repeat(150)}\nSTART - deobfuscating contents of eval string: ${evalledString}`); 137 | const deobfuscatedEvalString = evalContentsDeobfuscator.deobfuscate(); 138 | this.logger.info(`${'$'.repeat(150)}\nFINISH - deobfuscating contents of eval string.`); 139 | 140 | return this._createNewEvalNode(node, deobfuscatedEvalString); 141 | } 142 | 143 | _createNewEvalNode(oldNode, deobfuscatedEvalString){ 144 | const newNode = { 145 | type: 'CallExpression', 146 | callee: {type: 'Identifier', name: 'eval'}, 147 | arguments: [{type: 'Literal', value: deobfuscatedEvalString}], 148 | parent: oldNode.parent 149 | }; 150 | astOperations.ASTRelations.addParentsToASTNodesExcludingRoot(newNode); 151 | 152 | astOperations.ASTModifier.logDebugEstraverseReplace(oldNode, newNode, this.logger, this.obfuscatedSourceCode); 153 | 154 | return newNode; 155 | } 156 | } 157 | 158 | 159 | class FinalizingEscapeSequenceTransformer extends stageDeobfuscator.TransformerDeobfuscator{ 160 | constructor(logger, obfuscatedSourceCode, ast, argv){ 161 | super(logger, obfuscatedSourceCode, ast, argv); 162 | } 163 | 164 | deobfuscate(currentCallIsFromEmbeddedEval=false){ 165 | if(!currentCallIsFromEmbeddedEval){ 166 | return; 167 | } 168 | var thisObj = this; 169 | 170 | estraverse.replace(this.ast, { 171 | enter: function(node){ 172 | if(thisObj._nodeIsDoubleEscapedString(node)){ 173 | return thisObj._createNewUnescapedStringNode(node); 174 | } 175 | } 176 | }); 177 | } 178 | 179 | _nodeIsDoubleEscapedString(node){ 180 | return (node.type == 'Literal') && (typeof node.value == 'string') 181 | && usefulModule.StringOperations.strContainsOnlyDoubleEscapedChars(node.value) 182 | } 183 | 184 | _createNewUnescapedStringNode(oldNode){ 185 | this.logger.debug(`[EVAL][EscapedString] ${oldNode.value}`); 186 | const newNode = { 187 | type: 'Literal', 188 | value: usefulModule.StringOperations.unescapeStrWithDoubleEscapedChars(oldNode.value), 189 | parent: oldNode.parent 190 | }; 191 | 192 | astOperations.ASTModifier.logDebugEstraverseReplace(oldNode, newNode, this.logger, this.obfuscatedSourceCode); 193 | 194 | return newNode; 195 | } 196 | } 197 | 198 | 199 | class ASTDeobfuscator{ 200 | constructor(logger, obfuscatedSourceCode, ast, argv, currentCallIsFromEmbeddedEval){ 201 | this.logger = logger; 202 | this.obfuscatedSourceCode = obfuscatedSourceCode; 203 | this.ast = ast; 204 | this.argv = argv; 205 | this.currentCallIsFromEmbeddedEval = currentCallIsFromEmbeddedEval; 206 | } 207 | 208 | static DeobfuscateStageClasses = { 209 | 'StringArray': stageStringArray.StringArrayStageDeobfuscator, 210 | 'EmbeddedEval': StageFinalizingEmbeddedEval, 211 | 'Finalizing': stageFinalizing.StageFinalizing, 212 | 'Simplifying': stageSimplifying.StageSimplifying, 213 | 'RenameIdentifiers': stageRenameIdentifiers.StageRenameIdentifiers, 214 | 'Converting': stageConverting.StageConverting, 215 | 'RenameProperties': stageRenameProperties.StageRenameProperties, 216 | 'ControlFlowFlattening': stageControlFlowFlattening.StageControlFlowFlattening, 217 | 'DeadCodeInjection': stageDeadCodeInjection.StageDeadCodeInjection, 218 | 'Preparing': stagePreparing.StagePreparing, 219 | 'Initializing': stageInitializing.StageInitializing, 220 | 'Finishing': stageFinishing.StageFinishing 221 | } 222 | 223 | deobfuscate(){ 224 | let i = 0; 225 | const nrStages = Object.keys(ASTDeobfuscator.DeobfuscateStageClasses).length; 226 | 227 | for (const stageName in ASTDeobfuscator.DeobfuscateStageClasses){ 228 | const stageDeobfuscatorObject = this._instantiateStageObject(stageName); 229 | 230 | this.logger.info(`[deobfuscator.js] ${i + 1}/${nrStages}) Deobfuscating stage '${stageName}'.`); 231 | console.log(`[deobfuscator.js] ${i + 1}/${nrStages}) Deobfuscating stage '${stageName}'.`); 232 | try{ 233 | this._callDeobfuscationForStageObject(stageDeobfuscatorObject, stageName); 234 | } 235 | catch(e){ 236 | this.logger.error(`[deobfuscator.js] Deobfuscation error for stage '${stageName}'. ` + 237 | `error = ${e}. Stack = ${e.stack}`); 238 | } 239 | i++; 240 | } 241 | } 242 | 243 | _instantiateStageObject(stageName){ 244 | const stageDeobfuscatorClass = ASTDeobfuscator.DeobfuscateStageClasses[stageName]; 245 | return new stageDeobfuscatorClass(this.logger, this.obfuscatedSourceCode, this.ast, this.argv, stageName); 246 | } 247 | 248 | _callDeobfuscationForStageObject(stageDeobfuscatorObj, stageName){ 249 | if(stageName == 'EmbeddedEval'){ 250 | stageDeobfuscatorObj.deobfuscate(this.currentCallIsFromEmbeddedEval); 251 | } 252 | else{ 253 | stageDeobfuscatorObj.deobfuscate(); 254 | } 255 | } 256 | } 257 | 258 | 259 | module.exports = {SourceCodeDeobfuscator}; 260 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const winston = require('winston'); 5 | const yargs = require('yargs'); 6 | const fs = require('fs'); 7 | const deobfuscatorModule = require('./deobfuscator'); 8 | const usefulModule = require('./useful'); 9 | 10 | 11 | 12 | 13 | Error.stackTraceLimit = Infinity; 14 | 15 | 16 | function parseCommandLineArgs(){ 17 | const argv = yargs 18 | .usage('Usage: program [options]') 19 | .example('-s stringarray.txt -w stringarraywrappers.txt -n _0x471d,_0x9cad,_0x4cd9 ' 20 | + '-r stringarrayrotate.txt -i obfuscated.txt -o output.txt') 21 | .example('-i obfuscated.txt -o deobfuscated.txt') 22 | .option('inputPath', { 23 | alias: 'i', 24 | description: 'Path of input (obfuscated) file.', 25 | type: 'string', 26 | default: 'input.txt' 27 | }) 28 | .option('outputPath', { 29 | alias: 'o', 30 | description: 'Path where the output (deobfuscated) file is stored.', 31 | type: 'string', 32 | default: 'output.txt' 33 | }) 34 | .option('debug', { 35 | alias: 'd', 36 | description: 'Display debug log messages (for large input files, debug log might be large).', 37 | type: 'boolean', 38 | default: false 39 | }) 40 | .option('debugall', { 41 | alias: 'a', 42 | description: 'Display all AST operations for debugging. The \'debug\' option needs to be set ' 43 | + 'for this to work.', 44 | type: 'boolean', 45 | default: false 46 | }) 47 | .option('separateloggers', { 48 | alias: 'l', 49 | description: 'Use a separate logger for each deobfuscation stage. This will lead to the creation of a ' 50 | + 'debug log file for each deobfuscation stage (11 stages). This is useful so that instead of a single ' 51 | + 'huge debug log file, several smaller ones are created (one per each stage). The \'debug\' option ' 52 | + 'needs to be set for this to work.', 53 | type: 'boolean', 54 | default: false 55 | }) 56 | .option('writedifffiles', { 57 | alias: 'f', 58 | description: 'Write before&after files for each transformation modifying the source code' 59 | + '(used for debugging). The files are written in the working directory of the script.', 60 | type: 'boolean', 61 | default: false 62 | }) 63 | .option('stringarray', { 64 | alias: 's', 65 | description: '[StringArray] The path at which the code for the string array is found' 66 | + '(can be just an array or a function containing the array).', 67 | type: 'string', 68 | default: '' 69 | }) 70 | .option('stringarraywrappers', { 71 | alias: 'w', 72 | description: '[StringArray] The path at which the code for the string wrappers is found' 73 | + '(there can be multiple wrappers depending on the \'string-array-encoding\' obfuscation option) ' 74 | + '(the wrappers can contain the self defending code).', 75 | type: 'string', 76 | default: '' 77 | }) 78 | .option('stringarraywrappernames', { 79 | alias: 'n', 80 | description: '[StringArray] The names of the string array wrapper functions in a comma separated string ' 81 | + 'without spaces. (these are the functions from the code indicated by the \'stringarraywrappers\' path).', 82 | type: 'string', 83 | default: '' 84 | }) 85 | .option('stringarrayrotate', { 86 | alias: 'r', 87 | desscription: '[StringArray] The path at which the code for the string array rotate function ' 88 | + 'is found. (This is optional as it is not mandatory for the stringarray rotate option to be used ' 89 | + 'when obfuscating.)', 90 | type: 'string', 91 | default: '' 92 | }) 93 | .option('cleanuplog', { 94 | alias: 'c', 95 | desscription: 'The log files are created by appending to existing ones. This option deletes the existing ' 96 | + 'log files before deobfuscation so that \'fresh\' logs without information from other deobfuscation ' 97 | + 'runs are created.', 98 | type: 'boolean', 99 | default: false 100 | }) 101 | .help() 102 | .alias('help', 'h').argv; 103 | 104 | if(argv.writedifffiles){ 105 | argv.transformNumber = 1; 106 | argv.replacerNumber = 1; 107 | } 108 | 109 | _validateCommandLineArgs(argv); 110 | _extractStringArraySpecificCmdLineNodesInfo(argv); 111 | _setGlobalVariablesRelatedToCmdLine(argv); 112 | 113 | return argv; 114 | } 115 | 116 | function _validateCommandLineArgs(argv){ 117 | _validateStringArrayCommandLineArgs(argv); 118 | _validateDebugCommandLineArgs(argv); 119 | } 120 | 121 | function _validateStringArrayCommandLineArgs(argv){ 122 | if((argv.stringarray != '') || (argv.stringarraywrappers != '') 123 | || (argv.stringarraywrappernames != '') || (argv.stringarrayrotate != '')){ 124 | if((argv.stringarray == '') || (argv.stringarraywrappers == '') || (argv.stringarraywrappernames == '')){ 125 | console.log('Invalid command line usage. If any of the \'[StringArray]\' non-optional command line ' 126 | + 'arguments is useed, the rest of the non-optional \'[StringArray]\' arguments need to be used' 127 | + 'as well.'); 128 | process.exit(1); 129 | } 130 | } 131 | } 132 | 133 | function _validateDebugCommandLineArgs(argv){ 134 | if(!argv.debug){ 135 | argv.debugall = false; 136 | argv.separateloggers = false; 137 | } 138 | } 139 | 140 | function _extractStringArraySpecificCmdLineNodesInfo(argv){ 141 | argv.stringArrayCmdLineSpecificNodesInfo = null; 142 | 143 | if(argv.stringarray == ''){ 144 | return; 145 | } 146 | 147 | argv.stringArrayCmdLineSpecificNodesInfo = { 148 | stringArrayTemplateCode: _readCodeForStringArrayCmdLineSpecificInfo(argv.stringarray), 149 | stringArrayWrapperTemplates: _readCodeForStringArrayCmdLineSpecificInfo(argv.stringarraywrappers), 150 | stringArrayWrapperNames: argv.stringarraywrappernames.split(','), 151 | stringArrayRotate: ((argv.stringarrayrotate != '') ? readTextFile(argv.stringarrayrotate) : null) 152 | }; 153 | 154 | } 155 | 156 | function _readCodeForStringArrayCmdLineSpecificInfo(path){ 157 | let code = readTextFile(path); 158 | if(code.startsWith('const')){ 159 | code = `var ${code.substring(6)}`; 160 | } 161 | return code; 162 | } 163 | 164 | function _setGlobalVariablesRelatedToCmdLine(argv){ 165 | global.global_createDebugLogEachOperation = false; 166 | if(argv.debugall){ 167 | global.global_createDebugLogEachOperation = true; 168 | } 169 | } 170 | 171 | 172 | function createLogger(createDebugLog){ 173 | const logger = winston.createLogger({ 174 | level: 'info', 175 | format: winston.format.combine( 176 | winston.format.timestamp({format: 'HH:mm:ss'}), 177 | winston.format.simple() 178 | ), 179 | transports: [ 180 | new winston.transports.File({ filename: 'warn.log', level: 'warn', options: {flags: 'a'}}), 181 | new winston.transports.File({ filename: 'info.log', level: 'info', options: {flags: 'a'}}), 182 | new winston.transports.Console({ 183 | level: 'info', 184 | format: winston.format.combine( 185 | winston.format.colorize(), 186 | winston.format.simple() 187 | ) 188 | }) 189 | ] 190 | }); 191 | 192 | if(createDebugLog){ 193 | logger.add(new winston.transports.File({ filename: 'debug.log', level: 'debug', options: {flags: 'w'}})); 194 | } 195 | 196 | return logger; 197 | } 198 | 199 | 200 | function cleanupLogFiles(logger){ 201 | const logFileNames = ['debug.log', 'debug_ControlFlowFlattening.log', 'debug_Converting.log', 202 | 'debug_DeadCodeInjection.log', 'debug_EmbeddedEval.log', 'debug_Finalizing.log', 203 | 'debug_Finishing.log', 'debug_Initializing.log', 'debug_Preparing.log', 204 | 'debug_RenameIdentifiers.log', 'debug_RenameProperties.log', 'debug_Simplifying.log', 205 | 'debug_StringArray.log', 'info.log', 'warn.log']; 206 | for(let i = 0; i < logFileNames.length; i++){ 207 | const fileName = logFileNames[i]; 208 | try{ 209 | fs.unlinkSync(fileName); 210 | } 211 | catch(e){ 212 | if(e.toString().includes('no such file or directory')){ 213 | logger.warn(`[index.js] Could not delete log file with name = '${fileName}' as it does not exist.`); 214 | } 215 | else{ 216 | logger.warn(`[index.js] Could not delete log file with name = '${fileName}'. error = ${e}. ` 217 | + `Stack = \n${e.stack}`); 218 | } 219 | } 220 | } 221 | } 222 | 223 | 224 | function readTextFile(path){ 225 | return fs.readFileSync(path).toString(); 226 | } 227 | 228 | 229 | function main(){ 230 | const argv = parseCommandLineArgs(); 231 | const logger = createLogger(argv.debug); 232 | if(argv.cleanuplog){ 233 | cleanupLogFiles(logger); 234 | } 235 | 236 | logger.info(`[index.js] Starting deobfuscation process for file ${argv.inputPath}.`); 237 | 238 | const obfuscatedSourceCode = readTextFile(argv.inputPath); 239 | logger.debug(`[index.js] Obfuscated source code: \n${obfuscatedSourceCode}`); 240 | 241 | let deobfuscatedSourceCode = null; 242 | const myDeobfuscator = new deobfuscatorModule.SourceCodeDeobfuscator(logger, obfuscatedSourceCode, argv); 243 | try{ 244 | deobfuscatedSourceCode = myDeobfuscator.deobfuscate(); 245 | } 246 | catch(e){ 247 | logger.error(`[index.js] Deobfuscation error in main function. error = ${e}. Stack = \n${e.stack}`); 248 | } 249 | 250 | usefulModule.writeTextFile(argv.outputPath, deobfuscatedSourceCode); 251 | logger.debug(`[index.js] Deobfuscated source code: \n${deobfuscatedSourceCode}`); 252 | 253 | logger.info('[index.js] Finished deobfuscation process.'); 254 | } 255 | 256 | main(); 257 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-deobfuscator", 3 | "version": "1.0.2", 4 | "description": "Deobfuscator for javascript samples obfuscated by obfuscator.io.", 5 | "keywords": [ 6 | "deobfuscation", 7 | "deobfuscator", 8 | "deobfuscate", 9 | "obfuscation", 10 | "obfuscator", 11 | "obfuscate", 12 | "unpack", 13 | "unpacker", 14 | "javascript" 15 | ], 16 | "main": "index.js", 17 | "scripts": { 18 | "test": "echo \"Error: no test specified\" && exit 1" 19 | }, 20 | "author": "0x1Avram", 21 | "license": "MIT", 22 | "repository": { 23 | "type": "git", 24 | "url": "https://github.com/0x1Avram/js-deobfuscator.git" 25 | }, 26 | "dependencies": { 27 | "escodegen": "^2.0.0", 28 | "esprima": "^4.0.1", 29 | "esquery": "^1.4.0", 30 | "estraverse": "^5.3.0", 31 | "winston": "^3.8.1", 32 | "yargs": "^17.5.1" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /useful.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | 4 | const fs = require('fs'); 5 | 6 | 7 | class StringOperations{ 8 | static strContainsOnlyDoubleEscapedChars(strToCheck){ 9 | if(strToCheck.match(/(?:\\x[0-9a-fA-F][0-9a-fA-F])+/)){ 10 | const allEscapedCharMatches = [...strToCheck.matchAll(/\\x([0-9a-fA-F][0-9a-fA-F])/g)]; 11 | allEscapedCharMatches.forEach((escapedCharMatchStr) => { 12 | const asciiCode = Number(`0x${escapedCharMatchStr}`); 13 | if(asciiCode > 0x7F){ 14 | return false; 15 | } 16 | }); 17 | return true; 18 | } 19 | return false; 20 | } 21 | 22 | static unescapeStrWithDoubleEscapedChars(strToParse){ 23 | return eval(`"${strToParse}"`); 24 | } 25 | 26 | static isValidIdentifierName(strToCheck){ 27 | if(strToCheck.length == 0){ 28 | return false; 29 | } 30 | 31 | const firstChar = strToCheck[0]; 32 | if((firstChar.toLowerCase() == firstChar.toUpperCase()) && (firstChar != '$') && (firstChar != '_')){ 33 | return false; 34 | } 35 | 36 | if(strToCheck.indexOf('-') != -1){ 37 | return false; 38 | } 39 | 40 | return true; 41 | } 42 | } 43 | 44 | 45 | class NumberOperations{ 46 | static numberIsFloat(nr){ 47 | return nr.toString().indexOf('.') != -1; 48 | } 49 | } 50 | 51 | function writeTextFile(path, content){ 52 | fs.writeFileSync(path, content, {flag: 'w'}); 53 | } 54 | 55 | 56 | 57 | module.exports = { 58 | StringOperations, 59 | NumberOperations, 60 | writeTextFile 61 | }; 62 | --------------------------------------------------------------------------------