Skip to main content

Python cross-version byte-code decompiler

Project description

buildstatus Latest Version Supported Python Versions

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.3 to version 3.7, spanning over 22 years of Python releases. We include Dropbox’s Python 2.5 bytecode and some PyPy 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 at run time 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 those 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.4, 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 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.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.0 is weird in that it in some ways resembles 2.6 more than it does 3.1 or 2.7. 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.

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.3.tar.gz (1.6 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.3-py36-none-any.whl (200.9 kB view details)

Uploaded Python 3.6

uncompyle6-3.2.3-py35-none-any.whl (200.9 kB view details)

Uploaded Python 3.5

uncompyle6-3.2.3-py34-none-any.whl (200.9 kB view details)

Uploaded Python 3.4

uncompyle6-3.2.3-py32-none-any.whl (206.7 kB view details)

Uploaded Python 3.2

uncompyle6-3.2.3-py27-none-any.whl (206.7 kB view details)

Uploaded Python 2.7

uncompyle6-3.2.3-py26-none-any.whl (206.7 kB view details)

Uploaded Python 2.6

uncompyle6-3.2.3-py3.6.egg (414.9 kB view details)

Uploaded Egg

uncompyle6-3.2.3-py3.5.egg (421.5 kB view details)

Uploaded Egg

uncompyle6-3.2.3-py3.4.egg (423.7 kB view details)

Uploaded Egg

uncompyle6-3.2.3-py3.2.egg (423.1 kB view details)

Uploaded Egg

uncompyle6-3.2.3-py2.7.egg (416.3 kB view details)

Uploaded Egg

uncompyle6-3.2.3-py2.6.egg (417.0 kB view details)

Uploaded Egg

uncompyle6-3.2.3-py2.5.egg (415.8 kB view details)

Uploaded Egg

uncompyle6-3.2.3-py2.4.egg (420.3 kB view details)

Uploaded Egg

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-3.2.3.tar.gz
Algorithm Hash digest
SHA256 bd882f3c979b49d28ba7accc5ce7380ced8cab12e782e9170769ca15f0b81f8a
MD5 5ec0075540a010745eb64f2a95857f63
BLAKE2b-256 148b0791a49ca176d20fdacd3e34a2ac50ccd5119b8de67c044da0a9bba856fa

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.3-py36-none-any.whl.

File metadata

File hashes

Hashes for uncompyle6-3.2.3-py36-none-any.whl
Algorithm Hash digest
SHA256 42a2cfd6e6c4219fd4b389cdc2d90ffa03ad75b03e30bc82f3a1feeb05f8b0f2
MD5 a8721c5133f8efa1c8312614cd038ca0
BLAKE2b-256 b1816f51ce184aae921d770a17503ba6bc49e1ab72950bbb916e5268ea4e9b14

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-3.2.3-py35-none-any.whl
Algorithm Hash digest
SHA256 0e5a7b253ab52b8c1f9a783c8b6aa8b832f295d3b745e8537b0a40c86c6f5019
MD5 149ffa44fb495a0011129119e21ece3e
BLAKE2b-256 4ecdfe23ceac84fb14bc9af2ea849714965453ba7c150e4c2425179ec9c63ffd

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.3-py34-none-any.whl.

File metadata

File hashes

Hashes for uncompyle6-3.2.3-py34-none-any.whl
Algorithm Hash digest
SHA256 d40b841326c1688990fdbbb9782f63e0b42fe879c4631340c628df75941228ac
MD5 6a499a8f680030172503b007c8562374
BLAKE2b-256 ab103b1a82a85805fe3eded7202d1dc9489c1aac0ba3f10417ddaed3ffc7f351

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-3.2.3-py32-none-any.whl
Algorithm Hash digest
SHA256 44234bb0bb6847e7274930518b7099bc80c0ecb07bf050e8e600d91ac6a231bb
MD5 644cc17ab2b8f5b2efb11edc8d1fdcbc
BLAKE2b-256 2d9e20b688360c8b62bb3f3fc11d1bcfae8c2257896f0f03ce4e08601c5017f7

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-3.2.3-py27-none-any.whl
Algorithm Hash digest
SHA256 e02502aac990e8a2dd53f4607d610f7e1d58f243e65b8be51ab538b3f6061a65
MD5 2ea22a3fe1747b6b42c6be9d22610a0f
BLAKE2b-256 cc31c00d1547cd46621bfd05e3b1b8dfe6d62df9b478d34a810bd4a831bae050

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-3.2.3-py26-none-any.whl
Algorithm Hash digest
SHA256 a55ed1ae2b216f9af497f2ab1f35b65923aeb0c6ad0e4e3fff23f8f7e1008501
MD5 6eb3dfa6c98467406054cdc524c0c67d
BLAKE2b-256 b8b42ecf5110ac575ffc8643ffaaf6c9f595b8b3c908a353c9f1202066e87b91

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.3-py3.6.egg.

File metadata

  • Download URL: uncompyle6-3.2.3-py3.6.egg
  • Upload date:
  • Size: 414.9 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.3-py3.6.egg
Algorithm Hash digest
SHA256 ebe8af75f2c51ac1d0957fcc3ae404076d6310d234949486cc112e4587346268
MD5 564d61af653511ee592a81dbaa071c0b
BLAKE2b-256 3e04cb72d6eec4a7a5a45e466da7c426b91c69668ee65c7054daa45431648591

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-3.2.3-py3.5.egg
Algorithm Hash digest
SHA256 19138975ab15baa70dbd9dd34abe2e835981841de4339792b654150bb8c6f41f
MD5 cab0d9c6ae77ec0f9921e12eaf993159
BLAKE2b-256 3b52d98a446ba693532b8ccca39682c5f15a7b43f27ca1fdf3db297834c5409c

See more details on using hashes here.

File details

Details for the file uncompyle6-3.2.3-py3.4.egg.

File metadata

  • Download URL: uncompyle6-3.2.3-py3.4.egg
  • Upload date:
  • Size: 423.7 kB
  • Tags: Egg
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-3.2.3-py3.4.egg
Algorithm Hash digest
SHA256 97e70a8303a7aaacaf95cfb0053865d60bfcdeeb8a00ef0c2ab28317b682821f
MD5 5b122a38e32af952efc8ed826cfbd183
BLAKE2b-256 0bef25c6c54204fe186f303d0b770a74c24c43489e2ab763f99b8ed186832c8b

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-3.2.3-py3.2.egg
Algorithm Hash digest
SHA256 10c94137d6d6b79dc520f0c000cf144af3fd90bd3afaacbeecd2212ef17370c4
MD5 c98dbfdbfd5932a3c05756d2aa89f68a
BLAKE2b-256 080602ad28afae9ff04ede8c7cae34ae9d670470d81e9fda2c3a67259f5a5c95

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-3.2.3-py2.7.egg
Algorithm Hash digest
SHA256 1fcc46dd712b627f2c3e45bc17f67c2c1d71b2d29e7946f3964b6dbcb3f67298
MD5 558f041ed23866f5746b403af5ce26a8
BLAKE2b-256 1fecf11e9db440d62f775b912c2d500b348237dab386d1786ca62d6731658aa1

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-3.2.3-py2.6.egg
Algorithm Hash digest
SHA256 6259bd72dfd061dd134077233e1b8f87ca20bb336710d97a8c393cbe4f53b07b
MD5 9063597bbec6e009a7361b3ae766806e
BLAKE2b-256 4e66630987c85c37ed57f0ead7632a581ed4c019c8eea7f09a12f06138001729

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-3.2.3-py2.5.egg
Algorithm Hash digest
SHA256 1110ee839c76b6d0a70ccfe1bb72a7de89a738e680ab03b81cf40692b9c4ea51
MD5 6b2d4a715f3cfedcd4f8cad19f943f8b
BLAKE2b-256 152746ada49c356b65aeceaf5273c81bc4fa993058f2184815fbcc59f2b0c98c

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-3.2.3-py2.4.egg
Algorithm Hash digest
SHA256 69e0ce5019b675a6654967992a60a1574cfd4faac93100240ec6e92e281aa2d8
MD5 60adbf897a0e9b92c5f78e35d9c5bb6f
BLAKE2b-256 b58e6bd6598abf798e26d57dfe2d9b3d845a92b3c13819f0f6e78b9b8dd6dc5f

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