作 者:
水中雁
时 间:
2008-05-15,23:36
链 接:
http://bbs.pediy.com/showthread.php?t=64902
3年前在看雪论坛注册了个号,但嫌ID不好听,因此一直没有发过帖。后来想换个ID,却发现不能注册了。昨天来逛逛,发现能注册了,终于注册了个自己比较喜欢的ID。
分析比较长,仅贴出驱动部分的分析。完整版请参看附件。(已贴附件)
附件包含:
机器狗0506技术剖析.pdf
dll_unpack.idb
sys.idb
由于自己能力有限,以及基本没有动态调试。故难免有所纰漏或错误,请各位不吝指正。
摘要
机器狗新变种使用了一些流行的技术,包含了修复SSDT Hook、修复FSD Hook、并对一些系统还原软件进行有针对的Hook,使能达到突破还原软件保护的目的。做了那么多,最终目的还是下载大量的木马到用户的系统上。
一、修复SSDT
1、获取内核第一个模块名(XP系统:ntkrnlpa.exe)及SVA(System Virtual Adrress),映射一份ntkrnlpa.exe到内存中,根据导出表获取KeServiceDescriptorTable的RVA转换成VA,为X,根据重定位表信息获得需要重定位的地址Y,比较[Y]是否等于X,否则循环,是则比较[Y-2]的特征是否是5C7h,是则取[Y+4]到Z。即:
C705E046480040C94200mov ds:_KeServiceDescriptorTable, offset _KiServiceTable
因此,Z得到的是_KiServiceTable的地址。会对Z再通过重定位表验证,最后减去基地址得到KiServiceTable的RVA。
2、映射文件//SystemRoot//System32//ntdll.dll到内存。根据导出表定位下列函数的RVA,转换成VA为X,取[X+1]得Y,Y即为该ZwXXX函数的序号。
ZwOpenProcess
ZwCreateThread
ZwWriteVirtualMemory
ZwRestoreKey
3、根据序号从内存映射文件ntkrnlpa.exe获得上列函数的RVA,并转换成相对于ntkrnlpa.exe模块的地址,为RealAddress。
4、根据内存映射文件ntkrnlpa.exe获得KeServiceDescriptorTable的RVA为X,X+SImageBase获得KeServiceDescriptorTable在系统中的SVA,根据上列函数的序号获得这些函数在系统中的SVA,即NowAddress。
5、判断RealAddress和NowAddress是否相等。如果不相等,则将RealAddress和NowAddress互换,以达到修复SSDT的目的。
二、获取关键函数的SVA
dll和驱动的通信是通过以下注册表value进行的。
/Registry/Machine/SOFTWARE/Microsoft/IE4/Data
1、Dll判断内核中是否存在这些模块,是则映射文件到内存。通过特征码找到函数偏移地址。转换成SVA后,记录入注册表。格式为 序号 地址,每条记录8个字节。
2、驱动读取该注册表value,把地址保存在全局变量中,以便以后调用。
3、有以下的函数:
classpnp.sys:ClassReadWrite
classpnp.sys:ClassDeviceControlDispatch
stpdrive.sys:??? //没有找到这个模块,未知驱动文件。
ntfs.sys:NtfsFsdFileSystemControl
fastfat.sys:FatFsdFileSystemControl
ntoskrnl.exe(NTKRNLPA.exe、ntkrnlmp.exe、ntkrpamp.exe):
Dr_FastCallDrSave_Offset,不是在函数首部,是在函数的中部。
atapi.sys:IdePortDispatch
三、修复FSD的FsdFileSystemControl Object Hook
1、获取/FileSystem/Ntfs或/FileSystem/FastFat的DriverObject。
2、判断_DRIVER_OBJECT.IrpFileSystemControlDispatch的地址是否和从注册表中读到的NtfsFsdFileSystemControl或FatFsdFileSystemControl相等,如果不相等,则恢复。
四、修复对DrFastCallDrSave的inline Hook
不经过检测,直接向从注册表获取的地址Dr_FastCallDrSave_Offset处写入5个字节的数据。2B E1 C1 E9 02这些数据为系统正常Dr_FastCallDrSave_Offset处的数据。
重复修复4遍
五、过还原系统
1、获取/device/Harddisk0/DR0的设备对象。
使用IoGetDeviceObjectPointer获取DeviceObject失败后,会枚举/device/Harddisk0的OBJECT_DIRECTORY_ENTRY,根据ObQueryNameString判断符号名来得到DR0的DeviceObject。
lea ecx, [ebp+pObjectDirectroy]
push ecx
push 0
push 0
mov edx, ds:IoDeviceObjectType
mov eax, [edx]
push eax
push 0
push 0
push 40h
lea ecx, [ebp+wszDeviceName]
push ecx
call ObReferenceObjectByName ;
对内核不熟,奇怪的是为什么参数为IoDeviceObjectType,而返回的是OBJECT_DIRECTORY_ENTRY?请大虾指点迷津。
2、获取还原软件的DriverObject
枚举/device/Harddisk0/DR0的AttachedDevice,根据对应的DriverObject的DriverName来获取还原软件设备的DriverObject。如果是影子系统,则会获取/Driver/Atapi的DriverObject。
/Driver/DeepFrz 冰点还原精灵
/Driver/snpshot 影子系统
/Driver/YzIdiot 网络还原精灵
如果没有找到上列还原软件,则走3-5,如果找到了则走6。
3、Inline Hook stpdrive.sys
直接将从注册表中读取的stpdrive.sys的某个偏移地址,写入一个字节C3,即Ret。由于没有stpdrive.sys文件,猜测是patch掉stpdrive.sys的主要功能,从而使之失效。
4、再次修复FSD Object Hook
同三(修复FSD的FsdFileSystemControl Object Hook)。
5、/device/Harddisk0/DR0对应驱动对象的Driver Object Hook
1)、修复DR0设备对应的IrpDeviceControlDispatch
判断_DRIVER_OBJECT.IrpDeviceControlDispatch是否和从注册表读出的ClassDeviceControlDispatch的SVA相等,不相等则修复。
2)、Hook DR0设备对应的IrpWriteDispatch
判断_DRIVER_OBJECT.IrpWriteDispatch是否和从注册表读取的ClassReadWrite的SVA相等,不相等则进行自己的Object Hook。
3)、fnIrpWriteDispatch_0
判断写入文件的内存是否满足条件,满足则直接调用SVA_ClassReadWrite进行写文件,不满足则调用原来的Old_IrpWriteDispatch。
条件算法比较苛刻,判断写入的文件头4个字节是否是4D5A9111,即被感染的Services.exe,如果满足,则直接调用SVA_ClassReadWrite进行写文件。并将Key置1。如果Key为1,则判断写入文件的尾部4个字节是否为4B435546,即病毒dll文件,如果是,则直接调用SVA_ClassReadWrite进行写文件。并且将Object Hook恢复到之前的状态(非系统状态)。
这种方法只进行对2个文件进行过还原的写入,写入完成后,会恢复其它还原软件的Object Hook。
还原系统的Object Hook
6、原理基本同5,Hook的对象为还原设备的Driver Object。
不同点:
1)、首先DrFastCallDrSaveHooK,同四(修复对DrFastCallDrSave的inline Hook)。
2)、修复atapi.sys的IrpInternalDeviceControlDispatch
根据_DRIVER_OBJECT.IrpInternalDeviceControlDispatch和从注册表读取的IdePortDispatch相比较,不同则恢复。
3)、写文件的方式不同
调用IofCallDriver,直接向前一个AttachedDevice发送IRP进行写文件操作。
4)、恢复Object Hook
除了恢复IrpWriteDispatch到之前的状态,也恢复Atapi.sys的IrpInternalDeviceControlDispatch到之前的状态。