MBR感染病毒分析报告

基本信息

样本名称 1.exe11.vir
样本类型 MBR感染型病毒
样本大小 236 KB (242,176 字节)
MD5 8cfa512ba62399f135c03505a93533f3

简介

该样本为MBR感染型病毒,其通过修改原始MBR,从而实现在开机运行操作系统之前,执行修改后的MBR中的指令,其对系统进行了3次Hook,最终再开始时加载其写入的驱动文件来实施攻击。经过分析该样本只针对于XP操作系统进行攻击,攻击手段十分隐蔽,并且攻击十分底层,一般情况下很难发现该恶意样本的恶意源头。

流程图

08_MBR感染性病毒分析报告

简单行为分析

文件写入行为

运行样本后,该样本进行了3次文件写入行为,分别为:

  • 1.往磁盘DR0中写入数据;

  • 2.在样本目录中释放与样本同名的dll文件;

  • 3.在临时目录中写入临时文件00000218.tmp

image-20191028110112117

图1
## 注册系统服务

运行样本后,该样本通过调用regsvr32.exe,将释放出来的样本同名的dll文件注册为系统服务。执行的参数如下:

1
regsvr32 /s "C:\Documents and Settings\Administrator\桌面\8cfa512ba62399f135c03505a93533f3_1.dll"

image-20191028110816898

图2
# 样本详细分析

分析样本文件本身

首先通过查壳工具,发现该样本文件是ASPack壳,如图:

image-20191028111357118

然后通过ESP定律将其脱去。脱壳中值得注意的是,该样本有2层ASPack壳,脱壳时需要脱两次。

然后将其拖入IDA和OD中分析,该样本主要行为有:

  • 往临时文件C:\Windows\temp\00000218.tmp中,写入执行日志。
  • 将控制代码IOCTL_VOLUME_LOGICAL_TO_PHYSICAL发送到\\.\C:,来获取物理磁盘号和物理偏移量相对应的逻辑偏移量。
  • 然后根据内存地址MEMORY[0x7FFE0500] 中的值是否等于0xEE00A121,来判断当前操作系统是否已经被感染,若被感染执行相应操作。
  • 创建互斥体==Global\7BC8413E-DEF5-4BF6-9530-9EAD7F45338B==。
  • 修改MBR中的数据,并将原始MBR数据存储在62扇区中。另外还从当前文件中读取两个512字节的数据写入到60和61扇区中,还写入了一个PE文件。
  • 重启后删除自身文件,拷贝自身文件到当前目录,并伪装成一个dll文件。然后再将该dll文件注册为系统服务。
  • 强制重启计算机。从而执行感染后的MBR。

主函数代码如图:

image-20191028132331860

写入执行日志

通过调用函数WriteFile_401B81,将传进来的记录日志的字符串,写入”C:\Windows\temp\00000218.tmp”文件中。从而记录该样本执行过程的相关日志,函数WriteFile_401B81代码如下:

image-20191028133224104

获取逻辑偏移量

通过调用函数DeviceIoControl,将控制代码IOCTL_VOLUME_LOGICAL_TO_PHYSICAL发送到\\.\C:中,从而来获取物理磁盘号和物理偏移量相对应的==逻辑偏移量==。 其中函数DeviceIoControl_402BF9代码如下:

image-20191028133729406

判断是否被感染

根据内存地址MEMORY[0x7FFE0500] 中的值是否等于0xEE00A121,来进行判断当前操作系统是否已经被感染,若被感染执行相应操作。感染前改地址处的值为0,当被感染后改地址的值将被置为0xEE00A121,然后根据判断结果执行不同的操作,如图:

image-20191028134719868

创建互斥体

通过调用函数CreateMutex_402B93,来进行判断互斥体”Global\7BC8413E-DEF5-4BF6-9530-9EAD7F45338B”是否存在,若不存在则创建该互斥体,若存在直接退出当前进程。如图:

image-20191028134830359

修改MBR往扇区中写入数据

通过调用函数AlterMBR_402407,修改原始MBR中的数据,并将原始MBR数据存储在62扇区中。另外还从当前文件中读取两个512字节的数据写入到60和61扇区中。

读取原始MBR

先通过函数CreateFileA,获取\.\physicalDrive0文件的句柄hDevice。

再通过调用函数DeviceIoControl,来检索有关物理磁盘的信息,然后再从DR0中偏移00位置处读取原始MBR到指定Buffer_init00MBR中。

image-20191028140620390

写入数据

然后连续调用5次WriteFile,分别写入:

  • 往偏移0xE0FFF00000处,写入大小为0x3BC00大小的PE文件
  • 往偏移0x7800(60扇区)处,写入大小为512字节的数据
  • 往偏移0x7A00(61扇区)处,写入经过修改的大小为512字节的数据
  • 往偏移0x7C00(62扇区)处,写入之前读取到的原始MBR数据
  • 往偏移为0x0(MBR)处,写入修改后的MBR数据,从而实现感染MBR

image-20191028142205471

拷贝自身文件并注册系统服务

  • 通过调用函数MoveFileExA将自身文件拷贝到当前目录,并将文件后缀名重命名为.dll,然后设置参数为MOVEFILE_DELAY_UNTIL_REBOOT,重启后删除自身文件。
  • 通过调用函数AlterCharacteristic_403422修改复制后的.dll文件的characteristics,来将该EXE文件的属性修改为DLL文件
  • 通过函数CreateService_40316F调用regsvr32,执行命令regsvr32 /s “C:\Users\\Desktop\dump.dll”,来将复制后的dll文件注册为系统服务

image-20191028145157927

强制重新启动

先获取特权SeShutdownPrivilege,再调用函数InitiateSystemShutdownA,强制关闭应用程序,并重新启动本地计算机,从而执行感染后的MBR,代码如图:

image-20191028145711134

分析修改后的MBR

首先修改虚拟机的VMX文件,再通过强大的IDA来调试虚拟机中的系统MBR。

并在MBR载入内存的地方==7C00==处下断,然后运行到此处。由于MBR是运行在==实模式==下的,所以这里还需要将IDA区段属性修改为16位汇编模式。然后就能看到==7C00==处解析出的16位汇编代码,如下图:

1571824196358

修改后的MBR主要实现了功能有:

  • 申请2KB大小的内存空间,将修改后的MBR数据写入申请的内存空间中
  • 读取60和61扇区中的数据到申请的内存空间中
  • Hookint 13中断表中的跳转的地址,将要跳转的地址修改为申请的内存空间
  • 恢复原始MBR,通过调用被Hook的int 13,将磁盘62扇区中的原始MBR数据读取到内存0x7C00,再跳转到0x7C00执行原本MBR指令。

将修改后的MBR写入申请的内存空间中

申请内存空间

偏移[0x413]中记录了bios内存可用区域,通过将偏移[0X413]的数值减2,来申请大小为2KB的内存空间,如图:

1571837198321

将修改后的MBR写入申请的内存空间中

首先通过寄存器ax左移6位,计算出分配的内存的段起始地址。然后再将当前内存地址为[0x7C00]也就是当前执行的修改后的MBR指令,拷贝到分配的段起始位置ES:00(9F000)中,如图:

image-20191028162052653

拷贝后内存地址0x9F000上的数据,如图:

image-20191028162432362

读取60和61扇中的数据到申请的内存空间中

通过调用int 13h中断,跳转到地址ECBE2执行指令,来读取磁盘==0磁道60扇区(7800)和61扇区(7A00)==大小为2个扇区的数据到ES:BX(9F00:200)(9F200),紧挨着上一步写入的修改后的MBR数据后面。其中60和61扇区中的数据是之前分析过的样本==恶意写入磁盘中的两段数据==,汇编指 令如图:

image-20191028163914300

int 13中断处的跳转的地址为ECBE2,跳到该地址查看汇编指令。由于此时的int 13中断表跳转的地址是由系统加载的,并没有被修改,所要执行的的指令都是正常的,因此这里也就不需要跟下去分析了,ECBE2汇编指令如图:

image-20191028165018664

直接查看拷贝后的数据 ,查看申请的内存地址0x9EE00中存储的之前样本恶意写入==60和61扇区==中的数据,拷贝后内存地址0x9EE00上的数据如图:

image-20191028165823587

此时内存空间中数据与样本写入磁盘的数据对应关系,如下表:

开辟的内存地址 数据来源
9F000 修改后的MBR数据
9F200 样本写入磁盘60扇区中的数据
9F400 样本写入磁盘61扇区中的数据

Hook int 13中断表

Hookint 13中断表,修改int 13中断表中原本要跳转的地址ECBE2修改为申请的内存空间地址9F066,并将原本int 13中断要跳转的地址存储在ES:0x73(9F073)中,后面恢复时会用到,从而实现Hook。

然后将9F00004D压进栈,通过retf指令跳转到内存地址9F04D去执行。由于之前已经将修改后的MBR写入到了申请的内存空间9F000中,所以这里跳到9F04D去执行,其实就等同于执行修改后MBR数据+偏移0x4D的处的指令。Hook int 13 中断表和跳转指令如图:

image-20191028170333376

被Hook前后的 int 13要跳转的地址,如图:

image-20191028171033742

恢复原始MBR

在地址9F04D中,通过调用被Hook的int 13中断,将==0扇道62扇区(7C00)==中的原始MBR的数据写入到内存地址7C00处。写入完成后,再通过跳转到内存地址7C00中,去执行原始的MBR,从而实现恢复执行原本的正常开机操作,指令如图:

image-20191028172543515

将原始MBR拷贝到0x7C00,0x7C00处的指令前后对比如图:

image-20191028190441620

分析被Hook的int 13中断

由于上一步恢复原始MBR时,会调用被Hook的int 13中断来实现。当调用被Hook的int 13中断时,会使其跳转到申请的内存地址9FC66中去执行。接下来将主要分析要执行的Hook函数。

Hook int 13的hook函数进行的操作有:

  • 根据判断调用int 13中断的不同方式,恢复原本int 13要执行的操作。
  • 遍历匹配ntldr寻找特征序列码:==8B F0 85 F6 74 21 80 3D==
  • Hook 找到的特征码指令,将其指令修改为call 9F1FC,但实际call的地址是9F200,也就是执行之前拷贝到内存空间的==第60扇区中的数据==,这样就又回到了病毒代码。

恢复原本int 13要执行的操作

在之前Hook int 13中断时,将原本int 13要跳转的地址存在了CS:0x73的偏移处(可看之前hook int 13有分析),

然后首先通过对比ah的值来判断调用int 13的方式,分为扩展int 13调用读方式和非扩展int 13调用读方式,当不是这两种时,便会跳转到原本int 13应该跳转的地址ECBE2,执行原本的int 13应该执行的操作;若是这两种调用方式,便跳转到9F077去执行,然而在9F07E处,又重新call 了原本int 13的地址,代码如图:

image-20191028181744048

遍历匹配特征序列码

通过汇编指令repne scasb来遍历ntldr匹配特征序列:8B F0 85 F6 74 21 80 3D,来寻找要Hook的地方,指令如图:

image-20191028192647478

匹配到的特征序列(要被Hook的指令)对应的反汇编,如图:

image-20191028194904794

Hook 匹配到的特征码的指令

Hook 找到的特征码指令,将其指令mov si,ax修改为call 9F1FC,当执行这条指令时,便会跳转到地址9F200中去执行,也就是执行之前拷贝到内存空间的==第60扇区中的数据==,这样就又回到了病毒的代码区域。

image-20191028194835292

Hook前后的指令,对比如下图:

image-20191028195313983

分析被Hook的ntldr

通过上一步通过匹配特征Hook了ntldr中的地址46C3C中的指令,当执行到地址46C3C时,便会执行指令call off_9F1FC(实际call到内存地址0x9F200上去执行),重新回到之前拷贝到申请的内存中的60扇区中的指令去执行,接下来将详细分析拷贝到申请内存中的60扇区中的指令。

写入60扇区中的指令主要操作有:

  • 通过遍历匹配特征,定位到 BlLoaderBlock 结构,再根据层层结果遍历得到ntoskrnl.exe的模块基址。
  • 遍历模块ntoskrnl.exe,匹配特征6A 4B 6A 19 E8 和 E8 xx xx xx xx xx 84 C0,找到要Hook的地址,也就是找到函数IoInitSystem
  • 将61扇区中大小为512字节的指令,拷贝至该ntoskrnl.exe模块的最后512字节的位置中,并记下拷贝后的起始地址。
  • Hook之前匹配的执行函数IoInitSystem处的地址,将其指令修改为跳转到拷贝后的起始位置去执行。

获取ntoskrnl.exe模块基址

通过遍历匹配特征 ==C7 46 34 00 40==,定位到 BlLoaderBlock 结构,再根据BlLoaderBlock->LoadOrderListHead->nt!_LDR_DATA_TABLE_ENTRY->ntoskrnl.exe,遍历得到ntoskrnl.exe的模块基址,指令如图:

image-20191028202135933

匹配特征找到要Hook的地址

遍历获取到的ntoskrnl.exe的模块,先根据特征值==6A 4B 6A 19 E8==再根据==E8 xx xx xx xx xx 84 C0==匹配到要Hook的地址0x8069A3CF(执行函数IoInitSystem的地址),并将执行函数IoInitSystem的地址保存至0x9F400(61扇区)+0x4的偏移处,用来恢复被Hook的IoInitSystem指令,然后将要Hook的地址压进栈中保存。指令如图:

image-20191030195826804

匹配到特征的地址处的指令(Hook前的原始指令),如图:

image-20191030195236994

拷贝61扇区中的数据至文件末尾

遍历文件ntoskrnl.exe,找到该文件末尾512字节地址处,并将样本写入61扇区中的数据拷贝到该位置处,并记录下拷贝后的起始地址。

image-20191030195645876

文件末尾512字节(0x806E5E00)拷贝前后对比图:

image-20191031192527569

Hook 匹配到特征的地址

首先将之前通过匹配特征码找到的函数IoInitSystem执行的地址,从栈中取出来,然后将执行函数IoInitSystem的指令修改为执行拷贝61扇区到最后512字节的地址0x806E5E00处,此时hook后就会call到拷贝61扇区数据后的地址处去执行,就能执行回样本写入的指令处,实现Hook。

image-20191031192929062Hook前后的指令对比图:

image-20191031193523206

分析被Hook的ntoskrnl

当操作系统启动时,便会执行ntoskrnl中被Hook的函数,便会跳转到文件末尾的病毒代码空间中去执行。也就是病毒写入61扇区中的指令,其主要功能是实现加载并运行之前写入的驱动程序。

写入ntoskrnl中的病毒代码(61扇区)主要实现了:

  • 调用函数ExAllocatePool,开辟内存空间,然后将(61扇区中)剩下的未执行的指令拷贝至开辟的内存空间中,并跳转到内存空间中执行。
  • 执行之前被Hook 的函数IoInitSystem,初始化操作系统。
  • 将恶意样本之前写入的驱动文件加载至内存中,将其展开并运行该驱动程序。

开辟内存空间拷贝数据并执行

首先根据hash值3707E062h,调用函数SearchKernelFunctionAddress,来获取函数ExAllocatePool的地址。然后再执行函数ExAllocatePool开辟大小为1ABh的内存空间,将(61扇区拷贝至ntoskrnl中的指令)剩下还未执行的指令拷贝到虚拟内存空间中执行。代码如图:

image-20191103160909136

执行之前被Hook的函数IoInitSystem

通过将之前压进栈的函数IoInitSystem的地址取出,然后Call去调用之前被Hook的函数IoInitSystem,来初始化操作系统。指令如图:

image-20191103161919014

### 加载恶意驱动文件并执行

首先获取一些内核函数,如ntOpenFile,ntReadFile,ntClose,ExAllocatepool。然后再将之前样本写入磁盘的驱动程序加载到内存中,将其展开并跳转到OEP处去运行,指令如下图:

读取到样本写入的驱动文件:

image-20191103174921598

将其再内存中展开:

image-20191103175101629

跳转到驱动程序的OEP处执行:

image-20191103175319220

恶意驱动程序有待进一步分析

由于驱动相关方面的知识还很匮乏,这里就先不继续进行分析了。以后有相关知识的累积再进一步进行分析。

样本溯源

经过分析可知,该样本属于Bootkit类型病毒, Bootkit是更高级的Rootkit。经过查找相关指令应该是早些年爆发的==鬼影病毒==,利用感染MBR,加载恶意驱动程序来实施攻击。

相关文件信息

FileName FileSize MD5
1.exe11.vir 236 KB (242,176 字节) 8CFA512BA62399F135C03505A93533F3
1.exe11.dll 236 KB (242,176 字节) 8CFA512BA62399F135C03505A93533F3
恶意驱动文件 239 KB (244,736 字节) D00123F9C4C3226B8800A623C9999D70
00000218.tmp 根据系统环境不定 根据系统环境不定

查杀方案

恢复原始MBR

由于该样本修改了原始的MBR,执行修改后的MBR来实施攻击,只需要将原始的MBR还原就可以阻止该攻击了,具体操作为:

  • 删除修改后的MBR中的数据,将存储在62扇区中的原本的MBR数据还原回MBR中,就可以达到恢复的效果了。

删除注册的服务

由于该样本将自身修改为一个dll文件,并注册为了系统服务。在恢复时还需要将该服务进行删除,执行如下指令即可:

1
regsvr32 /u  "<SamplePath>.dll"

删除恶意写入的数据

恢复过MBR后,还需要将恶意样本写入到操作系统中的数据删除,具体操作为:

  • 删除60,61,62扇区中的数据
  • 删除写入磁盘中的驱动文件
  • 删除释放在样本当前目录下的dll文件
  • 删除释放在临时目录下的00000218.tmp文件

总结

该恶意样本通过感染MBR实现早于系统执行自己的恶意代码来将写入磁盘中的驱动文件加载起来运行。整个样本以非文件形式存在,直接写入磁盘扇区。并且是对MBR进行的感染,在很大程度上能隐蔽自身,并在一定程度上逃避杀软的检测。因此建议在平时使用计算机时,不要随意下载不正常文件,不接受不明来源的文件,以避免感染病毒。