A native Python cross-version decompiler and fragment decompiler. A reworking of uncompyle6.
decompyle3 translates Python bytecode back into equivalent Python source code. It accepts bytecodes from Python version 3.7 on.
For decompilation of older Python bytecode see uncompyle6.
Uncompyle6 is awesome, but it has has a fundamental problem in the way it handles control flow. In the early days of Python when there was little optimization and code was generated in a very template-oriented way, figuring ot control flow-structures could be done by simply looking at code patterns.
Over the years more code optimization, specifically around handling jumps has made it harder to support detecting control flow strictly from code patterns. This was noticed as far back as Python 2.4 (2004) but since this is a difficult problem, so far it hasn't been tackled.
The initial attempt to fix to this problem was to add markers in the instruction stream, initially this was a COME_FROM instruction, and then use that in pattern detection.
Over the years, I've extended that to be more specific, so COME_FROM_LOOP and COME_FROM_WITH were added. And I added checks at grammar reduce type to make try to make sure jumps match with supposed COME_FROM targets.
However all of this is complicated, not robust, and not really tenable.
So in this project we'll address control flow directly via the python-control-flow project.
I expect it will be a while before this is as good as uncompyle6 for Python 3.7, but if decompilation is to have a future in Python, this work is necessary.
The code here can be run on Python versions 3.7 or later. The bytecode files it can read have been tested on Python bytecodes from versions 3.7 and later.
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.
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
$ decompyle3 *compiled-python-file-pyc-or-pyo*
For usage help:
$ decompyle3 -h
If you want Python syntax verification of the correctness of the decompilation process, add the --syntax-verify option. However since Python syntax changes, you should use this option if the bytecode is the right bytecode for the Python interpreter that will be checking the syntax.
You can also cross compare the results with another python decompiler like unpyc37 . Since they work differently, bugs here often aren't in that, and vice versa.
There is an interesting class of these programs that is readily available give stronger verification: those programs that when run test themselves. Our test suite includes these.
And Python comes with another a set of programs like this: its test suite for the standard library. We have some code in test/stdlib to facilitate this kind of checking too.
We support only released versions, not candidate versions. Note however that the magic of a released version is usually the same as the last candidate version prior to release.
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.
- https://github.com/andrew-tavera/unpyc37/ : indirect fork of https://code.google.com/archive/p/unpyc3/ The above projects use a different decompiling technique than what is used here. Instructions are walked. Some instructions use the stack to generate strings, while others don't. Because control flow isn't dealt with directly, it too suffers the same problems as the various uncompyle and decompyle prorgrams.
- https://github.com/rocky/python-xdis : Cross Python version disassembler
- https://github.com/rocky/python-xasm : Cross Python version assembler
- https://github.com/rocky/python-decompile3/wiki : Wiki Documents which describe the code and aspects of it in more detail