閱讀923 返回首頁    go 阿裏雲 go 技術社區[雲棲]


過濾驅動加密文件(代碼)

摘要:     我想做一個unlocker一樣的程序,不管這個文件有沒有被使用,先實現刪除它。在查資料過程中,就知道了如果不訪問磁盤扇區的話,除非寫驅動才能做到。奈何時間有限,工作匆忙,一直沒有完成。而且忽視了更簡便的方法——在別的路徑下把修改後的OCX控件重新注冊一下就可以了。

    這些都不要說了,這段閑暇時間,我寫了一個過濾加密,就這麼簡單。在DDK的示例Sfilter基礎上改的。

 

文件過濾加密的源代碼

 

//過濾讀

NTSTATUS SfRead(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

{

  PIO_STACK_LOCATION    irp_stack; 

  BOOLEAN           is_crypt;

  NTSTATUS          status;

  PSFILTER_DEVICE_EXTENSION devExt;

 

  PAGED_CODE();

 

  ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));

  ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));

  devExt = (PSFILTER_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);

 

  if(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))

  {

    irp_stack = IoGetCurrentIrpStackLocation( Irp );

    is_crypt = IsMyCryptFile(irp_stack->FileObject);

 

    if(is_crypt) //是我的加密文件

    {

      //設置完成例程

      IoCopyCurrentIrpStackLocationToNext( Irp );

      IoSetCompletionRoutine(Irp, SfReadCompletion, 0, TRUE, FALSE, FALSE);

 

      //調用原來的驅動

      return IoCallDriver(devExt->AttachedToDeviceObject, Irp);

    }

  }

 

  //非加密文件

  IoSkipCurrentIrpStackLocation(Irp);

  return IoCallDriver(devExt->AttachedToDeviceObject, Irp);

}

 

//讀操作的完成例程

NTSTATUS SfReadCompletion(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID Context)

{

  ULONG        length; //長度

  PUCHAR       buffer; //緩衝區

  ULONG        i;

  PIO_STACK_LOCATION irp_stack;  

 

  irp_stack = IoGetCurrentIrpStackLocation( Irp );

  ShowUnicodeString(&(irp_stack->FileObject->FileName));

  DbgPrint("SfReadCompletion 讀文件解密");

 

  length = Irp->IoStatus.Information;

  buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

  for(i = 0; i < length; i++)

  {

    buffer[i] = buffer[i] - 17; //解密

  }

 

  return STATUS_SUCCESS;

}

 

//過濾寫

NTSTATUS SfWrite(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

{

  PIO_STACK_LOCATION    irp_stack; 

  BOOLEAN           is_crypt;

  NTSTATUS          status;

  PSFILTER_DEVICE_EXTENSION devExt;

 

  PAGED_CODE();

 

  ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));

  ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject )); 

  devExt = (PSFILTER_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);

 

  if(Irp->Flags & (IRP_NOCACHE | IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO))

  {

    irp_stack = IoGetCurrentIrpStackLocation( Irp );

    is_crypt = IsMyCryptFile(irp_stack->FileObject);

 

    if(is_crypt)

    {

      ULONG  length;       //長度

      PUCHAR buffer, buffer2;  //原來緩衝區和加密後緩衝區

      ULONG  i;

      PMDL   new_mdl;

 

      length = irp_stack->Parameters.Write.Length;

      buffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

 

      //分配同樣大小的空間

      buffer2 = (PUCHAR)ExAllocatePool(NonPagedPool, length);

 

      if(buffer2 != 0)

      {

        ShowUnicodeString(&(irp_stack->FileObject->FileName));

        DbgPrint("SfWrite 寫文件加密");

 

        for(i = 0; i < length; i++)

        {

          buffer2[i] = buffer[i] + 17; //加密

        }

 

        //設置完成例程

        IoCopyCurrentIrpStackLocationToNext( Irp );

        IoSetCompletionRoutine(Irp, SfWriteCompletion, Irp->MdlAddress, TRUE, TRUE, TRUE);

       

        //替換成新的緩衝區

        new_mdl = IoAllocateMdl(buffer2, length, FALSE, TRUE, NULL);

        MmBuildMdlForNonPagedPool(new_mdl);

        Irp->MdlAddress = new_mdl;

 

        //調用原來的驅動

        return IoCallDriver(devExt->AttachedToDeviceObject, Irp);

      }

      else

      {

        ShowUnicodeString(&(irp_stack->FileObject->FileName));

        DbgPrint("SfWrite 寫不能分配內存");

 

        Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;

        Irp->IoStatus.Information = 0;

        IoCompleteRequest( Irp, IO_NO_INCREMENT );

        return Irp->IoStatus.Status;

      }

    }

  }

 

  //非加密文件

  IoSkipCurrentIrpStackLocation(Irp);

  return IoCallDriver(devExt->AttachedToDeviceObject, Irp);

}

 

//寫完成後就把分配的空間給刪除掉

NTSTATUS SfWriteCompletion(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID Context)

{

  PMDL         old_mdl, new_mdl;

  PUCHAR       buffer2; //我分配的緩衝區

  PIO_STACK_LOCATION irp_stack;  

 

  irp_stack = IoGetCurrentIrpStackLocation( Irp );

  ShowUnicodeString(&(irp_stack->FileObject->FileName));

  DbgPrint("完成: SfWriteCompletion");

 

  new_mdl = Irp->MdlAddress;

  old_mdl = (PMDL)Context;

 

  //還是指向原來的緩衝區

  Irp->MdlAddress = old_mdl;

 

  //刪除掉我分配的緩衝區

  buffer2 = MmGetSystemAddressForMdlSafe(new_mdl, NormalPagePriority);

 

  IoFreeMdl(new_mdl);

  ExFreePool(buffer2);

 

  return STATUS_SUCCESS;

}

 

//文件打開的時候調用

NTSTATUS SfCreate(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

{

  NTSTATUS          status;

  PSFILTER_DEVICE_EXTENSION devExt;

 

  PAGED_CODE();

 

  //如果不是過濾驅動設備就退出

  if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))

  {

    Irp->IoStatus.Status = STATUS_SUCCESS;

    Irp->IoStatus.Information = 0;

    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    return STATUS_SUCCESS;

  }

 

  ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));

  devExt = (PSFILTER_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);

 

  //設置完成例程

  IoCopyCurrentIrpStackLocationToNext( Irp );

  IoSetCompletionRoutine(Irp, SfCreateCompletion, 0, TRUE, FALSE, FALSE);

 

  //調用原來的驅動

  return IoCallDriver( devExt->AttachedToDeviceObject, Irp );

}

 

//在打開文件的完成例程中記錄文件對象

NTSTATUS SfCreateCompletion(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp, __in PVOID Context)

{

  PIO_STACK_LOCATION irp_stack;

  PFILE_OBJECT     file_obj;

  BOOLEAN      is_crypt;

 

  irp_stack = IoGetCurrentIrpStackLocation(Irp);

  file_obj = irp_stack->FileObject;

  is_crypt = IsMyCryptFile(file_obj);

 

  if(is_crypt)

  {

    if(CcIsFileCached(file_obj))

    {

      ShowUnicodeString(&(file_obj->FileName));

      DbgPrint("打開時清除緩存 \n");

      CcPurgeCacheSection(file_obj->SectionObjectPointer, 0, 0, FALSE);

    }

  }

  return STATUS_SUCCESS;

}

 

//關閉文件後的清理工作

NTSTATUS SfCleanupClose(__in PDEVICE_OBJECT DeviceObject, __in PIRP Irp)

{

  NTSTATUS          status;

  PSFILTER_DEVICE_EXTENSION devExt;

  PIO_STACK_LOCATION    irp_stack;

  PFILE_OBJECT        file_obj;

  BOOLEAN           is_crypt;

 

  PAGED_CODE();

 

  if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))

  {

    Irp->IoStatus.Status = STATUS_SUCCESS;

    Irp->IoStatus.Information = 0;

    IoCompleteRequest( Irp, IO_NO_INCREMENT );

    return STATUS_SUCCESS;

  }

 

  ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));

 

  irp_stack = IoGetCurrentIrpStackLocation(Irp);

  file_obj = irp_stack->FileObject;

  is_crypt = IsMyCryptFile(file_obj);

 

  if(is_crypt)

  {

    if(CcIsFileCached(file_obj))

    {

      ShowUnicodeString(&(file_obj->FileName));

      DbgPrint("關閉時清除緩存 \n");

      CcPurgeCacheSection(file_obj->SectionObjectPointer, 0, 0, FALSE);

    }

  }

 

  IoSkipCurrentIrpStackLocation( Irp );

  devExt = (PSFILTER_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);

  return IoCallDriver(devExt->AttachedToDeviceObject, Irp);

}

 

開始寫的時候,我本想保持保持緩衝區的數據同磁盤上一樣,也是密文,這樣就不用清理緩衝區了。但是試驗沒能成功,因為程序要是按照內存文件映射的方法或者DMA的方法讀寫緩衝區,我找不到機會解密。

最後更新:2017-04-03 15:21:56

  上一篇:go C++ 定義數組大小問題
  下一篇:go 實戰DeviceIoControl 之四:獲取硬盤的詳細信息