1. 程式人生 > >讀取硬碟的MBR引導扇區(Windows各系統通用)

讀取硬碟的MBR引導扇區(Windows各系統通用)

原文:

-----------------------------------------------------------------------------------------------------------

知識普及:

硬碟的引導扇區位於 0 磁軌 0 磁頭 1 扇區位置,該扇區存放著系統的載入程式和硬碟的分割槽表等重要資訊。另外小甲魚八卦一下,該扇區常常是病毒的重點攻擊目標!

實現要求:讀取硬碟引導扇區並儲存為boot.ini檔案

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

實現原理:

上節課小甲魚不是說會告訴大家如何在使用者模式下直接訪問硬碟麼?嗯,而且承諾絕對簡單通俗。好吧,事實上,硬碟核心驅動程式將硬碟作為一個檔案,檔名為:"\\.\\physicaldrive0"

我們可以利用這個鮮為人知的檔名,通過 CreateFile, ReadFile, WriteFile 和 DeviceIoControl API 來進行訪問硬碟。

程式碼及詳細註釋:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; by 小甲魚, http://www.fishc.com
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
; 功能:讀取硬碟引導扇區並保存於boot.ini檔案中
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
        .386
        .model flat,stdcall
        option casemap:none

include windows.inc
include comdlg32.inc
include user32.inc
include kernel32.inc
includelib comdlg32.lib
includelib user32.lib
includelib kernel32.lib

    .data
szFileName  db  '\\.\\physicaldrive0', 0            ; 硬碟裝置名

    .data?
szBuffer        db  512 dup (?)
@hFile          dd  ?
@dwBytesRead    dd  ?
@szLogFile      db  MAX_PATH dup (?)

    .const
szNewFile       db  'boot.ini', 0
szErrOpenFile   db  '無法開啟硬碟檔案!', 0
szErrCreateFile db  '無法建立boot.ini檔案!', 0
szSuccess       db  '成功讀取硬碟引導區並寫入boot.ini檔案!', 0    
szCaption       db  '魚C工作室', 0    
    
    .code
start:
    invoke CreateFile,              ; 開啟或建立檔案
        addr szFileName,            ; 檔案的名字
        GENERIC_READ,               ; 允許讀訪問
        FILE_SHARE_READ,            ; 允許對檔案進行共享訪問
        0,                          ; 指向一個SECURITY_ATTRIBUTES結構的指標
        OPEN_EXISTING,              ; 檔案必須存在
        FILE_ATTRIBUTE_NORMAL,      ; 預設屬性
        0
    
    .if eax == INVALID_HANDLE_VALUE ; 開啟檔案錯誤
        invoke MessageBox,
            NULL,
            addr szErrOpenFile,
            addr szCaption,
            MB_OK
            
        jmp exit
    .endif
    
    mov @hFile, eax                 ; 返回檔案控制代碼,這時候硬碟被看成是一個檔案的哦~
    
    invoke ReadFile,                ; 從檔案中讀取資料
        @hFile,                     ; 檔案控制代碼
        addr szBuffer,              ; 用於儲存讀入資料的緩衝區
        sizeof szBuffer,            ; 需要讀入的字元數
        addr @dwBytesRead,          ; 實際讀入的位元組數
        0
    
    invoke CloseHandle, @hFile      ; 小甲魚溫馨提醒:記得檔案開啟後要擦屁股->關閉檔案,否則造成記憶體洩漏
    
    invoke lstrcpy,                 ; 拷貝字串
        addr @szLogFile,
        addr szNewFile
    
    invoke CreateFile,              ; 建立boot.ini檔案
        addr @szLogFile,            
        GENERIC_WRITE,              
        FILE_SHARE_READ,            
        0,                          
        CREATE_ALWAYS,              
        FILE_ATTRIBUTE_NORMAL,      
        0
    
    .if eax != INVALID_HANDLE_VALUE
        mov @hFile, eax
        
        invoke WriteFile,           ; 將資料寫入boot.ini檔案
            @hFile,
            addr szBuffer,
            sizeof szBuffer,
            addr @dwBytesRead,
            0
    
        invoke CloseHandle, @hFile  ; 擦屁股
        
        invoke wsprintf,            ; 這個事實上常用的函式,如果有問題的魚油可以在論壇搜尋下,有篇文章中小甲魚已經做好了詳細的解釋給大家。
            addr szBuffer,
            addr szSuccess
         
        invoke MessageBox,
            NULL,
            addr szBuffer,
            addr szCaption,
            MB_OK
            
    .else
        invoke MessageBox,
            NULL,
            addr szErrCreateFile,
            addr szCaption,
            MB_OK
    .endif    
        
exit:
    invoke ExitProcess, NULL
        
    end start