├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .vercelignore
├── README.md
├── babel.config.js
├── components
├── form.js
├── header.js
├── layout.js
└── output.js
├── lib
└── javascriptobfuscator_unpacker.js
├── modules
└── hooks
│ ├── use-clipboard.js
│ ├── use-event-listener.js
│ └── use-key-press.js
├── next.config.js
├── package-lock.json
├── package.json
├── pages
├── _app.js
└── index.js
├── public
├── card.png
├── favicon.ico
├── favicon.png
├── lib
│ └── jsdec.js
├── manifest.json
├── touch-icon-512x512.png
└── touch-icon.png
├── styles
├── global.css
└── reset.css
└── webpack.config.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | lib/*
2 | public/*
3 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es2020: true,
5 | },
6 | extends: [
7 | 'airbnb-base',
8 | 'plugin:react/recommended',
9 | 'plugin:react-hooks/recommended',
10 | ],
11 | parserOptions: {
12 | ecmaFeatures: {
13 | jsx: true,
14 | },
15 | ecmaVersion: 11,
16 | sourceType: 'module',
17 | },
18 | plugins: ['react'],
19 | rules: {
20 | 'react/react-in-jsx-scope': 'off',
21 | 'react/jsx-filename-extension': 'off',
22 | 'react/prop-types': 'off',
23 | },
24 | settings: {
25 | react: {
26 | version: 'detect',
27 | },
28 | 'import/resolver': {
29 | webpack: {
30 | config: require('./webpack.config'),
31 | },
32 | },
33 | 'import/core-modules': ['fs', 'path'],
34 | },
35 | };
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | .env*
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
--------------------------------------------------------------------------------
/.vercelignore:
--------------------------------------------------------------------------------
1 | README.md
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | ```
12 |
13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
14 |
15 | You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file.
16 |
17 | ## Learn More
18 |
19 | To learn more about Next.js, take a look at the following resources:
20 |
21 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
22 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
23 |
24 | You can check out [the Next.js GitHub repository](https://github.com/zeit/next.js/) - your feedback and contributions are welcome!
25 |
26 | ## Deploy on ZEIT Now
27 |
28 | The easiest way to deploy your Next.js app is to use the [ZEIT Now Platform](https://zeit.co/import?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
29 |
30 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
31 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [
4 | 'next/babel',
5 | {
6 | 'preset-env': {
7 | targets: {
8 | chrome: '58',
9 | },
10 | },
11 | },
12 | ],
13 | ],
14 | };
15 |
--------------------------------------------------------------------------------
/components/form.js:
--------------------------------------------------------------------------------
1 | import {
2 | useState, useEffect, useRef,
3 | } from 'react';
4 | import useKeyPress from '@/modules/hooks/use-key-press';
5 | import JavascriptObfuscator from '@/lib/javascriptobfuscator_unpacker';
6 |
7 | const TYPES_MAPPING = {
8 | Auto: process.browser && window.autoscan,
9 | Eval: process.browser && window.uneval,
10 | 'jsjiami/Obfuscator': process.browser && window.obdec_default,
11 | 'sojson v5': process.browser && window.dec_sojsonv5_default,
12 | 'sojson v4': process.browser && window.decsojson4,
13 | 'sojson 高级版': process.browser && window.decsojsonp,
14 | 'JS Beautifier': process.browser && JavascriptObfuscator.unpack,
15 | };
16 |
17 | export default function Form({ onChange }) {
18 | const textareaRef = useRef();
19 | const [formData, setFormData] = useState({
20 | content: '',
21 | type: 'Auto',
22 | });
23 |
24 | const handleSubmit = (event) => {
25 | event?.preventDefault();
26 | const fn = TYPES_MAPPING[formData.type];
27 | let result;
28 | try {
29 | result = fn(formData.content);
30 | } catch (error) {
31 | result = `Failed!\n${error}`;
32 | }
33 | onChange(result);
34 | };
35 |
36 | useEffect(() => {
37 | handleSubmit();
38 | }, [formData.content, formData.type]);
39 |
40 | useKeyPress(textareaRef.current, 'enter', (event) => {
41 | if (event.metaKey || event.ctrlKey) handleSubmit();
42 | });
43 |
44 | const handleChange = (event) => {
45 | setFormData((prevData) => ({
46 | ...prevData,
47 | [event.target.name]: event.target.value,
48 | }));
49 | };
50 |
51 | const handleClear = () => {
52 | setFormData((prevData) => ({
53 | ...prevData,
54 | content: '',
55 | }));
56 | onChange('');
57 | };
58 |
59 | return (
60 |
159 | );
160 | }
161 |
--------------------------------------------------------------------------------
/components/header.js:
--------------------------------------------------------------------------------
1 | export default function Header() {
2 | return (
3 |
4 | de4js
5 | JavaScript Deobfuscator and Unpacker
6 |
28 |
58 |
59 | );
60 | }
61 |
--------------------------------------------------------------------------------
/components/layout.js:
--------------------------------------------------------------------------------
1 | import NextHead from 'next/head';
2 |
3 | export default function Layout({
4 | children,
5 | title = 'de4js - JavaScript Deobfuscator',
6 | description = 'JavaScript Deobfuscator and Unpacker',
7 | url = 'https://de4js.kshift.me',
8 | image = 'https://de4js.kshift.me/card.png',
9 | }) {
10 | return (
11 | <>
12 |
13 |
14 | {title}
15 |
16 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {children}
38 |
45 | >
46 | );
47 | }
48 |
--------------------------------------------------------------------------------
/components/output.js:
--------------------------------------------------------------------------------
1 | import { useState, useEffect, useRef } from 'react';
2 | import { js_beautify as jsBeautify } from 'js-beautify';
3 | import hljs from 'highlight.js/lib/core';
4 | import javascript from 'highlight.js/lib/languages/javascript';
5 | import 'highlight.js/styles/github.css';
6 | import useClipboard from '@/modules/hooks/use-clipboard';
7 |
8 | export default function Output({ content: contentProp }) {
9 | const element = useRef();
10 | const { copy } = useClipboard();
11 | const [content, setContent] = useState();
12 |
13 | useEffect(() => {
14 | hljs.registerLanguage('javascript', javascript);
15 | }, []);
16 |
17 | useEffect(() => {
18 | setContent(jsBeautify(contentProp));
19 | }, [contentProp]);
20 |
21 | useEffect(() => {
22 | hljs.highlightBlock(element.current);
23 | }, [content]);
24 |
25 | const handleCopy = () => {
26 | copy(content);
27 | };
28 |
29 | return (
30 |
31 |
32 | {/^Failed/.test(content) && '💡 try JS Beautifier!'}
33 |
34 | {content}
35 |
36 |
37 |
38 | {Boolean(content) && (
39 |
42 | )}
43 |
44 |
61 |
62 | );
63 | }
64 |
--------------------------------------------------------------------------------
/lib/javascriptobfuscator_unpacker.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2007-2018 Einar Lielmanis, Liam Newman, and contributors.
6 |
7 | Permission is hereby granted, free of charge, to any person
8 | obtaining a copy of this software and associated documentation files
9 | (the "Software"), to deal in the Software without restriction,
10 | including without limitation the rights to use, copy, modify, merge,
11 | publish, distribute, sublicense, and/or sell copies of the Software,
12 | and to permit persons to whom the Software is furnished to do so,
13 | subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 | BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | SOFTWARE.
26 | */
27 |
28 | //
29 | // simple unpacker/deobfuscator for scripts messed up with javascriptobfuscator.com
30 | // written by Einar Lielmanis
31 | //
32 | // usage:
33 | //
34 | // if (JavascriptObfuscator.detect(some_string)) {
35 | // var unpacked = JavascriptObfuscator.unpack(some_string);
36 | // }
37 | //
38 | //
39 |
40 | /*jshint strict:false */
41 |
42 | var JavascriptObfuscator = {
43 | detect: function (str) {
44 | return /^var _0x[a-f0-9]+ ?\= ?\[/.test(str);
45 | },
46 |
47 | unpack: function (str) {
48 | if (JavascriptObfuscator.detect(str)) {
49 | var matches = /var (_0x[a-f\d]+) ?\= ?\[(.*?)\];/.exec(str);
50 | if (matches) {
51 | var var_name = matches[1];
52 | var strings = JavascriptObfuscator._smart_split(matches[2]);
53 | str = str.substring(matches[0].length);
54 | for (var k in strings) {
55 | str = str.replace(
56 | new RegExp(var_name + '\\[' + k + '\\]', 'g'),
57 | JavascriptObfuscator._fix_quotes(
58 | JavascriptObfuscator._unescape(strings[k]),
59 | ),
60 | );
61 | }
62 | }
63 | }
64 | return str;
65 | },
66 |
67 | _fix_quotes: function (str) {
68 | var matches = /^"(.*)"$/.exec(str);
69 | if (matches) {
70 | str = matches[1];
71 | str = "'" + str.replace(/'/g, "\\'") + "'";
72 | }
73 | return str;
74 | },
75 |
76 | _smart_split: function (str) {
77 | var strings = [];
78 | var pos = 0;
79 | while (pos < str.length) {
80 | if (str.charAt(pos) === '"') {
81 | // new word
82 | var word = '';
83 | pos += 1;
84 | while (pos < str.length) {
85 | if (str.charAt(pos) === '"') {
86 | break;
87 | }
88 | if (str.charAt(pos) === '\\') {
89 | word += '\\';
90 | pos++;
91 | }
92 | word += str.charAt(pos);
93 | pos++;
94 | }
95 | strings.push('"' + word + '"');
96 | }
97 | pos += 1;
98 | }
99 | return strings;
100 | },
101 |
102 | _unescape: function (str) {
103 | // inefficient if used repeatedly or on small strings, but wonderful on single large chunk of text
104 | for (var i = 32; i < 128; i++) {
105 | str = str.replace(
106 | new RegExp('\\\\x' + i.toString(16), 'ig'),
107 | String.fromCharCode(i),
108 | );
109 | }
110 | str = str.replace(/\\x09/g, '\t');
111 | return str;
112 | },
113 |
114 | run_tests: function (sanity_test) {
115 | var t = sanity_test || new SanityTest();
116 |
117 | t.test_function(
118 | JavascriptObfuscator._smart_split,
119 | 'JavascriptObfuscator._smart_split',
120 | );
121 | t.expect('', []);
122 | t.expect('"a", "b"', ['"a"', '"b"']);
123 | t.expect('"aaa","bbbb"', ['"aaa"', '"bbbb"']);
124 | t.expect('"a", "b\\""', ['"a"', '"b\\""']);
125 | t.test_function(
126 | JavascriptObfuscator._unescape,
127 | 'JavascriptObfuscator._unescape',
128 | );
129 | t.expect('\\x40', '@');
130 | t.expect('\\x10', '\\x10');
131 | t.expect('\\x1', '\\x1');
132 | t.expect('\\x61\\x62\\x22\\x63\\x64', 'ab"cd');
133 | t.test_function(JavascriptObfuscator.detect, 'JavascriptObfuscator.detect');
134 | t.expect('', false);
135 | t.expect('abcd', false);
136 | t.expect('var _0xaaaa', false);
137 | t.expect('var _0xaaaa = ["a", "b"]', true);
138 | t.expect('var _0xaaaa=["a", "b"]', true);
139 | t.expect('var _0x1234=["a","b"]', true);
140 | return t;
141 | },
142 | };
143 |
144 | export default JavascriptObfuscator;
145 |
--------------------------------------------------------------------------------
/modules/hooks/use-clipboard.js:
--------------------------------------------------------------------------------
1 | function copy(text) {
2 | if (navigator.clipboard) {
3 | return navigator.clipboard.writeText(text).catch((error) => {
4 | throw error !== undefined
5 | ? error
6 | : new DOMException('The request is not allowed', 'NotAllowedError');
7 | });
8 | }
9 |
10 | const span = document.createElement('span');
11 | span.textContent = text;
12 | span.style.whiteSpace = 'pre';
13 | document.body.appendChild(span);
14 |
15 | const selection = window.getSelection();
16 | const range = window.document.createRange();
17 | selection.removeAllRanges();
18 | range.selectNode(span);
19 | selection.addRange(range);
20 |
21 | let success = false;
22 | try {
23 | success = window.document.execCommand('copy');
24 | } catch (error) {
25 | // eslint-disable-next-line no-console
26 | console.log(error);
27 | }
28 |
29 | selection.removeAllRanges();
30 | window.document.body.removeChild(span);
31 |
32 | return success
33 | ? Promise.resolve()
34 | : Promise.reject(
35 | new DOMException('The request is not allowed', 'NotAllowedError'),
36 | );
37 | }
38 |
39 | const noop = () => {};
40 |
41 | export default function useClipboard(options = {}) {
42 | const { onSuccess = noop, onError = noop } = options;
43 | const clipboardCopy = (text) => {
44 | copy(text).then(onSuccess).catch(onError);
45 | };
46 |
47 | const isSupported = () => !!(
48 | navigator.clipboard
49 | || (document.execCommand
50 | && document.queryCommandSupported
51 | && document.queryCommandSupported('copy'))
52 | );
53 |
54 | return {
55 | copy: clipboardCopy,
56 | isSupported,
57 | };
58 | }
59 |
--------------------------------------------------------------------------------
/modules/hooks/use-event-listener.js:
--------------------------------------------------------------------------------
1 | import { useEffect, useRef } from 'react';
2 |
3 | function getElement(element) {
4 | return typeof element === 'function' ? element() : element;
5 | }
6 |
7 | export default function useEventListener(
8 | element, eventName, handler, { skip = false, ...options } = {},
9 | ) {
10 | const handlerRef = useRef();
11 | useEffect(() => {
12 | handlerRef.current = handler;
13 | }, [handler]);
14 |
15 | useEffect(() => {
16 | if (skip) return undefined;
17 |
18 | const target = getElement(element);
19 | if (target && handlerRef.current) {
20 | const eventHandler = (event) => handlerRef.current(event);
21 | target.addEventListener(eventName, eventHandler, options);
22 |
23 | return () => {
24 | target.removeEventListener(eventName, eventHandler, options);
25 | };
26 | }
27 |
28 | return undefined;
29 | }, [element, eventName, skip, options]);
30 | }
31 |
32 | export function useGlobalEventListener(eventName, handler, options) {
33 | useEventListener(() => window, eventName, handler, options);
34 | }
35 |
--------------------------------------------------------------------------------
/modules/hooks/use-key-press.js:
--------------------------------------------------------------------------------
1 | import { useRef, useCallback, useEffect } from 'react';
2 | import useEventListener from './use-event-listener';
3 |
4 | const keyCodeAliasMapping = {
5 | esc: 27,
6 | tab: 9,
7 | enter: 13,
8 | space: 32,
9 | up: 38,
10 | left: 37,
11 | right: 39,
12 | down: 40,
13 | delete: [8, 46],
14 | };
15 |
16 | const keyAliasMapping = {
17 | esc: 'Escape',
18 | tab: 'Tab',
19 | enter: 'Enter',
20 | space: ' ',
21 | up: ['Up', 'ArrowUp'],
22 | left: ['Left', 'ArrowLeft'],
23 | right: ['Right', 'ArrowRight'],
24 | down: ['Down', 'ArrowDown'],
25 | delete: ['Backspace', 'Delete'],
26 | };
27 |
28 | export const ignoreEscKeyEvents = ({ target }) => target.matches('input')
29 | || target.matches('textarea')
30 | || target.closest('form')
31 | || target.closest('button')
32 | || target.closest('[contenteditable]');
33 |
34 | export const keyMatched = (event, keyAlias) => {
35 | if (event.isComposing || event.keyCode === 229) return false;
36 |
37 | let keyCode = keyCodeAliasMapping[keyAlias];
38 | if (!Array.isArray(keyCode)) keyCode = [keyCode];
39 |
40 | let key = keyAliasMapping[keyAlias];
41 | if (!Array.isArray(key)) key = [key];
42 |
43 | return keyCode.includes(event.keyCode) || key.includes(event.key);
44 | };
45 |
46 | export default function useKeyPress(element, keyAlias, handler) {
47 | const handlerRef = useRef();
48 |
49 | useEffect(() => {
50 | handlerRef.current = handler;
51 | }, [handler]);
52 |
53 | const eventHandler = useCallback(
54 | (event) => {
55 | if (keyMatched(event, keyAlias)) {
56 | handlerRef.current(event);
57 | }
58 | },
59 | [keyAlias],
60 | );
61 |
62 | useEventListener(element, 'keydown', eventHandler);
63 | }
64 |
65 | export function useGlobalKeyPress(keyAlias, handler) {
66 | useKeyPress(() => window, keyAlias, handler);
67 | }
68 |
--------------------------------------------------------------------------------
/next.config.js:
--------------------------------------------------------------------------------
1 | const { merge } = require('webpack-merge');
2 | const webpackConfig = require('./webpack.config');
3 |
4 | module.exports = {
5 | webpack(config) {
6 | const mergedConfig = merge(config, webpackConfig);
7 | return mergedConfig;
8 | },
9 | };
10 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-deobfuscate",
3 | "version": "0.1.0",
4 | "private": false,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start"
9 | },
10 | "dependencies": {
11 | "highlight.js": "^10.3.1",
12 | "install": "^0.13.0",
13 | "js-beautify": "^1.13.0",
14 | "next": "9.5.5",
15 | "npm": "^6.14.8",
16 | "react": "17.0.0",
17 | "react-dom": "17.0.0",
18 | "webpack-merge": "^5.2.0"
19 | },
20 | "devDependencies": {
21 | "babel-eslint": "^10.1.0",
22 | "eslint": "^7.11.0",
23 | "eslint-config-airbnb-base": "^14.2.0",
24 | "eslint-import-resolver-webpack": "^0.13.0",
25 | "eslint-plugin-import": "^2.22.1",
26 | "eslint-plugin-react": "^7.21.5",
27 | "eslint-plugin-react-hooks": "^4.2.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/pages/_app.js:
--------------------------------------------------------------------------------
1 | import '@/styles/reset.css';
2 | import '@/styles/global.css';
3 |
4 | export default function MyApp({ Component, pageProps }) {
5 | return ;
6 | }
7 |
--------------------------------------------------------------------------------
/pages/index.js:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import Layout from '@/components/layout';
3 | import Header from '@/components/header';
4 | import Form from '@/components/form';
5 | import Output from '@/components/output';
6 |
7 | export default function Home() {
8 | const [content, setContent] = useState('');
9 |
10 | const handleChange = (result) => {
11 | setContent(result);
12 | };
13 |
14 | return (
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/public/card.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuochenLyu/js-deobfuscate/544e5b0a2360474598b7b3c766a016c1fa76af1a/public/card.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuochenLyu/js-deobfuscate/544e5b0a2360474598b7b3c766a016c1fa76af1a/public/favicon.ico
--------------------------------------------------------------------------------
/public/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuochenLyu/js-deobfuscate/544e5b0a2360474598b7b3c766a016c1fa76af1a/public/favicon.png
--------------------------------------------------------------------------------
/public/lib/jsdec.js:
--------------------------------------------------------------------------------
1 | function autoscan(jsf) {
2 | function checklist(f) {
3 | if (
4 | f.indexOf(',') != -1
5 | && f.indexOf('=') != -1
6 | && f.indexOf('[') != -1
7 | && f.indexOf(']') != -1
8 | && f.indexOf('var ') != -1
9 | ) {
10 | return true;
11 | }
12 | }
13 | if (jsf.indexOf("['sojson.v4']") != -1) {
14 | return decsojson4(jsf);
15 | }
16 | if (jsf.indexOf("var __encode ='sojson.com") != -1) {
17 | return decsojsonp(jsf);
18 | }
19 | if (jsf.indexOf("var encode_version = 'sojson.v5',") != -1) {
20 | return dec_sojsonv5_default(jsf);
21 | }
22 | if (jsf.indexOf("'jsjiami.com'") != -1) {
23 | return obdec_default(jsf);
24 | }
25 | if (jsf.indexOf("'];(function(_0x") != -1) {
26 | return obdec_default(jsf);
27 | }
28 | if (checklist(jsf.substring(0, jsf.indexOf(';')))) {
29 | return dec_list(jsf);
30 | }
31 | if (
32 | jsf
33 | .substring(0, 100)
34 | .replace(/ /g, '')
35 | .replace(/\(/g, '')
36 | .replace(/\)/g, '')
37 | .replace(/\[/g, '')
38 | .replace(/\]/g, '')
39 | .replace(/\+/g, '')
40 | .replace(/!/g, '') == ''
41 | ) {
42 | return decjsf(jsf);
43 | }
44 | if (jsf.substring(0, 50).indexOf('eval') != -1) {
45 | return uneval(jsf);
46 | }
47 | let jstmp = aadecode(jsf);
48 | if (jstmp != 'Failed!\nGiven code is not encoded as aaencode.') {
49 | return jstmp;
50 | }
51 | jstmp = jjdecode(jsf);
52 | if (jstmp != 'Failed!\nGiven code is not encoded as jjencode.') {
53 | return jstmp;
54 | }
55 | return 'Failed!\nAuto-Scan Failed.';
56 | }
57 |
58 | function uneval(jsf) {
59 | const s = jsf.indexOf('eval');
60 | const f = jsf.lastIndexOf(')');
61 | eval(`jsf=String${jsf.substring(s + 4, f + 1)}`);
62 | return jsf;
63 | }
64 |
65 | function decsojson4(jsf) {
66 | const head = "['sojson.v4']";
67 | if (jsf.indexOf(head) == -1) {
68 | return 'Failed!\nGiven code is not encoded as Sojson v4.';
69 | }
70 | args = jsf.substring(240, jsf.length - 58).split(/[a-zA-Z]{1,}/);
71 | let str = '';
72 | for (let i = 0; i < args.length; i++) {
73 | str += String.fromCharCode(args[i]);
74 | }
75 | return str;
76 | }
77 |
78 | function obdec_default(jsf, thr1 = false, throwederror = '') {
79 | const ojs = jsf;
80 | let spljs;
81 | try {
82 | function sandbox() {
83 | function th() {
84 | if (head2.indexOf(head1) == -1) return;
85 | let countn;
86 | const c = head2.substring(head2.indexOf(head1), head2.length);
87 | let jstmp = c.substring(0, c.indexOf("')") + 2);
88 | try {
89 | countn = eval(jstmp);
90 | } catch (e) {
91 | const jstmp2 = c.substring(c.indexOf("')") + 2, c.length);
92 | jstmp += jstmp2.substring(0, jstmp2.indexOf("')") + 2);
93 | countn = eval(jstmp);
94 | }
95 | head2 = head2.replace(
96 | jstmp,
97 | `'${countn.replace(/\n/g, '\\n').replace(/'/g, "\\'")}'`,
98 | );
99 | th();
100 | }
101 | eval(head3);
102 | th();
103 | }
104 | if (jsf.indexOf('));var') != -1) {
105 | var indf = jsf.indexOf('));var');
106 | spljs = '));var';
107 | } else if (jsf.indexOf(')); var') != -1) {
108 | var indf = jsf.indexOf(')); var');
109 | spljs = ')); var';
110 | } else if (jsf.indexOf('));\nvar') != -1) {
111 | var indf = jsf.indexOf('));\nvar');
112 | spljs = '));\nvar';
113 | } else {
114 | throw 'Cannot Found function.';
115 | }
116 | let head1;
117 | var head2 = jsf.substring(indf + 3, jsf.length);
118 | var head3 = head2.substring(head2.indexOf(')') + 1, head2.length).split('');
119 | let c = 0;
120 | let pos;
121 | let ch = -1;
122 | for (let i = 0; i < head3.length; i++) {
123 | if (head3[i] == '{') {
124 | c++;
125 | if (ch == -1) {
126 | ch = 0;
127 | }
128 | } else if (head3[i] == '}') {
129 | c--;
130 | }
131 | if (c == 0 && ch == 0) {
132 | ch = 1;
133 | pos = i;
134 | }
135 | }
136 | head1 = head2.substring(4, head2.indexOf('=')).replace(/ /g, '');
137 | head3 = jsf.substring(0, pos + head2.indexOf(')') + 6 + indf);
138 | head2 = jsf.substring(pos + head2.indexOf(')') + 6 + indf, jsf.length);
139 | sandbox(head2);
140 | return head2;
141 | } catch (e) {
142 | if (thr1 == false) {
143 | return obdec_default(ojs.replace(spljs, '));\tvar'), true, e);
144 | }
145 | return `Failed!\nthrowed1:${throwederror}\nthrowed2:${e}`;
146 | }
147 | }
148 |
149 | function dec_sojsonv5_default(jsf) {
150 | if (jsf.indexOf("sojson.v5',") == -1) {
151 | return 'Failed\nNot Encoded as sojson.v5';
152 | }
153 | jsf = jsf.substring(jsf.indexOf("sojson.v5',") + 12, jsf.length);
154 | jsf = `var ${jsf.substring(jsf.indexOf(', ') + 2, jsf.length)}`;
155 | const js = obdec_default(jsf);
156 | return js.substring(0, js.indexOf('(function(_0x'));
157 | }
158 |
159 | function dec_list(jsf) {
160 | if (
161 | !(
162 | jsf.indexOf(',') != -1
163 | && jsf.indexOf('=') != -1
164 | && jsf.indexOf('[') != -1
165 | && jsf.indexOf(']') != -1
166 | && jsf.indexOf('var ') != -1
167 | )
168 | ) {
169 | throw 'Type Error!';
170 | }
171 | let result;
172 | let name;
173 |
174 | function th() {
175 | const s = result.split('');
176 | if (result.indexOf(name) == -1) {
177 | } else {
178 | const c = result.substring(result.indexOf(name), result.length);
179 | const jstmp = c.substring(0, c.indexOf(']') + 1);
180 | const countn = eval(jstmp);
181 | result = result.replace(
182 | jstmp,
183 | `'${countn.replace(/\n/g, '\\n').replace(/'/g, "\\'")}'`,
184 | );
185 | th();
186 | }
187 | }
188 | name = jsf.substring(4, jsf.indexOf('='));
189 | eval(jsf.substring(0, jsf.indexOf(';') + 1));
190 | result = jsf.substring(jsf.indexOf(';') + 1, jsf.length);
191 | th();
192 | return result;
193 | }
194 |
195 | function decsojsonp(jsf) {
196 | if (jsf.indexOf("var __encode ='sojson.com") == -1) {
197 | return 'Failed!\nGiven code is not encoded as Sojson Primium.';
198 | }
199 | jsf = jsf.substring(
200 | jsf.indexOf(');var _') + 2,
201 | jsf.lastIndexOf('(function(_0x'),
202 | );
203 | return dec_list(jsf);
204 | }
205 |
206 | function aadecode(text) {
207 | const evalPreamble = "(\uFF9F\u0414\uFF9F) ['_'] ( (\uFF9F\u0414\uFF9F) ['_'] (";
208 | const decodePreamble = "( (\uFF9F\u0414\uFF9F) ['_'] (";
209 | const evalPostamble = ") (\uFF9F\u0398\uFF9F)) ('_');";
210 | const decodePostamble = ') ());';
211 | text = text.replace(/^\s*/, '').replace(/\s*$/, '');
212 | if (/^\s*$/.test(text)) {
213 | return '';
214 | }
215 | if (text.lastIndexOf(evalPreamble) < 0) {
216 | return 'Failed!\nGiven code is not encoded as aaencode.';
217 | }
218 | if (text.lastIndexOf(evalPostamble) != text.length - evalPostamble.length) {
219 | return 'Failed!\nGiven code is not encoded as aaencode.';
220 | }
221 | const decodingScript = text
222 | .replace(evalPreamble, decodePreamble)
223 | .replace(evalPostamble, decodePostamble);
224 | return eval(decodingScript);
225 | }
226 |
227 | function jjdecode(t) {
228 | let jjvalue = '';
229 | t.replace(/^\s+|\s+$/g, '');
230 | let startpos;
231 | let endpos;
232 | let gv;
233 | let gvl;
234 | if (t.indexOf('"\'\\"+\'+",') == 0) {
235 | startpos = t.indexOf('$$+"\\""+') + 8;
236 | endpos = t.indexOf('"\\"")())()');
237 | gv = t.substring(t.indexOf('"\'\\"+\'+",') + 9, t.indexOf('=~[]'));
238 | gvl = gv.length;
239 | } else {
240 | gv = t.substr(0, t.indexOf('='));
241 | gvl = gv.length;
242 | startpos = t.indexOf('"\\""+') + 5;
243 | endpos = t.indexOf('"\\"")())()');
244 | }
245 | if (startpos == endpos) {
246 | alert('No data !');
247 | return;
248 | }
249 | let data = t.substring(startpos, endpos);
250 | const b = [
251 | '___+',
252 | '__$+',
253 | '_$_+',
254 | '_$$+',
255 | '$__+',
256 | '$_$+',
257 | '$$_+',
258 | '$$$+',
259 | '$___+',
260 | '$__$+',
261 | '$_$_+',
262 | '$_$$+',
263 | '$$__+',
264 | '$$_$+',
265 | '$$$_+',
266 | '$$$$+',
267 | ];
268 | const str_l = `(![]+"")[${gv}._$_]+`;
269 | const str_o = `${gv}._$+`;
270 | const str_t = `${gv}.__+`;
271 | const str_u = `${gv}._+`;
272 | const str_hex = `${gv}.`;
273 | const str_s = '"';
274 | const gvsig = `${gv}.`;
275 | const str_quote = '\\\\\\"';
276 | const str_slash = '\\\\\\\\';
277 | const str_lower = '\\\\"+';
278 | const str_upper = `\\\\"+${gv}._+`;
279 | const str_end = '"+';
280 | while (data != '') {
281 | if (data.indexOf(str_l) == 0) {
282 | data = data.substr(str_l.length);
283 | jjvalue += 'l';
284 | continue;
285 | } else if (data.indexOf(str_o) == 0) {
286 | data = data.substr(str_o.length);
287 | jjvalue += 'o';
288 | continue;
289 | } else if (data.indexOf(str_t) == 0) {
290 | data = data.substr(str_t.length);
291 | jjvalue += 't';
292 | continue;
293 | } else if (data.indexOf(str_u) == 0) {
294 | data = data.substr(str_u.length);
295 | jjvalue += 'u';
296 | continue;
297 | }
298 | if (data.indexOf(str_hex) == 0) {
299 | data = data.substr(str_hex.length);
300 | var i = 0;
301 | for (i = 0; i < b.length; i++) {
302 | if (data.indexOf(b[i]) == 0) {
303 | data = data.substr(b[i].length);
304 | jjvalue += i.toString(16);
305 | break;
306 | }
307 | }
308 | continue;
309 | }
310 | if (data.indexOf(str_s) == 0) {
311 | data = data.substr(str_s.length);
312 | if (data.indexOf(str_upper) == 0) {
313 | data = data.substr(str_upper.length);
314 | var ch_str = '';
315 | for (j = 0; j < 2; j++) {
316 | if (data.indexOf(gvsig) == 0) {
317 | data = data.substr(gvsig.length);
318 | for (k = 0; k < b.length; k++) {
319 | if (data.indexOf(b[k]) == 0) {
320 | data = data.substr(b[k].length);
321 | ch_str += `${k.toString(16)}`;
322 | break;
323 | }
324 | }
325 | } else {
326 | break;
327 | }
328 | }
329 | jjvalue += String.fromCharCode(parseInt(ch_str, 16));
330 | continue;
331 | } else if (data.indexOf(str_lower) == 0) {
332 | data = data.substr(str_lower.length);
333 | var ch_str = '';
334 | var ch_lotux = '';
335 | var temp = '';
336 | var b_checkR1 = 0;
337 | for (j = 0; j < 3; j++) {
338 | if (j > 1) {
339 | if (data.indexOf(str_l) == 0) {
340 | data = data.substr(str_l.length);
341 | ch_lotux = 'l';
342 | break;
343 | } else if (data.indexOf(str_o) == 0) {
344 | data = data.substr(str_o.length);
345 | ch_lotux = 'o';
346 | break;
347 | } else if (data.indexOf(str_t) == 0) {
348 | data = data.substr(str_t.length);
349 | ch_lotux = 't';
350 | break;
351 | } else if (data.indexOf(str_u) == 0) {
352 | data = data.substr(str_u.length);
353 | ch_lotux = 'u';
354 | break;
355 | }
356 | }
357 | if (data.indexOf(gvsig) == 0) {
358 | temp = data.substr(gvsig.length);
359 | for (k = 0; k < 8; k++) {
360 | if (temp.indexOf(b[k]) == 0) {
361 | if (parseInt(`${ch_str + k}`, 8) > 128) {
362 | b_checkR1 = 1;
363 | break;
364 | }
365 | ch_str += `${k}`;
366 | data = data.substr(gvsig.length);
367 | data = data.substr(b[k].length);
368 | break;
369 | }
370 | }
371 | if (b_checkR1 == 1) {
372 | if (data.indexOf(str_hex) == 0) {
373 | data = data.substr(str_hex.length);
374 | var i = 0;
375 | for (i = 0; i < b.length; i++) {
376 | if (data.indexOf(b[i]) == 0) {
377 | data = data.substr(b[i].length);
378 | ch_lotux = i.toString(16);
379 | break;
380 | }
381 | }
382 | break;
383 | }
384 | }
385 | } else {
386 | break;
387 | }
388 | }
389 | jjvalue += String.fromCharCode(parseInt(ch_str, 8)) + ch_lotux;
390 | continue;
391 | } else {
392 | let match = 0;
393 | var n;
394 | while (true) {
395 | n = data.charCodeAt(0);
396 | if (data.indexOf(str_quote) == 0) {
397 | data = data.substr(str_quote.length);
398 | jjvalue += '"';
399 | match += 1;
400 | continue;
401 | } else if (data.indexOf(str_slash) == 0) {
402 | data = data.substr(str_slash.length);
403 | jjvalue += '\\';
404 | match += 1;
405 | continue;
406 | } else if (data.indexOf(str_end) == 0) {
407 | if (match == 0) {
408 | alert(`+ no match S block: ${data}`);
409 | return;
410 | }
411 | data = data.substr(str_end.length);
412 | break;
413 | } else if (data.indexOf(str_upper) == 0) {
414 | if (match == 0) {
415 | alert(`no match S block n>128: ${data}`);
416 | return;
417 | }
418 | data = data.substr(str_upper.length);
419 | var ch_str = '';
420 | var ch_lotux = '';
421 | for (j = 0; j < 10; j++) {
422 | if (j > 1) {
423 | if (data.indexOf(str_l) == 0) {
424 | data = data.substr(str_l.length);
425 | ch_lotux = 'l';
426 | break;
427 | } else if (data.indexOf(str_o) == 0) {
428 | data = data.substr(str_o.length);
429 | ch_lotux = 'o';
430 | break;
431 | } else if (data.indexOf(str_t) == 0) {
432 | data = data.substr(str_t.length);
433 | ch_lotux = 't';
434 | break;
435 | } else if (data.indexOf(str_u) == 0) {
436 | data = data.substr(str_u.length);
437 | ch_lotux = 'u';
438 | break;
439 | }
440 | }
441 | if (data.indexOf(gvsig) == 0) {
442 | data = data.substr(gvsig.length);
443 | for (k = 0; k < b.length; k++) {
444 | if (data.indexOf(b[k]) == 0) {
445 | data = data.substr(b[k].length);
446 | ch_str += `${k.toString(16)}`;
447 | break;
448 | }
449 | }
450 | } else {
451 | break;
452 | }
453 | }
454 | jjvalue += String.fromCharCode(parseInt(ch_str, 16));
455 | break;
456 | } else if (data.indexOf(str_lower) == 0) {
457 | if (match == 0) {
458 | alert(`no match S block n<128: ${data}`);
459 | return;
460 | }
461 | data = data.substr(str_lower.length);
462 | var ch_str = '';
463 | var ch_lotux = '';
464 | var temp = '';
465 | var b_checkR1 = 0;
466 | for (j = 0; j < 3; j++) {
467 | if (j > 1) {
468 | if (data.indexOf(str_l) == 0) {
469 | data = data.substr(str_l.length);
470 | ch_lotux = 'l';
471 | break;
472 | } else if (data.indexOf(str_o) == 0) {
473 | data = data.substr(str_o.length);
474 | ch_lotux = 'o';
475 | break;
476 | } else if (data.indexOf(str_t) == 0) {
477 | data = data.substr(str_t.length);
478 | ch_lotux = 't';
479 | break;
480 | } else if (data.indexOf(str_u) == 0) {
481 | data = data.substr(str_u.length);
482 | ch_lotux = 'u';
483 | break;
484 | }
485 | }
486 | if (data.indexOf(gvsig) == 0) {
487 | temp = data.substr(gvsig.length);
488 | for (k = 0; k < 8; k++) {
489 | if (temp.indexOf(b[k]) == 0) {
490 | if (parseInt(`${ch_str + k}`, 8) > 128) {
491 | b_checkR1 = 1;
492 | break;
493 | }
494 | ch_str += `${k}`;
495 | data = data.substr(gvsig.length);
496 | data = data.substr(b[k].length);
497 | break;
498 | }
499 | }
500 | if (b_checkR1 == 1) {
501 | if (data.indexOf(str_hex) == 0) {
502 | data = data.substr(str_hex.length);
503 | var i = 0;
504 | for (i = 0; i < b.length; i++) {
505 | if (data.indexOf(b[i]) == 0) {
506 | data = data.substr(b[i].length);
507 | ch_lotux = i.toString(16);
508 | break;
509 | }
510 | }
511 | }
512 | }
513 | } else {
514 | break;
515 | }
516 | }
517 | jjvalue += String.fromCharCode(parseInt(ch_str, 8)) + ch_lotux;
518 | break;
519 | } else if (
520 | (n >= 0x21 && n <= 0x2f)
521 | || (n >= 0x3a && n <= 0x40)
522 | || (n >= 0x5b && n <= 0x60)
523 | || (n >= 0x7b && n <= 0x7f)
524 | ) {
525 | jjvalue += data.charAt(0);
526 | data = data.substr(1);
527 | match += 1;
528 | }
529 | }
530 | continue;
531 | }
532 | }
533 | break;
534 | }
535 | if (jjvalue != '') {
536 | return jjvalue;
537 | }
538 | return 'Failed!\nGiven code is not encoded as jjencode.';
539 | }
540 |
541 | function decjsf(js) {
542 | function patternCreator(prefix, postfix) {
543 | replacedPrefix = prefix.replace(/[\[\]\(\)\+\!]/g, '\\$&');
544 | replacedPostfix = postfix.replace(/[\[\]\(\)\+\!]/g, '\\$&');
545 | return `${replacedPrefix}(.*)${replacedPostfix}`;
546 | }
547 |
548 | function isMatching(string, pattern) {
549 | const result = string.match(new RegExp(pattern));
550 | if (result) return result[1];
551 | return null;
552 | }
553 |
554 | function decodejsf() {
555 | let prefix = '[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()(';
556 | let postfix = ')';
557 | let result = isMatching(code, patternCreator(prefix, postfix));
558 | if (result) {
559 | code = eval(result);
560 | return;
561 | }
562 | prefix = '[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]](';
563 | postfix = ')()';
564 | result = isMatching(code, patternCreator(prefix, postfix));
565 | if (result) {
566 | code = eval(result);
567 | return;
568 | }
569 | prefix = '[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]](';
570 | postfix = ')()';
571 | result = isMatching(code, patternCreator(prefix, postfix));
572 | if (result) {
573 | code = eval(result);
574 | return;
575 | }
576 | code = eval(code);
577 | }
578 | try {
579 | var code = js;
580 | decodejsf();
581 | return code;
582 | } catch (e) {
583 | return `Failed\n${e}`;
584 | }
585 | }
586 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Thumbnail Hunter",
3 | "short_name": "Thumbnail Hunter",
4 | "description": "A simple tool that allows you to download the image thumbnail of any YouTube video by entering the URL of the video.",
5 | "background_color": "#edf2f7",
6 | "theme_color": "#edf2f7",
7 | "display": "minimal-ui",
8 | "start_url": "/",
9 | "icons": [
10 | {
11 | "src": "/touch-icon.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "/touch-icon-512x512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/public/touch-icon-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuochenLyu/js-deobfuscate/544e5b0a2360474598b7b3c766a016c1fa76af1a/public/touch-icon-512x512.png
--------------------------------------------------------------------------------
/public/touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuochenLyu/js-deobfuscate/544e5b0a2360474598b7b3c766a016c1fa76af1a/public/touch-icon.png
--------------------------------------------------------------------------------
/styles/global.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --textColor: #2d3748;
3 | --textColorLight: #a0aec0;
4 | --backgroundColor: #f7f9f9;
5 | --uiColor: #e7742e;
6 | --MonospaceFont: Monaco, Terminal, monospace;
7 | }
8 |
9 | body {
10 | color: var(--textColor);
11 | font-size: 14px;
12 | font-family: var(--MonospaceFont);
13 | background: var(--backgroundColor);
14 | }
15 |
16 | button {
17 | border: none;
18 | margin: 0;
19 | padding: 0 12px;
20 | width: auto;
21 | height: 40px;
22 | overflow: visible;
23 | background: transparent;
24 | border-radius: 4px;
25 | color: inherit;
26 | font: inherit;
27 | line-height: normal;
28 | font-weight: bold;
29 | cursor: pointer;
30 | outline: none;
31 | -webkit-font-smoothing: inherit;
32 | -moz-osx-font-smoothing: inherit;
33 | -webkit-appearance: none;
34 | }
35 |
36 | button:hover {
37 | opacity: 0.7;
38 | }
39 |
40 | button:active {
41 | opacity: 0.9;
42 | }
43 |
44 | button[disabled] {
45 | background: #ccc !important;
46 | }
47 |
--------------------------------------------------------------------------------
/styles/reset.css:
--------------------------------------------------------------------------------
1 | /* Box sizing rules */
2 | *,
3 | *::before,
4 | *::after {
5 | box-sizing: border-box;
6 | }
7 |
8 | /* Remove default padding */
9 | ul[class],
10 | ol[class] {
11 | padding: 0;
12 | }
13 |
14 | /* Remove default margin */
15 | body,
16 | h1,
17 | h2,
18 | h3,
19 | h4,
20 | p,
21 | ul[class],
22 | ol[class],
23 | li,
24 | figure,
25 | figcaption,
26 | blockquote,
27 | dl,
28 | dd {
29 | margin: 0;
30 | }
31 |
32 | /* Set core body defaults */
33 | body {
34 | min-height: 100vh;
35 | scroll-behavior: smooth;
36 | text-rendering: optimizeSpeed;
37 | line-height: 1.5;
38 | }
39 |
40 | /* Remove list styles on ul, ol elements with a class attribute */
41 | ul[class],
42 | ol[class] {
43 | list-style: none;
44 | }
45 |
46 | /* A elements that don't have a class get default styles */
47 | a:not([class]) {
48 | text-decoration-skip-ink: auto;
49 | }
50 |
51 | /* Make images easier to work with */
52 | img {
53 | max-width: 100%;
54 | display: block;
55 | }
56 |
57 | /* Natural flow and rhythm in articles by default */
58 | article > * + * {
59 | margin-top: 1em;
60 | }
61 |
62 | /* Inherit fonts for inputs and buttons */
63 | input,
64 | button,
65 | textarea,
66 | select {
67 | font: inherit;
68 | }
69 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | resolve: {
5 | alias: {
6 | '@': path.resolve(__dirname, './'),
7 | },
8 | },
9 | };
10 |
--------------------------------------------------------------------------------