本文将详细讲解如何使用pyi-archive_viewer
提取 PyInstaller 打包生成的 EXE 文件中的 PYC 字节码文件,并使用uncompyle6
工具将其反编译成 Python源码。
提取 PYC 文件
.pyc
文件是 Python 字节码(Bytecode)文件,由 Python 解释器自动生成,用于缓存已编译的 Python 代码,以加快后续的模块加载速度。
PYC 保留了足够的信息可用来还原原始代码结构;无优化的.pyc
文件几乎可以100%还原;
可以使用pyi-archive_viewer
命令提取 EXE 文件中的字节码文件;
运行py-archive_viewer
,查看程序的捆绑文件:
py-archive_viewer 只对 PyInstaller生成的 EXE 可执行文件有用;
pyi-archive_viewer main.exe
以main.exe
为例,该命令会列出程序捆绑的文件,并进入交互模式,输出大致如下:
Options in 'main.exe' (PKG/CArchive): pyi-contents-directory _internal Contents of 'main.exe' (PKG/CArchive): position, length, uncompressed_length, is_compressed, typecode, name 0, 248, 344, 1, 'm', 'struct' 248, 2861, 5304, 1, 'm', 'pyimod01_archive' 3109, 14025, 34022, 1, 'm', 'pyimod02_importers' 22113, 1564, 3065, 1, 's', 'pyi_rth_inspect' 23677, 589, 982, 1, 's', 'main' 24266, 56219, 109440, 1, 'b', 'VCRUNTIME140.dll' 80485, 45317, 84760, 1, 'b', '_bz2.pyd' ... ?
其中main
就是需要提取的文件,通常和程序名一样;这里假定 Python 程序只有一个文件,实际上可能存在多个;
输入命令x main
提取文件,保存为main.pyc
,输入q
退出程序:
? x main Output filename? main.pyc ? q
保存的字节码文件不是一个完整的文件,目前还不能直接使用,PyInstaller 在处理过程中,移除了MAGIC
信息;我们需要将其补全;
补全 MAGIC
从main.exe
中再提取base_library.zip
文件,方法上文中提到;这是个压缩文件,将其解压;
使用十六进制编辑器,打开base_library.zip
中的任意.pyc文件;
将E3 00 00 00
之前的内容复制到main.pyc
文件的头部,使其看起来像这样:
A7 0D 0D 0A 00 00 00 00 06 F5 69 68 19 00 00 00 E3 00 00 00 ...
这部分内容会根据 Python 版本不同而有所不同,所以不要直接复制这个示例;
反编译 PYC
现在可以使用uncompyle6
对 PYC 进行反编译;uncompyle6
可以将 Python 字节码转换回等效的 Python 源代码;
安装 uncompyle6
使用 pip 进行安装:
pip install uncompyle6
安装完成后,执行命令:
uncompyle6 .\main.pyc --output .
你将在当前目录得到反编译后的文件。