转载自http://www.misssir.cn/art/_show.aspx?art=49 摘要: 我想做一个unlocker一样的程序,不管这个文件有没有被使用,先实现删除它。在查资料过程中,就知道了如果不访问磁盘扇区的话,除非写驱动才能做到。奈何时间有限,工作匆忙,一直没有完成。而且忽视了更简便的方法——在别的路径下把修改后的OCX控件重新注册一下就可以了。 |
文件过滤加密的源代码 //过滤读 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的方法读写缓冲区,我找不到机会解密。 |