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 project has the most complete support for Python 3.3 and above and the best all-around Python support.

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.

Verification is the process of decompiling bytecode, compiling with a Python for that bytecode version, and then comparing the bytecode produced by the decompiled/compiled program. Some allowance is made for inessential differences. But other semantically equivalent differences are not caught. For example 1 and 0 is decompiled to the equivalent 0; remnants of the first true evaluation (1) is lost when Python compiles this. When Python next compiles 0 the resulting code is simpler.

Weak Verification on the other hand 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 used in the bytecode.

Finally, we have automated running the standard Python tests after first compiling and decompiling the test program. Results here are a bit weak (if not better than most other Python decompilers). But over time this will probably get better.

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-2.16.0.tar.gz (911.1 kB view details)

Uploaded Source

Built Distributions

uncompyle6-2.16.0-py36-none-any.whl (182.5 kB view details)

Uploaded Python 3.6

uncompyle6-2.16.0-py35-none-any.whl (182.5 kB view details)

Uploaded Python 3.5

uncompyle6-2.16.0-py34-none-any.whl (182.5 kB view details)

Uploaded Python 3.4

uncompyle6-2.16.0-py33-none-any.whl (182.5 kB view details)

Uploaded Python 3.3

uncompyle6-2.16.0-py27-none-any.whl (182.5 kB view details)

Uploaded Python 2.7

uncompyle6-2.16.0-py26-none-any.whl (182.5 kB view details)

Uploaded Python 2.6

uncompyle6-2.16.0-py3.6.egg (377.9 kB view details)

Uploaded Source

uncompyle6-2.16.0-py3.5.egg (384.4 kB view details)

Uploaded Source

uncompyle6-2.16.0-py3.4.egg (386.3 kB view details)

Uploaded Source

uncompyle6-2.16.0-py3.3.egg (391.2 kB view details)

Uploaded Source

uncompyle6-2.16.0-py2.7.egg (379.5 kB view details)

Uploaded Source

uncompyle6-2.16.0-py2.6.egg (380.2 kB view details)

Uploaded Source

uncompyle6-2.16.0-py2.5.egg (379.7 kB view details)

Uploaded Source

uncompyle6-2.16.0-py2.4.egg (384.0 kB view details)

Uploaded Source

File details

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

File metadata

  • Download URL: uncompyle6-2.16.0.tar.gz
  • Upload date:
  • Size: 911.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for uncompyle6-2.16.0.tar.gz
Algorithm Hash digest
SHA256 9616ce52c4cb84e9f0ef4a5218e5ea0fe8266576245971b3bfd537853163bb1c
MD5 27d54aa5c44f6f1184e703f0309e1d6e
BLAKE2b-256 5f8d805da16483b4b3f48de9854d3ba4ccbeb5b4fed8339d3eb943f2befb0e42

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py36-none-any.whl
Algorithm Hash digest
SHA256 ecb8775bd4510e99692139c5a37e292116956b14e92cf4d91b16788e3b14f8de
MD5 f0daf80054c243e4b6f633698959f817
BLAKE2b-256 e5b79e6770a77eb2aac1ea62011871770728fa5cda187933ae84042aa65faa1e

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py35-none-any.whl
Algorithm Hash digest
SHA256 b2362aa5291263315ed0a81a0a66fd07f5181cd5d24770a1338b2e53d0fcecf9
MD5 215e4bcae94cafe01a0ca68123d85545
BLAKE2b-256 725fa3478179a7c5b7942fc669012cd64f6cb07668f164364b5aeab34253f47a

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py34-none-any.whl
Algorithm Hash digest
SHA256 f13e2a60b22fe1179fe6998b5ed386b437e1709badfec5ebab7fe3bb3447e53b
MD5 43ecf848fe029913528b6c761a7bfd8a
BLAKE2b-256 28f119c496c851fa101a65782c54c45d3f0c1afeb366ae3677c4218ce617572c

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py33-none-any.whl
Algorithm Hash digest
SHA256 5401154df6cbb38d3f30d8079a98b74bad84a5ee8eb15fd6aa52216858545f2e
MD5 5e53ba9644ed011017a38531f594d83c
BLAKE2b-256 049fd06c3f6accf8b29abeb3ec8a05aa911bdc64e475adae8dec331169571f8d

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py27-none-any.whl
Algorithm Hash digest
SHA256 c9072d771b705f435f92329b77e112d6f4f370d650475031a64807072edd3b1c
MD5 c5e6ca075457bf1a7cca127e31986c17
BLAKE2b-256 f5b68d1d40248c04044dcf80a085f60a288d04c197fde41c7ad2bf29e305f62c

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py26-none-any.whl
Algorithm Hash digest
SHA256 4f490fbbe9c5b609eff1b182129e713f044a1b5dc5db1be1b7610e466b5a9421
MD5 b3face373e54e2a1daaf7d68fef3ac02
BLAKE2b-256 3273832737ba615a988931e4ee341a05fed489a7a3152462298b444b1051d8b5

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py3.6.egg
Algorithm Hash digest
SHA256 350747ea5ec2d077ef636a6ec9ebb8c3a08b179eee6a940cea560a07468677ba
MD5 1a835d462a287e5e0b8503e03bae2853
BLAKE2b-256 4760918fa2facacaf5f943f0e9dcee0c92e2272938f2c57bdfad1d8fbb7259d7

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py3.5.egg
Algorithm Hash digest
SHA256 feeb26bc16aac185a2a2f1656c45ece5fe395573dd637b3cbac10c27cc42d7f8
MD5 1597ad665b8e07f638941ca7a8971c2a
BLAKE2b-256 14cb3c709f1f0841e5c8493b3a25a82dfa4d0991a4e46f558928bc6367ffa6fb

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py3.4.egg
Algorithm Hash digest
SHA256 d557a875b1737e8d3d6da001ad40c35a77e6995ac8efa03edc44d2712f85ee43
MD5 7d82936b27618dfac351462388561dd7
BLAKE2b-256 fb7910b150960c49345a67fcb5556c0951304d5a5535e3b01e9da47464f640ac

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py3.3.egg
Algorithm Hash digest
SHA256 3c1e1c87b89e94b1b3df0a60230b88cd19c9a28df190bc3b5d0bba1feb2bffad
MD5 4c2b5c68a3a8ff3aa0ecb4b482a11fd4
BLAKE2b-256 789005123c345afb3aa49bcba3e57a2d5fead8c24e808c76c29b33e11535d5d5

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py2.7.egg
Algorithm Hash digest
SHA256 6c1eaa070efe3a25dfd0fa4562fc3b7a4e1de7fb5371dd3d5adc3c17288aa072
MD5 29c7fab5c6e30a4015396ba490f12a44
BLAKE2b-256 74e35e68efc96eb264f496aadda0833f51c6d3797e18b31971aa023003247b09

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py2.6.egg
Algorithm Hash digest
SHA256 5829fd2655dc83876f20d71f94bd5583e42b9237cb5f02b599beab2c56c03e49
MD5 2216a1d26f33c03e2c942aab699de5ac
BLAKE2b-256 6f427c1fb412482fba63d2e4db23663500b1eb55b1635540d87ea8d457616253

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py2.5.egg
Algorithm Hash digest
SHA256 49fb02d1b40c854fa57004565541afaf0a58cdf84a6fddd93c74d31e873994da
MD5 d40d8eab3b72e91e7d53803391115973
BLAKE2b-256 33facccca04fa16bc17ba43fbb75d94e4a05901d102a9584635b3820cf564b85

See more details on using hashes here.

Provenance

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.16.0-py2.4.egg
Algorithm Hash digest
SHA256 cc2a0280ad0765334b7d3ab97550697809b324806da99a189ee43cc77f57a4d9
MD5 a5de59eb35d2440fe4cb933a32a61c17
BLAKE2b-256 12e433dd0e9868c8ce339981d7c0ba3cee6e6d25df39d1041a8fd272d26bcdb5

See more details on using hashes here.

Provenance

Supported by

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