diff options
Diffstat (limited to 'venv/lib/python3.11/site-packages/jsbeautifier/unpackers')
22 files changed, 693 insertions, 0 deletions
| diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__init__.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__init__.py new file mode 100644 index 0000000..01c254f --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__init__.py @@ -0,0 +1,73 @@ +# +# General code for JSBeautifier unpackers infrastructure. See README.specs +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# + +"""General code for JSBeautifier unpackers infrastructure.""" + +import pkgutil +import re +from jsbeautifier.unpackers import evalbased + +# NOTE: AT THE MOMENT, IT IS DEACTIVATED FOR YOUR SECURITY: it runs js! +BLACKLIST = ["jsbeautifier.unpackers.evalbased"] + + +class UnpackingError(Exception): +    """Badly packed source or general error. Argument is a +    meaningful description.""" + +    pass + + +def getunpackers(): +    """Scans the unpackers dir, finds unpackers and add them to UNPACKERS list. +    An unpacker will be loaded only if it is a valid python module (name must +    adhere to naming conventions) and it is not blacklisted (i.e. inserted +    into BLACKLIST.""" +    path = __path__ +    prefix = __name__ + "." +    unpackers = [] +    interface = ["unpack", "detect", "PRIORITY"] +    for _importer, modname, _ispkg in pkgutil.iter_modules(path, prefix): +        if "tests" not in modname and modname not in BLACKLIST: +            try: +                module = __import__(modname, fromlist=interface) +            except ImportError: +                raise UnpackingError("Bad unpacker: %s" % modname) +            else: +                unpackers.append(module) + +    return sorted(unpackers, key=lambda mod: mod.PRIORITY) + + +UNPACKERS = getunpackers() + + +def run(source, evalcode=False): +    """Runs the applicable unpackers and return unpacked source as a string.""" +    for unpacker in [mod for mod in UNPACKERS if mod.detect(source)]: +        source = unpacker.unpack(source) +    if evalcode and evalbased.detect(source): +        source = evalbased.unpack(source) +    return source + + +def filtercomments(source): +    """NOT USED: strips trailing comments and put them at the top.""" +    trailing_comments = [] +    comment = True + +    while comment: +        if re.search(r"^\s*\/\*", source): +            comment = source[0, source.index("*/") + 2] +        elif re.search(r"^\s*\/\/", source): +            comment = re.search(r"^\s*\/\/", source).group(0) +        else: +            comment = None + +        if comment: +            source = re.sub(r"^\s+", "", source[len(comment) :]) +            trailing_comments.append(comment) + +    return "\n".join(trailing_comments) + source diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/__init__.cpython-311.pycBinary files differ new file mode 100644 index 0000000..824dc1c --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/__init__.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/evalbased.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/evalbased.cpython-311.pycBinary files differ new file mode 100644 index 0000000..38644e1 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/evalbased.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/javascriptobfuscator.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/javascriptobfuscator.cpython-311.pycBinary files differ new file mode 100644 index 0000000..8ee047d --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/javascriptobfuscator.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/myobfuscate.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/myobfuscate.cpython-311.pycBinary files differ new file mode 100644 index 0000000..cf2948e --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/myobfuscate.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/packer.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/packer.cpython-311.pycBinary files differ new file mode 100644 index 0000000..c0abc98 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/packer.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/urlencode.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/urlencode.cpython-311.pycBinary files differ new file mode 100644 index 0000000..ba90614 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/__pycache__/urlencode.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/evalbased.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/evalbased.py new file mode 100644 index 0000000..74f1f0f --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/evalbased.py @@ -0,0 +1,44 @@ +# +# Unpacker for eval() based packers, a part of javascript beautifier +# by Einar Lielmanis <einar@beautifier.io> +# +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# +# usage: +# +# if detect(some_string): +#     unpacked = unpack(some_string) +# + +"""Unpacker for eval() based packers: runs JS code and returns result. +Works only if a JS interpreter (e.g. Mozilla's Rhino) is installed and +properly set up on host.""" + +from subprocess import PIPE, Popen + +PRIORITY = 3 + + +def detect(source): +    """Detects if source is likely to be eval() packed.""" +    return source.strip().lower().startswith("eval(function(") + + +def unpack(source): +    """Runs source and return resulting code.""" +    return jseval("print %s;" % source[4:]) if detect(source) else source + + +# In case of failure, we'll just return the original, without crashing on user. + + +def jseval(script): +    """Run code in the JS interpreter and return output.""" +    try: +        interpreter = Popen(["js"], stdin=PIPE, stdout=PIPE) +    except OSError: +        return script +    result, errors = interpreter.communicate(script) +    if interpreter.poll() or errors: +        return script +    return result diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/javascriptobfuscator.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/javascriptobfuscator.py new file mode 100644 index 0000000..bd3a331 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/javascriptobfuscator.py @@ -0,0 +1,61 @@ +# +# simple unpacker/deobfuscator for scripts messed up with +# javascriptobfuscator.com +# +#     written by Einar Lielmanis <einar@beautifier.io> +#     rewritten in Python by Stefano Sanfilippo <a.little.coder@gmail.com> +# +# Will always return valid javascript: if `detect()` is false, `code` is +# returned, unmodified. +# +# usage: +# +# if javascriptobfuscator.detect(some_string): +#     some_string = javascriptobfuscator.unpack(some_string) +# + +"""deobfuscator for scripts messed up with JavascriptObfuscator.com""" + +import re + +PRIORITY = 1 + + +def smartsplit(code): +    """Split `code` at " symbol, only if it is not escaped.""" +    strings = [] +    pos = 0 +    while pos < len(code): +        if code[pos] == '"': +            word = ""  # new word +            pos += 1 +            while pos < len(code): +                if code[pos] == '"': +                    break +                if code[pos] == "\\": +                    word += "\\" +                    pos += 1 +                word += code[pos] +                pos += 1 +            strings.append('"%s"' % word) +        pos += 1 +    return strings + + +def detect(code): +    """Detects if `code` is JavascriptObfuscator.com packed.""" +    # prefer `is not` idiom, so that a true boolean is returned +    return re.search(r"^var _0x[a-f0-9]+ ?\= ?\[", code) is not None + + +def unpack(code): +    """Unpacks JavascriptObfuscator.com packed code.""" +    if detect(code): +        matches = re.search(r"var (_0x[a-f\d]+) ?\= ?\[(.*?)\];", code) +        if matches: +            variable = matches.group(1) +            dictionary = smartsplit(matches.group(2)) +            code = code[len(matches.group(0)) :] +            for key, value in enumerate(dictionary): +                code = code.replace(r"%s[%s]" % (variable, key), value) +    return code diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/myobfuscate.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/myobfuscate.py new file mode 100644 index 0000000..0cbc7f8 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/myobfuscate.py @@ -0,0 +1,90 @@ +# +# deobfuscator for scripts messed up with myobfuscate.com +# by Einar Lielmanis <einar@beautifier.io> +# +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# +# usage: +# +# if detect(some_string): +#     unpacked = unpack(some_string) +# + +# CAVEAT by Einar Lielmanis + +# +# You really don't want to obfuscate your scripts there: they're tracking +# your unpackings, your script gets turned into something like this, +# as of 2011-08-26: +# +#   var _escape = 'your_script_escaped'; +#   var _111 = document.createElement('script'); +#   _111.src = 'http://api.www.myobfuscate.com/?getsrc=ok' + +#              '&ref=' + encodeURIComponent(document.referrer) + +#              '&url=' + encodeURIComponent(document.URL); +#   var 000 = document.getElementsByTagName('head')[0]; +#   000.appendChild(_111); +#   document.write(unescape(_escape)); +# + +"""Deobfuscator for scripts messed up with MyObfuscate.com""" + +import re +import base64 + +# Python 2 retrocompatibility +# pylint: disable=F0401 +# pylint: disable=E0611 +try: +    from urllib import unquote +except ImportError: +    from urllib.parse import unquote + +from jsbeautifier.unpackers import UnpackingError + +PRIORITY = 1 + +CAVEAT = """// +// Unpacker warning: be careful when using myobfuscate.com for your projects: +// scripts obfuscated by the free online version call back home. +// + +""" + +SIGNATURE = ( +    r'["\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F' +    r"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x61\x62\x63\x64\x65" +    r"\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75" +    r"\x76\x77\x78\x79\x7A\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x2B" +    r'\x2F\x3D","","\x63\x68\x61\x72\x41\x74","\x69\x6E\x64\x65\x78' +    r'\x4F\x66","\x66\x72\x6F\x6D\x43\x68\x61\x72\x43\x6F\x64\x65","' +    r'\x6C\x65\x6E\x67\x74\x68"]' +) + + +def detect(source): +    """Detects MyObfuscate.com packer.""" +    return SIGNATURE in source + + +def unpack(source): +    """Unpacks js code packed with MyObfuscate.com""" +    if not detect(source): +        return source +    payload = unquote(_filter(source)) +    match = re.search(r"^var _escape\='<script>(.*)<\/script>'", payload, re.DOTALL) +    polished = match.group(1) if match else source +    return CAVEAT + polished + + +def _filter(source): +    """Extracts and decode payload (original file) from `source`""" +    try: +        varname = re.search(r"eval\(\w+\(\w+\((\w+)\)\)\);", source).group(1) +        reverse = re.search(r"var +%s *\= *'(.*)';" % varname, source).group(1) +    except AttributeError: +        raise UnpackingError("Malformed MyObfuscate data.") +    try: +        return base64.b64decode(reverse[::-1].encode("utf8")).decode("utf8") +    except TypeError: +        raise UnpackingError("MyObfuscate payload is not base64-encoded.") diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py new file mode 100644 index 0000000..117ff58 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/packer.py @@ -0,0 +1,161 @@ +# +# Unpacker for Dean Edward's p.a.c.k.e.r, a part of javascript beautifier +# by Einar Lielmanis <einar@beautifier.io> +# +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# +# usage: +# +# if detect(some_string): +#     unpacked = unpack(some_string) +# + +"""Unpacker for Dean Edward's p.a.c.k.e.r""" + +import re +import string +import sys +from jsbeautifier.unpackers import UnpackingError + +PRIORITY = 1 + + +def detect(source): +    global beginstr +    global endstr +    beginstr = "" +    endstr = "" +    begin_offset = -1 +    """Detects whether `source` is P.A.C.K.E.R. coded.""" +    mystr = re.search( +        r"eval[ ]*\([ ]*function[ ]*\([ ]*p[ ]*,[ ]*a[ ]*,[ ]*c[" +        " ]*,[ ]*k[ ]*,[ ]*e[ ]*,[ ]*", +        source, +    ) +    if mystr: +        begin_offset = mystr.start() +        beginstr = source[:begin_offset] +    if begin_offset != -1: +        """Find endstr""" +        source_end = source[begin_offset:] +        if source_end.split("')))", 1)[0] == source_end: +            try: +                endstr = source_end.split("}))", 1)[1] +            except IndexError: +                endstr = "" +        else: +            endstr = source_end.split("')))", 1)[1] +    return mystr is not None + + +def unpack(source): +    """Unpacks P.A.C.K.E.R. packed js code.""" +    payload, symtab, radix, count = _filterargs(source) + +    if count != len(symtab): +        raise UnpackingError("Malformed p.a.c.k.e.r. symtab.") + +    try: +        unbase = Unbaser(radix) +    except TypeError: +        raise UnpackingError("Unknown p.a.c.k.e.r. encoding.") + +    def lookup(match): +        """Look up symbols in the synthetic symtab.""" +        word = match.group(0) +        return symtab[unbase(word)] or word + +    payload = payload.replace("\\\\", "\\").replace("\\'", "'") +    if sys.version_info.major == 2: +        source = re.sub(r"\b\w+\b", lookup, payload) +    else: +        source = re.sub(r"\b\w+\b", lookup, payload, flags=re.ASCII) +    return _replacestrings(source) + + +def _filterargs(source): +    """Juice from a source file the four args needed by decoder.""" +    juicers = [ +        (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\), *(\d+), *(.*)\)\)"), +        (r"}\('(.*)', *(\d+|\[\]), *(\d+), *'(.*)'\.split\('\|'\)"), +    ] +    for juicer in juicers: +        args = re.search(juicer, source, re.DOTALL) +        if args: +            a = args.groups() +            if a[1] == "[]": +                a = list(a) +                a[1] = 62 +                a = tuple(a) +            try: +                return a[0], a[3].split("|"), int(a[1]), int(a[2]) +            except ValueError: +                raise UnpackingError("Corrupted p.a.c.k.e.r. data.") + +    # could not find a satisfying regex +    raise UnpackingError( +        "Could not make sense of p.a.c.k.e.r data (unexpected code structure)" +    ) + + +def _replacestrings(source): +    global beginstr +    global endstr +    """Strip string lookup table (list) and replace values in source.""" +    match = re.search(r'var *(_\w+)\=\["(.*?)"\];', source, re.DOTALL) + +    if match: +        varname, strings = match.groups() +        startpoint = len(match.group(0)) +        lookup = strings.split('","') +        variable = "%s[%%d]" % varname +        for index, value in enumerate(lookup): +            source = source.replace(variable % index, '"%s"' % value) +        return source[startpoint:] +    return beginstr + source + endstr + + +class Unbaser(object): +    """Functor for a given base. Will efficiently convert +    strings to natural numbers.""" + +    ALPHABET = { +        62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", +        95: ( +            " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" +            "[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" +        ), +    } + +    def __init__(self, base): +        self.base = base + +        # fill elements 37...61, if necessary +        if 36 < base < 62: +            if not hasattr(self.ALPHABET, self.ALPHABET[62][:base]): +                self.ALPHABET[base] = self.ALPHABET[62][:base] +        # attrs = self.ALPHABET +        # print ', '.join("%s: %s" % item for item in attrs.items()) +        # If base can be handled by int() builtin, let it do it for us +        if 2 <= base <= 36: +            self.unbase = lambda string: int(string, base) +        else: +            # Build conversion dictionary cache +            try: +                self.dictionary = dict( +                    (cipher, index) for index, cipher in enumerate(self.ALPHABET[base]) +                ) +            except KeyError: +                raise TypeError("Unsupported base encoding.") + +            self.unbase = self._dictunbaser + +    def __call__(self, string): +        return self.unbase(string) + +    def _dictunbaser(self, string): +        """Decodes a  value to an integer.""" +        ret = 0 +        for index, cipher in enumerate(string[::-1]): +            ret += (self.base**index) * self.dictionary[cipher] +        return ret diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__init__.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__init__.py new file mode 100644 index 0000000..dfe67ba --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__init__.py @@ -0,0 +1,2 @@ +# Empty file :) +# pylint: disable=C0111 diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/__init__.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/__init__.cpython-311.pycBinary files differ new file mode 100644 index 0000000..612fa57 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/__init__.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testjavascriptobfuscator.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testjavascriptobfuscator.cpython-311.pycBinary files differ new file mode 100644 index 0000000..6c1abb8 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testjavascriptobfuscator.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testmyobfuscate.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testmyobfuscate.cpython-311.pycBinary files differ new file mode 100644 index 0000000..c62db76 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testmyobfuscate.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testpacker.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testpacker.cpython-311.pycBinary files differ new file mode 100644 index 0000000..86d19bf --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testpacker.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testurlencode.cpython-311.pyc b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testurlencode.cpython-311.pycBinary files differ new file mode 100644 index 0000000..93bd7db --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/__pycache__/testurlencode.cpython-311.pyc diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testjavascriptobfuscator.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testjavascriptobfuscator.py new file mode 100644 index 0000000..d40db2d --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testjavascriptobfuscator.py @@ -0,0 +1,59 @@ +# +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# + +"""Tests for JavaScriptObfuscator unpacker.""" + +import unittest +from jsbeautifier.unpackers.javascriptobfuscator import unpack, detect, smartsplit + +# pylint: disable=R0904 + + +class TestJavascriptObfuscator(unittest.TestCase): +    """JavascriptObfuscator.com test case.""" + +    def test_smartsplit(self): +        """Test smartsplit() function.""" +        split = smartsplit + +        def equals(data, result): +            return self.assertEqual(split(data), result) + +        equals("", []) +        equals('"a", "b"', ['"a"', '"b"']) +        equals('"aaa","bbbb"', ['"aaa"', '"bbbb"']) +        equals('"a", "b\\""', ['"a"', '"b\\""']) + +    def test_detect(self): +        """Test detect() function.""" + +        def positive(source): +            return self.assertTrue(detect(source)) + +        def negative(source): +            return self.assertFalse(detect(source)) + +        negative("") +        negative("abcd") +        negative("var _0xaaaa") +        positive('var _0xaaaa = ["a", "b"]') +        positive('var _0xaaaa=["a", "b"]') +        positive('var _0x1234=["a","b"]') + +    def test_unpack(self): +        """Test unpack() function.""" + +        def decodeto(ob, original): +            return self.assertEqual(unpack(ob), original) + +        decodeto("var _0x8df3=[];var a=10;", "var a=10;") +        decodeto( +            'var _0xb2a7=["\x74\x27\x65\x73\x74"];var i;for(i=0;i<10;++i)' +            "{alert(_0xb2a7[0]);} ;", +            "var i;for(i=0;i<10;++i){alert" '("t\'est");} ;', +        ) + + +if __name__ == "__main__": +    unittest.main() diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testmyobfuscate.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testmyobfuscate.py new file mode 100644 index 0000000..d69df82 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testmyobfuscate.py @@ -0,0 +1,48 @@ +# +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# + +"""Tests for MyObfuscate unpacker.""" + +import unittest +import os +from jsbeautifier.unpackers.myobfuscate import detect, unpack +from jsbeautifier.unpackers.tests import __path__ as path + +INPUT = os.path.join(path[0], "test-myobfuscate-input.js") +OUTPUT = os.path.join(path[0], "test-myobfuscate-output.js") + +# pylint: disable=R0904 + + +class TestMyObfuscate(unittest.TestCase): +    # pylint: disable=C0103 +    """MyObfuscate obfuscator testcase.""" + +    @classmethod +    def setUpClass(cls): +        """Load source files (encoded and decoded version) for tests.""" +        with open(INPUT, "r") as data: +            cls.input = data.read() +        with open(OUTPUT, "r") as data: +            cls.output = data.read() + +    def test_detect(self): +        """Test detect() function.""" + +        def detected(source): +            return self.assertTrue(detect(source)) + +        detected(self.input) + +    def test_unpack(self): +        """Test unpack() function.""" + +        def check(inp, out): +            return self.assertEqual(unpack(inp), out) + +        check(self.input, self.output) + + +if __name__ == "__main__": +    unittest.main() diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testpacker.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testpacker.py new file mode 100644 index 0000000..1de9934 --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testpacker.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +# +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# + +"""Tests for P.A.C.K.E.R. unpacker.""" + +import unittest +from jsbeautifier.unpackers.packer import detect, unpack + +# pylint: disable=R0904 + + +class TestPacker(unittest.TestCase): +    """P.A.C.K.E.R. testcase.""" + +    def test_detect(self): +        """Test detect() function.""" + +        def positive(source): +            return self.assertTrue(detect(source)) + +        def negative(source): +            return self.assertFalse(detect(source)) + +        negative("") +        negative("var a = b") +        positive("eval(function(p,a,c,k,e,r") +        positive("eval ( function(p, a, c, k, e, r") + +    def test_unpack(self): +        """Test unpack() function.""" + +        def check(inp, out): +            return detect(inp) and self.assertEqual(unpack(inp), out) + +        check( +            "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String)" +            "){while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=" +            "function(){return'\\\\w+'};c=1};while(c--)if(k[c])p=p.replace(" +            "new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p}('0 2=1'," +            "62,3,'var||a'.split('|'),0,{}))", +            "var a=1", +        ) + +        check( +            "function test (){alert ('This is a test!')}; " +            "eval(function(p,a,c,k,e,r){e=String;if(!''.replace(/^/,String))" +            "{while(c--)r[c]=k[c]||c;k=[function(e){return r[e]}];e=function" +            "(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp(" +            "'\\b'+e(c)+'\\b','g'),k[c]);return p}('0 2=\\'{Íâ–+›ï;ã†Ù¥#\\'',3,3," +            "'var||a'.split('|'),0,{}))", +            "function test (){alert ('This is a test!')}; var a='{Íâ–+›ï;ã†Ù¥#'", +        ) + +        check( +            "eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('2 0=\"4 3!\";2 1=0.5(/b/6);a.9(\"8\").7=1;',12,12,'str|n|var|W3Schools|Visit|search|i|innerHTML|demo|getElementById|document|w3Schools'.split('|'),0,{}))", +            'var str="Visit W3Schools!";var n=str.search(/w3Schools/i);document.getElementById("demo").innerHTML=n;', +        ) + +        check( +            "a=b;\r\nwhile(1){\ng=h;{return'\\w+'};break;eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('$(5).4(3(){$('.1').0(2);$('.6').0(d);$('.7').0(b);$('.a').0(8);$('.9').0(c)});',14,14,'html|r5e57|8080|function|ready|document|r1655|rc15b|8888|r39b0|r6ae9|3128|65309|80'.split('|'),0,{}))c=abx;", +            "a=b;\r\nwhile(1){\ng=h;{return'\\w+'};break;$(document).ready(function(){$('.r5e57').html(8080);$('.r1655').html(80);$('.rc15b').html(3128);$('.r6ae9').html(8888);$('.r39b0').html(65309)});c=abx;", +        ) + +        check( +            "eval(function(p,a,c,k,e,r){e=function(c){return c.toString(36)};if('0'.replace(0,e)==0){while(c--)r[e(c)]=k[c];k=[function(e){return r[e]||e}];e=function(){return'[0-9ab]'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('$(5).a(6(){ $('.8').0(1); $('.b').0(4); $('.9').0(2); $('.7').0(3)})',[],12,'html|52136|555|65103|8088|document|function|r542c|r8ce6|rb0de|ready|rfab0'.split('|'),0,{}))", +            "$(document).ready(function(){ $('.r8ce6').html(52136); $('.rfab0').html(8088); $('.rb0de').html(555); $('.r542c').html(65103)})", +        ) + + +if __name__ == "__main__": +    unittest.main() diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testurlencode.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testurlencode.py new file mode 100644 index 0000000..10e236d --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/tests/testurlencode.py @@ -0,0 +1,46 @@ +# +#     written by Stefano Sanfilippo <a.little.coder@gmail.com> +# + +"""Tests for urlencoded unpacker.""" + +import unittest + +from jsbeautifier.unpackers.urlencode import detect, unpack + +# pylint: disable=R0904 + + +class TestUrlencode(unittest.TestCase): +    """urlencode test case.""" + +    def test_detect(self): +        """Test detect() function.""" + +        def encoded(source): +            return self.assertTrue(detect(source)) + +        def unencoded(source): +            return self.assertFalse(detect(source)) + +        unencoded("") +        unencoded("var a = b") +        encoded("var%20a+=+b") +        encoded("var%20a=b") +        encoded("var%20%21%22") + +    def test_unpack(self): +        """Test unpack function.""" + +        def equals(source, result): +            return self.assertEqual(unpack(source), result) + +        equals("", "") +        equals("abcd", "abcd") +        equals("var a = b", "var a = b") +        equals("var%20a=b", "var a=b") +        equals("var%20a+=+b", "var a = b") + + +if __name__ == "__main__": +    unittest.main() diff --git a/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/urlencode.py b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/urlencode.py new file mode 100644 index 0000000..d0d492a --- /dev/null +++ b/venv/lib/python3.11/site-packages/jsbeautifier/unpackers/urlencode.py @@ -0,0 +1,36 @@ +# +# Trivial bookmarklet/escaped script detector for the javascript beautifier +#     written by Einar Lielmanis <einar@beautifier.io> +#     rewritten in Python by Stefano Sanfilippo <a.little.coder@gmail.com> +# +# Will always return valid javascript: if `detect()` is false, `code` is +# returned, unmodified. +# +# usage: +# +# some_string = urlencode.unpack(some_string) +# + +"""Bookmarklet/escaped script unpacker.""" + +# Python 2 retrocompatibility +# pylint: disable=F0401 +# pylint: disable=E0611 +try: +    from urllib import unquote_plus +except ImportError: +    from urllib.parse import unquote_plus + +PRIORITY = 0 + + +def detect(code): +    """Detects if a scriptlet is urlencoded.""" +    # the fact that script doesn't contain any space, but has %20 instead +    # should be sufficient check for now. +    return " " not in code and ("%20" in code or code.count("%") > 3) + + +def unpack(code): +    """URL decode `code` source string.""" +    return unquote_plus(code) if detect(code) else code | 
