PyInstaller提取器pyinstxtractor完整实战指南:一条命令还原打包程序全部字节码
【免费下载链接】pyinstxtractorPyInstaller Extractor项目地址: https://gitcode.com/gh_mirrors/py/pyinstxtractor
你是否有过这样的瞬间:程序文件就在手边、双击就能运行,可翻遍整个电脑也找不到当初的.py源码。PyInstaller 打包产物(.exe或 Linux ELF 可执行文件)把所有逻辑压缩进了二进制里,普通编辑器打开全是乱码。而pyinstxtractor 提取器正是为解决这个问题而生——它是一个纯 Python 编写的单文件脚本,能一键拆解 PyInstaller 打包程序,还原出全部 Python 字节码文件(.pyc),并自动修复文件头,让后续的 pyc 文件反编译工作开箱即用。
先讲个糟心事:程序能跑,源码却人间蒸发 🔍
半年前你写了个内部工具,用 PyInstaller 打包发给同事。今天需求迭代,你却找不到源文件——代码库换过机器、备份盘早已格式化,唯独那个能跑的 exe 幸存下来。又或者,你手上有一个陌生程序,想弄清它的配置读取逻辑、接口地址藏在哪,对着二进制却无从下手。
这两种场景的共同诉求是:把 PyInstaller 打包程序还原成可分析的形式。pyinstxtractor 的价值就在于把这条原本复杂的逆向路径,压缩成一条命令。它不需要安装 PyInstaller,不依赖任何第三方库,脚本本身只调用 Python 标准库,因此 Python 2.x 和 3.x 环境都能直接运行。
60秒体验第一遍:让提取器先跑起来 ⚡
先别管原理,3 分钟内跑通第一遍提取,建立"原来这么简单"的直觉。
第一步,获取脚本。打开终端执行:
git clone https://gitcode.com/gh_mirrors/py/pyinstxtractor cd pyinstxtractor克隆完成后你会发现,整个工具只有一个核心文件pyinstxtractor.py,所有逻辑都封装在里面,没有任何多余的依赖。
第二步,运行提取。把待分析的程序路径作为参数传入:
python pyinstxtractor.py myapp.exe如果程序在其他目录,写完整路径即可;Windows 下同样一条命令适用:
python pyinstxtractor.py C:\path\to\myapp.exe第三步,看输出。一个典型的成功输出长这样:
[+] Processing myapp.exe [+] Pyinstaller version: 2.1+ [+] Python version: 3.8 [+] Length of package: 5612452 bytes [+] Found 59 files in CArchive [+] Beginning extraction...please standby [+] Possible entry point: myapp.pyc [+] Found 133 files in PYZ archive [+] Successfully extracted pyinstaller archive: myapp.exe看到末尾的Successfully extracted,提取就完成了。整个过程不超过几秒。
拆开看看:这个脚本到底在做什么 🔧
用一次提取前,值得花两分钟理解它背后的机制,这能帮你判断报错、选择合适的用法。项目源码(pyinstxtractor.py)里的逻辑其实非常清晰:
- 定位"签名":PyInstaller 产物在文件尾部藏着一串固定魔数
MEI\014\013\012\013\016,脚本从文件末尾向前搜索这串标记(对应源码中的MAGIC常量与checkFile()方法),找不到就说明目标并非 PyInstaller 打包,直接报错退出。 - 读取元信息:魔数之后紧跟着一个 cookie 结构,其中记录了包的总长度、目录表(TOC)位置和打包时使用的 Python 版本号。这一步决定了后续的解析策略。
- 解析两层归档:PyInstaller 打包程序内部实际是嵌套结构——外层 CArchive 存放主程序模块与资源文件,内层 PYZ 归档存放第三方依赖。脚本依次解出 CArchive 里的每个条目(需要时做 zlib 解压),遇到
z类型条目再递归进入 PYZ 解析。 - 修复 pyc 文件头:从 PyInstaller 5.3 起,打包时不再保留 pyc 的标准头部,脚本会把提取出的"裸字节码"记录下来,在全部解压结束后统一补写正确的魔数与时间戳字段(
_fixBarePycs()方法)。这正是"反编译工具开箱即用"的关键一步。
理解了这四步,你就知道:所谓提取,本质是按签名定位 → 按目录还原 → 按规则修补的机械流程,pyinstxtractor 把这个流程封装得足够可靠。
完整实操:从可执行文件到可读源码的四步路 🛠️
拿到一个 PyInstaller 打包程序后,完整的还原流程建议按下面四步走:
- 确认 Python 版本:在命令行执行
python --version,记录当前解释器版本。这个信息后面要用。 - 执行提取并读关键字段:运行提取命令后,重点看两行——
Pyinstaller version决定了解析策略;Python version是打包时的版本号,务必记住它,它直接关系到 PYZ 归档能否顺利解出。 - 检查提取目录:当前目录下会出现
myapp.exe_extracted文件夹,里面包括:- 主程序字节码(如
myapp.pyc),这是最核心的分析对象; PYZ-00.pyz_extracted子目录,装着os.pyc、__future__.pyc等全部第三方依赖;- 各种
.dll、.so动态库与数据资源文件。
- 主程序字节码(如
- 反编译字节码:用反编译工具处理
.pyc文件即可还原可读源码。较老的字节码版本可以用 Uncompyle6,Python 3.9 以上的新字节码建议换用 Decompyle++(pycdc):
uncompyle6 myapp.exe_extracted\myapp.pyc > myapp.py反编译入口文件后,顺着它的import语句逐层往下追,就能拼出整个程序的代码地图。
进阶玩法:三个让提取更值的深水区操作 🎯
基础流程之外,下面三个进阶操作能让你的分析效率和质量上一个台阶。
操作一:用匹配的 Python 版本运行提取器。PYZ 归档的目录结构是用marshal序列化的,而 marshal 对 Python 版本极其敏感。如果运行脚本的解释器与打包版本不一致,大概率会看到Unmarshalling FAILED或Skipping pyz extraction的警告,第三方依赖模块就解不出来了。最佳实践是:先用提取输出确认Python version,再切换到同版本解释器重跑一遍。
操作二:从入口点建立代码地图。输出里的Possible entry point就是程序启动时最先执行的脚本。逆向时先反编译它,再沿import关系追踪调用链,比漫无目的地翻几百个.pyc高效得多——尤其面对复杂业务程序,这是快速建立整体认知的捷径。
操作三:加密归档不放弃,原样导出留线索。如果程序对 PYZ 做了加密,脚本不会崩溃,而是把解不开的内容原样写为.encrypted后缀文件并继续处理其余部分。你可以结合调试器跟踪运行时的解密过程,或研究主程序里的解密逻辑,寻找突破口。
高频问题速查表 📋
把社区里最常见的几个问题收拢成一张表,遇到状况直接对号入座:
| 现象 | 原因 | 处理办法 |
|---|---|---|
提示Missing cookie | 目标不是 PyInstaller 打包,或版本过旧 | 确认文件来源,换用其他分析思路 |
Unmarshalling FAILED | 解释器版本与打包版本不一致 | 查看输出中Python version,切换同版本 Python 重跑 |
| PYZ 目录为空或缺失 | 版本不匹配导致 PYZ 被跳过 | 同上,版本对齐后重新提取 |
| 反编译工具不识别 pyc | 工具不支持对应字节码版本 | 确认 Python 版本后,换用 pycdc 等新工具 |
提取出.encrypted文件 | PYZ 归档被加密 | 原样导出属预期行为,结合调试分析解密逻辑 |
使用边界与合规提醒 ⚖️
技术工具本身是中立的,但用在哪、怎么用,边界必须清楚:
- 只处理你有权访问的程序:自己打包的产物、获得授权的安全测试目标、公司内部工具,都属于合理范围;未经授权拆解他人商业软件则可能越界。
- 尊重版权与许可协议:提取出的代码仍归原作者所有,不要将其用于商业用途或二次分发。
- 把能力用在正途:无论是找回丢失的源码、审计依赖版本,还是排查安全漏洞,提取只是手段,解决问题才是目的。
如果你做的是恶意分析或代码窃取,那已经超出了本工具的设计初衷,也超出了本文的讨论范围。
动手清单:现在就完成你的第一次提取 ✅
回顾全文,pyinstxtractor 的核心价值可以浓缩成几句话:单文件、零依赖,克隆即用;一条命令覆盖 PyInstaller 2.0 到 6.19.0 的全部主流版本;自动修复 pyc 文件头,反编译无需二次处理;遇到加密归档不崩溃,原样导出留待深挖。
现在轮到你动手了。挑一个你手头有权限处理的 PyInstaller 打包程序,依次完成:
- 克隆项目到本地;
- 运行
python pyinstxtractor.py 你的程序; - 记下输出的 Python 版本号;
- 打开
_extracted目录,找到入口点.pyc; - 用反编译工具还原第一份源码。
从"拿到一个陌生可执行文件"到"还原出可读的 Python 源码",整个过程压缩到三步:克隆、运行、反编译。赶紧找出手边第一个 PyInstaller 打包程序试试看吧。
【免费下载链接】pyinstxtractorPyInstaller Extractor项目地址: https://gitcode.com/gh_mirrors/py/pyinstxtractor
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考