记录一次pyinstaller解包过程
引言
分析由PyInstaller打包的Python程序是一个常见需求。本文将详细记录我对一个名为xxxx.exe的PyInstaller打包程序进行解包和反编译的全过程。
第一步:识别打包工具
通过观察程序图标和文件特征,确认这是一个由PyInstaller打包的Python脚本。PyInstaller是一个流行的Python打包工具,能将Python脚本转换为独立的可执行文件。
第二步:使用pyinstxtractor解包
我使用了专门针对PyInstaller的解包工具pyinstxtractor:
1 | python pyinstxtractor.py xxxx.exe |
执行后输出如下:
1 | [+] Processing xxxx.exe |
解包完成后,生成了一个xxxx.exe_extracted
目录,其中包含所有解包出的pyc文件和dll文件。
第三步:确定Python版本
要正确反编译pyc文件,必须知道原始Python的确切版本。通过以下方法确认:
(1) 可以直接在目录中看到python311.dll文件,可知是python3.11版本。
(2) 具体是python哪个版本,
我们随便打开一个PYZ-00.pyz_extracted目录下的pyc文件(例如base64.pyc),查看其头部信息,前四个字节为A70D0D0A。
我们可以在python的官方仓库中找到不同版本pyc的magic值: https://github.com/python/cpython/blob/main/Include/internal/pycore_magic_number.h
检索到python3.11这部分:
1 | Python 3.11a1 3450 Use exception table for unwinding ("zero cost" exception handling) |
Magic Number是4字节的二进制数据,我们找到对应的十进制数据后,通过以下代码得到相应的二进制数据
1 | MAGIC_NUMBER = (3495).to_bytes(2, 'little') + b'\r\n' |
可以得到0xA70D0D0A。从而确定具体的版本为3495也就是3.11b4。
第四步:修复pyc文件头
PyInstaller生成的pyc文件缺少标准pyc文件应有的头部信息,需要手动修复。步骤如下:
我们要逆向的是xxx.pyc文件,但是这一步,我们还不能直接反编译pyc文件,因为pyinstaller删除了pyc文件的头部信息中包含的magic number和时间戳等信息,我们需要先将其转换为可以被反编译器识别的格式。
观察xxxx.pyc头部
1 | E3 00 00 00 00 00 00 00 | 00 00 00 00 00 05 00 00 |
base64.pyc头部
1 | A7 0D 0D 0A 00 00 00 00 | 00 00 00 00 E3 00 00 00 |
虽然我完全看不出有什么关联。
接下来我们新建一个conda环境,版本号和上面的pyc文件版本一致,写一个hello world的py文件,编译为pyc文件。
1 | python -m py_compile hello_world.py |
再次观察头部信息
1 | A7 0D 0D 0A 00 00 00 00 | 42 3A 64 68 27 01 00 00 |
这时可以观察到规律了,”E3 00 00 00 00 00 00 00”这第二行以及”00 00 97 00 64 00 A0 00”第三行
我们将”A7 0D 0D 0A 00 00 00 00 | 42 3A 64 68 27 01 00 00”插入到xxxx.pyc的头部信息中。
第五步:尝试反编译
尝试使用uncompyle6
首先尝试使用uncompyle6进行反编译:
1 | uncompyle6 xxxx_patched.pyc |
但发现uncompyle6最高仅支持到Python 3.8版本,而我们的文件是3.11版本,无法兼容。
尝试使用pycdc
于是转向另一个反编译工具pycdc:
1 | git clone https://github.com/zrax/pycdc.git |
但遇到了错误:
1 | Error decompyling xxxx_patched.pyc: vector too long |
使用pycdas获取字节码
当直接反编译失败时,可以使用pycdc附带的pycdas工具获取字节码表示:
1 | ./pycdas xxxx_patched.pyc |
然后将输出的字节码提交给AI大模型(如DeepSeek)进行人工逆向分析,最终成功还原出原始Python代码。
经验总结
- 版本匹配至关重要:PyInstaller解包和pyc反编译都需要精确匹配Python版本
- 工具链组合使用:没有单一工具能解决所有问题,需要灵活组合多种工具
- 人工分析必不可少:当自动化工具失败时,人工分析字节码是最后的手段
工具推荐
- 解包工具:pyinstxtractor
- 反编译工具:
- 辅助工具:
- WinHex (用于二进制分析)
- AI大模型 (用于字节码解释)