DriverStartIo例程
在之前的文章中,我们可以知道DriverStartIo是被微端口用来执行一些硬盘的I/0的请求。和IoCallDriver例程一样,DriverStartIo一般会执行两个参数,分别为一个device object和一个IRP。但是现在大部分的硬件设备都不是通过微端口进行访问和连接了,他们大部分情况下都是通过正常端口进行访问。(在第一讲里面有端口和微端口的介绍)
注释:
IRP:它也叫做输入输出封包,全称为i/o request packet。
IRP_MJ_SCSI例程一般是指向atapi.sys驱动中的IdePortDispatch例程。通过对它进行反编汇,我们能够发现这些发送请求的设备是如何从DeviceExtension层来接收信息的。
在开头部分,我们可以看到ebx是device extension的一个地址,它能够被所有的ATAPI设备所分享。
调用逻辑顺序:
从一个device object中得到微端口的device extension。
从另外一个微端口device extension的offset 0x5C中得到IdePort1的device extension。
从其它的device extension中的offset 0x0C得到IdePort1的device object。
调用IoStartPacket例程到IRP和IdePort1列陈的device object。
注释:
device extension:设备扩展(DEVICE_EXTENSION)是与设备对象相关的另一种重要的数据结构。
device object:就是一个设备的对象。它是驱动程序在内核中的数据结构,每个驱动程序有唯一DRIVER_OBJECT,IO管理器使用驱动程序对象代表每个设备驱动程序。
这个关系图描述了一个bootkit的组件信息
atapi.sys驱动可以创建微端的device口和IdePort的device,而这个两个device的DriverObject例程又指定了一个一模一样的驱动组件。所以在这个驱动组件中,用DriverStartIo来进行挂钩子或者插入rootkit是非常简单的。
运用WinDbg来检测DriverStartIo的rootkit
如果要检测DriverStartIo类型的rootkit,我们可以根据下面几个比较简单的步骤来执行。
首先我们可以根据下面的命令找到引导磁盘和磁盘叠层
在干净的系统里面所显示的磁盘叠层
在被rootkit感染后所显示的磁盘叠层
根据我上一篇的文章,我想做一下修正。我之前说过被TDL4感染过的系统无法使用指令!drvobj和!devobj,但是我发现我的研究错了。。。事实并非如此。
你可能想在硬盘叠层里检查每一个驱动的组件,那么你可以使用“dt _DEVICE_OBJECT <address>”指令找到DriverObject例程。大部分的bootkit后门都在最底层的驱动文件里面,所以会使用这个指令给大家作为一个参考。
DriverStartIo 显示没有中bootkit
你可以看到DriverStartIo并没有被植入bootkit,因为这些地址显示的都是正常的符合。但是,这个并不是一个真正的驱动对象。我之前说过,IoStartPacket只能和IdePort1进行调用,并不是硬盘的微端口。这个意思就是当IoStartPacket调用DriverStartIo时,那么它就会从DriverObject例程得到一个驱动对象,然后就会得到DriverStartIo例程。很明显了,这个bootkit就植入在DriverStartIo里面。它只是很简单的创建了一个atapi驱动对象的副本,然后对DriverStartIo例程进行修改。之后,建立一个IdePort1驱动的DriverObject例程,那么它就会指向一个新的地址,也就是恶意的驱动对象。
事实就是,这个TDL4已经感染了系统,并且它成功在atapi的驱动对象里面植入了bootkit,然后把磁盘微端口的驱动的DriverObject例程换成了全部都是恶意代码的地址。并且不需要DriverStartIo进行修改。
还有一个更简单的方法来检测所有的虚假驱动对象。所有的设备的驱动都是指向同一个驱动对象。所以只要简单的枚举一下这些设备的微端口驱动,这样就可以查看所以的DriverObject例程是否都指向了同一个地址。
下面是这些方法的介绍。
方法1:DrvObj
带有bootkit的驱动对象都和真正的驱动对象有着个相同的名称,就是”\driver\atapi”。这时,你需要输入指令”!drvobj \driver\atapi 2″来查看那些是正常的驱动对象。在下面这张图里面你会发现有个驱动对象的地址变了,那么它很有可能带有bootkit。
方法2:NextDevice
枚举设备可以使用”dt _DEVICE_OBJECT <address>”命令。每一个驱动的对象里面都有NextDevice这么一个例程。这张图里面,我们可以看到所有的DriverObject例程。如果其中一个例程调用了微端口的驱动对象,那么这个例程很有可能感染了bootkit。
所以的设备都应该指向一个正确的驱动对象,而这个微端口却不是。
方法3: DeviceExtension
这个是最后一个方法,设备扩展能够改版从一个系统到另外一个系统。但是我之前提过,你可以在offset 0x5C中找到IdePort1例程的设备扩展,而不是在微端口的设备扩展进行寻找。这样的话,在offset 0x5C中的IdePort1例程的设备扩展,我们也就能够找到它的设备对象,因为IdePort1中的设备对象会指定一个真实的驱动对象。通过一个简单的指令,我们可以找到DeviceObject。
指令为”dt _DEVICE_OBJECT poi(poi(@@C++(((nt!_DEVICE_OBJECT *)<address>)->DeviceExtension)+0x5C)+0x0C)”, where “<address>”