因为pyinstaller方便、兼容性相对较好,所以我们会经常见到一些用pyinstaller打包的Python程序,在这里我们了解一下如何对这些打包好的exe文件进行反编译(即反编译出.py文件),也可以通过对抗去改进我们程序的保护措施。
0.前提准备
确认程序
我们首先要确认一个exe程序他是不是由pyinstaller编译的,如果不是那就没必要再往下操作了。
一般我们可以看程序图标,比较标志性的两个
上方图标表示不带命令行(即pyinstaller -w)
下方图标表示带命令行
也可以对其以压缩包形式打开,有一些pyinstaller打包的软件内部呈现这个结构
当然了这些都是一般情况,如果不确定试试也无妨。有的软件还会加壳(比如常见的upx壳),我们需要先对其脱壳才能继续反编译,限于篇幅查壳、脱壳等这里不细说,默认大家需要反编译的软件是未加壳/已脱壳的。
用到的工具
pyinstxtractor.py ---- 将.exe解包
我转储了一份到我的对象储存里,给无法连接github的朋友下载
uncompyle6 ---- .pyc转.py
pip install uncompyle6
Hex Editor Neo ---- 16进制编辑(用其他也可以)
大家可以在网上找找破解版的,出于版权保护我这里放上官网链接(155 CNY)
1.exe解包
将上面准备的 pyinstxtractor.py 和exe文件(例如叫demo.exe)放到目录下
python pyinstxtractor.py demo.exe
这里我们建议使用,与打包这个文件一致的Python版本。也就是比如用python3.9打包的,我们最好也用python3.9来执行 pyinstxtractor.py (实际上不会有大问题,不过遇到问题可以尝试,命令行中会提示我们打包时所用的Python版本)
不出意外的话,我们可以在目录下见到一个,形如 demo.exe_extracted 的文件夹,里面的目录结构大概是
我们只关心两部分文件 PYZ-00.pyz_extracted 和该目录下没有后缀名的文件,我们下面细说
2.pyc文件转.py
打开 PYZ-00.pyz_extracted 文件夹,这里分两种情况:
如果目录下的文件名都是 .pyc.encrypted ,说明经过了加密(pyinstaller --key),当然了我们也是可以解密的,解密方法我放在下一篇文章里详细讲述
如果都是.pyc,那说明没有加密,我们可以使用 uncompyle6 将其反编译成.py文件(也就是源码)
以反编译 Client.pyc 文件为例,我们在该目录下启动命令行,然后键入
uncompyle6 -o Client.py Client.pyc
不出意外可以看到目录下已经有一个 Client.py 文件,里面就是源代码,变量和方法名都不会变,说它是源代码没有问题。
可是这个目录下有那么多的文件(绝大多数是调的库),我们怎么知道哪些是关键代码呢?这里有2种方法:
1、暴力破解,先按照经验剔除掉一些文件,然后每个都反编译一个个检查。
2、先找到入口方法,然后通过检查其导入的库一步步找齐所有我们需要的文件。值得注意的是,程序入口不在这个文件夹里面。
3.反编译程序入口
返回到上级目录,我们可以在里面看到这种,没有后缀名的文件:
其中就有我们寻找的入口方法,当然我们不用每个都反编译一次,按照经验找到你觉得最有可能的那个文件(如main、client),我们就来处理这个文件。
首先我们可以把这个文件直接重命名,给他后缀加上.pyc,然后用上面的方法(uncompyle6)对它进行反编译,小概率可以直接反编译成功。大概率会遇到错误,形如:
ImportError: Unknown magic number 227 in main_2016.pyc
这是因为它缺少了一段 magic head,我们需要手动将其补齐,就可以反编译了。
打开我们的 Hex Editor Neo,或者是其他十六进制编辑器也可以。用它打开我们目录下的2个文件,struct 和我们刚刚选的文件(下文以 main_2016 来举例,并且我已经提前将它的后缀名补上.pyc)。
对比这两个文件,我们可以发现 struct 文件中e3 00 00 00前面还有一段33 0d 0d 0a 70 79 69 30,这就是我们要补充上去的内容。有的教程说补8个字节,也有说补4个的,但最好根据实际情况来处理。
我们复制struct文件中多出来的这一串,粘贴到 main_2016.pyc 的开头,如果你在使用Hex Editor Neo,要先打开右上方的插入模式
粘贴过去之后,它是这个样子
保存,然后按照上面的方法用 uncompyle6 反编译
uncompyle6 -o main_2016.py main_2016.pyc
就可以看到源代码了
同时我们也看到了它import了 client2016 这个库,我们回到上一步的 PYZ-00.pyz_extracted 文件夹,不出意外你会找到 client2016.pyc ,它就是关键代码之一,将它反编译之后根据import的内容再慢慢凑齐所有关键代码。
至此,本文就结束了,关于破解被加密过的 .pyc.encrypted 文件的方法我放在下一篇中详细讲述。文章中如有不清晰、错误的地方发现后我会尽快更改,不足之处还望指正。
本文撰写时部分参考、引用了下列文章,深表感谢。
对python生成的EXE文件 进行反编译_我要这头发有卵用?的博客-CSDN博客源代码误删?小问题,只要没有经过加壳操作,反编译一下吧我使用的python版本 Python 3.8.2第一步 准备需要的软件第二步 进行反编译以上方法反编译没有加壳的python生产的exe文件我使用的python版本 Python 3.8.2第一步 准备需要的软件下载Ming Loh的python反编译项目链接: https://github.com/countercept/pytho...https://blog.csdn.net/weixin_44362969/article/details/105616531python程序反编译_灬彬的博客-CSDN博客_python反编译目的:将使用pyinstaller生成的exe还原成.py文件 1、从生成的exe中提取出.pyc文件这里的方法有很多。。。可以使用pyinstxtractor。。也可以使用官方的archive_viewer.py(文末有下载)我这里使用的是官方的archive_viewer.py。。https://github.com/pyinstaller/pyinstaller/blob...
https://blog.csdn.net/x947955250/article/details/82777640