首页 > 应用 > 软件技巧 > 正文

Windows平台内核级文件访问

2024-07-16 17:58:54
字体:
来源:转载
供稿:网友

在windows平台下,应用程序通常使用API函数来进行文件访问,创建,打开,读写文件。从kernel32的CreateFile/ReadFile/WriteFile函数,到本地系统服务,再到FileSystem及其FilterDriver,经历了很多层次。在每个层次上,都存在着安全防护软件,病毒或者后门作监视或者过滤的机会。作为安全产品开发者,我们需要比别人走得更远,因此我们需要一个底层的“windows平台内核级文件访问”的方法来确保我们能够看到正确的干净的文件系统。

  直接访问FSD的内核级别文件访问

  FSD(FileSystemDriver)层是文件API函数经过本地系统服务层(native API)最后到达的驱动层次。如果我们可以模仿操作系统,在我们自己的驱动程序里直接向FSD发送IRP,就可以绕过那些native API 和win32 API了,也就可以绕过设置在这些层次上面的API钩子等监控措施。

  文件的Create和Open

  文件的Create和Open可以通过发送IRP_MJ_CREATE给FSD,或者调用IoCreateFile函数来完成。Create和Open的区别实际上在于IoCreateFile/IRP_MJ_CREATE的一个参数Disposition的取值。

  通过发送IRP_MJ_CREATE给FSD的方法与此类似,可以参考IFSDDK document的IRP_MJ_CREATE说明。不同于上面方法的是需要自己创建一个FILE_OBJECT,好于上面方法的是这种方法不需要一个HANDLE,HANDLE是线程依赖的,FileObject则是线程无关。

  文件的Read和Write

  我们通过给FSD发送IRP_MJ_READ来读取文件,给FSD发送IRP_MJ_WRITE来改写文件。

  如果我们是通过一个HANDLE来执行(如使用IoCreateFile打开的文件),就要先用ObReferenceObjectByHandle函数来获得这个Handle对应的FileObject。我们只能给FileObject发送IRP。

  之后我们使用IoAllocateIrp分配一个IRP。根据FileObject->DeviceObject->Flags的值,我们判断目标文件系统使用什么样的IO方式。

  对每种不同的IO方式使用不同的地址传递方式。随后我们填充IRP内的各个参数域,就可以发送IRP了。

  接着要考虑如果IRP不能及时完成,会异步的返回的情况,我们安装一个CompletionRoutine,在CompletionRoutine里面设置一个事件为已激活,通知我们的主线程读取或者写入操作已经完成。

  现在可以发送IRP了。如果不采取特殊的措施的话,IRP发送目标是FileObject对应的DeviceObject。发送后,等待IRP的完成并且释放资源,返回。

  文件的Delete

  Delete实际上是通过向FSD发送IRP_MJ_SET_INFORMATION的IRP,并把IrpSp->Parameters.SetFile.FileInformationClass设置为FileDispositionInformation,用一个FILE_DISPOSITION_INFORMATION结构填充buffer来执行的。

  文件的Rename

  类似于Delete,Rename是向FSD发送IRP_MJ_SET_INFORMATION的IRP,把IrpSp->Parameters.SetFile.FileInformationClass设置为FileRenameInformation,填充buffer为FILE_RENAME_INFORMATION结构。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表