PyInstaller打包的exe被逆向?手把手教你用pyinstxtractor和uncompyle6找回Python源码(附版本差异处理) Python逆向工程实战从PyInstaller打包的exe还原源码全流程指南当你接手一个遗留项目或需要分析某个Python应用时经常会遇到只有打包后的exe文件的情况。本文将带你深入探索如何系统性地解构PyInstaller打包的可执行文件逐步还原出原始Python代码。不同于基础教程我们会重点关注版本差异处理、加密文件解密等高级实战技巧。1. 逆向工程前的准备工作逆向PyInstaller打包的程序需要一套专门的工具链。以下是核心工具清单及其作用Detect It Easy (DIE)用于快速识别文件类型和打包方式pyinstxtractor解包PyInstaller生成的exe文件uncompyle6将pyc字节码反编译为Python源代码010 Editor十六进制编辑器用于分析文件头信息建议环境配置pip install uncompyle63.8.0 git clone https://github.com/extremecoders-re/pyinstxtractor.git版本匹配原则解包使用的Python版本必须与打包时一致uncompyle6需要匹配Python字节码版本加密文件解密方式随PyInstaller版本变化注意实际操作前请确认你有权分析目标文件避免法律风险2. 解包PyInstaller生成的exe文件使用pyinstxtractor进行解包的基本命令很简单python pyinstxtractor.py target.exe但实际操作中会遇到几个关键问题2.1 解包后的文件结构分析成功解包后会生成target.exe_extracted目录包含以下重要文件文件类型说明处理方式main.pyc主程序字节码直接反编译PYZ-00.pyz依赖库集合需进一步解压pyimod*.pycPyInstaller模块可能含加密密钥2.2 版本兼容性问题处理不同PyInstaller版本打包的文件结构差异4.0之前版本使用PyCrypto进行CFB模式加密依赖库存储在PYZ-00.pyz中4.0及之后版本采用tinyaes进行CTR模式加密可能出现pyc.encrypted扩展名识别版本技巧# 检查pyimod01_archive.pyc是否引用tinyaes uncompyle6 pyimod01_archive.pyc | grep tinyaes3. 处理加密的字节码文件当发现PYZ-00.pyz_extracted目录下存在.pyc.encrypted文件时需要先解密才能反编译。3.1 获取加密密钥密钥通常存储在pyimod00_crypto_key.pyc中uncompyle6 -o key.py pyimod00_crypto_key.pyc3.2 解密脚本选择根据PyInstaller版本选择对应的解密方案PyInstaller 4.0 解密脚本from Crypto.Cipher import AES import zlib def decrypt_legacy(input_path, output_path, key): with open(input_path, rb) as inf, open(output_path, wb) as outf: iv inf.read(16) cipher AES.new(key, AES.MODE_CFB, iv) plaintext zlib.decompress(cipher.decrypt(inf.read())) outf.write(plaintext)PyInstaller ≥ 4.0 解密脚本import tinyaes import zlib def decrypt_new(input_path, output_path, key): with open(input_path, rb) as inf, open(output_path, wb) as outf: iv inf.read(16) cipher tinyaes.AES(key, iv) plaintext zlib.decompress(cipher.CTR_xcrypt_buffer(inf.read())) outf.write(plaintext)关键点解密后需要手动添加正确的pyc文件头才能被uncompyle6识别4. 反编译字节码为源代码获得标准pyc文件后使用uncompyle6进行反编译uncompyle6 -o output.py input.pyc4.1 常见反编译问题解决Magic Number不匹配症状ValueError: Bad magic number in...解决使用正确版本的Python头信息混淆代码处理症状反编译后出现乱码或异常控制流应对尝试使用decompyle3等替代工具依赖缺失导致失败症状ImportErrorduring decompilation解决确保原环境依赖已安装4.2 批量反编译技巧对于大量pyc文件可以使用脚本批量处理import os from pathlib import Path def batch_decompile(root_dir): for pyc in Path(root_dir).rglob(*.pyc): try: os.system(funcompyle6 -o {pyc.with_suffix(.py)} {pyc}) except Exception as e: print(fFailed on {pyc}: {str(e)})5. 高级技巧与疑难问题处理5.1 Python版本头修复当pyc文件头损坏时需要手动修复。各版本Python的头信息Python版本魔数前缀3.7\x42\x0d\x0d\x0a3.8\x55\x0d\x0d\x0a3.9\x61\x0d\x0d\x0a3.10\x6f\x0d\x0d\x0a修复示例def fix_pyc_header(pyc_path, version): headers { 3.8: b\x55\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\0 } with open(pyc_path, rb) as f: original f.read() f.seek(0) f.write(headers[version] original[16:])5.2 依赖库路径修复解包后的依赖可能路径混乱需要调整检查PYZ-00.pyz_extracted内容将需要的库复制到项目目录修改导入语句匹配新路径5.3 反编译失败后的备选方案当标准工具失效时可以尝试pycdc支持更多Python版本的字节码手动分析dis模块输出import dis, marshal with open(file.pyc, rb) as f: f.seek(16) # Skip header dis.dis(marshal.load(f))商业工具如Decompyle等在实际项目中我遇到过PyInstaller 5.7打包的程序其加密方式又有变化。这时需要分析pyimod00_crypto_key.pyc的具体实现来调整解密逻辑。记住逆向工程是不断试错的过程保持耐心是关键。