📄 bpb.cpp
字号:
/*
BPB格式
序号 偏移地址 意义
1 03H-0AH OEM号
2 0BH-0CH 每扇区字节数
3 0DH 每簇扇区数
4 0EH-0FH 保留扇区数
5 10H FAT备份数
6 11H-12H 根目录项数
7 13H-14H 磁盘总扇区数
8 15H 描述介质
9 16H-17H 每FAT扇区数
10 18H-19H 每磁道扇区数
11 1AH-1BH 磁头数
12 1CH-1FH 特殊隐含扇区数
13 20H-23H 总扇区数
14 24H-25H 物理驱动器数
15 26H 扩展引导签证
16 27H-2AH 卷系列号
17 2BH-35H 卷标号
18 36H-3DH 文件系统号
DOS引导记录公式:
文件分配表≡保留扇区数
根目录≡保留扇区数+FAT的个数×每个FAT的扇区数
数据区≡根目录逻辑扇区号+(32×根目录中目录项数+(每扇区字节数-1))DIV每扇区字节数
绝对扇区号≡逻辑扇区号+隐含扇区数
扇区号≡(绝对扇区号MOD每磁道扇区数)+1
磁头号≡(绝对扇区号DIV每磁道扇区数)MOD磁头数
磁道号≡(绝对扇区号DIV每磁道扇区数)DIV磁头数
要点:(1)DBR位于柱面0,磁头1,扇区1,其逻辑扇区号为0
(2)DBR包含DOS引导程序和BPB
(3)BPB十分重要,由此可算出逻辑地址与物理地址。
*/
#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned int
#define UINT64 __int64
#define uint8 unsigned char
#define uint16 unsigned short
#define uint32 unsigned int
#define uint64 __int64
#define UCHAR unsigned char
#define USHORT unsigned short
#define ULONG unsigned int
#define ULONGLONG __int64
#pragma pack(1)
typedef struct{
uint8 Jumpto[3]; //00-02h
uint8 OemID[8]; //03-0ah
uint16 BytesPerSector; //0b-0ch "Bytes per sector"
uint8 SectorsPerCluster; //0d-0dh "Sectors per cluster"
uint16 ReservedSectors; //0e-0fh "Reserved sectors"
uint8 NumberOfFats; //10-10h "Number of FATs"
uint16 RootEntry; //11-12h "Root entries"
uint16 TotalSectors; //13-14h "Sectors (under 32 MB)"
uint8 MediaType; //15-15h 1 "Media descriptor (hex)"
uint16 SectorsPerFat; //16-17h "Sectors per FAT"
uint16 SectorsPerTrack; //18-19h "Sectors per track"
uint16 Heads; //1a-1bh "Heads"
uint32 HiddenSectors; //1c-1fh "Hidden sectors"
uint32 LargeSectors; //20-23h "Sectors (over 32 MB)"
}BIOS_PARAMETER_BLOCK;
typedef struct{
uint8 DriveType; //24-24h hex 1 "BIOS drive (hex, HD=8x)"
uint8 Reserved; //25-25h read-only uint8 (Unused)
uint8 ExtBootSignature; //26-26h hex 1 "Ext. boot signature (29h)"
uint32 VolumeSerialNumber;//27-2ah "Volume serial number (decimal)"
uint8 VolumeLabel[11]; //2b-35h char[11] "Volume label"
uint8 FileSystem[8]; //36-3dh char[8] "File system"
}FAT16_SECTION;
typedef struct{
uint32 SectorsPerFat; //24-27h "Sectors per FAT"
uint16 ExtendFlags; //28-29h "Flags"
uint16 Version; //2a-2bh "Version"
uint32 RootDir1st; //2c-2fh "Root dir 1st cluster"
uint16 FsInfoSector; //30-31h "FSInfo sector"
uint16 BackupBootSector; //32-33h "Backup boot sector"
uint8 reserved[12]; //34-3fh read-only hex 12 "(Reserved)"
}FAT32_SECTION;
/*
16、40H 该处为磁盘BIOS信息,第一块硬盘为“80H”,一般软盘为“00H”
17、47H~51H 用户设置的卷标,如果没有卷标此处常为字符串“NO NAME ”
18、52H~59H 文件系统,对于FAT32文件系统此处常为“FAT32 ”
19、1FEH~1FFH 结束标识,和上文提到的主引导区的结束标识一样为“55H AAH”
*/
typedef struct {
UCHAR Jump[3]; //0H~02H 一条跳转指令,指针指向后面的引导程序
UCHAR Format[8]; //03H~0AH 厂商名和系统版本 OEM_ID
USHORT BytesPerSector; //0BH~0CH 每扇字节数,一般为512字节
UCHAR SectorsPerCluster; //0DH 每簇扇区数,对于FAT32的磁盘该字节一般为08H,既每簇为8H*512B=4K。
USHORT BootSectors; //0EH~0FH 保留扇区数
UCHAR Mbz1; //10H 磁盘FAT的个数,一般为2个
USHORT Mbz2; //11H~12H 对于FAT16的磁盘为根目录的最大目录项,对于FAT32的磁盘该值总为“00H 00H”
USHORT Reserved1; //13H~14H 对于软盘或早期小硬盘该处为分区总扇区数,对于硬盘一般此值为“00H 00H”
UCHAR MediaType; //15H 介质描述,对于1.44软盘此处长为“F0H”,对于硬盘此处长为“F8H”
USHORT Mbz3; //16H~17H 对于软盘或早期小硬盘该处为每个FAT占用的扇区数,对于硬盘一般此值为“00H 00H”
USHORT SectorsPerTrack; //18H~19H 每道扇区数,一般为“3FH 00H”,即每道有63个扇区
USHORT NumberOfHeads; //1AH~1BH 磁头数,一般为“FFH 00H”,即每个柱面有255个磁头
ULONG PartitionOffset; //1CH~1FH 隐含扇区数
ULONG Reserved2[2]; //20H~23H 对于大硬盘来说该处存放的是该分区占用的扇区数 未被NTFS使用
//24H~27H 对于大硬盘来说该处存放的是每个FAT占用的扇区数 未被NTFS使用
ULONGLONG TotalSectors; //28H~2fH 该分区扇区数
ULONGLONG MftStartLcn; //30H~37H $MFT文件的逻辑簇数
ULONGLONG Mft2StartLcn; //38h~3fH $MFTMirr文件的逻辑簇数
ULONG ClustersPerFileRecord; //40h~43h 每文件记录段簇数
ULONG ClustersPerIndexBlock; //44h~47h 每索引块簇数
ULONGLONG VolumeSerialNumber; //48h~4fh 分区逻辑序列号
ULONG CheckSum; //50h~54h 校验和
UCHAR Code[0x1AA]; //54h~1FDh Bootstrap Code
USHORT BootSignature; //1FEH~1FFH 结束标识,和上文提到的主引导区的结束标识一样为“55H AAH”
} BOOT_BLOCK, *PBOOT_BLOCK;
typedef struct{ //Offset Size Field Required Value for BitLocker
UINT8 Reserved[3];
UINT8 Signature[8]; //0x003 8 Signature ‘-‘,’F’,’V’,’E’,’-‘,’F’,’S’,’-‘
UINT16 BytesPerSector; //0x00B 2 BytesPerSector
UINT8 SectorsPerCluster; //0x00D 1 SectorsPerCluster One of 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40 or 0x80
UINT16 ReservedClusters; //0x00E 2 ReservedClusters 0x0000
UINT8 FatCount; //0x010 1 FatCount 0x00
UINT16 RootEntries; //0x011 2 RootEntries 0x0000
UINT16 Sectors; //0x013 2 Sectors 0x0000
UINT8 MediaType; //0x015 1 Media Type
UINT16 SectorsPerFat; //0x016 2 SectorsPerFat 0x0000
UINT16 SectorsPerTrack; //0x018 2 SectorsPerTrack
UINT16 NumberOfTrackHead; //0x1a 2 NumberOfTrackHead
UINT32 NumberOfHiddenSectors; //0x1c 4 NumberOfHiddenSectors
UINT32 LargeSectors; //0x020 4 LargeSectors 0x00000000
UINT16 NumberOfPhyDriver; //0x024 2
UINT8 SignOfExtBoot; //0x026 1
UINT32 SerialOfVolume; //0x027 4
UINT8 LabelOfVolume[11]; //0x02b 11
UINT16 SerialOfFileSystem; //0x036 2
UINT32 MetadataLcn[2]; //0x038 8 MetadataLcn
}BPB;
typedef struct _NTFS_BOOT_SECTOR
{
UINT8 Jumpto[3]; //00-02h
UINT8 OemID[8]; //03-0ah
UINT16 SecInByte; //0b-0ch 扇区字节数
UINT8 SecPerClr; //0dh 每簇扇区数
UINT16 ResSct; //0e-0fh 保留扇区数。
UINT8 NtRevers0[5]; //10-14h NTFS中不使用
UINT8 FormatID; //15h 磁盘格式代号
UINT16 SecPerFat; //16-17h 每FAT扇区数
UINT16 SecPerTrk; //18-19h 每磁道扇区数
UINT16 Sides; //1a-1bh 磁盘面数
UINT32 Hsector; //1c-1fh 隐藏扇区数 user
UINT32 BigTotalSec; //20-23h NT UNUSED
UINT32 BigSecPerFat; //24-27h NT UNUSED
UINT32 TotalSecLow; //28-2bh 分区中扇区总数
UINT32 TotalSecHigh; //2c-2fh
UINT32 MftBeginClustL;//30-33h 文件$MFT的逻辑簇号
UINT32 MftBeginClustH;//34-37h
UINT32 MirBeginClustL;//38-3bh 文件$MFTMirr的逻辑簇号
UINT32 MirBeginClustH;//3c-3fh
UINT32 ClustPerRec; //40-43h 每个文件记录块所占的簇数
UINT32 ClustPerIndex; //44-47h 每个索引块占的簇数
UINT32 NtSerialNoL; //48-4bh 分区序列号
UINT32 NtSerialNoH; //4c-4fh
UINT16 NtCheckSum; //50-53h 校验和
}NTFS_BOOT_SECTOR;
/*
00H 引导标识字节,其值只能为00H或80H,为00H时表示该分区不可引导,为80H时表示该分区可用于引导 。在许多诸如BOOT MAGIC之类的软件都是利用了这一原理,实现多操作系统引导的,了解了这一原理,你也可以写出你自己的多操作系统引导程序了。
01H 分区起始磁头号
02H 其高2位为分区起始柱面号的高位,底6位为分区起始扇区号
03H 分区起始柱面号的低位
04H 分区系统标志,当该值为00H时,表示此分区为不可识别的系统;为04H时该分区为FAT16分区;为05H或0FH该分区为扩展分区;为0B时该分区为 FAT32分区 ;为83H时表示该分区为Linux分区, 为07时该分区为NTFS分区等等。一些如PQMAGIC磁盘软件在隐藏分区操作时就是将此字节的内容保存后在把它改为00H。
05H 分区结束磁头号
06H 其高2位为分区结束柱面号的高位,底6位为分区结束扇区号
07H 分区结束柱面号的低位
08H~0BH 此4个字节为在线性寻址方式下的分区的扇区地址。当分区大于8G时,扩展INT13H是通过该信息进行寻址的,我们可以发现在这种方式下寻址最多可访问的空间为:FFFFFFFFH扇*512B/扇=2048G,也就是说我们用扩展INT13H最大可以访问的空间为2048G,这个数字现在对我们来说是非常大的,但谁都不能想象计算机的发展之快,到时到底要如何来突破这个限制呢?现在谁也不知道。注意:此4个字节是从高位到低位排列的!例如我的分区表第一个分区项此4字节的内容为“3FH 00H 00H 00H”,它代表该分区是从0000003FH开始的,也就是从线性地址63扇开始的(线性地址把硬盘的第一个扇记为0H扇)
0CH~0FH 此4个字节为以扇区为单位的该分区大小(总扇区数),此4个字节同样是从高位到低位排列的
*/
typedef struct{
UINT8 Flag; //00h
UINT8 StartTrack; //01h
UINT8 StartSector; //02h
UINT8 StartCylinder; //03h
UINT8 SysFlag; //04h
UINT8 EndTrack; //05h
UINT8 EndSector; //06h
UINT8 EndCylinder; //07h
UINT32 SectorAddress; //08h
UINT32 NumberOfSector; //0ch
}DISK_PART;
#pragma pack()
char dispFormatStr[]="\n %21s : %s";
char dispFormatInt[]="\n %21s : %Xh";
char dispFormatIntD[]="\n %21s : %d";
char dispFormatIntL[]="\n %21s : %ld";
char dispFormatIntH[]="\n %21s : %lXh";
char buf[256];
char hexArr[]="0123456789ABCDEF";
char *bin2string(int length, unsigned char dat[])
{
int i,j;
for(i=0,j=0; i<length; i++)
{
buf[j++] = hexArr[(dat[i]>>4)&0x0f];
buf[j++] = hexArr[dat[i]&0x0f];
}
buf[j] = '\0';
return buf;
}
char *getString(int length, unsigned char dat[])
{
int i;
for(i=0; i<length; i++)
{
buf[i] = dat[i];
}
buf[i] = '\0';
return buf;
}
void dump_BIOS_PARAMETER_BLOCK(BIOS_PARAMETER_BLOCK *pBPB)
{
uint64 totalSize=0;
if(pBPB == NULL)
return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -