前言
简单了解反编译,为保证自己python工程有一定的安全性,尝试反编译文件。
目标
Python exe -> pyc -> py
环境
windows 7
python 3.7
PyInstaller 3.5
工具
uncompyle6 3.6.4 ( 注:安装命令 pip install uncompyle)
archive_viewer.py (注:该文件位于PyInstaller包中PyInstaller\utils\cliutils\archive_viewer.py)
010 editor (字节查看修改,用于补全pyc文件中的缺失部分)
使用方法
用archive_viewer打开exe文件,x命令解压(x)需要的文件,输出到指定文件,并退出(q)
# 法一 单个文件
python archive_viewer.py main.exe
? x struct
to filename? struct.pyc
? q
#########################
# 法二 所有文件
python pyinstxtractor.py main.exe
对比过程,可直接修改要修改的文件。
到工程目录下的__pycache__复制一个文件a.cpython-37.pyc
到解压的main.exe_extracted\PYZ-00.pyz_extracted中找到对应的文件,记为a.pyc
使用010editor打开两个文件,进行对比发现a.pyc少了4个字节,在字节8开始处插入4个0字节后保存(对比发现8到16个字节不同,但是已经可以反编译了,故忽略)
使用uncompyle6 反编译文件pyc到py
uncompyle6 a.pyc > a2.py
uncompyle6 a.cpython-37.pyc > a1.py
生成的py文件相同,且与源代码相同
总结:
1. 使用pyinstxtractor或者archive_viewer将exe文件解码出pyc文件(注,只适用于用pyinstaller编译生成的exe文件)
2. 使用二进制编辑工具,在第8个字节处插入4个0字节
3. 使用uncompyle6反编译pyc文件到py文件。
注:
参考文档:
pyc文件格式
1 最开始4个字节是一个Maigc int, 标识此pyc的版本信息, 不同的版本的 Magic 都在 Python/import.c 内定义
2 接下来四个字节还是个int,是pyc产生的时间(TIMESTAMP, 1970.01.01到产生pyc时候的秒数, 本文就是通过添加4个字节为0的时间戳字段来反编译pyc文件)
3 接下来是个序列化了的 PyCodeObject(此结构在 Include/code.h 内定义),序列化方法在 Python/marshal.c 内定义
Python脚本解压
importuncompyle6
with open("a.py", "w") as file:
uncompyle6.decompile_file("a.pyc", file)