⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filemon学习笔记 --- windows文件过滤系统驱动开发 - 驱动开发 - 私のウェブサイト.htm

📁 驱动开发的一些资料
💻 HTM
📖 第 1 页 / 共 5 页
字号:
                              <DIV>  中针对不同的MajorFunction,打印出相关操作信息。</DIV>
                              <DIV>  因此函数体太长 不再全部列出。</DIV>
                              <DIV>  其函数体总体框架为:得到被操作的文件名字,打印相关操作信息,然后下发IRP到底层驱动。</DIV>
                              <DIV>  在下发IRP到底层驱动处理前,本层驱动必须负责设置下层IO堆栈的内容。这样下一层驱动调用IoGetCurrentIrpStackLocation()时能得到相应的数据。</DIV>
                              <DIV>  设置下层IO堆栈的内容,一般用两个函数来实现:</DIV>
                              <DIV>  IoCopyCurrentIrpStackLocationToNext( Irp 
                              )</DIV>
                              <DIV>  此函数一般用在本驱动设置了完成例程时调用,把本层IO _STACK_LOCATION 
                              中的参数copy到下层,但与完成例程相关的参数信息例外。因为本驱动设置的完成例程只对本层驱动有效。</DIV>
                              <DIV>  IoSkipCurrentIrpStackLocationToNext(Irp)</DIV>
                              <DIV>  此函数的作用是:直接把本层驱动IO堆栈的内容设置为下层驱动IO堆栈指针的指向。因两层驱动IO堆栈的内容完全一致,省却copy过程。</DIV>
                              <DIV>  而在Filemon的处理中,它用了一个特别的办法,没有调用此两个函数,FilemonHookRoutine函数体里面有三句代码:</DIV>
                              <DIV>PIO_STACK_LOCATION currentIrpStack = 
                              IoGetCurrentIrpStackLocation(Irp);<BR>PIO_STACK_LOCATION nextIrpStack  = 
                              IoGetNextIrpStackLocation(Irp);<BR>*nextIrpStack = 
                              *currentIrpStack;//此步设置了下层驱动的IO_STACK_LOCATION<BR>直接设置了下层驱动IO堆栈的值。在FilemonHookRoutine函数里,用一个宏实现了复杂的获得拦截到的被操作文件的名字:if( 
                              FilterOn &amp;&amp; hookExt-&gt;Hooked ) 
                              {<BR>    GETPATHNAME( createPath 
                              );<BR>}GETPATHNAME( createPath )宏展开为:#define 
                              GETPATHNAME(_IsCreate)                         <BR>    fullPathName 
                              = ExAllocateFromNPagedLookasideList( 
                              &amp;FullPathLookaside );<BR>    if( fullPathName 
                              ) 
                              {                          <BR>      FilemonGetFullPath( 
                              _IsCreate, FileObject, hookExt, fullPathName 
                              );<BR>    } else 
                              {                                <BR>      fullPathName 
                              = 
                              InsufficientResources;               <BR>    } 在函数:FilemonGetFullPath( 
                              _IsCreate, FileObject, hookExt, fullPathName 
                              )中实现了获得被操作的文件名字,此函数代码较多,判断条件复杂,理解起来比较麻烦,下面重点讲解。</DIV>
                              <DIV>  对函数FilemonGetFullPath的理解关键在于理顺结构,</DIV>
                              <DIV>  此函数的功能就是获得文件名字,获得文件名字一般在三种状态下:</DIV>
                              <DIV>  一:在打开文件请求中,但在打开文件前。</DIV>
                              <DIV>  二:在打开文件请求中,但在打开文件后,通过在本层驱动中设置完成例程。在完成例程中获得。</DIV>
                              <DIV>  三:在过滤到读写等操作时。</DIV>
                              <DIV>  而在此函数中,它包含了第一种和第三种方法,通过一些烦琐的条件判断,先判断出目前是处于什么状态中,然后根据不同状态采取不同方法。</DIV>
                              <DIV>  先分析当在第一种条件下,此函数的处理方法,可以精炼为如下:VOID<BR>FilemonGetFullPath(<BR>  BOOLEAN 
                              createPath,<BR>  PFILE_OBJECT 
                              fileObject,<BR>  PHOOK_EXTENSION 
                              hookExt,<BR>  PCHAR 
                              fullPathName<BR>  )<BR>{<BR>  ULONG        
                              pathLen, prefixLen, slashes;<BR>  PCHAR        
                              pathOffset, ptr;<BR>  BOOLEAN       
                              gotPath;<BR>  PFILE_OBJECT    relatedFileObject;<BR>  <BR>  ANSI_STRING     
                              fileName;<BR>  ANSI_STRING     
                              relatedName;<BR>  <BR>  UNICODE_STRING   fullUniName;<BR> <BR>  prefixLen 
                              = 2; // "C:"<BR>  if( !fileObject ) 
                              {<BR>    sprintf( fullPathName, "%C:", 
                              hookExt-&gt;LogicalDrive 
                              );<BR>    return;<BR>  }<BR>  <BR>  //<BR>  // 
                              Initialize variables<BR>  //<BR>  fileName.Buffer 
                              = NULL;<BR>  relatedName.Buffer = 
                              NULL;<BR>  gotPath = FALSE;<BR>  if( 
                              !fileObject-&gt;FileName.Buffer)<BR>  {<BR>    sprintf( 
                              fullPathName, "%C:", 
                              hookExt-&gt;LogicalDrive);<BR>    return;<BR>  }else<BR>    DbgPrint("fileOjec-&gt;FileName:%s",fileObject-&gt;FileName);<BR>   
                              if( !NT_SUCCESS( RtlUnicodeStringToAnsiString( 
                              &amp;fileName, &amp;fileObject-&gt;FileName, TRUE 
                              ))) {<BR>      sprintf( fullPathName, "%C: &lt;Out 
                              of Memory&gt;", hookExt-&gt;LogicalDrive 
                              );<BR>      return;<BR>    }<BR>  <BR>    pathLen 
                              = fileName.Length + 
                              prefixLen;<BR>    relatedFileObject = 
                              fileObject-&gt;RelatedFileObject;<BR>     //<BR>    // 
                              Only look at related file object if this is a 
                              relative name<BR>    //<BR>    if( 
                              fileObject-&gt;FileName.Buffer[0] != L'' 
                              &amp;&amp;<BR>      relatedFileObject &amp;&amp; 
                              relatedFileObject-&gt;FileName.Length ) 
                              {<BR>      DbgPrint("relatedFileObject filename : 
                              %s",relatedFileObject-&gt;FileName);<BR>      <BR>      if( 
                              !NT_SUCCESS( RtlUnicodeStringToAnsiString( 
                              &amp;relatedName, 
                              &amp;relatedFileObject-&gt;FileName, TRUE ))) 
                              {<BR>       <BR>        sprintf( fullPathName, 
                              "%C: &lt;Out of Memory&gt;", 
                              hookExt-&gt;LogicalDrive 
                              );<BR>        RtlFreeAnsiString( &amp;fileName 
                              );<BR>        return;<BR>      }<BR>      pathLen 
                              += relatedName.Length+1;<BR>    }<BR>    if( 
                              fileObject-&gt;DeviceObject-&gt;DeviceType != 
                              FILE_DEVICE_NETWORK_FILE_SYSTEM ) 
                              {<BR>      sprintf( fullPathName, "%C:", 
                              hookExt-&gt;LogicalDrive );<BR>    }<BR>     if( 
                              pathLen &gt;= MAXPATHLEN ) 
                              {<BR>      <BR>      strcat( fullPathName, " 
                              &lt;Name Too Long&gt;" );<BR>    } else 
                              {<BR>  <BR>      //<BR>      // Now we can build 
                              the path name<BR>      //<BR>      fullPathName[ 
                              pathLen ] = 0;<BR>      <BR>      pathOffset = 
                              fullPathName + pathLen - 
                              fileName.Length;<BR>      memcpy( pathOffset, 
                              fileName.Buffer, fileName.Length + 1 
                              );<BR>  <BR>      if( 
                              fileObject-&gt;FileName.Buffer[0] != L'' 
                              &amp;&amp;<BR>        relatedFileObject &amp;&amp; 
                              relatedFileObject-&gt;FileName.Length ) 
                              {<BR>        //<BR>        // Copy the component, 
                              adding a slash 
                              separator<BR>        //<BR>        *(pathOffset - 
                              1) = '';<BR>        pathOffset -= 
                              relatedName.Length + 
                              1;<BR>          <BR>        memcpy( pathOffset, 
                              relatedName.Buffer, relatedName.Length 
                              );<BR>        //<BR>        // If we've got to 
                              slashes at the front zap 
                              one<BR>        //<BR>        if( pathLen &gt; 3 
                              &amp;&amp; fullPathName[2] == '' &amp;&amp; 
                              fullPathName[3] == '' 
                              ) {<BR>          <BR>          strcpy( 
                              fullPathName + 2, fullPathName + 3 
                              );<BR>        }<BR>      }<BR>    } <BR>} 上面的精简后的函数代码为只考虑目前处于第一种情况,即打开文件请求中,但文件尚未打开时。</DIV>
                              <DIV>  在此时,文件的名字信息存储在文件对象fileObject-&gt;FileName,与 
                              fileObject-&gt;RelatedFileObject-&gt;FileName, 
                              FileObject-&gt;FileName 是RelatedObject 
                              的相对路径,通过对两者的解析组合出文件名字。</DIV>
                              <DIV>  而在FilemonGetFullPath 
                              函数体中的另一段代码:FilemonGetFullPath<BR>{<BR>…………………..<BR>…………………..<BR>…………………..<BR>if( 
                              !gotPath &amp;&amp; !createPath ) 
                              {<BR>    <BR>    fileNameInfo = 
                              (PFILE_NAME_INFORMATION) ExAllocatePool( 
                              NonPagedPool,<BR>                                MAXPATHLEN*sizeof(WCHAR) 
                              );<BR>    if( fileNameInfo 
                              &amp;&amp;<BR>      FilemonQueryFile(hookExt-&gt;FileSystem, 
                              fileObject, FileNameInformation,<BR>               
                              fileNameInfo, (MAXPATHLEN - prefixLen - 
                              1)*sizeof(WCHAR) )) {<BR>      fullUniName.Length 
                              = (SHORT) 
                              fileNameInfo-&gt;FileNameLength;<BR>      fullUniName.Buffer 
                              = fileNameInfo-&gt;FileName;<BR>      if( 
                              NT_SUCCESS( RtlUnicodeStringToAnsiString( 
                              &amp;fileName, &amp;fullUniName, TRUE ))) 
                              {<BR>        fullPathName[ fileName.Length + 
                              prefixLen ] = 0;<BR>        if( hookExt-&gt;Type 
                              == NPFS ) {<BR>          <BR>          strcpy( 
                              fullPathName, NAMED_PIPE_PREFIX );<BR>        } 
                              else if( hookExt-&gt;Type == MSFS ) 
                              {<BR>          strcpy( fullPathName, 
                              MAIL_SLOT_PREFIX );<BR>        } else if( 
                              fileObject-&gt;DeviceObject-&gt;DeviceType != 
                              FILE_DEVICE_NETWORK_FILE_SYSTEM ) 
                              {<BR>          sprintf( fullPathName, "%C:", 
                              hookExt-&gt;LogicalDrive );<BR>        } else 
                              {<BR>        <BR>          //<BR>          // No 
                              prefix for network 
                              devices<BR>          //<BR>        }<BR>        memcpy( 
                              &amp;fullPathName[prefixLen], fileName.Buffer, 
                              fileName.Length );<BR>        gotPath = 
                              TRUE;<BR>        RtlFreeAnsiString( &amp;fileName 
                              );<BR>        fileName.Buffer = 
                              NULL;<BR>      }<BR>    }<BR>    if( fileNameInfo 
                              ) ExFreePool( fileNameInfo 
                              );<BR>}<BR>…………………<BR>…………………<BR>…………………<BR>}</DIV>
                              <DIV>  上面这段代码是处理另外一种情况,即是在其他读写请求中,自己根据拦截到的fileObject构建IRP,下发到底层,以此来查询文件名信息。整个过程还是易于理解的。</DIV>
                              <DIV>  在理清这两种脉络后,再剖析此整个函数,就很容易理解整个函数代码了。</DIV>
                              <DIV>  代码中对 MajorFunction == 
                              IRP_MJ_CREATE_NAMED_PIPE</DIV>
                              <DIV>  MajorFunction == IRP_MJ_CREATE_MAILSLOT 
                              的判断是为了辨别对拦截到的进程间的两种通信方式:命名管道与邮槽的处理。</DIV>
                              <DIV>  周末来了,祝大家周末愉快。余下的整理后再帖,希望和大家多交流。</DIV>
                              <DIV>  连城碧 QQ 276265852 MSN:<A 
                              href="mailto:haochao0000@hotmail.com">haochao0000@hotmail.com</A></DIV>
                              <DIV></DIV></DIV></TD></TR></TBODY></TABLE>
                        <P style="MARGIN: 5px; LINE-HEIGHT: 150%"></P></TD></TR>
                    <TR>
                      <TD height=25><FONT color=#000066>&nbsp;发表于: 
                        2008-12-06,修改于: 2008-12-06 
                        11:45&nbsp;已浏览165次,有评论0条</FONT> <A id=star title=推荐这篇文章 
                        onclick="NewWindows(this.href);return false;" 
                        href="http://blog.chinaunix.net/u2/star.php?blogid=21790&amp;artid=1682616">推荐</A> 
                     

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -