欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创](补充)关于那个密盘程序的一点说明

[原创](补充)关于那个密盘程序的一点说明

应用层的控制程序的功能:创建,打开,关闭函数的主要操作:
(1)MiniDiskCreateMount
检测指定盘符是否存在
若不存在,创建盘符并关联盘符和设备
打开虚拟磁盘设备,发送自定义IOCTL_MINI_DISK_CREATE_FILE控制码

int MiniDiskCreateMount(char DeviceNumber,POPEN_FILE_INFORMATION pOpen,char DriverTarget)
{
	……
	//尝试打开指定卷
	hDevice = CreateFile(
		VolumeName,
		GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_NO_BUFFERING,
		NULL);
	……
	//创建虚拟磁盘设备,盘符和设备捆绑
	if(!DefineDosDevice(DDD_RAW_TARGET_PATH,&VolumeName[4],DeviceName))
	{
		……
	}
	//打开虚拟磁盘设备
	hDevice = CreateFile(
		VolumeName,
		GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_NO_BUFFERING,
		NULL);
	if(hDevice == INVALID_HANDLE_VALUE)
	{
		……	
	}
	//发送IOCTL_MINI_DISK_CREATE_FILE控制码
	if(!DeviceIoControl(
		hDevice,
		IOCTL_MINI_DISK_CREATE_FILE,
		pOpen,
		sizeof(OPEN_FILE_INFORMATION)+pOpen->FileNameLength - 1,
		TempBuf,
		sizeof(TempBuf)/sizeof(char),
		&BytesReturned,
		NULL))
	{
		……
	}
	……
}

(2)MiniDiskOpenMount
检测指定盘符是否存在
若不存在,创建盘符并关联盘符和设备
打开虚拟磁盘设备,发送自定义IOCTL_MINI_DISK_OPEN_FILE控制码
int MiniDiskOpenMount(char DeviceNumber,POPEN_FILE_INFORMATION pOpen,char DriverTarget)
{
	……
	//尝试打开指定卷
	hDevice = CreateFile(
		VolumeName,
		GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_NO_BUFFERING,
		NULL);
	//当前卷已经存在,需要更改盘符
	if(hDevice != INVALID_HANDLE_VALUE)
	{
		……
	}
	……
	//创建虚拟磁盘设备,盘符和设备捆绑
	if(!DefineDosDevice(DDD_RAW_TARGET_PATH,&VolumeName[4],DeviceName))
	{
		……
	}
	//打开虚拟磁盘设备
	hDevice = CreateFile(
		VolumeName,
		GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_NO_BUFFERING,
		NULL);
	if(hDevice == INVALID_HANDLE_VALUE)
	{	
		……
	}
	//发送IOCTL_MINI_DISK_OPEN_FILE控制码
	if(!DeviceIoControl(
		hDevice,
		IOCTL_MINI_DISK_OPEN_FILE,
		pOpen,
		sizeof(OPEN_FILE_INFORMATION)+pOpen->FileNameLength - 1,
		TempBuf,
		sizeof(TempBuf)/sizeof(char),
		&BytesReturned,
		NULL))
	{
		……
	}
	……
}

(3)MiniDiskUnMount
打开虚拟磁盘设备
发送自定义IOCTL_MINI_DISK_CLOSE_FILE控制码
发送系统控制码FSCTL_DISMOUNT_VOLUME
删除盘符
int MiniDiskUnMount(char DriverTarget)
{
	……
	//检测设备是否存在
	hDevice = CreateFile(
		VolumeName,
		GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_FLAG_NO_BUFFERING,
		NULL);
	if(hDevice == INVALID_HANDLE_VALUE)
	{
		……
	}
	//发送控制码FSCTL_LOCK_VOLUME
	/*if(!DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&BytesReturned,NULL))
	{
		……
	}*/
	//发送控制码IOCTL_MINI_DISK_CLOSE_FILE
	if(!DeviceIoControl(hDevice,IOCTL_MINI_DISK_CLOSE_FILE,NULL,0,Buf,sizeof(Buf)/sizeof(char),&BytesReturned,NULL))
	{
		……
	}
	//发送控制码FSCTL_DISMOUNT_VOLUME
	if(!DeviceIoControl(hDevice,FSCTL_DISMOUNT_VOLUME,NULL,0,NULL,0,&BytesReturned,NULL))
	{
		……
	}
	//发送控制码FSCTL_UNLOCK_VOLUME
	/*if(!DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME,NULL,0,NULL,0,&BytesReturned,NULL))
	{
		……
	}*/
	//删除盘符
	if(!DefineDosDevice(DDD_REMOVE_DEFINITION,&VolumeName[4],NULL))
	{
		……
	}
	……
}

注:在原来的FileDisk项目中,关闭磁盘前,先用FSCTL_LOCK_VOLUME控制码锁住磁盘然后在进行关闭操作后再发送FSCTL_UNLOCK_VOLUME控制码解锁,存在一个问题,当磁盘里面有文件被引用时,FSCTL_LOCK_VOLUME控制码就会发送失败,后来查了一下,强行关闭,只需要发送FSCTL_DISMOUNT_VOLUME控制码即可。(强行关闭可能会造成没完成的数据丢失!)
内核层的驱动的几个主要功能:
(1)MiniDiskCreateDevice
创建设备,设置设备属性,创建符号链接,初始化读写请求链表,初始化自旋锁和事件,创建一个系统线程用于处理IO请求,该线程通过事件对象激活。
NTSTATUS MiniDiskCreateDevice(IN PDRIVER_OBJECT pDriverObject,IN ULONG Number,IN DEVICE_TYPE DeviceType)
{
	……
	//创建设备
	status = IoCreateDevice(
		pDriverObject,
		sizeof(DEVICE_EXTENSION),
		&DeviceName,
		DeviceType,
		0,
		FALSE,
		&pDeviceObject);
	……
	//添加DO_DIRECT_IO标志
	pDeviceObject->Flags |= DO_DIRECT_IO;
	pDeviceExtension = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;
	pDeviceExtension->FileExist = FALSE;
	pDeviceExtension->CheckDigest = FALSE;
	pDeviceExtension->key = NULL;
	//pDeviceExtension->pCProDigest = NULL;
	//初始化符号链接名
	RtlInitUnicodeString(&SymLinkName,L"\\??\\MiniDisk");
	pDeviceExtension->SymLinkName = SymLinkName;
	//创建符号链接
	status = IoCreateSymbolicLink(&SymLinkName,&DeviceName);
	……
	//初始化读写请求链表头
	InitializeListHead(&pDeviceExtension->ListHead);
	//初始化自旋锁[读写链表操作]
	KeInitializeSpinLock(&pDeviceExtension->ListLock);
	//初始化事件[线程等待]
	KeInitializeEvent(&pDeviceExtension->RequestEvent,SynchronizationEvent,FALSE);
	pDeviceExtension->TerminateThead = FALSE;
	//创建系统线程
	status = PsCreateSystemThread(&hThread,(ACCESS_MASK)0L,NULL,NULL,NULL,MiniDiskThread,pDeviceObject);
	……
}

(2)IOCTL_MINI_DISK_CREATE_FILE控制码
主要是参数检查,把当前IRP插入读写链表中,激活线程。在线程中主要是保存密钥,调用MiniDiskCreateFile函数创建密盘文件。
(3)IOCTL_MINI_DISK_OPEN_FILE控制码
主要是参数检查,把当前IRP插入读写链表中,激活线程。在线程中,检验密钥,若成功,调用MiniDiskOpenFile函数打开密盘文件。
(4)IOCTL_MINI_DISK_CLOSE_FILE控制码
主要是参数检查,把当前IRP插入读写链表中,激活线程。在线程中,调用MiniDiskCloseFile函数关闭密盘文件。
(5)IRP_MJ_READ,IRP_MJ_WRITE
在主要是线程中完成加解密操作,然后读写文件。写之前加密,读之后解密。
	//读文件操作
	ZwReadFile(pDeviceExtension->hFile,NULL,NULL,NULL,&pIrp->IoStatus,Buffer,pIo_Stack>Parameters.Read.Length,&pIo_Stack-
>Parameters.Read.ByteOffset,NULL);
	//解密
	for(i = 0; i < pIo_Stack->Parameters.Read.Length;i+=16)
	{
		InvCipher(pDeviceExtension,Buffer+i,Buffer+i);
	}
	RtlCopyMemory(SystemBuffer,Buffer,pIo_Stack->Parameters.Read.Length);
	……
	RtlCopyMemory(Buffer,SystemBuffer,pIo_Stack->Parameters.Write.Length);
	//加密
	for(i = 0; i < pIo_Stack->Parameters.Read.Length;i+=16)
	{
		Cipher(pDeviceExtension,Buffer+i,Buffer+i);
	}
	//写文件操作
	ZwWriteFile(pDeviceExtension->hFile,NULL,NULL,NULL,&pIrp->IoStatus,Buffer,pIo_Stack->Parameters.Write.Length,&pIo_Stack-
>Parameters.Write.ByteOffset,NULL);

(6)MiniDiskCreateFile
创建[ZwCreateFile]指定大小文件
查询[ZwQueryInformationFile]文件相关信息[FILE_STANDARD_INFORMATION、FILE_ALIGNMENT_INFORMATION和FILE_BASIC_INFORMATION]并保存到设备扩展
更新设备扩展中的设备状态标志。
(7)MiniDiskOpenFile
打开[ZwCreateFile]指定文件
查询[ZwQueryInformationFile]文件相关信息并保存到设备扩展
更新设备扩展中的设备状态标志。
(8)MiniDiskCloseFile
关闭文件句柄,释放内存空间,更新设备扩展中的设备状态标志。
(9)读写的序列化操作:
把读写请求按顺序插入一个链表中,再按顺序一个个取出来逐个处理,避免了读写重入的问题。
分发函数中:
//挂起当前IRP
IoMarkIrpPending(pIrp);
//插入请求队列
ExInterlockedInsertTailList(&pDeviceExtension->ListHead,&pIrp->Tail.Overlay.ListEntry,&pDeviceExtension->ListLock);
//激活线程事件
KeSetEvent(&pDeviceExtension->RequestEvent,IO_NO_INCREMENT,FALSE);

线程中:
while(1)
{
	//等待线程事件
	KeWaitForSingleObject(&pDeviceExtension->RequestEvent,Executive,KernelMode,FALSE,NULL);
	//从链表中取出读写请求
	while(RequestList = ExInterlockedRemoveHeadList(&pDeviceExtension->ListHead,&pDeviceExtension->ListLock))
		{
			pIrp = CONTAINING_RECORD(RequestList,IRP,Tail.Overlay.ListEntry);
			pIo_Stack = IoGetCurrentIrpStackLocation(pIrp);
			switch(pIo_Stack->MajorFunction)
			{
			……
			}
		}
}

(10)需要响应的系统IO控制码(处理代码见源码):
IOCTL_DISK_CHECK_VERIFY       
IOCTL_STORAGE_CHECK_VERIFY       
IOCTL_STORAGE_CHECK_VERIFY2       
IOCTL_DISK_GET_DRIVE_GEOMETRY       
IOCTL_DISK_GET_LENGTH_INFO       
IOCTL_DISK_GET_PARTITION_INFO       
IOCTL_DISK_GET_PARTITION_INFO_EX       
IOCTL_DISK_IS_WRITABLE       
IOCTL_STORAGE_MEDIA_REMOVAL       
IOCTL_DISK_MEDIA_REMOVAL       
IOCTL_DISK_SET_PARTITION_INFO       
IOCTL_DISK_VERIFY
(源码)单向链表:
http://bbs.pediy.com/showthread.php?t=170857

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功