1. 为什么我们需要从EXE里“挖”出源码?
你可能遇到过这种情况:几年前写的一个小工具,当时用PyInstaller打包成了EXE文件,现在想加点新功能或者修复个Bug,结果发现原始的.py源码文件早就不知道丢哪里去了,只剩下一个孤零零的EXE。或者,你从网上下载了一个用Python写的小工具,想学习一下它的实现思路,但作者只提供了EXE。这时候,一个很自然的想法就是:能不能把这个EXE文件“拆开”,把里面的Python源码给“还原”出来?
这个过程,在技术领域叫做“逆向工程”或“反编译”。对于由PyInstaller打包的EXE文件,传统上我们会用pyinstxtractor提取文件结构,再用uncompyle6或decompyle3这样的工具去反编译.pyc字节码文件。这个方法我用了好多年,一直很稳。但最近,随着Python版本的快速迭代,特别是到了Python 3.9、3.10以后,我踩坑了。很多反编译工具对新版本Python生成的字节码支持不及时,直接报错,让你束手无策。
我自己就亲身经历过。去年有个用Python 3.10.5写的自动化脚本,打包后源码备份丢失了。当我用老方法处理时,uncompyle6直接提示不支持该版本的字节码。当时真是有点懵,难道代码就这么丢了?后来经过一番搜索和折腾,我发现了pydumpck这个工具。它就像一个“全能钥匙”,专门解决这类新版Python打包文件的逆向问题。今天,我就把自己摸索出来的、用pydumpck从PyInstaller打包的EXE中提取Python 3.10源码的完整过程分享给你,手把手教你如何操作,并解释背后的原理,让你不仅能“知其然”,还能“知其所以然”。
2. 准备工作:认识我们的“对手”与“武器”
在开始动手之前,我们得先搞清楚两件事:PyInstaller是怎么把我们的代码“锁”进EXE的,以及pydumpck这把“钥匙”到底强在哪里。
2.1 PyInstaller打包机制浅析
你可以把PyInstaller想象成一个非常专业的“搬家打包公司”。你的Python项目(主脚本、依赖的模块、资源文件等)就是散落一屋子的物品。PyInstaller的工作是:
- 收集所有物品:它会分析你的主脚本,找到所有
import的库和模块,包括标准库和第三方库。 - 压缩打包:把这些Python源码(
.py文件)编译成字节码(.pyc文件),然后把字节码、Python解释器本身(一个精简版)、以及任何数据文件(如图片、配置文件)全部塞进一个(或多个)大箱子里。 - 制作一个“万能开箱器”:这个“开箱器”就是生成的EXE文件。当你运行EXE时,它首先会创建一个临时目录,把箱子里的所有东西解压出来,然后启动自带的Python解释器去执行你的主脚本字节码。
关键在于,这个过程中,你的原始.py源码并没有直接以明文形式存在,而是被编译成了.pyc字节码。.pyc是Python解释器能直接执行的、但人类难以直接阅读的中间格式。我们的目标,就是把这些.pyc文件找出来,并“翻译”回人类可读的.py源码。
2.2 为什么传统工具会失效?认识pydumpck
以前,我们“翻译”.pyc的工具主要是uncompyle6。但它本质上是一个针对特定Python字节码版本的“字典”。每当Python发布新版本,字节码的指令集和结构可能会有细微调整,uncompyle6就需要更新这本“字典”。如果它还没来得及更新到支持Python 3.10,那它面对3.10生成的

5432

被折叠的 条评论
为什么被折叠?



