Quantcast
Channel: 看雪安全论坛
Viewing all articles
Browse latest Browse all 9556

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

$
0
0
应用层的控制程序的功能:创建,打开,关闭函数的主要操作:
(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

Viewing all articles
Browse latest Browse all 9556

Trending Articles