Overview of the Master Boot Record

One of the most important parts of the computer is the Master Boot Record (MBR).  This little known hero is responsible for starting our operating systems – without it your Windows or Linux operating systems would not start.  In this post one will attempt to explain how the Master Boot Record is structured and how it works.  The post is an education for me, as what I’m about to write has been freshly researched due to my odd impulse to give the MBR its five minutes of glory.

The Basic Input Output System (BIOS)

The BIOS, or, Basic Input Output System is built into PC-compatible computers.  It it responsible for detecting the primary boot device such as hard drives, CD drives, legacy Floppy Disks, or even USB sticks (among other things).

With modern BIOS systems the boot order is configurable e.g.

BIOS boot order

If there is no suitable boot device the BIOS halts with a complaint like “Non-System disk or disk error.” e.g.

 

This may occur if your hard drive has failed, or,  it could simply mean the BIOS cannot locate a device with a valid MBR.   If an MBR is detected the BIOS will load and execute it.  The execution is achievable as part of the MBR contains machine code.  This machine code is executed; thus, the MBR takes control of the boot process from the BIOS.

The Anatomy of the MBR

The MBR occupies the first 512 bytes of the first sector (sector zero) of the boot device.  It is split into two sections.  The first section contains machine code known as the bootstrapping program and the second is reserved for the partition table of the disk.  The partition table contain information about how the hard drive is divided into partitions and the type of each.  For example, a common Windows partition table would specify a drive has having two partitions.  This first would be the partition to hold Windows itself and would span the majority of the disk and its type would be NTFS or FAT32. The second partition would normally contain a recovery partition for reverting the first partition back to the ‘factory default’. Instead of going over the theory and defining what each byte means within the 512 bytes, I am going to skip all that and do some practical.

Using the Linux dd command to back-up an MBR to file.  We can then have a look at the back-up file to reveal the MBR’s internals.  The MBR I’m going to dissect will be taken from a default CentOS 5 installation. To make a back-up of the MBR run the following Linux command:

[root@localhost ~]# dd if=/dev/sda bs=1 count=512 of=MBR
512+0 records in
512+0 records out
512 bytes (512 B) copied, 0.0200664 s, 25.5 kB/s

We can now look at the content of the MBR with hexdump:

[root@localhost ~]# hexdump -C MBR
00000000  eb 48 90 10 8e d0 bc 00  b0 b8 00 00 8e d8 8e c0  |.H..............|
00000010  fb be 00 7c bf 00 06 b9  00 02 f3 a4 ea 21 06 00  |...|.........!..|
00000020  00 be be 07 38 04 75 0b  83 c6 10 81 fe fe 07 75  |....8.u........u|
00000030  f3 eb 16 b4 02 b0 01 bb  00 7c b2 80 8a 74 03 02  |.........|...t..|
00000040  ff 00 00 20 01 00 00 00  00 02 fa 90 90 f6 c2 80  |... ............|
00000050  75 02 b2 80 ea 59 7c 00  00 31 c0 8e d8 8e d0 bc  |u....Y|..1......|
00000060  00 20 fb a0 40 7c 3c ff  74 02 88 c2 52 f6 c2 80  |. ..@|<.t...R...|
00000070  74 54 b4 41 bb aa 55 cd  13 5a 52 72 49 81 fb 55  |tT.A..U..ZRrI..U|
00000080  aa 75 43 a0 41 7c 84 c0  75 05 83 e1 01 74 37 66  |.uC.A|..u....t7f|
00000090  8b 4c 10 be 05 7c c6 44  ff 01 66 8b 1e 44 7c c7  |.L...|.D..f..D|.|
000000a0  04 10 00 c7 44 02 01 00  66 89 5c 08 c7 44 06 00  |....D...f.\..D..|
000000b0  70 66 31 c0 89 44 04 66  89 44 0c b4 42 cd 13 72  |pf1..D.f.D..B..r|
000000c0  05 bb 00 70 eb 7d b4 08  cd 13 73 0a f6 c2 80 0f  |...p.}....s.....|
000000d0  84 f0 00 e9 8d 00 be 05  7c c6 44 ff 00 66 31 c0  |........|.D..f1.|
000000e0  88 f0 40 66 89 44 04 31  d2 88 ca c1 e2 02 88 e8  |..@f.D.1........|
000000f0  88 f4 40 89 44 08 31 c0  88 d0 c0 e8 02 66 89 04  |..@.D.1......f..|
00000100  66 a1 44 7c 66 31 d2 66  f7 34 88 54 0a 66 31 d2  |f.D|f1.f.4.T.f1.|
00000110  66 f7 74 04 88 54 0b 89  44 0c 3b 44 08 7d 3c 8a  |f.t..T..D.;D.}<.|
00000120  54 0d c0 e2 06 8a 4c 0a  fe c1 08 d1 8a 6c 0c 5a  |T.....L......l.Z|
00000130  8a 74 0b bb 00 70 8e c3  31 db b8 01 02 cd 13 72  |.t...p..1......r|
00000140  2a 8c c3 8e 06 48 7c 60  1e b9 00 01 8e db 31 f6  |*....H|`......1.|
00000150  31 ff fc f3 a5 1f 61 ff  26 42 7c be 7f 7d e8 40  |1.....a.&B|..}.@|
00000160  00 eb 0e be 84 7d e8 38  00 eb 06 be 8e 7d e8 30  |.....}.8.....}.0|
00000170  00 be 93 7d e8 2a 00 eb  fe 47 52 55 42 20 00 47  |...}.*...GRUB .G|
00000180  65 6f 6d 00 48 61 72 64  20 44 69 73 6b 00 52 65  |eom.Hard Disk.Re|
00000190  61 64 00 20 45 72 72 6f  72 00 bb 01 00 b4 0e cd  |ad. Error.......|
000001a0  10 ac 3c 00 75 f4 c3 00  00 00 00 00 00 00 00 00  |..<.u...........|
000001b0  00 00 00 00 00 00 00 00  cb b7 08 00 00 00 80 20  |............... |
000001c0  21 00 83 dd 1e 3f 00 08  00 00 00 a0 0f 00 00 dd  |!....?..........|
000001d0  1f 3f 8e fe ff ff 00 a8  0f 00 00 58 f0 00 00 00  |.?.........X....|
000001e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|
00000200

Unless you are C3PO we can’t gleam much from the above; however, there are clues this is a MBR. The most obvious clue is the string literal printed in the character representation on the right of the hexdump output. The phrase “GRUB”, pops up!

[root@localhost ~]# dd if=/dev/sda bs=1 count=512 of=MBR
512+0 records in
512+0 records out
512 bytes (512 B) copied, 0.0200664 s, 25.5 kB/s

We can now look at the content of the MBR with hexdump:

00000170  00 be 93 7d e8 2a 00 eb  fe 47 52 55 42 20 00 47  |...}.*...GRUB .G|
00000180  65 6f 6d 00 48 61 72 64  20 44 69 73 6b 00 52 65  |eom.Hard Disk.Re|
00000190  61 64 00 20 45 72 72 6f  72 00 bb 01 00 b4 0e cd  |ad. Error.......|

GRUB is a Multiboot boot loader commonly used to boot Linux systems. Thus, we can be fairly confident we are looking at the GRUB MBR! What else can we see. Well, to an untrained eye – such as mine – not much. However, if we were to obtain a collection of MBRs from various sources we may noticed some similarities.  Let’s looks at a Windows XP MBR.

[root@localhost ~]# hexdump -C MBR.win
00000000  33 c0 8e d0 bc 00 7c fb  50 07 50 1f fc be 1b 7c  |3.....|.P.P....||
00000010  bf 1b 06 50 57 b9 e5 01  f3 a4 cb bd be 07 b1 04  |...PW...........|
00000020  38 6e 00 7c 09 75 13 83  c5 10 e2 f4 cd 18 8b f5  |8n.|.u..........|
00000030  83 c6 10 49 74 19 38 2c  74 f6 a0 b5 07 b4 07 8b  |...It.8,t.......|
00000040  f0 ac 3c 00 74 fc bb 07  00 b4 0e cd 10 eb f2 88  |...}U.t..~..t..|
00000090  b7 07 eb a9 8b fc 1e 57  8b f5 cb bf 05 00 8a 56  |.......W.......V|
000000a0  00 b4 08 cd 13 72 23 8a  c1 24 3f 98 8a de 8a fc  |.....r#..$?.....|
000000b0  43 f7 e3 8b d1 86 d6 b1  06 d2 ee 42 f7 e2 39 56  |C..........B..9V|
000000c0  0a 77 23 72 05 39 46 08  73 1c b8 01 02 bb 00 7c  |.w#r.9F.s......||
000000d0  8b 4e 02 8b 56 00 cd 13  73 51 4f 74 4e 32 e4 8a  |.N..V...sQOtN2..|
000000e0  56 00 cd 13 eb e4 8a 56  00 60 bb aa 55 b4 41 cd  |V......V.`..U.A.|
000000f0  13 72 36 81 fb 55 aa 75  30 f6 c1 01 74 2b 61 60  |.r6..U.u0...t+a`|
00000100  6a 00 6a 00 ff 76 0a ff  76 08 6a 00 68 00 7c 6a  |j.j..v..v.j.h.|j|
00000110  01 6a 10 b4 42 8b f4 cd  13 61 61 73 0e 4f 74 0b  |.j..B....aas.Ot.|
00000120  32 e4 8a 56 00 cd 13 eb  d6 61 f9 c3 49 6e 76 61  |2..V.....a..Inva|
00000130  6c 69 64 20 70 61 72 74  69 74 69 6f 6e 20 74 61  |lid partition ta|
00000140  62 6c 65 00 45 72 72 6f  72 20 6c 6f 61 64 69 6e  |ble.Error loadin|
00000150  67 20 6f 70 65 72 61 74  69 6e 67 20 73 79 73 74  |g operating syst|
00000160  65 6d 00 4d 69 73 73 69  6e 67 20 6f 70 65 72 61  |em.Missing opera|
00000170  74 69 6e 67 20 73 79 73  74 65 6d 00 00 00 00 00  |ting system.....|
00000180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001b0  00 00 00 00 00 2c 44 63  61 2d 62 2d 00 00 80 01  |.....,Dca-b-....|
000001c0  01 00 07 fe ff ff 3f 00  00 00 9e a1 7f 01 00 00  |......?.........|
000001d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000001f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 55 aa  |..............U.|

If your visual matching skills are sharp, you may notice that the values held within position 000001fe and 000001ff for both MBRs match: both have the hexadecimal sequence 55 aa.  A quick poke around the MBR specification reveals that this is the MBR signature.  This sequence is sometimes referred to as the magic number and is always located at the end of the MBR.  Most tools reading the MBR will check to ensure this magic number is present.  Thus, its presence it fundamental.  Take for example the tool fdisk.  The following code was extracted from the open-source fdisk code repository.  The highlighted section enforces the importance of this signature:

/* A valid partition table sector ends in 0x55 0xaa */
static unsigned int
part_table_flag(unsigned char *b) {
        return ((unsigned int) b[510]) + (((unsigned int) b[511]) << 8);
}

int
valid_part_table_flag(unsigned char *b) {
        return (b[510] == 0x55 && b[511] == 0xaa);
}

static void
write_part_table_flag(unsigned char *b) {
        b[510] = 0x55;
        b[511] = 0xaa;
}

/* Sample of the above in action */
static void get_partition_table_geometry(void) {
        unsigned char *bufp = MBRbuffer;
        struct partition *p;
        int i, h, s, hh, ss;
        int first = 1;
        int bad = 0;

        if (!(valid_part_table_flag(bufp)))
                return;

        hh = ss = 0;
        for (i=0; isys_ind != 0) {
                        h = p->end_head + 1;
                        s = (p->end_sector & 077);
                        if (first) {
                                hh = h;
                                ss = s;
                                first = 0;
                        } else if (hh != h || ss != s)
                                bad = 1;
                }
        }

        if (!first && !bad) {
                pt_heads = hh;
                pt_sectors = ss;
        }
}

So, we’ve established the basic structure of the MBR.  The graph below visualises this: MBR sections As stated above, the first 446 bytes (almost 90%) of the MBR contains machine code; the remaining 66 bytes are made up of 64 bytes for the partition table, of which 2 bytes are reserved  for the signature.

That concludes the post.

N.B I avoided posting this for at least a year as I wasn’t confident the detail was well explained; however, I decided to publish and share.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s