实战复盘:如何从PyInstaller打包的加密exe中找回丢失的Python源码(附完整解密脚本)
实战指南从PyInstaller加密EXE中高效恢复Python源码的完整方案当开发者面临Python源码丢失却只有PyInstaller打包的EXE文件时如何高效恢复原始代码成为一项关键技能。本文将提供一套完整的解决方案涵盖从基础工具使用到高级解密技巧的全流程操作指南。1. 准备工作与环境搭建在开始恢复源码之前需要准备以下工具和环境Python环境建议使用与打包EXE相同版本的Python解释器关键工具pyinstxtractor用于解包PyInstaller生成的EXE文件uncompyle6将.pyc文件反编译为可读的Python源码tinyaes/pycryptodome用于处理加密的.pyc文件010 Editor用于分析二进制文件结构安装这些工具的推荐命令pip install uncompyle6 tinyaes pycryptodome git clone https://github.com/extremecoders-re/pyinstxtractor.git注意确保使用的Python版本与打包EXE时一致否则可能导致解包失败2. EXE文件解包与结构分析使用pyinstxtractor进行解包的基本流程python pyinstxtractor.py your_program.exe解包后会生成一个your_program.exe_extracted目录包含以下关键文件文件/目录重要性说明main.pyc高主程序入口点pyimod00_crypto_key.pyc中可能包含加密密钥PYZ-00.pyz_extracted高包含所有依赖库的.pyc文件struct低打包时的结构信息对于加密的EXE文件PYZ-00.pyz_extracted目录中的文件可能显示为.pyc.encrypted扩展名这时需要额外的解密步骤。3. 加密处理与版本差异解决方案PyInstaller 4.0前后版本在加密方式上有重大变化版本差异对比表特性PyInstaller 4.0PyInstaller ≥4.0加密库PyCryptotinyaes加密模式CFBCTR密钥存储pyimod00_crypto_key.pycpyimod00_crypto_key.pyc文件扩展名.pyc.encrypted.pyc.encrypted判断EXE打包版本的两种方法检查pyimod01_archive.pyc是否引用tinyaes查看EXE文件的创建日期粗略估计针对不同版本的解密脚本示例# PyInstaller 4.0 解密脚本 from Crypto.Cipher import AES import zlib def decrypt_legacy(input_file, output_file, key): with open(input_file, rb) as inf, open(output_file, wb) as outf: iv inf.read(16) cipher AES.new(key, AES.MODE_CFB, iv) plaintext zlib.decompress(cipher.decrypt(inf.read())) outf.write(b\x55\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\0) # Python 3.8头 outf.write(plaintext)# PyInstaller ≥4.0 解密脚本 import tinyaes import zlib def decrypt_modern(input_file, output_file, key): with open(input_file, rb) as inf, open(output_file, wb) as outf: iv inf.read(16) cipher tinyaes.AES(key, iv) plaintext zlib.decompress(cipher.CTR_xcrypt_buffer(inf.read())) outf.write(b\x55\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\0) # Python 3.8头 outf.write(plaintext)4. 密钥提取与反编译实战获取加密密钥的标准流程使用uncompyle6反编译pyimod00_crypto_key.pycuncompyle6 -o key_source.py pyimod00_crypto_key.pyc检查生成的key_source.py文件通常会包含类似如下的代码# key_source.py示例内容 key 0000000000123456 # 这是加密时使用的密钥使用获取到的密钥解密所有.pyc.encrypted文件完整反编译工作流程批量解密所有加密的.pyc文件为每个.pyc文件添加正确的Python版本头使用uncompyle6进行反编译uncompyle6 -o recovered_script.py decompiled.pyc常见问题解决方案头不匹配错误确保.pyc文件头与Python版本匹配反编译失败尝试使用不同版本的uncompyle6部分代码无法恢复考虑使用pycdc等替代工具5. 高级技巧与疑难排解当标准流程遇到问题时可以尝试以下高级技巧技巧1手动修复.pyc文件头各Python版本的魔数头Python版本魔数头3.7\x42\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\03.8\x55\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\03.9\x61\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\03.10\x6f\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\0技巧2处理混淆代码遇到混淆代码时可以使用ast模块分析代码结构逐步替换混淆的变量名使用正则表达式批量清理无用代码技巧3多工具组合使用当uncompyle6失败时可以尝试pycdas显示字节码decompyle3uncompyle6的分支版本pycdc较新的反编译工具实际案例中我曾遇到一个使用PyInstaller 4.5打包的EXE通过组合使用tinyaes解密和pycdc反编译成功恢复了95%以上的源代码。关键是要耐心尝试不同工具的组合并仔细分析每一步的输出结果。