反编译 pyinstaller 产生的可执行文件
在一次计算中使用别人发布的由python编写然后编译打包的二进制程序进行操作时,总是报错"缺少链ID",但检查pdb文件已经添加了链ID。 为查明报错原因,对此二进制可执行文件进行了反编译。下面记录了操作过程:
python是解释型语言,故python编译打包成的可执行文件很容易被反编译,而像C,C++这样的编译型语言得到的可执行文件,则较难被反编译。 反编译pyinstaller 产生的可执行文件,可以分为两个步骤,一是由可执行文件获取pyc(pyo)文件,二是由pyc(pyo)文件得到py文件。
获取pyc文件
在Linux上运行pyintaller打包的可执行文件时,它会将打包好的文件解压到临时文件夹(/tmp
)中的_MEIxxxxxx
路径中暂时存放,执行完毕之后再删除,所以会存在解压缩的时间。然而这个_MEIxxxxxx
路径中主要是.so
文件,并不含有源码。
但是pyinstaller自带脚本archive_viewer.py
,可以由可执行文件解压得到pyc
文件:
1
python archive_viewer.py exefilename
1
2
3
4U: go Up one level
O <name>: open embedded archive name
X <name>: extract name
Q: quit
列表中有两个部分需要关注,一个是out00-PYZ.pyz
,其中包含主程序引用到的所有库;一个是主程序对应的文件名,其中会包含主程序。
比如,一个显示天气的程序,其主程序名称为show.py
,其中调用了calc.py
,则需要
1
2x show 提取到 show.pyc
o out00-PYZ.pyz 然后查看调用的库,然后 x calc 提取到 calc.pyc show.pyc
和calc.pyc
从pyc获取py文件
方法
方法比较多,比如 1. 在线程序,比如python反编译,在线pyc反编译等 2. uncompyle6,是python脚本,故而可以批量运行,使用方法为
uncompyle6 file.pyc
3. easypythondecompiler等
注意
pyinstaller编译成pyc时,会把pyc的magic value
去掉,如果使用easypythondecompiler
的话,需要再把magic value
补上(使用
010 Editor
编辑器)。magic value
一共8个字节,前四个对应于编译时所用python的版本,后四个对应于编译时间,比如python2.7
的03 f3 0d 0a 01 23 45 67
,python3.4
的ee 0c 0d 0a 01 23 45 67
.如果不知道编译时所用的python版本,可以通过一个trick来寻找:在可执行文件包含的前几个文件对应的pyc文件(比如
pyimod01_os_path
)中,前4个字节已经存在。
如此,便可反编译出show.py
和calc.py
等文件。
Ref: - Get Python Code From PYINSTALLER - python-pyinstaller-reverse-engineer