前言
呼,历时4天半,终于完成了对GandCrab病毒的分析,这个病毒是在52破解ScareCrowL前辈的帖子上参考借鉴而来,漫漫病毒分析之路,任重且道远,还好,我们拥有巨人的肩膀,让我们看的更远更多。
首先讲一下,为什么分析这个病毒,在四叶草公司实习,几天下来,有点厌倦分析病毒这件事了,哇,想到以后还要干好多年,心态炸了。公司峰哥给我了两个样本,说现在流行勒索和挖矿病毒,客户也中过,叫我去试试分析。然后就有了这篇病毒分析报告。顿时,分析出来有不一样的收获,这是传统病毒不一样的。
一月份,GandCrab勒索软件首次亮相,这是一种着名的恶意软件,分布在黑暗网络上,可能源于俄罗斯,主要针对斯堪的纳维亚和英语国家。……(码字太麻烦了,这里有一份关于GandCrab简介,了解一下:http://baijiahao.baidu.com/s?id=1599794170709869995&wfr=spider&for=pc)
IDA产生的分析数据库(IDA 6.8):https://pan.baidu.com/s/156A8SyhBVMjAKcjlf5SN4Q
一:目录
二:样本信息
- 样本名称:hmieuy.exe
- 样本md5:f42774332fb637650ff0e524ce1b1685
- 是否加壳:无壳
- 编译语言:Microsoft Visual C++ v.10 - 2010 ( E8 )
- 样本来源:https://www.52pojie.cn/forum.php?mod=viewthread&tid=712552&extra=page%3D1%26filter%3Dtypeid%26typeid%3D62
三:行为分析
- 这个样本的主要作用就是从资源段中检索数据,然后把其加载到内存,经过解密,然后调用解密好的shellcode。
- shellcode主要是调用LoadLibrary和GetProcAddress。获取所需要函数的地址,以便后期的生成新的病毒文件
- 重新开辟内存空间,解密新的PE文件,并把它映射入内存,复制文件头和各个区表。
- 修复IAT,这样就形成了新的病毒文件,命名为PE1.exe
- PE1.exe采用dll反射注入技术,利用ReflectiveLoader要完成的任务是对自身的装载(这一切都是在内存中发生)
- 调用dll文件的入口点
- 核心程序的行为
- 获取系统的DNS网域,本地用户名,键盘区域,CPU架构,CPU信息,磁盘驱动器
- 连接病毒服务器
- 判断病毒进程在系统中是否互斥,如果存在多个相同病毒进程,终止进程。
- 检查杀毒软件驱动,如果没有,则复制自身,修改注册表自启动
- 寻找并终止指定的进程,因为这些进程可能会影响到对文件的加密
- 利用机器数据生成加密赎金ID
- 启用微软加密服务
- 对磁盘文件除了必要文件必要路径下进行加密
- 检查进程安全令牌
- 删除卷影副本,避免管理员利用副本进行恢复。
- 执行指定的shell操作。
四:样本分析
原始样本(hmieuy.exe)
- 通读代码,发现EnumResourceNamesA API函数,函数目的是枚举指定的二进制资源,我们可以猜测程序功能是,枚举资源文件,然后映射如内存,经过解密,形成shellcode,然后执行shellcode。
- 修改内存保护设置,映射文件到内存,然后解密shellcode并且执行shellcode。
- 这是第一层保护
shellcode(内存中dump而来)
- 利用PEB,获取Kernel32.dll的基地址。
获取LoadLibrary和GetProcAddress的地址,以便在函数中调用其他函数。这个是使用shellcode最先做的两件事情。
再次申请空间,加载解密后续的病毒代码,首先加载文件头,然后遍历节区,
修改IAT
PE1.exe(内存中dump而来)
- 观察tmain函数,发现函数流程就是经过三个验证,最后执行sub_11A8.而这个函数是反射式dll注入的主要的函数。
- 调用了函数sub_获取的机器信息和dll导出函数ReflectiveLoader
- 修改内存保护设置
- 调用函数ReflectiveLoader,反射式dll注入自身[这是病毒保护自我的重点,了解反射式dll注入的流程]
- 1.需要获取被加载到内存dll的基地址,连自己在内存的哪里都不知道,还玩的屁啊
- 2.利用模块和函数的Hash来获取主要函数的地址。
- 3.分配内存区域,存放dll代码(之前应该已经注入好了)
- 4.修复,获取IAT
- 5.修复重定位表
- 6.得到OEP,跳转到dll文件的OEP地址。
- 1.需要获取被加载到内存dll的基地址,连自己在内存的哪里都不知道,还玩的屁啊
PE2.dll (内存中dump而来)
整体分析
- 病毒发作的前期:
- 病毒发作的中期:
- 病毒发作的晚期:
模块1:收集机器信息,链接url读取文件,生成互斥体
- 调用GetInforAndOpenUrl(10007580)获取系统信息,检测进程中是否存在指定给的杀毒软件,然后连接指定的url读取文件
- 系统的DNS网域,
- 本地用户名,
- 键盘区域,但是病毒并不感染俄罗斯用户
- CPU架构,
- CPU信息,
- 磁盘驱动器
- 检测进程中是否存在指定给的杀毒软件
- 连接到指定的URL,并且读取文件
- 打开Http请求,读取网络文件至缓冲区
- 打开Http请求,读取网络文件至缓冲区
- 以自身的硬件信息,生成ranson-id,并由此创建互斥体。
模块2:检测杀软驱动
- 检查是否有卡巴斯基和诺顿等杀软的驱动,先检查是否存在卡巴斯基的驱动,如果存在,XXX,如果不存在,在检查其他杀软的驱动,如果都不存在,那就将自身复制,同时写入注册表自启动项。
- 将病毒释放到系统目录下。
- 将释放的文件写入注册表Runonce中,以实现病毒的自启。
- 将病毒释放到系统目录下。
模块3:关闭相关进程
- 由于在进程文件加密的时候,不允许进程占用,所以需要终止某些特定的进程。
模块4:利用机器数据生成RansomID
- 产生了支付赎金的赎金ID,这个是由的pc_group和机器识别码生成的,
- 同时为了受害者方便交付赎金,提供了安装洋葱浏览器的教程,卧槽真的贴心。
模块5:启用微软的CSP加密服务
- 利用CryptAcquireContextW创建CSP密码容器句柄
- 利用 CryptGenKey产生随机秘钥
- 生成密钥有两种方式,CryptGenKey(生成随机密钥)和CryptImportKey(导入密钥),病毒使用了CryptGenKey方式。另:Microsoft Base Cryptographic Provider v1.0:密钥长度为512位。Microsoft Enhanced Cryptographic Provider v1.0:密钥长度为1024位
- 加密
- 销毁容器
模块6:发送Base加密后的公秘钥
- 产生特征的编码字符
- 将RSA生成的秘钥和公钥利用CryptBinaryToStringA函数Base64加密,以便后期网路传输。
- 检索系统信息,然后再进行Base64编码。
- 将获取的机器信息的Base64编码连接到秘钥的后面
- 读取之前释放到Hacky目录下的病毒,可以是利用后续的函数进行父子进程共享该段数据。
- 建立管道通信,解析域名,判断网络连接是否正常
模块7:建立管道通信
- 首先将三个域名传入。
- malwarehunterteam.bit
- politiaromana.bit
- gdcb.bit
- 创建管道连接,管道的作用是实现进程之间的消息交互
- 利用管道的通信机制,创建一个子进程,命令行参数是
nslookup %s ns1.virmach.ru
,目的是解析之前穿入的三个域名。读取文件,判断是否联网,如果没有联网,readfile的buf存在error信息,程序进程死循环
- 管道输入的一般新步骤:
- 修补可执行文件,我们将一些关键A24FF4等跳转jmp或者nop掉即可实现。
模块8:文件加密部分
- 病毒首先需要获取机器的磁盘驱动器。除了CD-ROM其他的驱动器都被感染,对于搜索到的每个驱动器,释放一个线程,进行加密。加快加密的速度。
- 病毒不会感染特殊目录和特殊格式的文件
- 然后在驱动器中遍历,如果是文档则递归调用原函数,负责调用加密函数。
- 管道通信
模块9:安全令牌检测
- 检测进程的安全令牌
模块10:删除卷影副本
- 利用shellExecute函数执行cmd,参数是
/c vssadmin delete shadows /all /quiet
,删除卷影副本,目的是不让管理员恢复数据。
五:技术总结
GandCrab病毒主要采用到的技术有,shellcode藏匿,利用shellcode的短小的特点,触发shellcode到内存,减少了被杀毒软件查杀的风险。经过第一层加密后,病毒释放了一个恶意代码文件(PE1.exe),该文件采用的是反射式dll注入技术,该技术不想传统的dll注入需要在文件系统中产生文件,所要执行的dll全在内存中,这是第二层保护手段。经过两次dump后,可以得到本次病毒的主体文件,建立了管道,实现子进程和父进程之间的通信。
shellcode
需要细细的看,参考自:https://zhuanlan.zhihu.com/p/28788521
反射式dll注入
传统的dll注入,是在文件系统中存放一个dll模块,然后进程利用LoadLibrary和CreateRemoteThread这两个API函数装载模块到内存空间,实现注入。而杀软在布置Hook的时候,重点钩取的就是这两种API函数。
反射式dll注入不需要dll文件落地,减少被查杀的风险。首先将需要注入的dll写入进程内存,然后为该dll添加一个导出函数,利用这个导出函数让其自动的装载dll。
主要有两个方向的问题:第一个如何将dll写入内存(注射器的实现),第二个如果调用自身(ReflectiveLoader的实现)
参考自:http://www.freebuf.com/articles/system/151161.html
注射器的实现
- 1.将待注入DLL读入自身内存(利用解密磁盘上加密的文件、网络传输等方式避免文件落地)
- 2.利用VirtualAlloc和WriteProcessMemory在目标进程中写入待注入的DLL文件
- 3.利用CreateRemoteThread等函数启动位于目标进程中的ReflectiveLoader
ReflectiveLoader的实现
- 1.定位DLL文件在内存中的基址
- 2.获取所需的系统API
- 3.分配一片用来装载DLL的空间
- 4.复制PE文件头和各个节
- 5.处理DLL的引入表,修复重定位表
- 6.调用DLL入口点
管道通信
管道是一种用于在进程间共享数据的机制,其实质是一段共享内存,病毒利用了管道进行父子进程的通信,这样子进程就可以直接影响父进程内存。为实现父子进程间通信,需要对子进程的管道进行重定向:创建子进程函数 CreateProcess中有一个参数STARUIINFO,默认情况下子进程的输入输出管道是标准输入输出流,可以通过下面的方法实现管道重定向: