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文件 赞,好详细的注释 本帖最后由 鱼无论次 于 2016-8-25 23:04 编辑
test cl, 1 ; 此时CL = 5
这里是笔误吗cl前面寻找活动分区不是赋值为4吗?
难道不是cl=4?
不好意思看错了,如果存在int13h扩展功能返回是CL = 5
好东西,收藏了 受教学习了,没想到这东西细分的话还有这么多的知识啊 楼主辛苦了~ 好东西,先收藏起来 好神奇的 感觉 哈哈 我去,可能楼主图片略大,我用遨游和ie全都崩溃,之后只能用火狐,差点呀,就差那么一点点。我现在怀疑我这电脑还能活几年 好文章 mark下 多谢楼主 Thanks LZ.