FileDisk驱动分析.

这差不多是去年写的学习笔记了...当时后面部分好像偷懒了...没写全的样子...呵呵~当时本来还打算A掉Virtual CD ROM的VcdRom.sys,不过debugman上已经有人放出src了...所以也就学习了一下...下面凑合着看.

 

filedisk是一个网上流传比较广泛的开源程序,它能够 mount / unmount CD/DVD images.通俗点说就是实现虚拟光驱的功能,也是一个学习磁盘过滤驱动非常好的例子.

 你可以从Windows driver examples下载最新的filedisk源代码,下面的代码是基于最新的filedisk-17.

[1.0] FileDisk的使用

 打开install.txt文件.里面讲述的很清楚.

 首先,将filedisk.sys驱动程序复制到%systemroot%\system32\drivers\.目录下.

 然后,双击filedisk.reg文件.添加到注册表中.

 最后,重启即可.

 上面这些其实就是实现对 filedisk.sys的驱动安装而已,在启动的时候将filedisk.sys加载到内核中.

 重启之后,就可以在控制台中运行filedisk.exe程序,可以使用 mount 和 unmount 命令了.

 

[2.0] FileDisk驱动分析.

FileDisk驱动程序,通过增加一个设备,实现磁盘过滤.

对磁盘的过滤,重点要关注的是对磁盘的读,写,以及关于磁盘信息的获取.

[2.1] filedisk.h

1.定义了设备名和符号链接名

2.定义三个IOCTL_CODE,分别与Read,Write,Query三个操作相关

3.定义了 OPEN_FILE_INFORMATION结构,该结构保存和传递关于被mount的文件的相关信息.

typedef struct _OPEN_FILE_INFORMATION {
   LARGE_INTEGER   FileSize;// 文件大小
   BOOLEAN        ReadOnly;// 是否可读写
   UCHAR          DriveLetter;// 盘符
   USHORT         FileNameLength;// 文件名的长度
   UCHAR          FileName[1];// 文件名
} OPEN_FILE_INFORMATION, *POPEN_FILE_INFORMATION;

 

[2.2]filedisk.c

再分析函数之前先来熟悉下几个结构

1.DEVICE_EXTENSION结构.

 其实关于DEVICE_EXTENSION,它是由I/O管理器自动分配这个内存,并把设备对象中的DeviceExtension指针指向这块内存.

typedef struct _DEVICE_EXTENSION {
   BOOLEAN                    media_in_device;//是否指定了一个文件作为存储媒介
   HANDLE                     file_handle; // 文件句柄
   ANSI_STRING                file_name;// 文件名
   LARGE_INTEGER              file_size;// 文件大小
   BOOLEAN                    read_only;// 是否只读
   BOOLEAN                    is_cd_or_dvd;// 是否为cd/dvd
   PSECURITY_CLIENT_CONTEXT   security_client_context;// 线程客户安全context
   LIST_ENTRY                 list_head;// 链表头
   KSPIN_LOCK                 list_lock;// 自旋锁
   KEVENT                     request_event;// 请求事件
   PVOID                      thread_pointer;// 线程函数指针
   BOOLEAN                    terminate_thread;// 线程结束标志
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

 media_in_device是指这个设备是否已经指定了一个文件作为存储媒质。这是一个用文件来虚拟磁盘的驱动。那么一个磁盘应该对应一个实际存在的文件。读写这个磁盘的请求最终转变为对文件的读写。如果一个磁盘设备对象还没有指定文件,那么这个内容是FALSE.
    file_handle是文件句柄。也就是这个虚拟磁盘所对应的文件。
    file_information是这个文件的一些信息。
    read_only是否只读。
    security_client_context 访问文件的时候需要使用的一个线程客户安全性上下文。
    list_head是一个链表头。一部分irp(windows发来的请求包)被放入这个链表中。我们为每个磁盘对象开启一个系统线程(处理线程),专门用来处理这些请求。
    list_lock是为了保证链表读写同步的锁。
    request_event是一个事件。当链表中没有请求的时候,处理请求的系统线程并不做任何事情,而只等待这个事件。当有请求到来,我们把请求放入链表,然后设置这个事件。处理线程就会开始处理这些请求。
    thread_pointer是线程的指针,用来最后等待这个线程的结束。
    terminate_thread是一个标志。如果设置为TRUE,处理线程执行的时候检测到这个,就会把自己终止掉。

 

在DriverEntry中.

1.首先通过RtlQueryRegistryValues()函数,获得注册表相关信息.

主要是为了获得n_devices的值.n_devices决定生成多少个磁盘设备对象,默认的数值为4.

2.然后通过FileDiskCreateDevice()创建磁盘设备对象.

3.设置好IRP分发函数.

NTSTATUS
DriverEntry (
   IN PDRIVER_OBJECT  DriverObject,
   IN PUNICODE_STRING  RegistryPath
   )
{

.....

//查询注册表信息,获取n_devices

   status = RtlQueryRegistryValues(
       RTL_REGISTRY_ABSOLUTE,
       parameter_path.Buffer,
       &query_table[0],
       NULL,
       NULL
       );

// 如果失败,将n_devices设为默认值4

   if (!NT_SUCCESS(status))
   {
       KdPrint(("FileDisk: Query registry failed, using default values.\n"));
       n_devices = DEFAULT_NUMBEROFDEVICES;
   }

....

// 创建n_devices个磁盘设备对象,FILE_DEVICE_DISK类型的

   for (n = 0, n_created_devices = 0; n < n_devices; n++)
   {
       status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_DISK);

       if (NT_SUCCESS(status))
       {
           n_created_devices++;
       }
   }

// 创建n_devices个磁盘设备对象,FILE_DEVICE_CD_ROM类型的.

   for (n = 0; n < n_devices; n++)
   {
       status = FileDiskCreateDevice(DriverObject, n, FILE_DEVICE_CD_ROM);

       if (NT_SUCCESS(status))
       {
           n_created_devices++;
       }
   }

.....

// 设置分发函数

   DriverObject->MajorFunction[IRP_MJ_CREATE]        = FileDiskCreateClose;
   DriverObject->MajorFunction[IRP_MJ_CLOSE]         = FileDiskCreateClose;
   DriverObject->MajorFunction[IRP_MJ_READ]          = FileDiskReadWrite;
   DriverObject->MajorFunction[IRP_MJ_WRITE]         = FileDiskReadWrite;
   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FileDiskDeviceControl;

   DriverObject->DriverUnload = FileDiskUnload;

   return STATUS_SUCCESS;
}

 FileDiskCreateDevice()函数.

1.首先判断DeviceType,然后根据类型的不同,添加的Devicename的前缀也不一样.CD类型的前缀带"Cd"

2.调用IoCreateSecureDevice(),创建设备.初始化链表头,初始化SpinLock(自旋锁),初始化Event(事件),这些都用于后面的线程同步.

3.调用PsCreateSystemThread(),创建系统线程函数.FileDiskThread(). thread_handle保存线程处理函数的句柄.

4.调用ObReferenceObjectByHandle(),保存线程函数的指针.

 

FileDiskThread()函数

1.调用KeSetPriorityThread(),设置当前线程的优先级为LOW_REALTIME_PRIORITY.

2.for(;;)死循环中调用KeWaitForSingleObject(),等待reques_event事件.如果等到事件,则判断事件类型,分别处理.

IRP_MJ_READ:调用ZwReadFile读取文件,从内核到用户缓冲区;
IRP_MJ_WRITE:调用ZwWriteFile写入文件,从用户到内核缓冲区;
IRP_MJ_DEVICE_CONTROL:在FileDiskDeviceControl设置事件才会触发,主要有如下两种操作码:
 IOCTL_FILE_DISK_OPEN_FILE:调用FileDiskOpenFile。
 IOCTL_FILE_DISK_CLOSE_FILE:调用FileDiskCloseFile。

FileDiskOpenFile:根据用户程序传入的映像文件全路径,调用ZwCreateFile在内核中打开它,如果文件不存在则再创建它,返回文件句柄。
FileDiskCloseFile:调用ZwClose关闭文件。

【转】FileDisk源码分析(以前的笔记了~)_任家_新浪博客 (sina.com.cn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值