MBR、DPT、DBR

硬碟主引導磁區 = 硬碟主引導記錄(MBR)+ 硬碟分區表(DPT)


--------------------------------------------------------------
物理位置:0面0道1磁區(clindyer 0, side 0, sector 1)
大小: 512字節0
其中:MBR 446字節(0000--01BD),DPT 64字節(01BE--01FD),結束標誌2字節(55 AA)
功能:MBR通過檢查DPT分區信息引導系統跳轉至DBR;
讀取: 使用NORTON DISKEDIT, 在OBJECT菜單中選擇DRIVE-->PHYSICAL DISK--HARD DISK,
然後, 在OBJECT菜單中選擇DISK PARTITION TABLE即可讀取, 並使用TOOLS菜單中的WRITE OBJECT TO 選項存入指定文件備份;
寫入: 使用NORTON DISKEDIT, 在OBJECT菜單中選擇DRIVE-->FLOOPY DISK, 選擇備份的DPT
文件, 然後使用TOOLS菜單中的WRITE OBJECT TO-->PHYSICAL SECTOR 選項寫入001
(clindyer 0, side 0, sector 1);

詳解:
000H--08AH MBR啟動程序(尋找開機分區)
08BH--0D9H MBR啟動字符串
0DAH--1BCH 保留("0")
1BEH--1FDH 硬碟分區表
1FEH--1FFH 結束標誌(55AA)


活動分區主引導磁區(DBR)
--------------------------
物理位置:1面0道1磁區(clindyer 0, side 1, sector 1)
大小: FAT16 1磁區 512字節
FAT32 3磁區 1536字節
功能:包含機器CMOS等信息(0000--0059), 核對該信息並引導指定的系統文件, 如NTLDR等;
讀取: 使用NORTON DISKEDIT, 在OBJECT菜單中選擇DRIVE-->LOGICAL DISK--DISK C,
然後, 在OBJECT菜單中選擇BOOT RECORD即可讀取, 並使用TOOLS菜單中的
WRITE OBJECT TO 選項存入指定文件備份;
寫入: 使用NORTON DISKEDIT, 在OBJECT菜單中選擇DRIVE-->FLOOPY DISK, 選擇備份的DBR
文件, 然後使用TOOLS菜單中的WRITE OBJECT TO-->PHYSICAL SECTOR 選項寫入011
(clindyer 0, side 1, sector 1);


詳解:

000H--002H 3 BYTE的跳轉指令(去啟動程序, 跳到03EH)
003H--03DH BIOS參數區
03EH--19DH DOS啟動程序
19EH--1E5H 開機字符串
1E6H--1FDH 文件名(IO.SYS, MSDOS.SYS)
1FEH--1FFH 結束標記(55AA)


硬碟分區表(DPT)
---------------------
偏移地址 字節數 含義分析

01BE 1 分區類型:00表示非活動分區:80表示活動分區;其他為無效分區。

01BF~01C1 3 *分區的起始地址(面/磁區/磁道),通常第一分區的起始地址開始
於1面0道1磁區,因此這三個字節應為010100

01C2 1 #分區的操作系統的類型。

01C3~01C5 3 *該分區的結束地址(面/扇/道)

01C6~01C9 4 該分區起始邏輯磁區

01CA~01CD 4 該分區佔用的總磁區數

註釋: * 注意分區的起始地址(面/磁區/磁道)和結束地址(面/扇/道)中字節分配:

00000000 01000001 00010101
~~~~~~~~ ==^^^^^^ ========

~ 面(磁頭) 8 位
^ 磁區 6 位
= 磁道 10 位

# 分區的操作系統類型(文件格式標誌碼)

4---DOS FAT16<32M
5---EXTEND
6---DOS FAT16>32M
7---NTFS(OS/2)
83---LINUX>64M


DPT 總共64字節(01BE--01FD), 如上所示每個分區佔16個字節, 所以可以表示四個分區, 這也
就是為什麼一個磁盤的主分區和擴展分區之和總共只能有四個的原因.


邏輯驅動器
-----------
擴展分區的信息位於以上所示的硬碟分區表(DPT)中, 而邏輯驅動器的信息則位於擴展分區的
起始磁區, 即該分區的起始地址(面/磁區/磁道)所對應的磁區, 該磁區中的信息與硬碟主引導
磁區的區別是不包含MBR, 而16字節的分區信息則表示的是邏輯驅動器的起始和結束地址等.


所以, 在磁盤僅含有一個主分區, 一個擴展分區(包含多個邏輯驅動器)的情況下, 即使由於病毒
或其他原因導致硬碟主引導磁區的數據丟失(包括DPT), 也可以通過邏輯驅動器的數據來恢復整個硬碟.

例如: 以下是一個硬碟的分區情況.

道 面 扇 道 面 扇 起始扇(邏輯) 結束扇 總共磁區
MBR 0 0 1 - - - - - -
C 0 1 1 276 239 63 63 4,188,239 4,188,177
擴 277 0 1 554 239 63 4,188,240 8,391,599 4,203,360
D 277 1 1 554 239 63 4,188,303 8,391,599 4,203,297


如果主分區表損壞, 則可以通過手工查找擴展分區表中所包含的邏輯驅動器數據, 在本例中就是D盤所對應的數據, 然後將其起始扇(邏輯)減去63就是所對 應的擴展分區的起始扇(邏輯), 將其起始地址(面/磁區/磁道)改為0面就是擴展分區的起始地址. 然後通過擴展分區就可以得到主分區C的信息, 然後 就可以使用FDISK/MBR命令和手工填寫分區表恢復整個硬碟.

實際使用這種方法比較麻煩, 如果知道每個分區的大小, 則可以通過使用PQ MAGIC 5 將磁盤重新分區為原來大小(注意: 千萬不能應用, 我們只是通過它來獲得數據), 並查看INFO來獲得以上
數據, 記錄以後取消該分區操作, 然後使用NORTON DISK2000手工修改DPT表, 恢復整個硬碟.

該例所對應的分區表數據:

80 01
01 00 06 EF 7F 14 3F 00 00 00 11 E8 3F 00 00 00
41 15 05 EF BF 2A 50 E8 3F 00 60 23 40 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA

擴展分區表數據:
00 01
41 15 07 EF BF 2A 8F E8 3F 00 21 23 40 00


注意: 邏輯起始磁區和總共分區數是左邊為低位, 如該例的擴展分區的起始地址為50 E8 3F 00轉換十進制時要先變為00 3F E8 50, 總共佔用分區數60 23 40 00要先變為00 40 23 60, 同理當手工填寫該值時也要進行高低位轉換.
/*定義分區表項的結構*/
typedef struct
{
BYTE BootFlag; /*啟動標誌*/
CHS StartCHS; /*分區開始的柱面、磁頭、磁區*/
BYTE SystemID; /*分區類型*/
CHS EndCHS; /*分區結束的柱面、磁頭、磁區*/
DWORD RelativeSectors; /*分區相對磁區數,指分區相對於記錄該分區的分區表的磁區位置之差*/
DWORD TotalSectors; /*分區總磁區數*/
}PartitionTable;

/*定義主引導磁區結構*/
typedef struct
{
CHAR bootcode[0x1be]; /*啟動代碼*/
PartitionTable PT[4]; /*分區表*/
WORD EndingFlag; /*結束標識*/
}MBR;

/*
引導磁區是文件系統的第一個磁區,其中包含分區重要的數據信息--BPB(BIOS Paramenter
Block-磁盤參數表)。磁盤參數表中包含分區總大小、磁盤參數等重要信息。其C語言定義為:
*/

typedef struct
{
BYTE JMPCode[3]; /*引導跳轉代碼*/
CHAR System_ID[8]; /*廠商標誌和版本號*/
WORD SectorBytes; /*每磁區字節數*/
BYTE SectorsPerCluster; /*每簇磁區數*/
WORD ReservedSectors; /*保留磁區數*/
BYTE NbrFat; /*FAT的個數*/
WORD RootEntry; /*根目錄項數*/
WORD TotalSectors; /*分區總磁區數(分區小於32M時)*/
BYTE Media; /*分區介質標識*/
WORD SectorsPerFAT; /*每個FAT佔的磁區數*/
WORD SectorsPerTrack; /*每道磁區數*/
WORD Heads; /*磁頭數*/
DWORD HiddenSectors; /*隱含磁區數*/
DWORD BigTotalSectors; /*分區總磁區數(分區大於32M時)*//*end of 23 Bytes*/
BYTE Drive; /*驅動器號*/
BYTE Head; /*磁頭號*/
BYTE boot_rec_sig; /*含義未知*/
WORD Vol_Serial_NoL; /*磁盤序列號*/
WORD Vol_Serial_NoH;
CHAR Label[11]; /*磁盤捲標號*/
CHAR FileSys_ID[8]; /*文件系統標識號*/
BYTE BootCode[450]; /*啟動代碼*/
}BPB_FAT16;

/*定義驅動器參數塊,方便文件管理*/
typedef struct
{
BYTE DriveNo; /* 驅動器號,A = 1,B = 2,etc.*/
BYTE PhyDrive; /* 物理驅動器號*/
WORD BytePerSec; /*每磁區字節數*/
WORD SectorsPerTrack; /*每道磁區號*/
BYTE SecPerClu; /*每簇磁區數,以零為基數*/
WORD FirstFATSec; /*包含第一個FAT的磁區號*/
BYTE NbrFAT; /*FAT份數*/
WORD RootEntry; /*根目錄項數*/
WORD FirstDataSec; /*第一個數據磁區號*/
WORD LastClu; /*最後一個簇*/
WORD SecPreFAT; /*每FAT磁區數*/
WORD RootStartSec; /*根目錄起始磁區號*/
BYTE MediaID; /*介質描述字節*/
WORD FirstFreeClu; /*第一個自由的簇號,= -1 未知*/
WORD FreeClu; /*自由簇數*/
DWORD RelativeSectors; /*指BOOT磁區以前的磁區數*/
DWORD TotalSectors; /*本分區總的磁區數*/
} DPB;

/*目錄項中的時間和日期定義*/
typedef struct
{
WORD Sec:5;
WORD Min:6;
WORD Hour:5;
} FILEMIDTIME;

typedef struct
{
WORD Day:5;
WORD Mon:4;
WORD Year:7;
} FILEMIDDATE;

/*目錄表項的含義*/
typedef struct
{
CHAR FileName[FILENAMELEN]; /*主文件名*/
CHAR ExtName[FILEXTNAMELEN]; /*擴展文件名*/
BYTE ReadOnly:1; /*文件屬性,只讀位*/
BYTE Hidden:1; /*隱含*/
BYTE System:1; /*系統*/
BYTE Volume:1; /*卷標*/
BYTE Directory:1; /*目錄*/
BYTE Archives:1; /*檔案*/
CHAR Reserived[10]; /*保留*/
FILEMIDTIME FileMidTime; /*文件創建時間*/
FILEMIDDATE FileMidDate; /*日期*/
WORD StartCluster; /*起始簇*/
DWORD FileLength; /*文件長度*/
}Directory_FAT12_16;

/*目錄項首字節含義*/
enum DirFirstChar
{
DirUnUsed = 0x00, /*本表項沒有使用*/
DirCharE5 = 0x05, /*首字符為0xe5*/
DirisSubDir = 0x2e, /*是一個子目錄 .,..為父目錄*/
DirFileisDeleted = 0xe5 /*文件已刪除*/
};

/*文件結點*/
typedef struct
{
WORD UserCount; /*文件用戶數*/
WORD Mode; /*打開模式,讀,寫*/
struct
{
BOOL DirIsModified:1; /*目錄項是否已改變*/
BOOL DirIsNew:1; /*目錄項是新建的*/
BOOL DirIsFull:1; /*目錄是否已滿*/
} DirFlag;
Directory_FAT12_16 DirImg; /*本文件目錄映像*/
DWORD DirOffset; /*本目錄項偏移*/
DWORD DirStart; /*本目錄起始磁區*/
DPB *FileDPB; /*文件設備塊*/
DWORD ByteOffset; /*當前文件指針字節偏移*/
DWORD LargeOffset; /*文件最大偏移量*/
WORD BackClu; /*前一個簇*/
WORD CurrClu; /*當前簇*/
BYTE SectorInClu; /*簇中的磁區*/
WORD ByteInClu; /*在簇中的字節數*/
} FILENODE;

/*磁盤介質類型*/
enum MediaType
{
HardDisk = 0xf8, /*硬碟*/
RAMDisk = 0xfa /*RAM盤*/
};
/*分區類型*/
enum PartionType
{
ParUNUsed = 0x00,/*分區沒有使用*/
FAT12 = 0x01,
XENIX = 0x02,
FAT16 = 0x04,
Extend = 0x05,
BigDOS = 0x06,
HPFS = 0x07,
SPLIT = 0x08,
FAT32 = 0x0b,
DM = 0x50,
GB = 0x56,
SPEED = 0x61,
ix386 = 0x63,
Novell286 = 0x64,
Novell386 = 0x65,
PCIX = 0x75,
CPM = 0xdb,
BBT = 0xff
};
/*FAT16 FAT表項的含義*/
enum FAT16TYPE
{
FATUnUsed = 0, /*尚未分配*/
FATReserved = 0xFFF0, /*保留*/
FATReserved1 = 0xFFF0,
FATReserved2 = 0xFFF1,
FATReserved3 = 0xFFF2,
FATReserved4 = 0xFFF3,
FATReserved5 = 0xFFF4,
FATReserved6 = 0xFFF6,
FATBADClu = 0xFFF7, /*表示壞簇,即該簇中磁盤有損壞;*/
FileEnd = 0xFFFF, /*文件結束標識*/
FileEnd1 = 0xFFF8,
FileEnd2 = 0xFFF9,
FileEnd3 = 0xFFFA,
FileEnd4 = 0xFFFB,
FileEnd5 = 0xFFFC,
FileEnd6 = 0xFFFD,
FileEnd7 = 0xFFFE,
FileEnd8 = 0xFFFF
};

/*硬碟緩存結構*/
#define BUFFERSIZE 512
typedef struct
{
struct BUFFER *p_B_next; /* 指向下一個緩存塊 */
BYTE uc_DiskNo; /* 硬碟號 */
BYTE uc_Flag; /* 緩存標誌,淨、不淨 */
DWORD ui_SectorNo; /* 緩存對應的邏輯磁區號 */
BYTE uc_Buffer [BUFFERSIZE]; /* 數據緩存BUFFERSIZE=512字節 */
} BUFFER;

typedef struct
{
DWORD Sector; /*當前磁區*/
WORD CluInSec; /*簇在磁區中的偏移*/
}CLUINFAT;

typedef struct
{
DWORD Sector;/*當前磁區*/
WORD DirInSec;/*目錄項在磁區中的偏移*/
}DIRINSEC;

typedef struct
{
DWORD Sector;
BYTE IsMided:1;
BYTE Buf[512];
}ABSSECBUFFER;

typedef struct
{
DWORD Sector;
BYTE IsMided:1;
WORD Buf[256];
}FATBUFFER;

0 意見: