Skip to main content

Python cross-version byte-code deparser

Project description

|buildstatus| |Supported Python Versions|

uncompyle6
==========

A native Python cross-version Decompiler and Fragment Decompiler.
Follows in the tradition of 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.6 or so, including PyPy bytecode and Dropbox's Python 2.5 bytecode.

Why this?
---------

There were a number of decompyle, uncompile, uncompyle2, uncompyle3
forks around. All of them came basically from the same code base, and
almost all of them no were no longer actively maintained. Only one
handled Python 3, and even there, only 3.2 or 3.3 depending on which
code is used. This code pulls these together and moves forward. This
project has the most complete support for Python 3.3 and above. It
also addresses a number of open issues in the previous forks.

What makes this different from other CPython bytecode decompilers?: its
ability to deparse just fragments and give source-code information
around a given bytecode offset.

I use this to deparse fragments of code inside my trepan_
debuggers_. For that, I need to record text fragments for all
bytecode offsets (of interest). This purpose although largely
compatible with the original intention is yet a little bit different.
See this_ for more information.

The idea of Python fragment deparsing given an instruction offset can
be used in showing stack traces or any program that wants to show a
location in more detail than just a line number. It can be also used
when source-code information does not exist and there is just bytecode
information.

Requirements
------------

This project requires Python 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 has 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 .
pip install -r requirements-dev.txt
python setup.py install # may need sudo
# or if you have pyenv:
python setup.py develop

A GNU makefile is also provided so :code:`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 :code:`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. All of the Python decompilers I have looked
at have the same problem. In some cases we can detect an erroneous
decompilation and report that.

Over 98% of the decompilation of Python standard library packages in
Python 2.7.12 verifies correctly. Over 99% of Python 2.7 and 3.3-3.5
"weakly" verify. Python 2.6 drops down to 96% weakly verifying.
Other versions drop off in quality too.

*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.

Later distributions average about 200 files. 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. That has been addressed, but then it also changes function call
opcodes and its semantics and has more problems with control flow than
3.5 has.

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.

Handling pathologically long lists of expressions or statements is
slow.


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

See Also
--------

* https://github.com/zrax/pycdc : supports all versions of Python and is written in C++. Support for later Python 3 versions is a bit lacking though.
* https://code.google.com/archive/p/unpyc3/ : supports Python 3.2 only. The above projects use a different decompiling technique than what is used here.
* https://github.com/figment/unpyc3/ : fork of above, but supports Python 3.3 only. Include some fixes like supporting function annotations
* The HISTORY_ file.
* `How to report a bug <https://github.com/rocky/python-uncompyle6/blob/master/HOW-TO-REPORT-A-BUG.md>`_
* https://github.com/rocky/python-xdis : Cross Python version disassembler
* https://github.com/rocky/python-xasm : Cross Python version assembler


.. _trepan: https://pypi.python.org/pypi/trepan2
.. _HISTORY: https://github.com/rocky/python-uncompyle6/blob/master/HISTORY.md
.. _debuggers: https://pypi.python.org/pypi/trepan3k
.. _remake: https://bashdb.sf.net/remake
.. _pycdc: https://github.com/zrax/pycdc
.. _this: https://github.com/rocky/python-uncompyle6/wiki/Deparsing-technology-and-its-use-in-exact-location-reporting
.. |buildstatus| image:: https://travis-ci.org/rocky/python-uncompyle6.svg
:target: https://travis-ci.org/rocky/python-uncompyle6
.. |Supported Python Versions| image:: https://img.shields.io/pypi/pyversions/uncompyle6.svg
:target: https://pypi.python.org/pypi/uncompyle6/
.. _PJOrion: http://www.koreanrandom.com/forum/topic/15280-pjorion-%D1%80%D0%B5%D0%B4%D0%B0%D0%BA%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%B4%D0%B5%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F-%D0%BE%D0%B1%D1%84
.. _Deobfuscator: https://github.com/extremecoders-re/PjOrion-Deobfuscator

Project details


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 Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

uncompyle6-2.11.4-py3.6.egg (327.4 kB view details)

Uploaded Egg

uncompyle6-2.11.4-py3.5.egg (333.3 kB view details)

Uploaded Egg

uncompyle6-2.11.4-py3.4.egg (334.7 kB view details)

Uploaded Egg

uncompyle6-2.11.4-py3.3.egg (338.9 kB view details)

Uploaded Egg

uncompyle6-2.11.4-py2.7.egg (328.5 kB view details)

Uploaded Egg

uncompyle6-2.11.4-py2.6.egg (329.1 kB view details)

Uploaded Egg

uncompyle6-2.11.4-py2.5.egg (328.0 kB view details)

Uploaded Egg

uncompyle6-2.11.4-py2.4.egg (331.7 kB view details)

Uploaded Egg

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py3.6.egg
Algorithm Hash digest
SHA256 6e0846360c1e5cb70160c071d5dc2e8dc9ab9465803913896ea7857bf3b5be2d
MD5 16234ac0487423ce6c1d79c2a39ffc02
BLAKE2b-256 56fa35f5923d1629891c15e53b831bdc065529137f5293732cf7c68f532440cf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py3.5.egg
Algorithm Hash digest
SHA256 de91150ebd774cc4ecaabe87658045d8176096c5b7c6d6190933f6f0c63be32b
MD5 f4c0afe1480c4bc81e6d5161e8a713e9
BLAKE2b-256 ae113804465ef5c91bed2d749f0ae20b1833697bf5b7afb7427cebc1bd839b09

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py3.4.egg
Algorithm Hash digest
SHA256 4892ec9c7b11969aaeb2ff6c1efb8968ebf3c9a83629262e35934d68dfade04e
MD5 382e5806d03063228aaf486a02f223c4
BLAKE2b-256 2299fe2c787055ee4fe00b1f3c5357a73a42f24e84cf6ebceb1b0a5728cc8cd5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py3.3.egg
Algorithm Hash digest
SHA256 6755bc871d2ec0229e06997c6a6acfc2250c71b0087d266f9707a39d441f750d
MD5 656a987c1275beb54176c9181886215f
BLAKE2b-256 0d27cdd098f2d0a12e831f646f7a9a0245b329e29af0a7cefa47be0a9f62f3a5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py2.7.egg
Algorithm Hash digest
SHA256 3e61918d8cef62532604021d94d96604c8372fa03f3d5ce0892af08b927fd558
MD5 54c448b4a9f44d686b6bddadf4bb6307
BLAKE2b-256 98e7a81813d4d0853bc8b81caec0bbc14892357647d25d8ab10aa2438ed2ffc8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py2.6.egg
Algorithm Hash digest
SHA256 7d2f2e10d91cae84fb2368f21d4cba607d6650415fa0b5d1a15105c57c9efa70
MD5 d2d3817fcaa15b87ecdeb8bca4a98875
BLAKE2b-256 808e1e761277e3eb08ede047fea65fccf1a20d2ef30ad3354eec3264bfe1c0a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py2.5.egg
Algorithm Hash digest
SHA256 8abc87a15bf92d8df0bc1513cab4c2dcd258b287aad055fcd62c16a98c522aa7
MD5 c6ff158d18b2e9710c1e2aefd8bf950f
BLAKE2b-256 15a15e3950c54f7c5d91d6333a300df10fedb4835f484205697413b2b5208e86

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for uncompyle6-2.11.4-py2.4.egg
Algorithm Hash digest
SHA256 9869b884adeb4b0b564ba351d8c7d56aea39dd478398f4d2500095715332238b
MD5 18e21764fd64a7e1d216a67e422be407
BLAKE2b-256 3306693e0850ee875f9909ea61c9add6d11826cde2fa9b1ef4a0304e1d88ef35

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