在学习《windows内核驱动安全编程与驱动开发》时,DP驱动的理解

新手上路大神轻喷。。。。
NTSTATUS DPQueryVolumeInformation(
	PDEVICE_OBJECT			DevObj,
	LARGE_INTEGER *			TotalSize,
	DWORD *					ClusterSize,
	DWORD *					SectorSize
	)
{
#define _FileSystemNameLength	64
//定义FAT16文件系统签名的偏移量
#define FAT16_SIG_OFFSET	54
//定义FAT32文件系统签名的偏移量
#define FAT32_SIG_OFFSET	82
//定义NTFS文件系统签名的偏移量
#define NTFS_SIG_OFFSET		3
	//这是FAT16文件系统的标志
	const UCHAR FAT16FLG[4] = {'F','A','T','1'};
	//这是FAT32文件系统的标志
	const UCHAR FAT32FLG[4] = {'F','A','T','3'};
	//这是NTFS文件系统的标志
	const UCHAR NTFSFLG[4] = {'N','T','F','S'};
	//返回值
	NTSTATUS ntStatus = STATUS_SUCCESS;
	//用来读取卷DBR扇区的数据缓冲区
	BYTE DBR[512] = { 0 };
	//DBR扇区有512个bytes大小
	ULONG DBRLength = 512;
	//以下是三个指针,统一指向读取的DBR数据,但是这三个指针的类型分别代表FAT16,FAT32和NTFS类型文件系统的DBR数据结构
	PDP_NTFS_BOOT_SECTOR pNtfsBootSector = (PDP_NTFS_BOOT_SECTOR)DBR;
	PDP_FAT32_BOOT_SECTOR pFat32BootSector = (PDP_FAT32_BOOT_SECTOR)DBR;
	PDP_FAT16_BOOT_SECTOR pFat16BootSector = (PDP_FAT16_BOOT_SECTOR)DBR;
	//读取的偏移量,对于DBR来说是卷的起始位置,所以偏移量为0
	LARGE_INTEGER readOffset = { 0 };
	//读取时的io操作状态
	IO_STATUS_BLOCK ios;
 	//为了同步读取所设置的同步事件
 	KEVENT Event;
 	//为了同步读取所需要构建的irp指针
 	PIRP   pIrp	= NULL;

	//下面我们首先从指定的卷设备上读取偏移量为0的一个扇区,也就是这个卷的DBR扇区,准备加以分析
 	//因为我们要同步读取,所以先初始化一个为了同步读取设置的事件
 	KeInitializeEvent(&Event, NotificationEvent, FALSE);
 	//构造一个irp用来发给卷设备来读取信息
 	pIrp = IoBuildAsynchronousFsdRequest(
 		IRP_MJ_READ,
 		DevObj,
 		DBR,
 		DBRLength,
 		&readOffset,
 		&ios
 		);
 	if (NULL == pIrp)
 	{
 		goto ERROUT;
 	}
 	//设置完成函数,并且将同步事件作为完成函数的参数传入
 	IoSetCompletionRoutine(
 		pIrp,
 		DPQueryVolumeInformationCompletionRoutine,
 		&Event,
 		TRUE,
 		TRUE,
 		TRUE
 		);
 	//调用目标设备去处理这个irp
 	ntStatus = IoCallDriver(DevObj, pIrp);
 	if(ntStatus = STATUS_PENDING)
 	{
 		//如果下层设备一时不能完成这个irp请求,我们就等
 		ntStatus = KeWaitForSingleObject(
 			&Event,
 			Executive,
 			KernelMode,
 			FALSE,
 			NULL
 			);
 		//将返回值设置为这个io操作的状态
 		ntStatus = pIrp->IoStatus.Status;
 		if (!NT_SUCCESS(ntStatus))
 		{
 			goto ERROUT;
 		}
 	}
	
	if (*(DWORD*)NTFSFLG == *(DWORD*)&DBR[NTFS_SIG_OFFSET])
	{
		//通过比较标志发现这个卷是一个ntfs文件系统的卷,下面根据ntfs卷的DBR定义来对各种需要获取的值进行赋值操作
		*SectorSize = (DWORD)(pNtfsBootSector->BytesPerSector);
		*ClusterSize = (*SectorSize) * (DWORD)(pNtfsBootSector->SectorsPerCluster);    
		TotalSize->QuadPart = (LONGLONG)(*SectorSize) * (LONGLONG)pNtfsBootSector->TotalSectors;
	}
	else if (*(DWORD*)FAT32FLG == *(DWORD*)&DBR[FAT32_SIG_OFFSET])
	{
		//通过比较标志发现这个卷是一个ntfs文件系统的卷,下面根据ntfs卷的DBR定义来对各种需要获取的值进行赋值操作
		*SectorSize = (DWORD)(pFat32BootSector->BytesPerSector);
		*ClusterSize = (*SectorSize) * (DWORD)(pFat32BootSector->SectorsPerCluster);    
		TotalSize->QuadPart = (LONGLONG)(*SectorSize) * 
			(LONGLONG)(pFat32BootSector->LargeSectors + pFat32BootSector->Sectors);
	}
	else if (*(DWORD*)FAT16FLG == *(DWORD*)&DBR[FAT16_SIG_OFFSET])
	{
		//通过比较标志发现这个卷是一个ntfs文件系统的卷,下面根据ntfs卷的DBR定义来对各种需要获取的值进行赋值操作
		*SectorSize = (DWORD)(pFat16BootSector->BytesPerSector);
		*ClusterSize = (*SectorSize) * (DWORD)(pFat16BootSector->SectorsPerCluster);    
		TotalSize->QuadPart = (LONGLONG)(*SectorSize) * 
			(LONGLONG)(pFat16BootSector->LargeSectors + pFat16BootSector->Sectors);
	}
	else
	{
		//走到这里,可能是其它任何文件系统,但是不是windows认识的文件系统,我们统一返回错
		ntStatus = STATUS_UNSUCCESSFUL;
	}
ERROUT:
 	if (NULL != pIrp)
 	{
 		IoFreeIrp(pIrp);
 	}
	return ntStatus;
}

我对这个函数很疑惑,为什么发送一个主功能号为“IRP_MJ_READ”就可以读出卷信息,经过大量查询资料,我才理清,

首先,我们要确定为了实现磁盘回闪的功能,基本原理是把磁盘修改的数据集中到一个文件中.

那么如何通过过滤驱动修改呢?

绑定到那个驱动上呢?

首先,在书后边简单的说了一句把驱动路径加到"\\HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Class\\{71A27CDD-812A-11D0-BEC7-08002BE2092F}"

那这个注册表干嘛用的

The HKLM\SYSTEM\CurrentControlSet\Control registry tree contains information for controlling system startup and some aspects of device configuration. The following subkeys are of particular interest:

Class
Contains information about the device setup classes on the system. There is a subkey for each class that is named using the GUID of the setup class. Each subkey contains information about a setup class, such as the class installer (if there is one), registered class upper-filter drivers, and registered class lower-filter drivers.

Each class subkey contains other subkeys known as software keys (or, driver keys) for each device instance of that class installed in the system. Each of these software keys is named by using a device instance ID, which is a base-10, four-digit ordinal value.

msdn说的很清楚了,不赘述了。

通过注册表,我们知道我们应该是绑定到了卷管理器上了,


然后我再《Windows Internals, 6ed, Part 2, Russinovich, Solomon, Ionescu, MS Press, 2012 》发现一句话彻底解决了我的问题


Whenever a file system driver or an application sends an I/O request to a device object that
represents a volume, the Windows I/O manager routes the request (which comes in an IRP—a self-contained package, described in Chapter 8, “I/O System”) to the volume manager that created the
target device object. Thus, if an application (running with administrator privileges) wants to read the
boot sector of the second volume on the system (which is a simple volume in this example), it opens
a handle to \\.\HarddiskVolume2 and then calls
ReadFile to read 512 bytes starting at offset zero on
the device. (Both the starting byte offset and length must be a multiple of the sector size.) The I/O
manager sends the application’s request in the form of an IRP to the volume manager that owns the
device object, notifying it that the IRP is directed at the HarddiskVolume2 device.


也就是说,只要往目标卷发送一个偏移为0目标大小512读请求就可以读取到启动扇区的信息。。。。而启动扇区的内容就可以用不同数据结构来解释

	PDP_NTFS_BOOT_SECTOR pNtfsBootSector = (PDP_NTFS_BOOT_SECTOR)DBR;
	PDP_FAT32_BOOT_SECTOR pFat32BootSector = (PDP_FAT32_BOOT_SECTOR)DBR;
	PDP_FAT16_BOOT_SECTOR pFat16BootSector = (PDP_FAT16_BOOT_SECTOR)DBR;

:>


猜你喜欢

转载自blog.csdn.net/qq_19326035/article/details/80656873