pyinstxtractor 解包 exe 文件
1 | python pyinstxtractor.py pyexe.exe |
pyc 文件反编译
pyc 文件格式
可以通过 010Editor 打开 pyc 文件查看,pyc 文件的格式为:
- 4 个字节的 magic number (小端形式)
- 12个字节的源代码文件信息(不同版本的 Python 包含的长度和信息都不一样)
- 序列化之后的 PyCodeObject
Magic Number
pyc 文件头有一个 Magic Number,不同版本的 Python 生成的 pyc 文件的 magic number 都不相同,具体的可以见下表
pyc 文件的前两个字节以小端的形式写入,然后加上 \r\n(0D 0A) 形成了四个字节的 pyc 文件的 magic number
1 | MAGIC_1_0 = 0x00999902 |
在部分题目中,使用 pyinstaller 导出的 pyc 文件会将文件的 Magic Number 和时间戳信息抹去,反编译时工具会报错,于是需要手动添加 Magic Number 与时间戳,时间戳可以随便添加(全 0 也可以),但是每个版本 Python 编译的 pyc 文件 Magic Number 都不同,需要我们手动查找与填充
源代码文件信息
源代码文件信息在 Python 不同的版本之后差别较大
在Python2的时候,这部分只有 4 个字节,为源代码文件的修改时间的 Unix timestamp(精确到秒)以小端法写入,如:
(1586087865).to_bytes(4, 'little').hex() -> b9c7 895e
在 Python 3.5 之前的版本已经找不到了
Python 3.5 和 3.6 相对于 Python 2,源代码文件信息这部分,在时间后面增加了4个字节的源代码文件的大小,单位字节,以小端法写入。如源码文件大小为 57 个字节,那么文件信息部分就写入 5700 0000。加上前面的修改时间,就是 b9c7 895e 5700 0000
从 Python3.7 开始支持 hash-based pyc 文件,Python 不仅支持校验 timestrap 来判断文件是否修改过了,也支持校验 hash 值。Python 为了支持 hash 校验又使源代码文件信息这部分增加了4个字节,变为一共12个字节
- hash 校验默认是不启用,不启用时前4个字节为 0000 0000,后 8 个字节为 3.6 和 3.7 版本一样的源码文件的修改时间和大小;当启用时前 4 个字节变为 0100 0000 或者 0300 0000,后 8 个字节为源码文件的 hash 值
反编译工具
- uncompyle6
1 | uncompyle6 input.pyc > output.py |
- pycdc
工具在编译好的 build 文件夹里
1 | 反编译为 py 文件 |
有时候,反编译失败的时候,需要得到 python 字节码,然后手动分析
- 在线网站