MBR 是硬盘的主引导记录,它独立于操作系统之外,不管你装 Windows 操作系统还是
Linux 操作系统等等,它都存在,它包括引导程序、分区表、结束标志(0x55AA)。它被
bios将引导程序加载在0x7C00的起始位置,检查最后的两位标志位是否正确,如果正确,
取出活动分区的起始扇区(引导扇区),然后跳转到活动分区的引导扇区,通过引导扇区的
引导程序在找到 NTLDR 区域,如果 NTLDR 文件丢失或者损坏,就会出现一段熟悉的信
息:”NTLDR is missing,please Ctrl+Alt+Del”,然后你就只有重启计算机,或者修复
NTLDR。NTLDR(startup.com +osload), startup.com是16位的程序,它运行在实模式,其
中很重要的工作就是负责将实模式(不支持分页,采取段首址*0x10+偏移,所有读写都是特
权指令)切换到保护模式并且开启分页功能。然后重定位 osload 程序,这个就是核心的启
动程序,它加载核心设备(BOOT 型)的驱动,比如:ftdisk.sys、atapi.sys、disk.sys 等
等,加载后再加载 ntoskrnl.exe,控制权在交给 ntoskrnl.exe 程序,加载一些其他设备驱
动、服务等等,最后进去系统。具体的细节我以后在跟大家讨论。鬼影 2 就是替换
fips.sys驱动,并且替换bios的扩展in113,来接官对MBR的读写。所以MBR是极其重要,
在vista以后的系统,微软也意识到MBR的重要性,所以对MBR采取了保护措施,不能随便
改写,由于微软不在支持windows xp的升级,所以winxp下的MBR经常被病毒、木马利用。
但是目前还有很多用户在使用 winxp,下面我给大街介绍一种保护 MBR 的方式,通过 OBJECT
HOOK来实现。
通过对磁盘类驱动的IRP_MJ_WRITE的分发例程进行OBJECT HOOK,对写入的扇区偏移来进
行判定,如果是第一分区(mbr在第一分区的0柱面 0磁道0扇区)的磁盘设备,并且偏移
扇区为0,也就是从0扇区里的位置开始写入的操作全部拦截,从而保护mbr不被修改。我
的方法过于简单,可以将未被修改的 MBR512 个字节的内容进行 HASH。然后对要写入的 512
个字节也进行 HASH,如果 hash 值不同,则 MBR 证明已被修改过,则拦截该写入操作。主要
代码如下:
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING uniobjname={0};
PDRIVER_OBJECT diskdrvobj;
NTSTATUS status;
if ( g_bHooked&& g_Origal_disk_Write_Dispatch)
{
RtlInitUnicodeString(&uniobjname,L"\\Driver\\Disk");
status = ObReferenceObjectByName(&uniobjname,
OBJ_CASE_INSENSITIVE,
0,
0,
*IoDriverObjectType,
KernelMode,
0,
&diskdrvobj);
if (NT_SUCCESS(status))
{
InterlockedExchangePointer(&diskdrvobj->MajorFunction[IRP_MJ_WRITE],(PDRIVER
_DISPATCH)g_Origal_disk_Write_Dispatch);
g_bHooked =FALSE;
ObDereferenceObject(diskdrvobj);
}
}
return;
}
PDEVICE_OBJECT GetFirstPartitionDevice()
{
UNICODE_STRING uniobjname={0};
PDRIVER_OBJECT diskdrvobj;
NTSTATUS status;
PDEVICE_OBJECT result=NULL;
PDEVICE_OBJECT findev;
RtlInitUnicodeString(&uniobjname,L"\\Driver\\Disk");
status = ObReferenceObjectByName(&uniobjname,
OBJ_CASE_INSENSITIVE,
0,
0,
*IoDriverObjectType,
KernelMode,
0,
&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);
return status;
}
else
{
status = g_Origal_disk_Write_Dispatch(DeviceObject,Irp);
}
return status;
}
使用自己编写的程序进行测试或者使用 Winhex 以及内核读写扇区的工具 SectorEditor
来修改 MBR,发现对 MBR扇区的写操作全部无效。
这样不管你是在内核用NTWriteFilr 来写磁盘 MBR 还是通过构造 Scst写操作包发送至
DR0来改写MBR,全部无效,当然你可以发向更底层的端口驱动atapi.sys的StartIo或者重
定位类驱动的写例程,那样还是可以绕过这种保护,本来安全就没有绝对的,谢谢大家!
原文地址 http://www.jybase.net/windows/20111207700.html