用磁盤類驅動ObjectHook來保護MBR

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章