首页
社区
课程
招聘
[成果3.7]驱动程序设计基础专题-filedisk源码分析
发表于: 2007-12-26 13:29 26228

[成果3.7]驱动程序设计基础专题-filedisk源码分析

2007-12-26 13:29
26228

【文章标题】: WinMount虚拟磁盘深入研究(-)之filedisk源代码详细分析
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
    我的驱动入门三终结版,还再学习中。由于个人也有些事情要处理,研究起刘涛涛WinMount的虚拟
磁盘,而且这方面的书籍,貌似乎没见过,只有傻傻的几K代码存在,没注释什么的,整体框架也没说。  
  
  虚拟光驱用实现文件来模拟磁盘的原理,是文件系统驱动程序。
  把filedisk驱动安装,查看install.txt文件。
  1.Copy the driver (filedisk.sys) to %systemroot%\system32\drivers\.
  2.Import filedisk.reg to the Registry.
  3.Reboot.
  4.Use the program filedisk.exe to mount/umount files, for an example
  of use see the file example.txt.
  
  可以不用重起机子的方法,找一个动载加载驱动工具:DriverMonitor不错了。然后在“开始菜单”->
"运行"输入 "net start filedisk" 出现:“ 请求的服务已经启动”。这个必须得成功才行哦。
  
  接下来注意点。cmd后 出现这个目录 C:\Documents and Settings \Administrator>,在接下来敲入
  filedisk /mount 0 c:\temp\filedisk.img 8M f:  
  C:\Documents and Settings \Administrator>filedisk /mount 0 c:\temp\filedisk.img 8M r: 回车一下。  
  出现"FileDisk:系统找不到指定路径" 。原因就出在这 "c:\temp\filedisk.img" 中的C:\temp要这个目录才行。至于 filedisk.img不是必须,会自动创建。 如果有出现"FileDisk:函数不正确" 中的“filedisk /mount 0 ”中"0"代号已经被使用。可以改为"1".  查看一下,结果就出现一个还未格式化 8M R磁盘,查看C:\temp下生成一个filedisk.img也8M。想卸载
掉"filedisk /umount r:". 还可以创建很大的虚拟磁盘,你把"8M"改换其他的就是了。
  
  以上如果都没出现结果,基本上就没兴趣继续研究下去了,我看到了很多人初学filedisk都遇到以上这
些问题(包括我在内)  ,把我折腾了半天。  
  先来分析驱动层代码,后来分析应用层代码。更详细的请看附件里的源代码。我对代码工程方式重新布
局,用起来更方便。
  
  ===================================//先来分析驱动层代码
  1.对filedisk.h进行分析
  #define FILE_DEVICE_FILE_DISK       0x8000//用户定义范围0x8000~
  #define IOCTL_FILE_DISK_OPEN_FILE   CTL_CODE(FILE_DEVICE_FILE_DISK, 0x800,

METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  #define IOCTL_FILE_DISK_CLOSE_FILE  CTL_CODE(FILE_DEVICE_FILE_DISK, 0x801,

METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
  #define IOCTL_FILE_DISK_QUERY_FILE  CTL_CODE(FILE_DEVICE_FILE_DISK, 0x802,

METHOD_BUFFERED, FILE_READ_ACCESS)
  
  typedef struct _OPEN_FILE_INFORMATION {
      LARGE_INTEGER   FileSize;//文件大小
      BOOLEAN         ReadOnly;//只读属性
      USHORT          FileNameLength;//文件名长度
      UCHAR           FileName[1];//文件名
      UCHAR           DeviceType;//判断是K\G\M
  } OPEN_FILE_INFORMATION, *POPEN_FILE_INFORMATION;
  
  定义控制代码分别是“打开文件”、“关闭文件”、“查询?”
  2.看一下filedisk核心层\filedisk.c
  分析定义和声明的变量,接着从入口处分析,最后分析其他派谴例程。 定义几个IoCtrl合并宏,并定义几个结构体:MRB结构体、分区参数表等。  NTSTATUS DriverEntry()从入口点出发,嘿嘿。
  具体部分已经详细在源代码注释了。
  
  typedef struct _DEVICE_EXTENSION {
    BOOLEAN               media_in_device;
    HANDLE               file_handle;
    FILE_STANDARD_INFORMATION   file_information;
    BOOLEAN               read_only;
    PSECURITY_CLIENT_CONTEXT   security_client_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 访问文件的时候需要使用的一个线程客户安全性上下文。
  
  typedef struct _DISK_GEOMETRY {
               LARGE_INTEGER Cylinders;     // 磁柱个数
          MEDIA_TYPE MediaType;         // 媒质类型
          ULONG TracksPerCylinder;     // 每个磁柱上的磁道数
          ULONG SectorsPerTrack;         // 每个磁道上的扇区数
          ULONG BytesPerSector;         // 每个扇区上的字节数
      } DISK_GEOMETRY, *PDISK_GEOMETRY;
  
  
  核心层总体思路:从注册表获取关于驱动信息,接着由应用程序DeviceIoControl所发送的控制代码,

执行相应的派谴例程。最后进行对IRP进行处理就OK了。               
  
  ===================================//后来分析应用层代码
  这个是真的是不知道名字网友分析,我只能对他\她严重表示感谢。注释的很详细,非本人注释,本人
只是注释一点。我提一下整体思路就好了。先分析一些重要变量名接着分析5个函数,最后从main()函数分析,具体请看
  //变量分析
      char*                   Command;//命令行,比如你输入的“filedisk /umount r:”
      int                     DeviceNumber;//虚拟的盘数,比如 0-4个
      char*                   FileName;//用来虚拟磁盘所用的全文件名.比如:“c:\temp\filedisk.img ”
      char*                   Option;//可选比如“/ro| / cd”;ro:只读方式MOUNT,cd:虚拟CD_ROM
         char                    DriveLetter;//虚拟的盘符,比如"r:"盘
      BOOLEAN                 CdImage = FALSE;
         POPEN_FILE_INFORMATION  OpenFileInformation;//打开文件信息
      Command = argv[1];
   
  int Syntax(void);//syntax[sinteks]语法, 有秩序的排列, 句子构造, 句法意思。意思就是举例语
                   //式,怎么使用这个 filedisk.的语法格式  
void PrintLastError(char* Prefix)//打印出错信息,特别是里面的一个formatmessage()函数是用来  
  
  int FileDiskMount(int DeviceNumber,POPEN_FILE_INFORMATION  OpenFileInformation,char
                                        DriveLetter,BOOLEAN CdImage)
                 //这个函数很明显是安装上一个虚拟盘。首先判断是否存在该卷,存在则输出错误信息,不存在则创建。
          // 通过DeviceIoControl对驱动程序发送IRP消息。  
  int Umount(char DriveLetter)//这个函数很明显是卸载掉虚拟盘。判断要UnMount的盘存在否。
                            //DefineDosDevice()这个函数很帅。         
          //        1、锁定当前卷,通过发送FSCTL_LOCK_VOLUME到设备驱动实现
          //        2、关闭所有该卷上打开的所有文件,通过发送IOCTL_FILE_DISK_CLOSE_FILE到设备驱动实现
          //        3、卸载该卷,通过发送FSCTL_DISMOUNT_VOLUME到设备驱动实现
          //        4、解除该卷的锁定,通过发送FSCTL_UNLOCK_VOLUME到设备驱动实现
          //        5、关闭设备
          //        6、删除虚拟盘符  
  
  int main(int argc, char* argv[])//需要命令行。首先定义一下重要变量名,就上面说的重要变量名
。然后根据解析命令行,调用相应的函数来完成我们所需要的操作。  顺便联想一下。int main(int argc,char * argv[])参数的使用。  比如命令行输入: cfile computer C_Langle .此时argc=3. argv[]指向3个字符串,这些理解了。后面就没问题了。它是根据 argc来判断参数应该使用的命令。
  
应用层总体思路:
  (argc==5 || argc==6)因为其中有一个是可选的,进行操作是Mount。分析代码时,请一边看结果,一
边分析代码 更容易些。接着对这个option选项中的[size[k|M|G] | /ro | /cd]分别进行处理。最后开始调用Mount
操作。 argc==3,是进行UnMount操作。
  
只要打开filedisk核心层.dsw,VC自动把filedisk应用层和核心层这两个工程打开。
  
--------------------------------------------------------------------------------
【经验总结】
  下次继续分析,如何驱动加密、扩充容量、隐藏分区等等.......
  
  
  参考书籍《filedisk源代码作者》      
          《一些不知名网友解决方案》比如:驱网pdodge注释部分核心层程序、未知网友注释部分应用层程序、
          《Windows磁盘驱动基础教程》张云飞注释部分核心层程序
           在此表示感谢!
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2007年12月26日 13:26:06


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (13)
雪    币: 290
活跃值: (11)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
2
勤奋的人总是有沙发坐
2007-12-26 13:39
0
雪    币: 271
活跃值: (18)
能力值: ( LV12,RANK:370 )
在线值:
发帖
回帖
粉丝
3
呵呵 你真的很勤奋...fight...我很看好你哦....
2007-12-26 13:43
0
雪    币: 223
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
楼主,写的不错!
支持了。
2007-12-31 15:43
0
雪    币: 66
活跃值: (16)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
5
nice  期待后文
2007-12-31 18:10
0
雪    币: 223
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
6
首先感谢楼主的无私.
我下载了楼主的附件之后,运行了一下,发现与我手头的原文件有些差异,
主要是在应用程序中:
////////////////////////////////////////////////////////////////
        //如果不存在
        //则开始建立虚拟盘符
        //DEVICE_NAME_PREFIX=“\Device\FileDisk\FileDisk”
        ////////////////////////////////////////////////////////////////

        sprintf(DeviceName, DEVICE_NAME_PREFIX "%u", DeviceNumber);
个人感觉这里少了对"镜像文件得判断",所以这份代码在映射*.ISO得时候会出现错误。
后来经查证,在程序得源码中的确是由这样得判断得:
if (CdImage)
    {
        sprintf(DeviceName, DEVICE_NAME_PREFIX "Cd" "%u", DeviceNumber);
    }
    else
    {
        sprintf(DeviceName, DEVICE_NAME_PREFIX "%u", DeviceNumber);
    }
估计是楼主不小心遗漏了吧! (俺猜得
还是去网上找到了最新得版本,查看了一下发现在上面有添加了网络功能,所以把它一起传上来,
以便大家相互参照这看。
下载地址:http://www.acc.umu.se/~bosse/
里面还有很多好得资源呀。
上传的附件:
2008-1-1 21:02
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
严重学习ing,我现在正在学习ifs,对我太有用了阿
2008-3-3 10:15
0
雪    币: 357
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
严重关注zhong.....................
2008-5-28 13:27
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
不错!
期待下文 ... ...
2008-6-19 13:46
0
雪    币: 321
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
恩 确实有光盘加载不上的情况,换成新版本的驱动就好了
2008-10-22 20:48
0
雪    币: 91
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
分析的很不错,谢谢!
2009-8-27 12:35
0
雪    币: 224
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
最近正好在搞这块hoho路过
2009-8-28 15:01
0
雪    币: 55
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
学习一下,呵呵
2009-10-27 16:33
0
雪    币: 212
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
LZ那个应用层的CreateFile后没有closeHandle,是不是需要释放句柄啊!
2009-11-30 09:45
0
游客
登录 | 注册 方可回帖
返回
//