经过一上午的实验,梳理一下pyinstaller打包成的可执行文件如何反编译为python源代码
工具与环境
- pyinstxtractor
- decompile3
- uncompyle6
- Mac Mojave 10.14.6 + Python 3.7.4
- Win10虚拟机 + Python3.7.6 & Python 3.7.7 & Python 3.8.1 & Python 3.8.2
Python3.7以下版本
用uncompyle6就可以了,支持2.4-3.8的全部版本
在做实验之前,我的pyinstxtractor还是1.9版本,讲一下v1.9和v2.0的区别
2.0加了几个功能:
支持 3.6 版本的pyinstaller
支持 Python 3.7, 3.8
自动修复main.pyc(入口文件)
如果没有自动修复的话,则需要从别的文件中补一点十六进制头
对于python3.7以前的版本,一般补struct文件的前十二组数字
对于python3.7以后的版本,直接从反编译出来的一堆pyc依赖文件里,拿出前十二组数字补
反编译过程->使用pyinstxtractor将可执行文件反编译为pyc文件->使用uncompyle6将pyc反编译为py文件
Python3.7.6 & Python3.7.7
按照上述流程来一遍,可能会出报错
```
$ decompyle3 conf.conf.pyc
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 208, in load_module_from_file_object
co = marshal.loads(bytecode)
ValueError: bad marshal data (unknown type code)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 208, in load_module_from_file_object
co = marshal.loads(bytecode)
ValueError: bad marshal data (unknown type code)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/bin/decompyle3", line 11, in <module>
load_entry_point('decompyle3==3.3.2', 'console_scripts', 'decompyle3')()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/decompyle3-3.3.2-py3.7.egg/decompyle3/bin/decompile.py", line 190, in main_bin
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/decompyle3-3.3.2-py3.7.egg/decompyle3/main.py", line 302, in main
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/decompyle3-3.3.2-py3.7.egg/decompyle3/main.py", line 181, in decompile_file
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 116, in load_module
get_code=get_code,
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 222, in load_module_from_file_object
"Ill-formed bytecode file %s\n%s; %s" % (filename, kind, msg)
ImportError: Ill-formed bytecode file conf.conf.pyc
<class 'ValueError'>; bad marshal data (unknown type code)
```
* 根据 https://github.com/countercept/python-exe-unpacker/issues/14 修改xdis源码即可
```
Open the file /usr/local/lib/python3.7/site-packages/xdis/load.py
Find lines:
if my_magic_int == magic_int:
bytecode = fp.read()
co = marshal.loads(bytecode)
Replace with:
if my_magic_int == magic_int:
fp.seek(12)
bytecode = fp.read()
co = marshal.loads(bytecode)
fp.seek(12) skips reading of the first 12 bytes and makes the decompiler work again.
```
Python3.8.1 & Python3.8.2
按照上述流程来一遍,可能会出报错
```
$ uncompyle6 conf.conf.pyc
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 219, in load_module_from_file_object
co = xdis.unmarshal.load_code(fp, magic_int, code_objects)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/unmarshal.py", line 108, in load_code
"expecting code indicator 'c'; got '%s'" % (fp.name, c)
TypeError: File conf.conf.pyc doesn't smell like Python bytecode:
expecting code indicator 'c'; got ''
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 219, in load_module_from_file_object
co = xdis.unmarshal.load_code(fp, magic_int, code_objects)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/unmarshal.py", line 108, in load_code
"expecting code indicator 'c'; got '%s'" % (fp.name, c)
TypeError: File conf.conf.pyc doesn't smell like Python bytecode:
expecting code indicator 'c'; got ''
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/bin/uncompyle6", line 11, in <module>
load_entry_point('uncompyle6==3.6.5', 'console_scripts', 'uncompyle6')()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/uncompyle6-3.6.5-py3.7.egg/uncompyle6/bin/uncompile.py", line 194, in main_bin
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/uncompyle6-3.6.5-py3.7.egg/uncompyle6/main.py", line 327, in main
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/uncompyle6-3.6.5-py3.7.egg/uncompyle6/main.py", line 187, in decompile_file
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 124, in load_module
get_code=get_code,
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/xdis/load.py", line 229, in load_module_from_file_object
"Ill-formed bytecode file %s\n%s; %s" % (filename, kind, msg)
ImportError: Ill-formed bytecode file conf.conf.pyc
<class 'TypeError'>; File conf.conf.pyc doesn't smell like Python bytecode:
expecting code indicator 'c'; got ''
```
这个的原因是我在Win10上使用pyinstaller打包后,把main.exe复制到了Mac上,使用Mac上的Python 3.7.4 运行了pyinstxtractor,导致反编译失败
pyinstxtractor也会提示出来
```
[!] Warning: This script is running in a different Python version than the one used to build the executable.
[!] Please run this script in Python38 to prevent extraction errors during unmarshalling
[!] Skipping pyz extraction
```
Python3.9.x
看文档说还不支持,没试
科学的反编译方法
- 对于每个特定的Python版本使用pyinstaller打包出的可执行文件,尽量使用同版本的Python版本运行pyinstxtractor
- 保持decompile3或uncompyle6最新,保持xdis最新