原创 | 基于python编写系统的逆向与修改研究

admin 2020年12月28日16:15:33评论170 views字数 3424阅读11分24秒阅读模式

在工控领域多采用c/s架构的系统,客户端的项目部分采用pyinstaller将python代码打包为独立的二进制文件,其特点是可以脱离python环境直接运行,并且可以将源代码进行隐藏起到保护作用。本文主要目的就是研究pyinstaller打包后的python二进制文件,确定是否可以进行代码还原分析和修改。文章共分为两个部分,第一部分分析研究python编写的客户端逆向和修改的实现方式;第二部分进行实例分析,其中讲解了一个在工控系统中发现的勒索病毒进行文件加密方式以及分析后文件还原方法,以及一个安全扫描工具的代码还原修改并重新打包运行。

为了进行测试,我们首先写了一段简单的python代码:
原创 | 基于python编写系统的逆向与修改研究

保存为test1.py文件,然后使用pyinstaller -F test1.py将代码编译为二进制文件。

原创 | 基于python编写系统的逆向与修改研究

进入dist目录,可以看到编译后的test1.exe,直接运行可以输出结果:

原创 | 基于python编写系统的逆向与修改研究

首先尝试将这个exe文件进行逆向,看能否还原出python源码。先到网上搜索了一下,发现已经有大神针对pyinstaller写好了解包的脚本。地址是:https://github.com/extremecoders-re/pyinstxtractor

将脚本下载好,尝试一下用脚本对test1.exe进行解包:

原创 | 基于python编写系统的逆向与修改研究

脚本提示已经成功将test1.exe解包,并且程序的入口点为test1.pyc文件。

我们看一下解包后输出的目录结构:

原创 | 基于python编写系统的逆向与修改研究

其中PYZ-00.pyz_extracted文件夹里面为test1.py运行所调用的所有python库编译为pyc格式后的文件。

原创 | 基于python编写系统的逆向与修改研究

而和test1.pyc通目录下的其他文件,则是pyinstaller打包用的python环境文件。所以这里我们只需要想办法把test1.pyc转回源码,使用uncompyle6即可:

原创 | 基于python编写系统的逆向与修改研究

可见已经完全反编译出了python源码,如果利用反编译的源码修改加入恶意代码后再重新编译打包发给用户,即可利用此技术发起恶意攻击。

我们再考虑一种复杂的情况:python项目是采用多个文件相互导入的方式编写,然后再用pyinstaller一起编译打包。

先写一个test2.py,代码为:

原创 | 基于python编写系统的逆向与修改研究

再写一个test3.py,代码为:

原创 | 基于python编写系统的逆向与修改研究

这时候,执行python test3.py的结果为:

原创 | 基于python编写系统的逆向与修改研究

使用命令将test3.py打包pyinstaller -F test3.py:

原创 | 基于python编写系统的逆向与修改研究

尝试使用脚本对test3.exe进行解包,再看一下输出结果的目录。

原创 | 基于python编写系统的逆向与修改研究

我们可以看到,根目下只有test3.pyc,而没有test2.pyc。经过一番寻找,我们在PYZ-00.pyz_extracted目录下找到了test2.pyc:

原创 | 基于python编写系统的逆向与修改研究

可看到虽然只用了print()一个内置方法,导入了一个文件,但最终打包时候一起打包了134个文件。我们同样可以使用uncompyte6反汇编出test2.pyc的源码内容:

原创 | 基于python编写系统的逆向与修改研究

由此我们可以得出以下结论:

1.pyinstaller对python代码打包的二进制文件,必定可以还原为几乎原始的python代码。

2.pyinstaller在打包的过程中,会将主引导以外的系统内置库、第三方库以及项目的其他文件统一打包到一个PYZ-00.pyz文件中。

3.如果我们面对一个未知的pyinstaller打包过的二进制文件想要修改,只要该文件导入过任何内置库或公开的第三方库以外的文件,则几乎不可能使用将所有文件反编译回python源码再重新打包的方式。

因此,决定先看一下解包脚本的代码,如果可以把解包的过程逆向出来,则可以方便的把pyinstaller打包后的二进制文件解包--修改--再打包还原。

首先看到解包脚本存在4个关键方法:

原创 | 基于python编写系统的逆向与修改研究

checkFile()用来判断解包的文件是否是一个pyinstaller打包的文件;

getCArchiveFifo()用来获取打包数据的整体信息,如数据的大小,文件偏移地址,使用python的版本等。

parseTOC()用来获取打包数据中每个文件的信息,最后合并为一个表,关键部分代码如下:

原创 | 基于python编写系统的逆向与修改研究

extractFiles()则是根据parseTOC()方法最后生成的表,对每个文件数据进行解包释放,关键代码为:

原创 | 基于python编写系统的逆向与修改研究

文件类型为z的就是释放出的PYZ00.pyz文件,该文件还要再通过_extractPyz()方法再处理一次,下面我们接着看_extractPyz()这个方法,关键代码解释如下:

原创 | 基于python编写系统的逆向与修改研究

由此我们可以总结出pyinstaller解包过程:

1.先将pyinstaller打包后的二进制文件分为pe引导文件以及一个打包的数据文件。

2.通过读取指定偏移地址的信息将数据包文件逐一释放还原。

3.如果是pyz格式的文件,再进一步进行解包,并将解包出的pyc格式文件修复文件头。

因此如果我们想要将解包后的文件重新打包,也必须分为三个部分:

1.将pyz格式释放后的文件打包还原为pyz格式文件;

2.再将所有所有文件打包还原为数据文件;

3.再将数据文件和pe引导文件合并。

下面开始整个还原打包的过程:

1.将原始脚本做一定修改,记录输出一些关键数据,以方便还原的时候读取。修改代码后直接解包脚本效果如下:

原创 | 基于python编写系统的逆向与修改研究
原创 | 基于python编写系统的逆向与修改研究

同时,文件头的修复对于代码分析很有作用,但对于打包还原是多余的过程。我们直接再释放输出一份未修复的文件。

原创 | 基于python编写系统的逆向与修改研究

2.编写打包还原代码第一部分,重打包pyz格式文件,关键代码如下:

原创 | 基于python编写系统的逆向与修改研究

3.编写打包还原代码第二部分,将所有文件按原始顺序以及格式还原,关键代码如下:

原创 | 基于python编写系统的逆向与修改研究

4.将数据文件与pe引导文件进行合并还原:

原创 | 基于python编写系统的逆向与修改研究

接下来验证代码效果:

首先我们将test2.py的代码内容修改为如下:

原创 | 基于python编写系统的逆向与修改研究

然后使用命令python -m py_compile test2.py将其转换为pyc格式文件:

原创 | 基于python编写系统的逆向与修改研究

再使用010editor删掉test2.pyc文件的头信息:

原创 | 基于python编写系统的逆向与修改研究

然后将test2.pyc拷贝到nofix目录下覆盖同名文件,执行重打包代码:

原创 | 基于python编写系统的逆向与修改研究

测试一下,修改后的文件成功运行:

原创 | 基于python编写系统的逆向与修改研究

实战一:

尝试对一个工控系统中发现的python编写的勒索病毒样本进行分析。样本名称:tc6.exe,Sample Hash:

53854221c6c1fa513d6ecf83385518dbd8b0afefd9661f6ad831a5acf33c0f8e,先使用脚本进行解包:

原创 | 基于python编写系统的逆向与修改研究

使用uncompyle6对源码进行还原后分析关键代码:

原创 | 基于python编写系统的逆向与修改研究

从上图我们可以分析出,勒索病毒先获取了所有本地的物理驱动器;然后设置了一个加密的密码,接着打印勒索信息,其中交赎款的地址是从从地址池中随机选取的一个;接着遍历所有驱动器的文件,如果文件的扩展名在代码中设定的扩展名表中,则对文件执行加密操作。

再往上看一看文件加密的方法:

原创 | 基于python编写系统的逆向与修改研究

我们在这里,不仅发现了文件加密采用aes算法对文件进行加密,还有一个针对加密文件解密的方法。通过研究发现,我们使用这个解密方法即可对加密后的文件进行解密。

实战二:

尝试对一款国际上比较流行的安全类商业软件进行分析修改。该软件的ui界面采用python编写并打包为独立的二进制文件,我们首先使用脚本对该文件进行解包:

原创 | 基于python编写系统的逆向与修改研究

成功解包后,将入口引导文件进行修复,查看代码:

原创 | 基于python编写系统的逆向与修改研究

发现在主引导文件中只有很简单的启动服务代码,其他功能都是通过导入另外的文件来实现的。

我们看一下程序运行时的日志信息:

原创 | 基于python编写系统的逆向与修改研究

主程序在启动时先进行各个服务的初始化,然后检查激活状态,再检查版本更新信息。我们尝试修改下检查版本更新的代码,在将所有的导入文件进行反编译回python源码后,从helpers.updater.py文件中查看到相关代码:

原创 | 基于python编写系统的逆向与修改研究

我们对这行代码进行修改,多输出以下我们的信息:

原创 | 基于python编写系统的逆向与修改研究

然后按照之前测试步骤,将helpers.updater.py编译为pyc格式文件,然后移除pyc的文件头,再覆盖回nofix目录进行重打包。

原创 | 基于python编写系统的逆向与修改研究

使用修改后的文件覆盖原始文件,再重启服务,查看日志:

原创 | 基于python编写系统的逆向与修改研究

从运行日志中可以看到成功输出了我们在代码中添加的内容。

总结:

当前,python编写的系统可谓安全性极低。用户不仅可以很容易的解包后查看到python项目的源码,还可以对解包后的源码快速编辑后重新打包为二进制文件。而对于修改后的文件,普通用户没有办法进行简单的标识。因此,在工控领域使用python开发的项目风险极大,恶意用户可以轻松的插入勒索加密等代码,造成用户经济以及信息数据上的损失。



转载请注明来自:关键基础设施安全应急响应中心

原创 | 基于python编写系统的逆向与修改研究

本文始发于微信公众号(关键基础设施安全应急响应中心):原创 | 基于python编写系统的逆向与修改研究

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2020年12月28日16:15:33
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   原创 | 基于python编写系统的逆向与修改研究http://cn-sec.com/archives/222618.html

发表评论

匿名网友 填写信息