拉巴斯

首页 » 常识 » 预防 » 初窥卡巴斯基ARK读取MBR
TUhjnbcbe - 2021/12/5 15:10:00
白癜风康复宝典 http://pf.39.net/xwdt/161105/5036053.html

*本文原创作者:wrmsr,本文属FreeBuf原创奖励计划,未经许可禁止转载

背景

LONGLONGLONGAGO就发现通过Hook磁盘端口驱动程序中的IRP_MJ_SCSI派遣函数方式过不了KB了,最近又遇到这个问题就想借此机会分析一下,看看万能的KB是如何绕过Hook读取MBR的。

作为一款商用软件的KB,出于兼容性、稳定性等原因应该不会使用太特殊的方法,初步猜想会通过重载磁盘端口驱动,自建I/O通道来绕过我们读取MBR,至此我们就有了研究方向,下面来开始我们的研究。

为了验证猜想,我搭建了双机调试环境,编写了两个Windbg脚本,编译了FakeMBR驱动程序。至于双机调试环境的搭建和Windbg脚本语法在这里就不说了,具体内容可以在网上找到资料,FakeMbr的编译和一般的驱动程序编译过程无异,在这里也不说了。对了FakeMbr的代码可以在Github找到,具体链接在文章的末尾。

如果有些朋友对文章中说的相关内容不太了解,可以参考文章末尾给出的参考链接,学习相关内容。

环境

虚拟机:VMwareWorkstation12

操作系统:MicrosoftWindows7Ultimate6.1.BuildX86

调试工具:Windbg10.0..X86

杀毒软件:卡巴斯基全方位安全软件18.0.0.(h)

脚本HelloKB.txt

功能:Hook指定的函数地址,打印相关信息,并对CompletionRoutine进行Hook参数1:函数地址参数2:HelloKBC脚本路径---------------------------------------------------------------------------------------------------------------------aC:\HelloKB.txtstort_!RaDriverScsiIrpC:\HelloKbC.txtMZat-sizeName:storport.sysLoadedstorport.sysmoduleRaDriverScsiIrpIRPkddt-r2nt!_IRPpoi(

esp+0x8)StackLocationkddt-r2nt!_IO_STACK_LOCATIONpoi(poi(

esp+0x8)+0x60)SRBkddt-r2storport!_SCSI_REQUEST_BLOCKpoi(poi(poi(

esp+0x8)+0x60)+0x4)CDBkddt-r2storport!_CDB10(poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)nt!_IO_STACK_LOCATIONnt!_IO_STACK_LOCATION.CompletionRoutinekd?poi(poi(poi(

esp+0x8)+0x60)+0x1c)storport!_SCSI_REQUEST_BLOCKstorport!_SCSI_REQUEST_BLOCK.CdbLengthkd?poi(poi(poi(poi(

esp+0x8)+0x60)+0x4)+0xa)0x`00ffstortport!_CDB10stortport!_CDB10.LogicalBlockByte0kd?poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x2)0x`00ffstortport!_CDB10.LogicalBlockByte1kd?poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x3)0x`00ffstortport!_CDB10.LogicalBlockByte2kd?poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x4)0x`00ffstortport!_CDB10.LogicalBlockByte3kd?poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x5)0x`00ff---------------------------------------------------------------------------------------------------------------------bp1{arg1}"rt1=poi(poi(poi(poi(

esp+0x8)+0x60)+0x4)+0xa)0x`00ffas/x{/v:Length}t1.echo.printf\"{arg1}Length:%i\",t1.echo.block{.if({Length}==0xa){ad{/v:Length}rt2=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x0)0x`ffff.echo.printf\"{arg1}OpCode:%i\",t2.echo.if(t2==0x28){rt3=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x2)0x`00ffrt4=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x3)0x`00ffrt5=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x4)0x`00ffrt6=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x5)0x`00ff.echo.printf\"{arg1}LogicalBlockByte0:%iLogicalBlockByte1:%iLogicalBlockByte2:%iLogicalBlockByte3:%i\",t3,t4,t5,t6.echo.if((t3

t4

t5

t6)==0){rt7=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x7)0x`00ffrt8=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x8)0x`00ff.echo.printf\"{arg1}TransferBlocksMsb:%iTransferBlocksLsb:%i\",t7,t8.echo.if((t7

t8)==0){gc}.else{.echo.printf\"{arg1}!_CDB10\".echodt-r2storport!_CDB10(poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)rt9=poi(poi(poi(

esp+0x8)+0x60)+0x1c).echo.printf\"{arg1}CompletionRoutine:%i\",t9.echoa{arg2}t9}}.else{gc}}.elsif(t2==0x3c){rt3=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x2)0x`00ffrt4=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x3)0x`00ffrt5=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x4)0x`00ffrt6=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x5)0x`00ff.echo.printf\"{arg1}LogicalBlockByte0:%iLogicalBlockByte1:%iLogicalBlockByte2:%iLogicalBlockByte3:%i\",t3,t4,t5,t6.echo.if((t3

t4

t5

t6)==0){rt7=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x7)0x`00ffrt8=poi((poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)+0x8)0x`00ff.echo.printf\"{arg1}TransferBlocksMsb:%iTransferBlocksLsb:%i\",t7,t8.echo.if((t7

t8)==0){gc}.else{.echo.printf\"{arg1}!_CDB10\".echodt-r2storport!_CDB10(poi(poi(poi(

esp+0x8)+0x60)+0x4)+0x30)rt9=poi(poi(poi(

esp+0x8)+0x60)+0x1c).echo.printf\"{arg1}CompletionRoutine:%i\",t9.echoa{arg2}t9}}.else{gc}}.else{gc}}.else{ad{/v:Length}gc}}"HelloKBC.txt

功能:Hook指定的函数地址,打印相关信息参数1:函数地址-------------------------------------------------------------------------------------------------IRPkddt-r2nt!_IRPpoi(

esp+0x8)MDLkddt-r2nt!_MDLpoi(poi(

esp+0x8)+0x4)IoStatuskddt-r2nt!_IO_STATUS_BLOCK(poi(

esp+0x8)+0x18)StackLocationkddt-r2nt!_IO_STACK_LOCATIONpoi(poi(

esp+0x8)+0x60)nt!_IO_STATUS_BLOCKnt!_IO_STATUS_BLOCK.Statuskd?poi((poi(

esp+0x8)+0x18)+0x0)nt!_IO_STATUS_BLOCK.Pointerkd?poi((poi(

esp+0x8)+0x18)+0x0)nt!_IO_STATUS_BLOCK.Informationkd?poi((poi(

esp+0x8)+0x18)+0x4)nt!_MDLnt!_MDL.Sizekd?poi(poi(poi(

esp+0x8)+0x4)+0x4)nt!_MDL.MdlFlagskd?poi(poi(poi(

esp+0x8)+0x4)+0x6)nt!_MDL.Processkd?poi(poi(poi(

esp+0x8)+0x4)+0x8)nt!_MDL.MappedSystemVakd?poi(poi(poi(

esp+0x8)+0x4)+0xc)nt!_MDL.StartVakd?poi(poi(poi(

esp+0x8)+0x4)+0x10)nt!_MDL.ByteCountkd?poi(poi(poi(

esp+0x8)+0x4)+0x14)nt!_MDL.ByteOffsetkd?poi(poi(poi(

esp+0x8)+0x4)+0x18)-------------------------------------------------------------------------------------------------bp{arg1}"rt1=poi((poi(

esp+0x8)+0x18)+0x0).echo.printf\"{arg1}Status:%i\",t1.echo.if(t1==0){rt2=poi(poi(poi(

esp+0x8)+0x4)+0x10)rt3=poi(poi(poi(

esp+0x8)+0x4)+0x14)rt4=poi(poi(poi(

esp+0x8)+0x4)+0x18).echo.printf\"{arg1}StartVa:%iByteCount:%iByteOffset:%i\",t2,t3,t4.echo.if(t3==0){bcgc}.else{.echo.printf\"{arg1}!MDL\".echodt-r2nt!_MDLpoi(poi(

esp+0x8)+0x4)db/c10t2+t4Lbc}}.else{bcgc}"分析

首先,如果能在内存中找到重载的磁盘端口驱动程序镜像,猜想就算成功了一大半,如果找不到猜想也就算失败了,所以这一步很重要。可惜的是,这一步我一直没有太好的方法,只能用愚蠢的方法去暴力搜索物理内存。结果还被我给搜索到了,⊙﹏⊙‖∣,下面是我的具体操作过程。

其次,我们已经在内存中找到了重载的磁盘端口驱动程序镜像,接下来就要继续验证我们的猜想,去确认该程序镜像是由KB加载并调用的,这里就用到了我之前编写的两个Windbg脚本,让系统在读取MBR的时候断下来,通过查看调用堆栈以及读取到的MBR内容来验证我们的猜想。具体过程如下。

最后,通过上面的分析,我们已经验证了我们的猜想,现在让我们来进一步确认我们的猜想,接下来我们要通过手工修改内存中的MBR内容,看看KB是否可以检测到病毒。十分抱歉这里我偷懒了,没有完善我的脚本。

结语

至此我们的分析工作就已经告一段落了,KB会先通过普通方式读取MBR,如果检测结果为病毒的话就不会使用高级方式继续检测MBR了。如果检测结果为非病毒的话就会使用高级方式就检测MBR,就是我们上面分析的方式。

由于时间的关系我没有对KB进行更详细的分析,感兴趣的朋友可以继续完善脚本,直接修改KB读取到的MBR内容,看看KB是否还能检测到病毒。也可以根据回溯调用堆栈,具体分析一下KB的逻辑。

资料

1
查看完整版本: 初窥卡巴斯基ARK读取MBR