Skip to main content

Python cross-version byte-code decompiler

Project description

buildstatus

uncompyle6

A native Python cross-version decompiler and fragment decompiler. The successor to decompyle, uncompyle, and uncompyle2.

Introduction

uncompyle6 translates Python bytecode back into equivalent Python source code. It accepts bytecodes from Python version 1.5, and 2.1 to 3.7 or so, including PyPy bytecode and Dropbox’s Python 2.5 bytecode.

Why this?

Ok, I’ll say it: this software is amazing. It is more than your normal hacky decompiler. Using compiler technology, the program creates a parse tree of the program from the instructions; nodes at the upper levels that look a little like what might come from a Python AST. So we can really classify and understand what’s going on in sections of Python bytecode.

Building on this, another thing that makes this different from other CPython bytecode decompilers is the ability to deparse just fragments of source code and give source-code information around a given bytecode offset.

I use the tree fragments to deparse fragments of code inside my trepan debuggers. For that, bytecode offsets are recorded and associated with fragments of the source code. This purpose, although compatible with the original intention, is yet a little bit different. See this for more information.

Python fragment deparsing given an instruction offset is useful in showing stack traces and can be encorporated into any program that wants to show a location in more detail than just a line number at runtime. This code can be also used when source-code information does not exist and there is just bytecode. Again, my debuggers make use of this.

There were (and still are) a number of decompyle, uncompyle, uncompyle2, uncompyle3 forks around. Almost all of them come basically from the same code base, and (almost?) all of them are no longer actively maintained. One was really good at decompiling Python 1.5-2.3 or so, another really good at Python 2.7, but that only. Another handles Python 3.2 only; another patched that and handled only 3.3. You get the idea. This code pulls all of these forks together and moves forward. There is some serious refactoring and cleanup in this code base over those old forks.

This demonstrably does the best in decompiling Python across all Python versions. And even when there is another project that only provides decompilation for subset of Python versions, we generally do demonstrably better for those as well.

How can we tell? By taking Python bytecode that comes distributed with that version of Python and decompiling these. Among htose that successfully decompile, we can then make sure the resulting programs are syntactically correct by running the Python interpreter for that bytecode version. Finally, in cases where the program has a test for itself, we can run the check on the decompiled code.

We are serious about testing, and use automated processes to find bugs. In the issue trackers for other decompilers, you will find a number of bugs we’ve found along the way. Very few to none of them are fixed in the other decompilers.

Requirements

The code here can be run on Python versions 2.6 or later, PyPy 3-2.4, or PyPy-5.0.1. Python versions 2.4-2.7 are supported in the python-2.4 branch. The bytecode files it can read have been tested on Python bytecodes from versions 1.5, 2.1-2.7, and 3.0-3.6 and the above-mentioned PyPy versions.

Installation

This uses setup.py, so it follows the standard Python routine:

pip install -e .  # set up to run from source tree
                  # Or if you want to install instead
python setup.py install # may need sudo

A GNU makefile is also provided so make install (possibly as root or sudo) will do the steps above.

Testing

make check

A GNU makefile has been added to smooth over setting running the right command, and running tests from fastest to slowest.

If you have remake installed, you can see the list of all tasks including tests via remake --tasks

Usage

Run

$ uncompyle6 *compiled-python-file-pyc-or-pyo*

For usage help:

$ uncompyle6 -h

If you want strong verification of the correctness of the decompilation process, add the –verify option. But there are situations where this will indicate a failure, although the generated program is semantically equivalent. Using option –weak-verify will tell you if there is something definitely wrong. Generally, large swaths of code are decompiled correctly, if not the entire program.

You can also cross compare the results with pycdc . Since they work differently, bugs here often aren’t in that, and vice versa.

Known Bugs/Restrictions

The biggest known and possibly fixable (but hard) problem has to do with handling control flow. (Python has probably the most diverse and screwy set of compound statements I’ve ever seen; there are “else” clauses on loops and try blocks that I suspect many programmers don’t know about.)

All of the Python decompilers that I have looked at have problems decompiling Python’s control flow. In some cases we can detect an erroneous decompilation and report that.

In older versions of Python it was possible to verify bytecode by decompiling bytecode, and then compiling using the Python interpreter for that bytecode version. Having done this the bytecode produced could be compared with the original bytecode. However as Python’s code generation got better, this is no longer feasible.

There is a kind of weak verification that we use that doesn’t check bytecode for equivalence but does check to see if the resulting decompiled source is a valid Python program by running the Python interpreter. Because the Python language has changed so much, for best results you should use the same Python version in checking as was used in creating the bytecode.

There are however an interesting class of these programs that is readily available give stronger verification: those programs that when run check some computation, or even better themselves.

And already Python has a set of programs like this: the test suite for the standard library that comes with Python. We have some code in test/stdlib to facilitate this kind of checking.

Python support is strongest in Python 2 for 2.7 and drops off as you get further away from that. Support is also probably pretty good for python 2.3-2.4 since a lot of the goodness of early the version of the decompiler from that era has been preserved (and Python compilation in that era was minimal)

There is some work to do on the lower end Python versions which is more difficult for us to handle since we don’t have a Python interpreter for versions 1.5, 1.6, and 2.0.

In the Python 3 series, Python support is is strongest around 3.4 or 3.3 and drops off as you move further away from those versions. Python 3.6 changes things drastically by using word codes rather than byte codes. As a result, the jump offset field in a jump instruction argument has been reduced. This makes the EXTENDED_ARG instructions are now more prevalent in jump instruction; previously they had been rare. Perhaps to compensate for the additional EXTENDED_ARG instructions, additional jump optimization has been added. So in sum handling control flow by ad hoc means as is currently done is worse.

Also, between Python 3.5, 3.6 and 3.7 there have been major changes to the MAKE_FUNCTION and CALL_FUNCTION instructions.

Currently not all Python magic numbers are supported. Specifically in some versions of Python, notably Python 3.6, the magic number has changes several times within a version. We support only the released magic. There are also customized Python interpreters, notably Dropbox, which use their own magic and encrypt bytcode. With the exception of the Dropbox’s old Python 2.5 interpreter this kind of thing is not handled.

We also don’t handle PJOrion obfuscated code. For that try: PJOrion Deobfuscator to unscramble the bytecode to get valid bytecode before trying this tool. This program can’t decompile Microsoft Windows EXE files created by Py2EXE, although we can probably decompile the code after you extract the bytecode properly. For situations like this, you might want to consider a decompilation service like Crazy Compilers. Handling pathologically long lists of expressions or statements is slow.

There is lots to do, so please dig in and help.

See Also

Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

uncompyle6-3.2.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

uncompyle6-3.2.0-py35-none-any.whl (202.7 kB view details)

Uploaded Python 3.5

uncompyle6-3.2.0-py33-none-any.whl (202.7 kB view details)

Uploaded Python 3.3

uncompyle6-3.2.0-py32-none-any.whl (202.7 kB view details)

Uploaded Python 3.2

uncompyle6-3.2.0-py27-none-any.whl (202.7 kB view details)

Uploaded Python 2.7

uncompyle6-3.2.0-py26-none-any.whl (202.8 kB view details)

Uploaded Python 2.6

uncompyle6-3.2.0-py3.5.egg (413.9 kB view details)

Uploaded Egg

uncompyle6-3.2.0-py3.3.egg (420.6 kB view details)

Uploaded Egg

uncompyle6-3.2.0-py3.2.egg (415.5 kB view details)

Uploaded Egg

uncompyle6-3.2.0-py2.7.egg (408.7 kB view details)

Uploaded Egg

uncompyle6-3.2.0-py2.6.egg (409.4 kB view details)

Uploaded Egg

uncompyle6-3.2.0-py2.5.egg (408.8 kB view details)

Uploaded Egg

uncompyle6-3.2.0-py2.4.egg (413.4 kB view details)

Uploaded Egg

File details

Details for the file uncompyle6-3.2.0.tar.gz.

File metadata

  • Download URL: uncompyle6-3.2.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0.tar.gz
Algorithm Hash digest
SHA256 3985675039554fb0ce3c7cff823a747a93f96a29946c5f39ab3c0f72bad8a2a2
MD5 7553131a210a1cb175882285ffdb3452
BLAKE2b-256 282a4a6793d07d87268ea0baa6aa97a9c8d27e64fec48fbc9dbdf5293c026ed5

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py35-none-any.whl.

File metadata

File hashes

Hashes for uncompyle6-3.2.0-py35-none-any.whl
Algorithm Hash digest
SHA256 679c727e3c468a922ed8ee0094448db78448989362aa2ca23ba5d98b3db381f1
MD5 c7ccdaa4be43186fc85791696cb8c07c
BLAKE2b-256 d1a2508227a798eee243fa9568fa2fbdcd9a3dd23d4e31a3c4b3ad21973c335b

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py33-none-any.whl.

File metadata

File hashes

Hashes for uncompyle6-3.2.0-py33-none-any.whl
Algorithm Hash digest
SHA256 a7c3351e3b8357245faaa3934fb59623b5ecf75f629f6fb5a7d2d02f25ff8021
MD5 a56067ba31fcc138db6f62491c5a197d
BLAKE2b-256 bdcc802b7618b24f6ce7285452dbc9fd2ae1a8e824c26185bc35fc894eb3e4ab

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py32-none-any.whl.

File metadata

File hashes

Hashes for uncompyle6-3.2.0-py32-none-any.whl
Algorithm Hash digest
SHA256 9b91cecf8ad398cb13b804bbdbc34fb0570a3552777f873eb55c109c28221ded
MD5 eb6774b43dec5e0e12cf3173b7db1e99
BLAKE2b-256 2e0ad01521053be234c7274310368911ab99457c6d4dbc13ed403e609d24fba2

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py27-none-any.whl.

File metadata

File hashes

Hashes for uncompyle6-3.2.0-py27-none-any.whl
Algorithm Hash digest
SHA256 12b27e7179516d77136629b094e1665fd5c6fc4583eea4a2b81cd98dfb0d046d
MD5 ed01b24a489e28e9c9ede3f7de1fa635
BLAKE2b-256 d2c1cb75be732325593d086d4f62e919c313fa2768a40678ae58d5dac8638c38

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py26-none-any.whl.

File metadata

File hashes

Hashes for uncompyle6-3.2.0-py26-none-any.whl
Algorithm Hash digest
SHA256 ebe473b2e5b64adbeb9a2dc3cb88d1f811ff84cb7289d4f5b942568b558c091f
MD5 d82b1e04f04c0e4081f48784babbb715
BLAKE2b-256 33db32667829db95943d0ea1fc161a8108249e3444ee2abc17a69d8a5e2049ed

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py3.5.egg.

File metadata

  • Download URL: uncompyle6-3.2.0-py3.5.egg
  • Upload date:
  • Size: 413.9 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0-py3.5.egg
Algorithm Hash digest
SHA256 83fea296bb01a4e94bf1b0e70ab3eebeff8a1bb4029c0213bc89bdc2c55e7bb1
MD5 744ae4cebd495be15cec2eebf0aca610
BLAKE2b-256 da308dd95cad6692fc9de615563089f20ca821b8c6d3b782278b252cd4a9bf85

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py3.3.egg.

File metadata

  • Download URL: uncompyle6-3.2.0-py3.3.egg
  • Upload date:
  • Size: 420.6 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0-py3.3.egg
Algorithm Hash digest
SHA256 610335002a9c49c1e98a04f615d23602e4d081d3b2992a867a48e5162cb86c0a
MD5 931063b4f5add840d69d4f4916d2370e
BLAKE2b-256 1a22483653145069982fa8e8d0fdbbc09b6b3d5e06af2fde9a412ecf1d15025f

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py3.2.egg.

File metadata

  • Download URL: uncompyle6-3.2.0-py3.2.egg
  • Upload date:
  • Size: 415.5 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0-py3.2.egg
Algorithm Hash digest
SHA256 339329faf77ec6e53b87e70353545c472f253b0f7772ec369ef705e763de9ce6
MD5 347c8738b44917f6e2dddeffe96f5979
BLAKE2b-256 ae86133a13634363d7ea1c84f2da41546ab77a57cbcd1ebb55a0f56617edf829

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py2.7.egg.

File metadata

  • Download URL: uncompyle6-3.2.0-py2.7.egg
  • Upload date:
  • Size: 408.7 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0-py2.7.egg
Algorithm Hash digest
SHA256 f6ed1d07ac5c7addc23ca6d435fc0c3c9d124e99cb143edffbcdee5c0a564c66
MD5 ea2969799cee0f33db4d1de782d6e618
BLAKE2b-256 25eac273c789a89e92737873a1094a6b0a11fcf608373ce94ce0458ca194250b

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py2.6.egg.

File metadata

  • Download URL: uncompyle6-3.2.0-py2.6.egg
  • Upload date:
  • Size: 409.4 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0-py2.6.egg
Algorithm Hash digest
SHA256 d4a96c43cec878e438a8abca515d9a05203038adf41c28e9423232dd61b9aeeb
MD5 466cf006d3b308ecfdd6fdd94980c1f3
BLAKE2b-256 e67e799a37699eef7ea8afc24eb53893ea8bcd367da921bbeded2926321eb101

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py2.5.egg.

File metadata

  • Download URL: uncompyle6-3.2.0-py2.5.egg
  • Upload date:
  • Size: 408.8 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0-py2.5.egg
Algorithm Hash digest
SHA256 94a61a046e0754a76c64dc843a3e91d071dfe5dda6691a3b5c8539e4132b6ab1
MD5 2d4434318d9709ff4e9a1f297ad1a9ac
BLAKE2b-256 7eea6c38e5d2e2a6eecf28009dabd3bbe8f8b085c85f8c84b9b17504e4bed861

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.0-py2.4.egg.

File metadata

  • Download URL: uncompyle6-3.2.0-py2.4.egg
  • Upload date:
  • Size: 413.4 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.0-py2.4.egg
Algorithm Hash digest
SHA256 182a922633e09a688240718c67991da210967f8946755af6e2b2ba6c666c2f1b
MD5 271469d5a2d19ea6bcde01d686b79242
BLAKE2b-256 a55cb988f620967b8be4adc1c605e2b08286520f985e40e283bbc14a2171e629

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page