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.15.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distributions

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

uncompyle6-2.15.0-py36-none-any.whl (179.3 kB view details)

Uploaded Python 3.6

uncompyle6-2.15.0-py35-none-any.whl (179.3 kB view details)

Uploaded Python 3.5

uncompyle6-2.15.0-py34-none-any.whl (179.3 kB view details)

Uploaded Python 3.4

uncompyle6-2.15.0-py33-none-any.whl (179.4 kB view details)

Uploaded Python 3.3

uncompyle6-2.15.0-py27-none-any.whl (179.4 kB view details)

Uploaded Python 2.7

uncompyle6-2.15.0-py3.6.egg (373.8 kB view details)

Uploaded Egg

uncompyle6-2.15.0-py3.5.egg (380.2 kB view details)

Uploaded Egg

uncompyle6-2.15.0-py3.4.egg (382.2 kB view details)

Uploaded Egg

uncompyle6-2.15.0-py3.3.egg (387.0 kB view details)

Uploaded Egg

uncompyle6-2.15.0-py2.7.egg (375.4 kB view details)

Uploaded Egg

uncompyle6-2.15.0-py2.5.egg (375.6 kB view details)

Uploaded Egg

uncompyle6-2.15.0-py2.4.egg (380.0 kB view details)

Uploaded Egg

File details

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

File metadata

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

File hashes

Hashes for uncompyle6-2.15.0.tar.gz
Algorithm Hash digest
SHA256 7fd69d7818a529f857ce63e09ed525114972973c64866443340abfd6a34e6453
MD5 2f9c4315e08d66702867894b0630ba81
BLAKE2b-256 2b52b88f17698716700ea7512ab8dbf03003bdf03d6670185e09d00897101241

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py36-none-any.whl
Algorithm Hash digest
SHA256 ff7e4282f4161e38d91849a701100adf187de416f4dd4948da2540747ef27b37
MD5 d6a6bbf4e3312bd0f3c5975f0eef2daa
BLAKE2b-256 cdcdf72f42ae96a5b278b57139f1e363d0be9b64936de02bc51b10789b71fd2e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py35-none-any.whl
Algorithm Hash digest
SHA256 4695128e2516ee32c260eb8862ba56428386445fe4a8b855c2c1836136a9eae0
MD5 b4e7fef451fc9f620dd6858ab26eb9ba
BLAKE2b-256 0ebe4dd0c28958e3060df28b69425d2fe35d1c542b7aa4bdf052b4b5453ecf9a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py34-none-any.whl
Algorithm Hash digest
SHA256 ac6fba117a618a1b871b8207a6f5d59ea3423a04b8476985d670ac65194527ba
MD5 c05528c55257b500c1393e439fa1a569
BLAKE2b-256 c210a559210eb72101221c4c855587d0f81959087dfcbbf67f93d86bc860aa7c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py33-none-any.whl
Algorithm Hash digest
SHA256 607b858532f684dc45bef420b27a2c80138a02ad15d02b443b7de02946525c41
MD5 895af01c09d48f363beef4ee57fd6357
BLAKE2b-256 3ebc3664b843100ef1fd937aec11d708b095232f291d56754df580df8efcb944

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py27-none-any.whl
Algorithm Hash digest
SHA256 596f6aab0cef836e46ee36c3a62c3f0b83c0031e26b0bc7699765f204e7d26e1
MD5 7cc10cc09bab407fd741d68da675467c
BLAKE2b-256 16712135450231599ea75df47566fd25261f286877508598a38cb7978aea56d2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py3.6.egg
Algorithm Hash digest
SHA256 4393c520ae8706082d399d67b54224c8aa89835d899adb89f276442bbfd577dd
MD5 2c7450cf3e690637c1e0fa59ef5c0520
BLAKE2b-256 6a74181fa4bceebee292ce1a56a22041394f5ccd72822e2ced65d265ead7cb2a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py3.5.egg
Algorithm Hash digest
SHA256 7841bcc037906e80e59b5a2a0a0726aa7c020a86011bae2adad1f03804744ba2
MD5 7bf00a74693e2ebfef5c6c61ec36261f
BLAKE2b-256 c73c6848cdf3156160bb46f1e74cdc10d41264d232a01f6a5e372c458addf73a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py3.4.egg
Algorithm Hash digest
SHA256 ef3eccf8292da3e7a06a80dc68f221395fc0f0615288c177dc60e579eeec1628
MD5 3bb4a9689338027693d3358506632761
BLAKE2b-256 099f21fa4e00fda00ecc7c3c967f5ade701eed75325988be09549b2340c5003b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py3.3.egg
Algorithm Hash digest
SHA256 730cd1d64e4665453ab104c9ad0787ced3830e3b39d4880bcad890cca97d1d6a
MD5 ed7011958729fd1f1534c46d2e914df5
BLAKE2b-256 1a0fbbf4f43c1e68b6476367dae5ba59f70262e129b9f7d54aa17158dcc9638d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py2.7.egg
Algorithm Hash digest
SHA256 64dae13ac5eabcc4e347f8187d90564ae4f1f0dcff6ef03763e16093e1885703
MD5 3e15a7879dafed66bc15d4ce54345d79
BLAKE2b-256 5b0c9314215fba9762ae270f3bc817f86633a89edd46a6b79bd9c6c225bff532

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py2.5.egg
Algorithm Hash digest
SHA256 c17391e0c3addfcc87cec39ac3712b8ab5ba8332227b548745a06af60f5892b5
MD5 1aefe4c2a0eb11e1a5c72a0d651b880e
BLAKE2b-256 8deef6b779b2d3c27f653a4b17fcb63db096804f20a3524302b0846d26fae74e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.15.0-py2.4.egg
Algorithm Hash digest
SHA256 84c7374aa6fe0254133c84e8dd5b4fc8a58b065c650abed28c7a6d1b3c40b8ae
MD5 875b9ae0695b36996cc3c0f6764b9623
BLAKE2b-256 394574f04751fbfc2c48047c077d5c08d08c2afc400b161503030491aa9fb549

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