Ramnit感染病毒分析报告
简介
本文主要涵盖对Ramnit家族的3个变种(Ramnit.X,Ramnit.AS和Ramnit.A)的分析以及修复方案。其中Ramnit.X变种和Ramnit.AS变种感染文件的方式与之前分析的06—感染型病毒是一样的,所以本文将以Ramnit.A为主要分析对象来进行说明,并会说明Ramnit.A与Ramnit.X变种和Ramnit.AS变种的不同点。由于本文主要是对Ramnit家族的分析与修复方案,将不会特别细致的阐述每一个点,若想看更加详细的分析或想看Ramnit.X变种和Ramnit.AS变种的详细分析,可看Ramnit感染病毒分析报告02。
基本信息
Ramnit变种名 | 感染母体文件 | 文件对应MD5 |
---|---|---|
Ramnit.A | WaterMark.exe | BA4610E9CA3EBF61EC5800955A797C13 |
Ramnit.X,AS | DesktopLayer.exe | FF5E1F27193CE51EEC318714EF038BEF |
样本详细分析
病毒主体
复制自身
运行病毒样本后,会检索当前文件的路径,并判断该目录是否是C:\Program File\Microsoft\
,若不是便将自身复制到该目录下,并执行该目录下的病毒母体文件,然后退出当前进程。代码如图:
Ramnit.A变种与 Ramnit.X,AS 变种的不同点在于释放的感染母体文件不同,Ramnit.A变种释放名为WaterMark.exe
, Ramnit.X,AS 变种释放名为 DesktopLayer.exe
。
inline Hook
先将出主线程外的其他线程挂起,再对ntdll模块中的函数ZwWriteVirtualMemory
进行Hook,如图:
inline Hook的实现过程,如图:
创建傀儡进程
由于之前Hook了函数ZwWriteVirtualMemory
,恶意样本通过调用CreateProcess创建进程时,执行恶意样本自己写的Hookmain函数。
Hookmain函数主要行为是:往子进程中远程开辟虚拟空间,将PE文件展开并写入远程开辟的虚拟空间中,还写入3了个函数(修复IAT函数,修改区段属性函数,主行为逻辑函数),然后再修改子进程的入口点,从而创建傀儡进程,代码如图:
Ramnit.A变种与 Ramnit.X,AS 变种的不同点
Ramnit.A变种
Ramnit.A变种Hook了两次ZwWriteVirtualMemory
(分别进行了脱钩),并创建了两个Svchost.exe的傀儡进程,且注入的PE文件不是同一个文件,其中一个为感染傀儡进程,另一个简单看了一下维持进程当互斥体不在时,便遍历进程并注入所有进程。
Ramnit.X,AS 变种
Ramnit.X,AS 变种只Hook了一次,创建了一个浏览器(IE、Chrome等)傀儡进程。
感染傀儡进程
Ramnit.A变种创建了两个进程,其中只有一个是进行感染的,并且与Ramnit.X,AS 变种差不太多。
感染傀儡进程主要行为:
- 创建线程1,将感染母体文件(WaterMark.exe或DesktopLayer.exe)添加到注册表Winlogon表中的userinit项中,使其开机自启。
- 创建线程2,与google、bing、Yahoo进行连接,获取时间,来记录样本运行了多长时间。
- 创建线程3,将线程2中获取的样本运行的时间,记录到文件dmlconf.dat 来记录样本运行了多长时间。
- 创建线程4,进行网络通信,按照一定时间,将获取到的数据发送到C&C服务器 ==poopthree.com== 或 ==fget-career.com==。
- 感染PE文件和网页文件。
感染傀儡进程的主要行为代码,如下图:
添加自启动项
将感染母体文件(WaterMark.exe或DesktopLayer.exe)添加到注册表Winlogon表中的userinit项中,使其开机自启。代码如图:
加工感染数据
先读去感染母体的PE文件数据,然后根据函数GetTickCount
获取到的自操作系统启动后的时间作为密钥,来加密感染母体PE文件数据,然后在将VBscript与加密后的感染母体PE文件进行拼接。代码如图:
感染固定介质
遍历固定介质(硬盘),当磁盘大小大于512K时,开始遍历磁盘文件,通过匹配文件后缀名的方式,来判断要感染的文件。Ramnit.X,AS 变种和Ramnit.A变种都只感染4种文件后缀的文件,分别为:==.exe,.dll,.htm,.html==文件,如图:
感染PE文件
判断感染标志
感染==.exe和.dll==文件,先判断感染标志是否存在。
Ramnit.A变种的感染标记
为文件附加数据的最后24个字节,通过将最后24个字节每4个字节与第一个4字节进行异或,然后与特定的值进行比较。将最后24个字节进行异或解密,如图:
与特定值进行比较,来判断文件是否被感染,如图:
Ramnit.X,AS 变种的感染标记
,遍历节表,查看文件是否有rmnet
节,来判断文件是否被感染。
判断是否感染
判断目标文件是否是32位程序,是否是.net,是否有签名,当不是32位程序,不是.net,没有签名时,便不感染,代码如图:
遍历目标文件OFTs表
遍历目标文件的OFts表,获取LoadLibrary和GetProcAddr函数的FTs(IAT)的RVA,以及遍历导入表获取模块名为kernel32.dll的导入表位置,然后将获取到的RVA存到全局变量中,后面会跟着写入函数一同写到被感染文件中,如图:
添加新节
添加新区段,并设置感染区段的可读可写可执行属性,代码如图:
Ramnit.A变种
添加的区段名为.text
。
Ramnit.X,AS 变种
添加的区段名为.rmnet
。
修改OEP
先获取到目标文件的OEP,然后将==添加的新节RVA与OEP的差值存储在全局变量==中,后面会写入被感染的文件中,在将添加的新节的VA设置为新的OEP,代码如图:
Ramnit.A变种的OEP
存储在感染区段偏移为 ==0x771== 的地址处。
Ramnit.X,AS 变种的OEP
存储在感染区段偏移为 ==0x328== 的地址处。
写入加密后的感染母体及解密函数
由于之前将感染母体PE进行了加密处理,所以在感染的时候还需要将==解密函数==同==加密后的感染母体文件==同时写入被感染文件中去。下图中进行了两次写入,分别是写入解密函数,和加密后的感染母体文件(WaterMark或DesktopLayer),如图:
写入密钥和感染标志
这里Ramnit.A变种
就与 Ramnit.X,AS 变种
不太一样了,Ramnit.X,AS 变种
并没有这些操作。
之前在加工感染数据时提到过,Ramnit.A变种
根据获取到的自操作系统启动的时间作为密钥,来加密感染母体PE文件,因此,Ramnit.A变种
便将密钥经过加工写入被感染文件的附加数据中,也还会写入Ramnit.A变种
的感染标志(文件末尾24字节),代码如图:
修复文件
修复文件校验和,文件时间以及文件属性,代码如图:
Ramnit.A变种
会修复文件校验、修改时间和文件属性
Ramnit.X,AS 变种
只会修复文件校验和(但好像修复不成功)
感染网页文件
判断感染标志
Ramnit.A变种
的网页文件的感染标志与PE文件差不多,唯一区别为PE文件是直接读取最后24字节,而网页文件读取文件末尾倒数第27字节往后的24字节,其他的都一样,代码如图:
Ramnit.X,AS 变种
的网页感染标志为文件末尾的9个字节是否是</script>
写入感染脚本
Ramnit.A变种
先写入感染脚本,再写入解密感染母体需要的密钥和感染标志,代码如图:
Ramnit.X,AS 变种
就相对简单,直接写入感染脚本
修复文件
Ramnit.A变种
会修复修改时间和文件属性,代码如图:
Ramnit.X,AS 变种
对与网页文件并没有任何修复操作。
感染可移动介质
Ramnit.A变种
和Ramnit.X,AS 变种
对于可移动介质的感染操作,都是将恶意PE写入可移动介质的==autorun.inf==文件中,使当可移动介质插入计算机时自启动。
修复分析
修复目标:
- 判断当前操作系统感染类型
- 关闭创建的傀儡进程svchost(
Ramnit.A变种
)和默认浏览器IE,chrome等(Ramnit.X,AS 变种
),防止边修复遍感染。 - 删除感染母体文件,文件路径为
C:\Program File\Microsoft\
,目录下的感染母体文件WaterMark(Ramnit.A变种
)或是DesktopLayer(Ramnit.X,AS 变种
) - 删除自启动项,修改注册表
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon
- 根据当前感染类型,修复.exe文件、.dll文件、.htm文件、.html文件
文件修复
判断文件是否被感染
Ramnit.A变种
对于.exe和.dll文件根据文件末尾最后24字节与特定特征去比较,对于.htm和.html文件根据文件倒数第27字节读取到的24字节与特征去比较,本人写的判断Ramnit.A变种
是否被感染的代码如下:
1 | //判断文件末尾的感染特征 返回true,说明该文件被感染 |
Ramnit.X,AS 变种
的判断逻辑相对简单,对于.exe和.dll文件遍历PE文件的节表,查找是否有.rmnet节,若有便是被感染的,对于.htm和.html文件,则匹配最后9个字节的数据,本人写的代码(没有封装好)如下:
1 | 对于.exe和.dll文件 |
获取原始OEP
根据Ramnit.A变种的OEP
存储在感染区段偏移为 ==0x771== 的地址处。Ramnit.X,AS 变种的OEP
存储在感染区段偏移为 ==0x328== 的地址处。
代码如下:
1 | Ramnit.X,AS 变种的OEP |
设置感染标记
对于Ramnit.A
变种,在文件末尾添加任意被感染文件末尾24字节的感染标记即可。
1 | EF DA DA 59 BD 19 C1 A3 EA DA DA 59 EF DA DA 59 E2 DA DA 59 3D EF 0C 15 65 9B 0F 04 8D D4 DF 59 EA DA DA 59 |
对于Ramnit.X,AS 变种
,添加.rmnet节表
删除感染节表
删除感染节表
1 | //删除感染节表 |
删除感染数据
删除感染PE数据
Ramnit.A
变种和Ramnit.X,AS 变种
删除.exe和.dll文件都可用如下方法删除感染数据
1 | void deldata() |
删除感染网页数据
删除网页的感染数据稍微不同,因为Ramnit.A
变种网页数据后面还有随机长度的密钥以及感染标志,因此删除网页感染数据代码如下:
1 | //修复Ramnit.A |