方便无阻且全面的python程序exe反编译,可以不使用十六进制编辑器完成的常规反编操作

Python源代码能够被pyinstaller打包为脱离Python环境的exe可执行文件,然而,在有些特殊情况下,比如剖析病毒,数据恢复,需要反过来把可执行文件反编译为Python源代码,这个过程是比打包要麻烦的,需要用到较多的工具,在这里给大家提供一个比较方便的方法,有一步需要自已编写一个18行的小程序,一劳永逸。

工具:

1、pyinstxtractor.py(可以在网站搜索pyinstxtractor,也可以在下面的网站下载:https://sourceforge.net/projects/pyinstallerextractor/
2、uncompyle6 这是一个pyc反编成py的文件,可以使用pip下载,等会详细讲解。
3、一个能够处理十六进制字节的小程序或者是十六进制编辑器(这里我们打算两种方法都介绍,建议用python代码实现部分功能,因为大多数十六进制编辑器是付费的,而我们处理字节并不需要很多,无需小题大做,当然你有钱的话可以无视)

步骤:

1、cmd执行命令

下载好了pyinstxtractor.py之后,我们启动cmd(Win徽标键+R,之后输入cmd+回车)

pyinstxtractor的作用就是把打包好的exe文件拆开来,拆出一个个支持文件(比如base_librabry.zip,xxx.dll),其中也包括不完全的pyc文件(为什么说不完全呢,请参见后文)

我们要运行pyinstxtractor,在cmd切换到pyinstxtractor所在目录,准备把exe文件拆包为一系列文件,按照下面的格式执行命令:
pyinstxtractor.py FILE(FILE是指程序的名称)
反编译第一步拆包它会把拆好的文件放在本目录下的文件夹里面,叫做FILE.exe_extracted,然后到这个文件夹里面,我们着重关注两个文件:一个是struct,还有一个是以程序名为名称的文件(这里是“反编译转换器”,以下称之为“待反编文件”)。这两个文件都是没有扩展名的。
在这里插入图片描述

2、添加pyc文件字节头

这两个无扩展名文件需要进行编辑,不能直接作为pyc文件反编译,这是因为pyc文件以特定的十六进制字节打头,pyinstxtractor虽然反编译出了pyc文件的内容,但没有给它加上pyc文件的头衔字节。

我们已知的是,待反编文件与struct文件的前十几个字节有部分相似,只是前者好像少了一些字节,而struct文件的开头39个字节与真正的pyc文件开头39个字节几乎一样。

根据这些证据和网络上一些文章的经验,struct文件的前39个字节就是pyc文件的头衔字节的一种,待反编文件开头通常缺失了12个字节,我们可以把待反编文件应有的pyc头衔缺失的部分补回来,从struct拷贝这些字节过去,把它手动加入到待反编文件开头(但是直接添加扩展名是无效的,它不会改变文件的任何编码)

这里我提供两种方法,一种是使用十六进制编辑器,另一种是使用Python代码实现这一步。

方法一:使用十六进制编辑器

我们需要用到十六进制编码器,比如WinHexUltraEdit010Editor等等,他们非常强大,但是是要付费的,但是HiewwxHexEditorMiniHexHxD-Tool 是免费的,就是软件界面稍微难看一点,或者功能略逊于付费软件。

如果不会用Hiew可以参照网上软件的使用方法,这个软件同时支持文本查看和比较高级的反汇编,也可以用来破解和调试软件。不建议使用NotePad++安装HexEditor插件编辑,因为它解出来的十六进制编码和别的软件解得的编码大相径庭,而且编辑的时候也会出现问题,可能软件会停止工作,如果你觉得下载上述软件有点麻烦,你可以使用Python代码实现部分功能(仅满足当前添加字节头的需求,参见方法二)

首先我们选择一款十六进制编码器,以WinHex为例:
(前面一个是待反编文件,后面一个是struct)
在这里插入图片描述
在这里插入图片描述
我们发现,待反编文件以“E3 00 00 00…”打头,而struct的第13个字节也开始“E3 00 00 00…”,那么,我们只要把struct前面十二个字节,拷贝到待反编文件的开头,这个任务就完成了,然后,点击保存,关闭,只要原来的代码不超过200KBWinHex就能够保存,否则,它不会让你保存,因为这是完整版的功能。
之后,我们才可以给待反编文件添加.pyc的扩展名。

方法二:自行编写一个添加pyc字节头的小程序

如果遇到了200KB以上的文件,试用版的十六进制编辑器通常是无法保存的,而自己制作的小程序是不受限制的,还非常灵活。我们制作这个小程序,只是为了添加pyc字节头,所以我们并不需要把所有字节显示出来,我们只要把两个文件前十六个字节显示在屏幕上,我们可以一眼看出缺少了哪些字节,然后把需要的字节填进去就能自动写入了。

在这里献上代码:

f=open(input('Struct path:'), 'rb')#打开struct文件
name=input('Program path:')
f2=open(name, 'rb')#打开待反编文件
w_all=f2.read()#先读取待反编文件原来的内容
f2.seek(0)#读取完之后从头开始
w=f.read(16).hex()#再读取16个字节用于比较
w2=f2.read(16).hex()#struct也读取16个用于比较
print(w,w2,sep='\n')#打印出来让我们看见
add=input('Please input the codes you need to write:')#然后问你要在开头写入什么
add=bytes.fromhex(add)#把普通字符串转换为bytes格式,并不是encode,而是fromhex(),把字符串看成是十六进制编码
f2.close()#关闭
f2=open(name+'.pyc', 'wb')#创建pyc待反编文件
f2.write(add+w_all)#把加入的字节和原来的字节合并写入文件
f.close()
f2.close()
print('Done.')
input()

对于不同的Python版本,翻译出来格式也不尽相同,不是所有待反编文件都缺12个字节,所以为了适用于所有版本,把两个文件前16个字节(甚至20个字节)都打印出来人工比较是很有必要的。如果觉得自己输入文件名很麻烦,不妨把这个小程序放在拆包后的目录下,把一开始改为:

name=input('Program name:')
f=open('struct','rb')
f2=open(name,'rb')

这样的好处就是你可以不用每次输入文件名,只要求输入程序名就行,但是要放在反编译后的目录下才能使用,请根据自己的喜好,选取最方便的方法。

这个反编译转换器我已经把它上传为资源,免费,下载链接:https://download.csdn.net/download/weixin_46847476/12313346

3、最终反编译

最终反编译用到的工具是uncompyle6,可以使用pip下载,如果在pip下载过程中遇到了问题,可以参照我发过的一篇博文,虽然不是安装uncompyle6时候遇到的问题,但是经验同样适用于其他任何需要pip安装的模块

https://blog.csdn.net/weixin_46847476/article/details/105346569
pip安装pyinstaller老是报错?进来看看解决方案!

使用指令:pip install uncompyle6 --timeout 480
或者pip download uncompyle6 以及 pip install uncompyle6
两种方法各有长短,参见pip安装pyinstaller的文章

下面是uncompyle6的使用方法:
在这里插入图片描述
常用的option就是这个-o了,它反编译完会把py文件放在指定的路径,便于寻找,否则它会把代码显示在控制台上,供你查阅,比较一下两者的效果:
在这里插入图片描述
发现第二条指令的结果只有一句话,我们去目标路径看看。
在这里插入图片描述
非常的成功,我们看到uncompyle加上了一点注释,指明了反编译的时间和uncompyle的版本,我们恢复了源代码,成功反编译了这个exe文件。

4、检查代码

千万不能少了这一步,越是大型的程序,就需要越仔细地检查代码,我对很多自己的程序进行反编译,遇到了问题就是,pyinstxtractor不能识别elif关键字,这是个最大的漏洞,这种漏洞的并发现象就是代码的缩进不正确,导致这样的一个问题:

#这是源代码的模样
a=input()
if a==1:
    print(1)
elif a==2:
    print(2)
elif a==3:
    print(3)
print('done.')

#这是反编译以后的模样
a = input()
if a == 1:
    print(1)
else:
    if a == 2:
        print(2)
    else:
        if a == 3:
            print(3)
        print('done.')

对于pyinstxtractor来说,它要分析程序的运作,写出代码很不容易,但是可能因为pyinstxtractor版本比较旧,最近也没有更新,所以出现用else:if:来模拟elif的情况,通常执行效果没有问题,但是最后print(‘done.’)的缩进错了,本来a输入任何值,都会print,现在只有a=3的时候才会print,这个错误不容小觑,容易产生很多隐藏的bug,所以务必检查,改正错误

好了,今天给大家的常规反编译python程序的教程就到这里结束了,有问题的话,欢迎在下方留言,说出你的看法。

本文章为作者原创,未经作者允许,禁止转载

------------------END--------------------

  • 9
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值