天天看點

Linux系統的機器上檢視MBR資料 (續)1. 概述 2. 疊代1:讀MBR所在第一個扇區的資料3. 疊代2:領域無關代碼的重構4. 疊代3:MBR領域模組化5. 疊代4:自動分析裝置名稱

1. 概述

在 Linux系統的機器上檢視MBR資料 一文中,通過指令的方式給出了Linux下面MBR的資料示例,其中對MBR中每個資料結構的讀取&解析也是人工方式的。本文繼續該内容,但通過代碼自動分析MBR各個字段的内容。

本文編碼所在的環境和上篇不同,是以MBR資料和上文存在差異。

2. 疊代1:讀MBR所在第一個扇區的資料

本文采用靈活開發的模式,一步步給出問題的最終解決方案。

作為第一步,要能夠讀取到硬碟的第一個扇區,即MBR資料。至于資料解析,我們留到下一個疊代。

2.1 代碼

下面是讀取MBR的代碼:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
	int fd = -1;
	const unsigned int SECTOR_SIZE = 512;
	unsigned char buf[SECTOR_SIZE];
	ssize_t read_count;
	const char* DEV_NAME = "/dev/sda";

	fd = open(DEV_NAME, O_RDONLY);
	if (fd == -1) {
		printf("Open file failed.\n");
		return -1;
	}

	read_count = read(fd, buf, SECTOR_SIZE);
	if (read_count != SECTOR_SIZE) {
		printf("Read error: %d\n", read_count);
		close(fd);
		return -1;
	}

	printf("\n\n Addr  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
	for (ssize_t i = 0; i < SECTOR_SIZE; i++) {
		if (i % 16 == 0) {
			printf("\n0x%04X ", i);
		}

		printf("%02X ", buf[i]);
	}
	
	printf("\n");
	close(fd);
	return 0;
}
           

2.2 運作

[email protected]:~/examples/cpp/read_mbr$ gcc -std=c99 main.c
[email protected]:~/examples/cpp/read_mbr$ sudo ./a.out 


 Addr  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

0x0000 EB 63 90 00 02 8E D7 BC 00 7A BB A0 07 8B CE 8E 
0x0010 DB 8E C3 F3 A4 EA 5D 00 A0 07 10 00 01 00 00 7A 
0x0020 00 00 00 00 00 00 00 00 00 00 07 66 8B 55 08 B4 
0x0030 42 C6 06 1F 00 7C 32 C0 66 89 16 22 00 BE 1A 00 
0x0040 B2 80 CD 13 0F 82 CD 00 81 3E FE 03 55 AA C3 AC 
0x0050 0A C0 74 FA B4 0E BB 07 00 CD 00 80 01 00 00 00 
0x0060 00 00 00 00 FF FA 90 90 F6 C2 80 74 05 F6 C2 70 
0x0070 74 02 B2 80 EA 79 7C 00 00 31 C0 8E D8 8E D0 BC 
0x0080 00 20 FB A0 64 7C 3C FF 74 02 88 C2 52 BB 17 04 
0x0090 80 27 03 74 06 BE 88 7D E8 17 01 BE 05 7C B4 41 
0x00A0 BB AA 55 CD 13 5A 52 72 3D 81 FB 55 AA 75 37 83 
0x00B0 E1 01 74 32 31 C0 89 44 04 40 88 44 FF 89 44 02 
0x00C0 C7 04 10 00 66 8B 1E 5C 7C 66 89 5C 08 66 8B 1E 
0x00D0 60 7C 66 89 5C 0C C7 44 06 00 70 B4 42 CD 13 72 
0x00E0 05 BB 00 70 EB 76 B4 08 CD 13 73 0D F6 C2 80 0F 
0x00F0 84 D0 00 BE 93 7D E9 82 00 66 0F B6 C6 88 64 FF 
0x0100 40 66 89 44 04 0F B6 D1 C1 E2 02 88 E8 88 F4 40 
0x0110 89 44 08 0F B6 C2 C0 E8 02 66 89 04 66 A1 60 7C 
0x0120 66 09 C0 75 4E 66 A1 5C 7C 66 31 D2 66 F7 34 88 
0x0130 D1 31 D2 66 F7 74 04 3B 44 08 7D 37 FE C1 88 C5 
0x0140 30 C0 C1 E8 02 08 C1 88 D0 5A 88 C6 BB 00 70 8E 
0x0150 C3 31 DB B8 01 02 CD 13 72 1E 8C C3 60 1E B9 00 
0x0160 01 8E DB 31 F6 BF 00 80 8E C6 FC F3 A5 1F 61 FF 
0x0170 26 5A 7C BE 8E 7D EB 03 BE 9D 7D E8 34 00 BE A2 
0x0180 7D E8 2E 00 CD 18 EB FE 47 52 55 42 20 00 47 65 
0x0190 6F 6D 00 48 61 72 64 20 44 69 73 6B 00 52 65 61 
0x01A0 64 00 20 45 72 72 6F 72 0D 0A 00 BB 01 00 B4 0E 
0x01B0 CD 10 AC 3C 00 75 F4 C3 32 F2 49 15 00 00 80 01 
0x01C0 01 00 07 EF FF FF 3F 00 00 00 D0 88 81 1D 00 FE 
0x01D0 FF FF 05 FE FF FF FE 8F 81 1D 02 60 07 1C 00 EF 
0x01E0 FF FF 07 EF FF FF 10 F1 88 39 80 57 AF 00 00 00 
0x01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA 
[email protected]:~/examples/cpp/read_mbr$ 
           

初步地分析這個碼流,我們知道已成功讀取MBR的資料,比如最後的55 AA;再倒數的每16個位元組一組的MBR Partition Record。進一步地,可以用上一節的指令做對比:

[email protected]:~/examples/cpp/read_mbr$ sudo dd if=/dev/sda ibs=512 count=1 | hexdump -C
00000000  eb 63 90 00 02 8e d7 bc  00 7a bb a0 07 8b ce 8e  |.c.......z......|
00000010  db 8e c3 f3 a4 ea 5d 00  a0 07 10 00 01 00 00 7a  |......]........z|
00000020  00 00 00 00 00 00 00 00  00 00 07 66 8b 55 08 b4  |...........f.U..|
00000030  42 c6 06 1f 00 7c 32 c0  66 89 16 22 00 be 1a 00  |B....|2.f.."....|
00000040  b2 80 cd 13 0f 82 cd 00  81 3e fe 03 55 aa c3 ac  |.........>..U...|
00000050  0a c0 74 fa b4 0e bb 07  00 cd 00 80 01 00 00 00  |..t.............|
00000060  00 00 00 00 ff fa 90 90  f6 c2 80 74 05 f6 c2 70  |...........t...p|
00000070  74 02 b2 80 ea 79 7c 00  00 31 c0 8e d8 8e d0 bc  |t....y|..1......|
00000080  00 20 fb a0 64 7c 3c ff  74 02 88 c2 52 bb 17 04  |. ..d|<.t...R...|
00000090  80 27 03 74 06 be 88 7d  e8 17 01 be 05 7c b4 41  |.'.t...}.....|.A|
000000a0  bb aa 55 cd 13 5a 52 72  3d 81 fb 55 aa 75 37 83  |..U..ZRr=..U.u7.|
000000b0  e1 01 74 32 31 c0 89 44  04 40 88 44 ff 89 44 02  |[email protected].|
000000c0  c7 04 10 00 66 8b 1e 5c  7c 66 89 5c 08 66 8b 1e  |....f..\|f.\.f..|
000000d0  60 7c 66 89 5c 0c c7 44  06 00 70 b4 42 cd 13 72  |`|f.\..D..p.B..r|
000000e0  05 bb 00 70 eb 76 b4 08  cd 13 73 0d f6 c2 80 0f  |...p.v....s.....|
000000f0  84 d0 00 be 93 7d e9 82  00 66 0f b6 c6 88 64 ff  |.....}...f....d.|
00000100  40 66 89 44 04 0f b6 d1  c1 e2 02 88 e8 88 f4 40  |@f.D...........@|
00000110  89 44 08 0f b6 c2 c0 e8  02 66 89 04 66 a1 60 7c  |.D.......f..f.`||
00000120  66 09 c0 75 4e 66 a1 5c  7c 66 31 d2 66 f7 34 88  |f..uNf.\|f1.f.4.|
00000130  d1 31 d2 66 f7 74 04 3b  44 08 7d 37 fe c1 88 c5  |.1.f.t.;D.}7....|
00000140  30 c0 c1 e8 02 08 c1 88  d0 5a 88 c6 bb 00 70 8e  |0........Z....p.|
00000150  c3 31 db b8 01 02 cd 13  72 1e 8c c3 60 1e b9 00  |.1......r...`...|
00000160  01 8e db 31 f6 bf 00 80  8e c6 fc f3 a5 1f 61 ff  |...1..........a.|
00000170  26 5a 7c be 8e 7d eb 03  be 9d 7d e8 34 00 be a2  |&Z|..}....}.4...|
00000180  7d e8 2e 00 cd 18 eb fe  47 52 55 42 20 00 47 65  |}.......GRUB .Ge|
00000190  6f 6d 00 48 61 72 64 20  44 69 73 6b 00 52 65 61  |om.Hard Disk.Rea|
000001a0  64 00 20 45 72 72 6f 72  0d 0a 00 bb 01 00 b4 0e  |d. Error........|
000001b0  cd 10 ac 3c 00 75 f4 c3  32 f2 49 15 00 00 80 01  |...<.u..2.I.....|
000001c0  01 00 07 ef ff ff 3f 00  00 00 d0 88 81 1d 00 fe  |......?.........|
000001d0  ff ff 05 fe ff ff fe 8f  81 1d 02 60 07 1c 00 ef  |...........`....|
000001e0  ff ff 07 ef ff ff 10 f1  88 39 80 57 af 00 00 00  |.........9.W....|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
記錄了1+0 的讀入
記錄了1+0 的寫出
512位元組(512 B)已複制,0.00250075 秒,205 kB/秒
00000200
[email protected]:~/examples/cpp/read_mbr$ 
           

2.3 幾個問題分析

1. 在上面的代碼中,有一大段是輸出碼流的代碼,而且這個功能也相對獨立。是以需要把這一部分代碼重構到一個獨立的函數中。

2. 再者,對裝置檔案是寫死的,是以如果能夠參數化,則更加靈活。再進一步,如果能夠自動識别MBR所在的裝置名稱,代碼就更具有可移植性。

3. MBR中每一個組成部分還沒有自動分析出來,是以需要增加結構化分析。

接下來就是通過每一個疊代來實作上述功能。

3. 疊代2:領域無關代碼的重構

這一步,我們把和讀取&解析MBR無關的代碼分離出去,也就是把輸出二進制碼流部分的代碼利用Extract Method手法提取出去。

另外從現在開始,我們從C切換到C++。此時代碼包括如下幾個檔案:

  • main.cpp:領域代碼;
  • file-utils.h:提取出來的列印二進制碼流的實用小函數,頭檔案;
  • file-tuils.cpp:使用小函數的實作檔案。

3.1 main.cpp

#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <file-utils.h>

int main() 
{
    int fd = -1;
    const unsigned int SECTOR_SIZE = 512;
    unsigned char buf[SECTOR_SIZE];
    ssize_t read_count;
    const char* DEV_NAME = "/dev/sda";

    fd = open(DEV_NAME, O_RDONLY);
    if (fd == -1) {
        printf("Open file failed.\n");
        return -1;
    }

    read_count = read(fd, buf, SECTOR_SIZE);
    if (read_count != SECTOR_SIZE) {
        printf("Read error: %d\n", read_count);
        close(fd);
        return -1;
    }

    dump_binary(buf, SECTOR_SIZE);

    close(fd);
    return 0;
}

           

3.2 file-utils.h

/*
 * File utilities.
 * 
 */
#ifndef __FILE_UTILS_H
#define __FILE_UTILS_H

/*
 * Dump the binary stream.
 * 16 bytes each line.
 */
void dump_binary(unsigned char *buf, unsigned int len);

#endif //__FILE_UTILS_H
           

3.3 file-utils.cpp

#include <file-utils.h>

#include <cstdio>

void dump_binary(unsigned char *buf, unsigned int len) 
{
    printf("\n\n Addr  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
    for (unsigned int i = 0; i < len; i++) {
        if (i % 16 == 0) {
            printf("\n0x%04X ", i);
        }

        printf("%02X ", buf[i]);
    }

    printf("\n\n");
}
           

3.4 編譯&運作

[email protected]:~/examples/cpp/read_mbr$ g++ main.cpp file-utils.cpp -I.
[email protected]:~/examples/cpp/read_mbr$ sudo ./a.out 


 Addr  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

0x0000 EB 63 90 00 02 8E D7 BC 00 7A BB A0 07 8B CE 8E 
0x0010 DB 8E C3 F3 A4 EA 5D 00 A0 07 10 00 01 00 00 7A 
0x0020 00 00 00 00 00 00 00 00 00 00 07 66 8B 55 08 B4 
0x0030 42 C6 06 1F 00 7C 32 C0 66 89 16 22 00 BE 1A 00 
0x0040 B2 80 CD 13 0F 82 CD 00 81 3E FE 03 55 AA C3 AC 
0x0050 0A C0 74 FA B4 0E BB 07 00 CD 00 80 01 00 00 00 
0x0060 00 00 00 00 FF FA 90 90 F6 C2 80 74 05 F6 C2 70 
0x0070 74 02 B2 80 EA 79 7C 00 00 31 C0 8E D8 8E D0 BC 
0x0080 00 20 FB A0 64 7C 3C FF 74 02 88 C2 52 BB 17 04 
0x0090 80 27 03 74 06 BE 88 7D E8 17 01 BE 05 7C B4 41 
0x00A0 BB AA 55 CD 13 5A 52 72 3D 81 FB 55 AA 75 37 83 
0x00B0 E1 01 74 32 31 C0 89 44 04 40 88 44 FF 89 44 02 
0x00C0 C7 04 10 00 66 8B 1E 5C 7C 66 89 5C 08 66 8B 1E 
0x00D0 60 7C 66 89 5C 0C C7 44 06 00 70 B4 42 CD 13 72 
0x00E0 05 BB 00 70 EB 76 B4 08 CD 13 73 0D F6 C2 80 0F 
0x00F0 84 D0 00 BE 93 7D E9 82 00 66 0F B6 C6 88 64 FF 
0x0100 40 66 89 44 04 0F B6 D1 C1 E2 02 88 E8 88 F4 40 
0x0110 89 44 08 0F B6 C2 C0 E8 02 66 89 04 66 A1 60 7C 
0x0120 66 09 C0 75 4E 66 A1 5C 7C 66 31 D2 66 F7 34 88 
0x0130 D1 31 D2 66 F7 74 04 3B 44 08 7D 37 FE C1 88 C5 
0x0140 30 C0 C1 E8 02 08 C1 88 D0 5A 88 C6 BB 00 70 8E 
0x0150 C3 31 DB B8 01 02 CD 13 72 1E 8C C3 60 1E B9 00 
0x0160 01 8E DB 31 F6 BF 00 80 8E C6 FC F3 A5 1F 61 FF 
0x0170 26 5A 7C BE 8E 7D EB 03 BE 9D 7D E8 34 00 BE A2 
0x0180 7D E8 2E 00 CD 18 EB FE 47 52 55 42 20 00 47 65 
0x0190 6F 6D 00 48 61 72 64 20 44 69 73 6B 00 52 65 61 
0x01A0 64 00 20 45 72 72 6F 72 0D 0A 00 BB 01 00 B4 0E 
0x01B0 CD 10 AC 3C 00 75 F4 C3 32 F2 49 15 00 00 80 01 
0x01C0 01 00 07 EF FF FF 3F 00 00 00 D0 88 81 1D 00 FE 
0x01D0 FF FF 05 FE FF FF FE 8F 81 1D 02 60 07 1C 00 EF 
0x01E0 FF FF 07 EF FF FF 10 F1 88 39 80 57 AF 00 00 00 
0x01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA 

[email protected]:~/examples/cpp/read_mbr$ 
           

4. 疊代3:MBR領域模組化

前面的示範,僅列印了第一個扇區的碼流,具體内容是我們根據MBR格式,去查找對應位置的二進制資料。接下來我們對MBR模組化,即對MBR所在第一個扇區的内容重構到對應的資料結構中。

此時新增了mbr.h,.cpp,并對main.cpp進行了重構。同時,我們重用了 Windows上面讀磁盤分區表 一文中的代碼。

4.1 mbr.h

#ifndef __MBR_H
#define __MBR_H

struct CHS {  
    unsigned int header;  
    unsigned int sector;   
    unsigned int cylinder;  
};  

struct partition_record {  
    unsigned char boot_indicator;  
    unsigned char os_type;  
    struct CHS starting_chs;  
    struct CHS ending_chs;  
    unsigned int starting_LBA;  
    unsigned int size_in_LBA;  
};  

const unsigned int BOOT_LOADER_CODE_SIZE = 446;


struct mbr {
    unsigned char boot_loader_code[BOOT_LOADER_CODE_SIZE];
    struct partition_record partition_records[4];
};

/*
buffer: the 512-bytes of first sector.
        The caller ensure that it is the right data.

return: 0 - SUCCESS.
        -1: invalid mbr, i.e. the signature is not 0xaa55.
*/
int get_mbr(unsigned char buffer[], struct mbr &mbr);

#endif //__MBR_H
           

4.2 mbr.cpp

#include "mbr.h"

#include <cstdio>
#include <cstring> //memcpy
#include "file-utils.h"

static void dump_partition_record(const partition_record& record) 
{  
    const double DISK_SECTOR_SIZE = 512.0;  
    const size_t GB = 1024 * 1024 * 1024;  
  
    printf(  
        "\tboot indicator: 0x%02x\n"  
        "\tOS Type: 0x%02x\n"  
        "\tStarting CHS: (%d, %d, %d)\n"  
        "\tEnding_CHS: (%d, %d, %d)\n"  
        "\tSize in LBA: %d\n"  
        "\tSize:%.2f\n\n",  
        record.boot_indicator,   
        record.os_type,   
        record.starting_chs.cylinder,  
        record.starting_chs.header,  
        record.starting_chs.sector,  
        record.ending_chs.cylinder,  
        record.ending_chs.header,  
        record.ending_chs.sector,  
        record.size_in_LBA,  
        record.size_in_LBA * DISK_SECTOR_SIZE / GB);  
}  
  
// transform the 16-bytes buffer to partition record  
static void get_partition_record(unsigned char buffer[], struct partition_record& record) 
{  
    record.boot_indicator = buffer[0];  
  
    record.starting_chs.header = buffer[1];  
    record.starting_chs.sector = buffer[2] & 0x3f;  
    record.starting_chs.cylinder = (((buffer[2] & 0xff) >> 6) << 8) + buffer[3];  
  
    record.os_type = buffer[4];  
  
    record.ending_chs.header = buffer[5];  
    record.ending_chs.sector = buffer[6] & 0x3f;  
    record.ending_chs.cylinder = (((buffer[6] & 0xff) >> 6) << 8) + buffer[7];  
  
    record.size_in_LBA = *(unsigned int*)(buffer + 12);  
}

int get_mbr(unsigned char buffer[], struct mbr &mbr) 
{
    // check the signature, it must be 0xaa55
    const unsigned int SIGNATURE_OFFSET = 510;
    if (buffer[SIGNATURE_OFFSET] != 0x55 && buffer[SIGNATURE_OFFSET + 1] != 0xaa) {
        printf("ERROR: invalid mbr!\n");
        return -1;
    }

    memcpy(mbr.boot_loader_code, buffer, BOOT_LOADER_CODE_SIZE);
    printf("boot loader:");
    dump_binary(mbr.boot_loader_code, BOOT_LOADER_CODE_SIZE);

    unsigned char *partition_record = buffer + BOOT_LOADER_CODE_SIZE;
    const unsigned int PARTITION_RECORD_SIZE = 16;

    for (unsigned int i = 0; i < 4; i++) {
      get_partition_record(
            buffer + BOOT_LOADER_CODE_SIZE + i * PARTITION_RECORD_SIZE, 
            mbr.partition_records[0]);  
      dump_partition_record(mbr.partition_records[0]);  
    }

    return 0;
}
           

4.3 main.cpp

#include <cstdio>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include "mbr.h"

int main() 
{
    int fd = -1;
    const unsigned int SECTOR_SIZE = 512;
    unsigned char buf[SECTOR_SIZE];
    ssize_t read_count;
    const char* DEV_NAME = "/dev/sda";

    fd = open(DEV_NAME, O_RDONLY);
    if (fd == -1) {
        printf("Open file failed.\n");
        return -1;
    }

    read_count = read(fd, buf, SECTOR_SIZE);
    if (read_count != SECTOR_SIZE) {
        printf("Read error: %d\n", read_count);
        close(fd);
        return -1;
    }

    struct mbr mbr = {0};

    get_mbr(buf, mbr);

    close(fd);
    return 0;
}

           

4.4 運作結果

[email protected]:~/examples/cpp/read_mbr$ g++ main.cpp file-utils.cpp mbr.cpp -I.
[email protected]:~/examples/cpp/read_mbr$ sudo ./a.out 
boot loader:

 Addr  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

0x0000 EB 63 90 00 02 8E D7 BC 00 7A BB A0 07 8B CE 8E 
0x0010 DB 8E C3 F3 A4 EA 5D 00 A0 07 10 00 01 00 00 7A 
0x0020 00 00 00 00 00 00 00 00 00 00 07 66 8B 55 08 B4 
0x0030 42 C6 06 1F 00 7C 32 C0 66 89 16 22 00 BE 1A 00 
0x0040 B2 80 CD 13 0F 82 CD 00 81 3E FE 03 55 AA C3 AC 
0x0050 0A C0 74 FA B4 0E BB 07 00 CD 00 80 01 00 00 00 
0x0060 00 00 00 00 FF FA 90 90 F6 C2 80 74 05 F6 C2 70 
0x0070 74 02 B2 80 EA 79 7C 00 00 31 C0 8E D8 8E D0 BC 
0x0080 00 20 FB A0 64 7C 3C FF 74 02 88 C2 52 BB 17 04 
0x0090 80 27 03 74 06 BE 88 7D E8 17 01 BE 05 7C B4 41 
0x00A0 BB AA 55 CD 13 5A 52 72 3D 81 FB 55 AA 75 37 83 
0x00B0 E1 01 74 32 31 C0 89 44 04 40 88 44 FF 89 44 02 
0x00C0 C7 04 10 00 66 8B 1E 5C 7C 66 89 5C 08 66 8B 1E 
0x00D0 60 7C 66 89 5C 0C C7 44 06 00 70 B4 42 CD 13 72 
0x00E0 05 BB 00 70 EB 76 B4 08 CD 13 73 0D F6 C2 80 0F 
0x00F0 84 D0 00 BE 93 7D E9 82 00 66 0F B6 C6 88 64 FF 
0x0100 40 66 89 44 04 0F B6 D1 C1 E2 02 88 E8 88 F4 40 
0x0110 89 44 08 0F B6 C2 C0 E8 02 66 89 04 66 A1 60 7C 
0x0120 66 09 C0 75 4E 66 A1 5C 7C 66 31 D2 66 F7 34 88 
0x0130 D1 31 D2 66 F7 74 04 3B 44 08 7D 37 FE C1 88 C5 
0x0140 30 C0 C1 E8 02 08 C1 88 D0 5A 88 C6 BB 00 70 8E 
0x0150 C3 31 DB B8 01 02 CD 13 72 1E 8C C3 60 1E B9 00 
0x0160 01 8E DB 31 F6 BF 00 80 8E C6 FC F3 A5 1F 61 FF 
0x0170 26 5A 7C BE 8E 7D EB 03 BE 9D 7D E8 34 00 BE A2 
0x0180 7D E8 2E 00 CD 18 EB FE 47 52 55 42 20 00 47 65 
0x0190 6F 6D 00 48 61 72 64 20 44 69 73 6B 00 52 65 61 
0x01A0 64 00 20 45 72 72 6F 72 0D 0A 00 BB 01 00 B4 0E 
0x01B0 CD 10 AC 3C 00 75 F4 C3 32 F2 49 15 00 00 

	boot indicator: 0x80
	OS Type: 0x07
	Starting CHS: (0, 1, 1)
	Ending_CHS: (1023, 239, 63)
	Size in LBA: 495028432
	Size:236.05

	boot indicator: 0x00
	OS Type: 0x05
	Starting CHS: (1023, 254, 63)
	Ending_CHS: (1023, 254, 63)
	Size in LBA: 470245378
	Size:224.23

	boot indicator: 0x00
	OS Type: 0x07
	Starting CHS: (1023, 239, 63)
	Ending_CHS: (1023, 239, 63)
	Size in LBA: 11491200
	Size:5.48

	boot indicator: 0x00
	OS Type: 0x00
	Starting CHS: (0, 0, 0)
	Ending_CHS: (0, 0, 0)
	Size in LBA: 0
	Size:0.00

[email protected]:~/examples/cpp/read_mbr$ 
           

可以看到,和 Windows上面讀磁盤分區表 一文的partition record資料一樣,但boot loader不一樣。這是因為在windows系統上,後來裝成了雙系統,是以更新了boot loader。

5. 疊代4:自動分析裝置名稱

前面的代碼中,裝置名稱是hard code成/dev/sda。但不同的環境可能并不都是這個裝置名稱,比如雙硬碟的情況,還可能MBR在sdb上面。為此,可否自動分析出MBR所在裝置名稱呢?接下來就實作這個功能。

繼續閱讀