JoyChou 发表于 2013-9-30 18:58

MBR学习笔记

本帖最后由 JoyChou 于 2013-9-30 19:04 编辑

//Author: JoyChou
//Date: 2013年9月30日 19:04:55
//Blog: http://www.cnblogs.com/Joy7/

关于MBR介绍,网上已经有很多了
这里分享下自己xp的mbr分析笔记

什么是MBR?
也叫主引导记录(Master Boot Record,简称MBR) MBR位于整个硬盘的0柱面0磁头1扇区的位置处
主引导记录(Master Boot Record,缩写:MBR),又叫做主引导扇区Master Boot Sector
它在硬盘上的三维地址为(柱面,磁头,扇区)=(0,0,1)

MBR组成
MBR可以分为五个部分(512字节)
1、引导程序(440字节)
2、Windows磁盘签名(4个字节)
3、保留位(2个字节)
4、硬盘分区表(Disk Partition Table 简称DPT) 64个字节
5、结束标志 (2个字节)

也可以分成3部分(1.引导程序2.分区表3.结束标志)

分区表

一个分区表项为0x10大小字节,所以存在4个分区表项
当然,也就只能有四个主分区或者3个主分区+1个扩展分区,但是平时看到有的电脑分成CDEFGH等盘,这是为什么呢?
因为此时,一般只有C盘是主分区,DEFGH盘一般是扩展分区细分出来的逻辑分区。也就是说扩展分区只能有一个,然后可以再细分为多个逻辑分区。

扩展分区也是主分区的一种,但它与主分区的不同在于理论上可以划分为无数个逻辑分区。


调试之前先要了解windows系统启动过程
1、开机
2、BIOS加点自检(Power On Self Test,即POST),此时电源稳定后,CPU从内存地址0fff:0000处开始执行
3、将硬盘第一个扇区(0磁头0柱面1扇区)读取内存地址0000:7c00处
4、检测(WORD)0000:7dfe是否等于0xaa55,若不等于则转去尝试其他启动介质,如果没有其他启动介质则显示"No ROM BASIC"
5、跳转到0000:7c00处执行MBR中的程序

6、MBR首先将自己复制到0000:0600处,然后继续执行
7、在主分区表中搜索标志为活动的分区。如果发现没有活动分区或有不止一个活动分区,则显示“Invalid partiton table”
8、将活动分区的第一个扇区读入内存地址0000:7c00处
9、检测(WORD)000:7dfe是否等于0xaa55,若不等于则显示"Miss Operating System",然后停止,或尝试软盘启动
10、跳转到0000:7c00处继续执行DBR
11、启动系统

以上步骤中2,3,4,5步由BIOS的引导程序完成,6、7、8、9、10步由MBR中的引导程序完成。
知道了过程,调试就简单多了,所以过程是分析一个很关键的步骤。

关于MBR的调试看willJ大大的文章吧~

最好先用IDA动态跟下自己的mbr,接着静态分析(每个系统的mbr都不会是一模一样的)。

IDA静态分析代码
seg000:7C00 seg000          segment byte public 'CODE' use16
seg000:7C00               assume cs:seg000
seg000:7C00               ;org 7C00h
seg000:7C00               assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:7C00               xor   ax, ax          ; ax = 0
seg000:7C02               mov   ss, ax          ; ss = 0
seg000:7C04               mov   sp, 7C00h       ; sp = 0x7c00
seg000:7C07               sti                     ; 开起段中断
seg000:7C08               push    ax
seg000:7C09               pop   es            ; es = 0
seg000:7C0A               push    ax
seg000:7C0B               pop   ds            ; ds = 0
seg000:7C0C               cld                     ; 关闭段中断
seg000:7C0D               push    ax
seg000:7C0E               mov   si, 7C00h
seg000:7C11               mov   di, 600h
seg000:7C14               mov   cx, 200h      ; 循环次数,512次,也就是mbr的大小
seg000:7C17               rep movsb               ; rep movsb将ds:si拷贝到es:di处,长度为cx
seg000:7C17                                       ; 即将mbr从0x7c00拷贝到0x600处
seg000:7C19               mov   di, 61Eh
seg000:7C1C               push    di
seg000:7C1D               retf                  ; jmp到0x61E
seg000:7C1D                                       ; 也就是继续执行下一条指令(可以用IDA动态调试看)
seg000:7C1E ; ---------------------------------------------------------------------------
seg000:7C1E               xor   bx, bx          ; 这里本来是7c1E,因为静态调试,就把它当成61E
seg000:7C20               xor   dx, dx
seg000:7C22               mov   si, 7BEh      ; 0x600+0x1BE偏移0x1BE为分区表起始位置
seg000:7C25               mov   cl, 4         ; 4个分区表项
seg000:7C27
seg000:7C27 loc_7C27:                               ; CODE XREF: seg000:7C32j
seg000:7C27               test    byte ptr , 80h ; 判断是否是活动分区,0x80为活动分区,由于是2个字节,我测试的为0x180
seg000:7C2A               jz      short loc_7C2F; 是活动分区的时候不跳转,否则跳转
seg000:7C2C               mov   dx, si
seg000:7C2E               inc   bx            ; bx=1,接着之前的0
seg000:7C2F
seg000:7C2F loc_7C2F:                               ; CODE XREF: seg000:7C2Aj
seg000:7C2F               add   si, 10h         ; 活动分区表指向下一个
seg000:7C32               loop    loc_7C27      ; 判断是否是活动分区,0x80为活动分区,由于是2个字节,我测试的为0x180
seg000:7C34               cmp   bx, 1         ; 判断是否只有一个活动分区表
seg000:7C37               jz      short Find_Partition ; 只有一个就跳转
seg000:7C39               mov   si, 0C4h      ; 如果活动分区表为0或者大于1,则错误,si = C4h
seg000:7C3C               mov   cx, 17h         ; cx = 17h 十进制的23(Invalid partition table的长度)
seg000:7C3F               jmp   short Print_Error ; si = C4h + 600h = 6C4h,指向Invalid partition table字符串
seg000:7C41 ; ---------------------------------------------------------------------------
seg000:7C41               nop
seg000:7C42
seg000:7C42 Find_Partition:                         ; CODE XREF: seg000:7C37j
seg000:7C43               mov   ah, 41h         ; int13 41号功能,检测特定驱动器是否有扩展功能
seg000:7C45               mov   dl, 80h
seg000:7C47               mov   bx, 55AAh       ; 如果存在扩展13H功能,执行完int13,bx = AA55h,CL = 5
seg000:7C4A               int   13h             ; DISK - Check for INT 13h Extensions
seg000:7C4A                                       ; BX = 55AAh, DL = drive number
seg000:7C4A                                       ; Return: CF set if not supported
seg000:7C4A                                       ; AH = extensions version
seg000:7C4A                                       ; BX = AA55h
seg000:7C4A                                       ; CX = Interface support bit map
seg000:7C4C               pop   dx
seg000:7C4D               cmp   bx, 0AA55h      ; 判断是否存在扩展INT13功能
seg000:7C51               jnz   short loc_7C86; 调用int13的02号读扇区功能
seg000:7C53               test    cl, 1         ; 此时CL = 5
seg000:7C56               jz      short loc_7C86; 调用int13的02号读扇区功能
seg000:7C58               mov   ax, 4200h
seg000:7C5B               mov   si, 7ADh      ; si = 7ADh
seg000:7C5E               mov   cl, 10h         ; 循环次数
seg000:7C60
seg000:7C60 loc_7C60:                               ; CODE XREF: seg000:7C64j
seg000:7C60               mov   byte ptr , 0 ; 7ADh到7BDh之间这0x10全部赋值为0
seg000:7C63               inc   si
seg000:7C64               loop    loc_7C60      ; 7ADh到7BDh之间这0x10全部赋值为0
seg000:7C66               mov   si, 7ADh
seg000:7C69               mov   di, dx          ; dx = 0x7BE
seg000:7C6B               mov   byte ptr , 10h ; 设置7AD到7BD之间的值分别为
seg000:7C6B                                       ; 10 00 01 00 00 7C 00 003F 00 00 00 00 00 00 00
seg000:7C6E               mov   byte ptr , 1
seg000:7C72               mov   word ptr , 7C00h
seg000:7C77               mov   bx,
seg000:7C7A               mov   , bx
seg000:7C7D               mov   bx,
seg000:7C80               mov   , bx
seg000:7C83               jmp   short loc_7C94; 此时ax = 4200h,
seg000:7C83                                       ; 继续利用int 13检测驱动器的扩展性
seg000:7C83 ; ---------------------------------------------------------------------------
seg000:7C85               db90h ;
seg000:7C86 ; ---------------------------------------------------------------------------
seg000:7C86
seg000:7C86 loc_7C86:                               ; CODE XREF: seg000:7C51j
seg000:7C86                                       ; seg000:7C56j
seg000:7C86               mov   ax, 201h      ; 调用int13的02号读扇区功能
seg000:7C89               mov   bx, 7C00h
seg000:7C8C               mov   si, dx
seg000:7C8E               mov   cx,
seg000:7C91               mov   dh,       ; 将活动分区的第一个扇区读入到内存地址0000:7c00
seg000:7C94
seg000:7C94 loc_7C94:                               ; CODE XREF: seg000:7C83j
seg000:7C94               mov   dl, 80h         ; 此时ax = 4200h,
seg000:7C94                                       ; 继续利用int 13检测驱动器的扩展性
seg000:7C96               int   13h             ; DISK - READ SECTORS INTO MEMORY
seg000:7C96                                       ; AL = number of sectors to read, CH = track, CL = sector
seg000:7C96                                       ; DH = head, DL = drive, ES:BX -> buffer to fill
seg000:7C96                                       ; Return: CF set on error, AH = status, AL = number of sectors read
seg000:7C98               mov   si, 7DFEh
seg000:7C9B               cmp   word ptr , 0AA55h ; 检测0000:7dfe是否等于0xaa55,若不等于则显示"Missing Operating System"
seg000:7C9F               jz      short DBR       ; 相等就跳到DBR执行
seg000:7CA1               mov   si, 0DBh
seg000:7CA4               mov   cx, 18h         ; 循环次数十进制24,Missing Operating System长度为24
seg000:7CA7               jmp   short Print_Error ; si = C4h + 600h = 6C4h,指向Invalid partition table字符串
seg000:7CA7 ; ---------------------------------------------------------------------------
seg000:7CA9               db90h ;
seg000:7CAA ; ---------------------------------------------------------------------------
seg000:7CAA
seg000:7CAA DBR:                                    ; CODE XREF: seg000:7C9Fj
seg000:7CAA               xor   ax, ax
seg000:7CAC               push    ax
seg000:7CAD               mov   ax, 7C00h
seg000:7CB0               push    ax
seg000:7CB1               retf                  ; jmp到0000:7c00处,将控制权交给DBR
seg000:7CB2 ; ---------------------------------------------------------------------------
seg000:7CB2
seg000:7CB2 Print_Error:                            ; CODE XREF: seg000:7C3Fj
seg000:7CB2                                       ; seg000:7CA7j
seg000:7CB2               add   si, 600h      ; si = C4h + 600h = 6C4h,指向Invalid partition table字符串
seg000:7CB6
seg000:7CB6 loc_7CB6:                               ; CODE XREF: seg000:7CBEj
seg000:7CB6               lodsb                   ; 块装入指令,ds:si的值赋给al
seg000:7CB6                                       ; cx = 23为循环变量(loop的循环结束条件cx = 0)
seg000:7CB6                                       ; 一次显示一个al字符
seg000:7CB7               mov   bx, 7
seg000:7CBA               mov   ah, 0Eh
seg000:7CBC               int   10h             ; - VIDEO - WRITE CHARACTER AND ADVANCE CURSOR (TTY WRITE)
seg000:7CBC                                       ; AL = character, BH = display page (alpha modes)
seg000:7CBC                                       ; BL = foreground color (graphics modes)
seg000:7CBE               loop    loc_7CB6      ; 块装入指令,ds:si的值赋给al
seg000:7CBE                                       ; cx = 23为循环变量(loop的循环结束条件cx = 0)
seg000:7CBE                                       ; 一次显示一个al字符
seg000:7CC0
seg000:7CC0 loc_7CC0:                               ; CODE XREF: seg000:7CC2j
seg000:7CC0               mov   cl, 0Fh
seg000:7CC2               loop    loc_7CC0
seg000:7CC2 ; ---------------------------------------------------------------------------
seg000:7CC4 aInvalidPartitionTa db 'Invalid partition tableMissing operating system',0
seg000:7CF4 aMasterBootReco db 'Master Boot Record Wrote by MBR By DiskGenius',0

PS:
我动态跟的时候,不知道为什么,没有看到“将活动分区的第一个扇区读入到内存地址0000:7c00”这个步骤,
而是直接进行了两次int13 41功能号函数,最后跳到了DBR执行,然后启动。

慢慢分析,觉得还是蛮简单,贵在坚持。如果有分析得错误的地方,忘指点交流。

附件:idb和mbr文件

零度x 发表于 2013-10-2 00:38

赞,好详细的注释

鱼无论次 发表于 2016-8-25 22:47

本帖最后由 鱼无论次 于 2016-8-25 23:04 编辑

test    cl, 1         ; 此时CL = 5
这里是笔误吗cl前面寻找活动分区不是赋值为4吗?
难道不是cl=4?
不好意思看错了,如果存在int13h扩展功能返回是CL = 5

ILoveBBS 发表于 2013-11-11 21:35

好东西,收藏了

soleil 发表于 2013-11-16 12:39

受教学习了,没想到这东西细分的话还有这么多的知识啊

吾乐乐丶小米 发表于 2013-11-16 12:41

楼主辛苦了~

风2013 发表于 2013-11-24 08:11

好东西,先收藏起来

拆及鸡鸡 发表于 2013-11-24 21:06

好神奇的 感觉 哈哈

zxszx4 发表于 2013-12-20 12:10

我去,可能楼主图片略大,我用遨游和ie全都崩溃,之后只能用火狐,差点呀,就差那么一点点。我现在怀疑我这电脑还能活几年

小人物大智慧 发表于 2013-12-23 19:45

好文章 mark下 多谢楼主

Fochess 发表于 2014-2-23 16:17

Thanks LZ.
页: [1] 2 3
查看完整版本: MBR学习笔记