主引导记录(MBR)信息分析与获取

前段时间在安装黑苹果时,发现一个问题,电脑在启动时,会找激活分区,如果没有找到,那就启动不起来。

那能否写个小程序读取一下MBR信息,把激活分区换成其它,搞点恶作剧呢,于是就有了这篇读取MBR信息的文章,但是没写入,不敢尝试。

通过动手学习,对硬盘MBR信息有了更好的了解。

1、我的硬盘主引导记录信息及分析

80 01 01 00 07 FE FF FF 3F 00 00 00 0D F0 BF 03(主分区)
偏移00H---80---激活标志---表示可引导
偏移01H---01---表示分区开始的磁头号为1
偏移02H---01---转换为二进制后为8位,0-5位表示该分区的起始扇区号---此处为1
偏移03H---00---02H的6-7位与03H的全部8位,共10位,组成起始磁柱号---此处为0
偏移04H---07---表示文件系统类型NTFS。
偏移05H---FE---转换为十进制254,表示分区结束的磁头号为254
偏移06H---FF---转换为二进制1111 1111,0-5位即3F,十进制下的63---该分区的结束扇区号为63。
偏移07H---FF---与06H的6-7位10合起来为3FF,即十进制下的1023---该分区的结束磁柱号为1023。
偏移08H、09H、0AH,0BH---3F 00 00 00---为分区起始相对扇区号63
偏移0CH、0DH、0EH,0FH---0D F0 BF 03---为分区总的扇区数3BFF00D,转换为十进制为62910477。

00 FE FF FF 05 FE FF FF 4C F0 BF 03 75 E6 82 21(扩展分区)
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(MBR的结束标志位)
从上面可以看出MBR开分区结构最多只能识别4个主要分区,但是为什么我们的电脑上可以分4个以上的盘呢?
这是因为一般电脑上是一个主分区,一个扩展分区,在扩展分区中又分的逻辑分区(扩展分区中可以有多个逻辑分区)


2、获取相关信息的代码(Win7下,请以管理员身份运行)

//基于http://www.cnblogs.com/onepc/archive/2011/12/01/2270468.html来修改的。
//在此感谢此博友
//2012.10.10
#include <iostream>
#include <windows.h>
using namespace std;

#pragma pack(1) //字节对齐
typedef struct _PARTITION_ENTRY//分区表结构
{
    UCHAR active; //状态(是否被激活)   重要
    UCHAR StartHead; //分区起始磁头号   
    USHORT StartSecCyli; //与63相位与得出的是开始扇区,把它右移6位就是开始柱面
    UCHAR PartitionType; // 分区类型   重要 
    UCHAR EndHead; //分区结束磁头号
    USHORT EndSecCyli; //与63相位与得出的就是结束扇区,把它右移6位就是结束柱面
    ULONG StartLBA; // 扇区起始逻辑地址(相对扇区号)   重要
    ULONG TotalSector; // 分区大小      重要
} PARTITION_ENTRY, *PPARTITION_ENTRY;

//引导区512BYTE结构
typedef struct _MBR_SECTOR
{
    UCHAR BootCode[440];//启动记录440 Byte
    ULONG DiskSignature;//磁盘签名
    USHORT NoneDisk;//二个字节
    PARTITION_ENTRY Partition[4];//分区表结构64 Byte
    USHORT Signature;//结束标志2 Byte 55 AA
} MBR_SECTOR, *PMBR_SECTOR;

#pragma pack()

int main()
{
	TCHAR szDevicename[64]={0};
	MBR_SECTOR _ReadMbr;
	wsprintf(szDevicename,L"\\\\.\\PHYSICALDRIVE0");
	HANDLE hDevice=CreateFile(szDevicename,GENERIC_READ|GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
	if(hDevice==INVALID_HANDLE_VALUE)
	{
		cout<<"打开设备出错"<<endl;
		return -1;
	}
	memset(&_ReadMbr,0,sizeof(MBR_SECTOR));
	DWORD leng=512;
	DWORD count;
	DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&count,NULL);
	UCHAR sz[512]={0};
	//ReadFile(hDevice,sz,512,&leng,NULL);
	BOOL bcheck=ReadFile(hDevice,&_ReadMbr,512,&leng,NULL);
	memcpy(sz,&_ReadMbr,512);
	for(int i=0;i<66;i++)
	{
		printf("%02X ",sz[446+i]);
		if((i+1)%16==0)
			printf("\n");
	}
	printf("\n");
	if(bcheck==FALSE && leng<512)
	{
		cout<<"读取MBR出错!"<<endl;
		DeviceIoControl(hDevice,FSCTL_UNLOCK_VOLUME,NULL,0,NULL,0,&count,NULL);
		CloseHandle(hDevice);
		return -1;
	}
	char *szTemp=new char[64];
	for(int i=0;i<4;i++)
	{
		if(_ReadMbr.Partition[i].PartitionType==0)
		{
			continue;
		}
		memset(szTemp,0,64);
		if(_ReadMbr.Partition[i].active==128)
		{
			cout<<"激活分区"<<endl;
		}else
			cout<<"非激活分区"<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"激活分区标志位:%02X",_ReadMbr.Partition[i].active);
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"分区起始磁头号:%d",_ReadMbr.Partition[i].StartHead);
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        int temp = _ReadMbr.Partition[i].StartSecCyli;
        sprintf(szTemp,"分区起始扇区号:%d",temp & 63);//63转为二进制111111,做&运算,只取低6位
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"分区起始磁柱号:%d",temp>>6);//取高10位
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"分区文件类型标识:%02d",_ReadMbr.Partition[i].PartitionType);
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"分区结束磁头号:%d",_ReadMbr.Partition[i].EndHead);
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        temp = _ReadMbr.Partition[i].EndSecCyli;
        sprintf(szTemp,"分区结束扇区号:%d",temp & 63);
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"分区结束磁柱号:%d",temp>>6);
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"分区起始相对扇区号:%d",_ReadMbr.Partition[i].StartLBA);
        cout<<szTemp<<endl;
        memset(szTemp,0,64);
        sprintf(szTemp,"分区总的扇区数:%d",_ReadMbr.Partition[i].TotalSector);
        cout<<szTemp<<endl;
	}
	DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &count, NULL);
    CloseHandle(hDevice);
	system("pause");
	return 0;
}




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值