&diskdrvobj); if (!NT_SUCCESS(status)) return result; findev = diskdrvobj->DeviceObject; while (findev) { if (findev->DeviceType == FILE_DEVICE_DISK) result = findev; findev = findev->NextDevice; } ObDereferenceObject(diskdrvobj); return result; } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath) { NTSTATUS status=STATUS_SUCCESS; PDRIVER_OBJECT diskdrvobj; UNICODE_STRING uniobjname={0}; PDRIVER_DISPATCH originalDispatch=NULL; RtlInitUnicodeString(&uniobjname,L"\\Driver\\Disk"); DriverObject->DriverUnload=DriverUnload; status = ObReferenceObjectByName(&uniobjname, OBJ_CASE_INSENSITIVE, 0, 0, *IoDriverObjectType, KernelMode, 0, &diskdrvobj); if (NT_SUCCESS(status)) { originalDispatch = (PDRIVER_DISPATCH)InterlockedExchangePointer(&diskdrvobj->MajorFunction[IRP _MJ_WRITE], fake_disk_Write_dispatch); if (originalDispatch) { g_Origal_disk_Write_Dispatch = originalDispatch; g_bHooked = TRUE; } ObDereferenceObject(diskdrvobj); } return status; } //这里过滤掉对MBR的读写 NTSTATUS fake_disk_Write_dispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; IO_STACK_LOCATION *irpsp= IoGetCurrentIrpStackLocation(Irp); LARGE_INTEGER WriteOffsetInBytes= irpsp->Parameters.Write.ByteOffset; ULONG writeLength = irpsp->Parameters.Write.Length; LARGE_INTEGER Sectionpos={0}; ULONG SectorRange; 使用自己编写的程序进行测试或者使用 Winhex 以及内核读写扇区的工具 SectorEditor 来修改 MBR,发现对 MBR扇区的写操作全部无效。效果示意图如下: 图1 这样不管你是在内核用NTWriteFilr 来写磁盘 MBR 还是通过构造 Scst写操作包发送至 DR0来改写MBR,全部无效,当然你可以发向更底层的端口驱动atapi.sys的StartIo或者重 定位类驱动的写例程,那样还是可以绕过这种保护,本来安全就没有绝对的,谢谢大家! (编辑提醒,本文涉及的代码直接在PDF 附件下载即可) BOOLEAN IsDeniedAccess = FALSE; PDEVICE_OBJECT firstPartition; do { firstPartition=GetFirstPartitionDevice(); Sectionpos.HighPart = 0; Sectionpos.LowPart = BytesBySECTION; SectorRange= WriteOffsetInBytes.QuadPart/Sectionpos.QuadPart; //保护 MBR if ( SectorRange==0 && firstPartition == DeviceObject) { IsDeniedAccess =TRUE; break; } } while(0); //不让其写入,直接往上返回,其实这方法不好,不如读取MBR 的内容进行hash, 和保存好的Hash比较判定 if (IsDeniedAccess) { Irp->IoStatus.Information = writeLength; Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp,IO_NO_INCREMENT); |