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