Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Merge pull request #77 from satufk/master

Adding new encodings to P.A.C.K.E.R. unpacker.
  • Loading branch information...
commit 2a34726a857a385301f09900eb7f9ef67f0b0c07 2 parents e5c8a0c + 47f6634
Stefano Sanfilippo authored
16 python/js-beautify-profile
... ... @@ -0,0 +1,16 @@
  1 +#! /usr/bin/env python
  2 +
  3 +import sys
  4 +import unittest
  5 +
  6 +#Speedup things...
  7 +try:
  8 + import cProfile as profile
  9 +except ImportError:
  10 + import profile
  11 +
  12 +def run():
  13 + sys.argv.append('discover')
  14 + unittest.main()
  15 +
  16 +profile.run('run()')
54 python/jsbeautifier/unpackers/packer.py
@@ -26,16 +26,18 @@ def unpack(source):
26 26 """Unpacks P.A.C.K.E.R. packed js code."""
27 27 payload, symtab, radix, count = _filterargs(source)
28 28
29   - if radix != 62:
30   - raise UnpackingError('Unknown p.a.c.k.e.r. encoding.')
31   -
32 29 if count != len(symtab):
33 30 raise UnpackingError('Malformed p.a.c.k.e.r. symtab.')
34 31
  32 + try:
  33 + unbase = Unbaser(radix)
  34 + except TypeError:
  35 + raise UnpackingError('Unknown p.a.c.k.e.r. encoding.')
  36 +
35 37 def lookup(match):
36 38 """Look up symbols in the synthetic symtab."""
37 39 word = match.group(0)
38   - return symtab[unbase62(word)] or word
  40 + return symtab[unbase(word)] or word
39 41
40 42 source = re.sub(r'\b\w+\b', lookup, payload)
41 43 return _replacestrings(source)
@@ -45,6 +47,7 @@ def _filterargs(source):
45 47 argsregex = (r"}\('(.*)', *(\d+), *(\d+), *'(.*)'\."
46 48 r"split\('\|'\), *(\d+), *(.*)\)\)")
47 49 args = re.search(argsregex, source, re.DOTALL).groups()
  50 +
48 51 try:
49 52 return args[0], args[3].split('|'), int(args[1]), int(args[2])
50 53 except ValueError:
@@ -53,6 +56,7 @@ def _filterargs(source):
53 56 def _replacestrings(source):
54 57 """Strip string lookup table (list) and replace values in source."""
55 58 match = re.search(r'var *(_\w+)\=\["(.*?)"\];', source, re.DOTALL)
  59 +
56 60 if match:
57 61 varname, strings = match.groups()
58 62 startpoint = len(match.group(0))
@@ -63,12 +67,38 @@ def _replacestrings(source):
63 67 return source[startpoint:]
64 68 return source
65 69
66   -ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
67   -BASE_DICT = dict((cipher, index) for index, cipher in enumerate(ALPHABET))
68 70
69   -def unbase62(string):
70   - """Decodes a base62 value to an integer."""
71   - ret = 0
72   - for index, cipher in enumerate(string[::-1]):
73   - ret += (62 ** index) * BASE_DICT[cipher]
74   - return ret
  71 +class Unbaser(object):
  72 + """Functor for a given base. Will efficiently convert
  73 + strings to natural numbers."""
  74 + ALPHABET = {
  75 + 62 : '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
  76 + 95 : (' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  77 + '[\]^_`abcdefghijklmnopqrstuvwxyz{|}~')
  78 + }
  79 +
  80 + def __init__(self, base):
  81 + self.base = base
  82 +
  83 + # If base can be handled by int() builtin, let it do it for us
  84 + if 2 <= base <= 36:
  85 + self.unbase = lambda string: int(string, base)
  86 + else:
  87 + # Build conversion dictionary cache
  88 + try:
  89 + self.dictionary = dict((cipher, index) for
  90 + index, cipher in enumerate(self.ALPHABET[base]))
  91 + except KeyError:
  92 + raise TypeError('Unsupported base encoding.')
  93 +
  94 + self.unbase = self._dictunbaser
  95 +
  96 + def __call__(self, string):
  97 + return self.unbase(string)
  98 +
  99 + def _dictunbaser(self, string):
  100 + """Decodes a value to an integer."""
  101 + ret = 0
  102 + for index, cipher in enumerate(string[::-1]):
  103 + ret += (self.base ** index) * self.dictionary[cipher]
  104 + return ret

0 comments on commit 2a34726

Please sign in to comment.
Something went wrong with that request. Please try again.