windows xp MBR结构分析

1、系统通电启动-->BIOS启动代码进行加电自检,包括显卡,内存,主板等-->根据用户指定的启动顺序。

从指定设备加载MBR(第一个扇区,0磁头0柱面1扇区)到内存地址0x7c00处。

2、用winhex软件打开磁盘,内容0x00-0x200总共512个字节为MBR。

0x0000-0x01BD, 446字节,引导代码和数据区域

0x01BE-0x01FD, 64字节,4个分区表,每个分区表占16个字节

0x01FE-0x01FF,    2字节,MBR结构标志,值为0xAA55

3、分区表结构(16字节):

0x1BE,1bytes;    =0x00: 不可启动分区,=0x80:可启动分区

0x1BF-0x1C1, 3bytes;  0x1BF,分区起始磁头号

              0x1C0-0xC01,分区起始扇区和柱面号,0x1C0低6位为起始扇区,0x1C0高2位加上0xC01组成10位为起始柱面号

0x1C2,  1bytest; =0x07,分区文件系统类型,07为ntfs,0x0B为FAT32,0x83为Linux等

0x1C3-0x1C5, 3bytes;   分区结束磁头号,结束扇区,结束柱面号,定义同前

0x1C6-0x1C9, 4bytes;   分区前扇区数,即此分区的起始扇区号

0x1CA-0x1CD,4bytes;   分区大小,即总扇区数

4、winxp mbr反汇编代码分析

 利用工具ndisasmw生成MBR反汇编代码,命令

ndisasmw -o 0x7c00 mbr.bin >> dismbr.asm

4.1:第一步,MBR代码拷贝。(0x7c1b到0x61b)

00007C00  33C0              xor ax,ax      ;ax=0
00007C02  8ED0              mov ss,ax      ;ss=0
00007C04  BC007C            mov sp,0x7c00    ;sp=0x7c00
00007C07  FB                sti           ;开中断
00007C08  50                push ax       
00007C09  07                pop es        ;es=0
00007C0A  50                push ax
00007C0B  1F                pop ds        ;ds=0
00007C0C  FC                cld          ;CLD是使得si,di传送方向从低地址到高地址增长
00007C0D  BE1B7C            mov si,0x7c1b      ;si=0x7c1b
00007C10  BF1B06            mov di,0x61b      ;di=0x61b
00007C13  50                push ax
00007C14  57                push di
00007C15  B9E501            mov cx,0x1e5     ;200h-1bh=1e5,cx=485个字节拷贝
00007C18  F3A4              rep movsb       ;[ds:si]=[0:0x7c1b], [es:di] =[0:0x61b],拷贝0x7c1b地址以上的485个字节的内容到0x61b内存地址中
00007C1A  CB                retf          ;ip=0x61b,cs=0,跳转到内存地址0x61b处执行,即后面的代码

4.2:第二步,MBR查找分区表信息,找到启动分区表以后,读取第一个扇区内容,并跳转至启动分区执行相关代码。

00007C1B  BDBE07            mov bp,0x7be    ;bp=0x7be  4个分区表的开始地址
00007C1E  B104              mov cl,0x4      ;cl=4  最多有4个分区表
00007C20  386E00            cmp [bp+0x0],ch  ;判断分区表的第一个字节是否为0x80,和0比较
00007C23  7C09              jl 0x7c2e      ;jl小于(有符号),0x80有符号是-128,小于0,成功表示找到启动分区,失败是普通分区
00007C25  7513              jnz 0x7c3a     ;不等于0,跳转,显示分区表无效
00007C27  83C510            add bp,byte +0x10  ;bp指向下一个分区表
00007C2A  E2F4              loop 0x7c20     ;cl不等于0,继续循环
00007C2C  CD18              int 0x18       ;ROM BASIC中断
00007C2E  8BF5              mov si,bp       ;si=0x7be
00007C30  83C610            add si,byte +0x10   ;si=0x7ce,下一个分区表
00007C33  49                dec cx         ;cx减1
00007C34  7419              jz 0x7c4f        ;cx=0,如果4个表项都检查完毕就跳转
00007C36  382C              cmp [si],ch       ;检查分区指示符
00007C38  74F6              jz 0x7c30        ;如果分区指示符是0就跳转,否则分区表是无效的
00007C3A  A0B507            mov al,[0x7b5]    ;0x1b5偏移地址处为2c,0x12c文件偏移地址处指向字符串"Invalid partition table"
00007C3D  B407              mov ah,0x7
00007C3F  8BF0              mov si,ax        ;si指向字符串
00007C41  AC                lodsb          ;读取一个字节到al
00007C42  3C00              cmp al,0x0       ;字符串是否显示完成
00007C44  74FC              jz 0x7c42       ;如果是就跳转(跳转到上面那条指令,系统陷入死循环),否则就调用10h号中断显示字符
00007C46  BB0700            mov bx,0x7
00007C49  B40E              mov ah,0xe
00007C4B  CD10              int 0x10         ;显示字符  
00007C4D  EBF2              jmp short 0x7c41
00007C4F  884E10            mov [bp+0x10],cl    ;cl=0,bp=0x7be
00007C52  E84600            call word 0x7c9b   ;读取启动分区的第一个扇区(512字节)信息到0x7c00
00007C55  732A              jnc 0x7c81         ;加载成功跳转
00007C57  FE4610            inc byte [bp+0x10]
00007C5A  807E040B          cmp byte [bp+0x4],0xb  ;0bh:用传统INT 13h就可以访问的FAT32分区
00007C5E  740B              jz 0x7c6b
00007C60  807E040C          cmp byte [bp+0x4],0xc  ;0ch:需要用扩展INT 13h访问的FAT32分区
00007C64  7405              jz 0x7c6b
00007C66  A0B607            mov al,[0x7b6]      ;0x1b6偏移地址处为0x44,0x144文件偏移地址处指向字符串"Error loading operating system"
00007C69  75D2              jnz 0x7c3d         ;错误信息显示出来(显示完后,系统进入死循环)
00007C6B  80460206          add byte [bp+0x2],0x6
00007C6F  83460806          add word [bp+0x8],byte +0x6
00007C73  83560A00          adc word [bp+0xa],byte +0x0
00007C77  E82100            call word 0x7c9b
00007C7A  7305              jnc 0x7c81
00007C7C  A0B607            mov al,[0x7b6]
00007C7F  EBBC              jmp short 0x7c3d
00007C81  813EFE7D55AA      cmp word [0x7dfe],0xaa55   ;检查启动分区的头个扇区是不是0xaa55结尾
00007C87  740B              jz 0x7c94            ;如果是,以0xaa55结尾就跳转
00007C89  807E1000          cmp byte [bp+0x10],0x0
00007C8D  74C8              jz 0x7c57
00007C8F  A0B707            mov al,[0x7b7]          ;0x1b7偏移地址处为0x63,0x163文件偏移地址处指向字符串"Missing operating system"
00007C92  EBA9              jmp short 0x7c3d        ;错误信息显示出来(显示完后,系统进入死循环)
00007C94  8BFC              mov di,sp
00007C96  1E                push ds             
00007C97  57                push di  
00007C98  8BF5              mov si,bp
00007C9A  CB                retf          ;代码回到0x7c00,0x7c00是启动分区的第一个扇区拷贝的代码,MBR引导代码结束
00007C9B  BF0500            mov di,0x5    ;di=5,最多读取启动分区第一个扇区5次,如果5次都失败了,提示载入系统失败
00007C9E  8A5600            mov dl,[bp+0x0]  ;dl=80H(00H~7FH:软盘;80H~0FFH:硬盘)
00007CA1  B408              mov ah,0x8    ;ah=0x8 08h表示读取驱动器参数
00007CA3  CD13              int 0x13     ;ah=08,int 13h 读取驱动器参数,是为了决定用CHS方式还是LBA方式读取磁盘数据
00007CA5  7223              jc 0x7cca     ;jc跳转,CF=1,操作失败,跳转,采用CHS方式
00007CA7  8AC1              mov al,cl     ;ch=柱面数的低8位  cl的位7~6=柱面数的高2位  CL的位5~0=扇区数
00007CA9  243F              and al,0x3f    ;获取扇区数
00007CAB  98                cbw
00007CAC  8ADE              mov bl,dh     ;磁头数
00007CAE  8AFC              mov bh,ah
00007CB0  43                inc bx
00007CB1  F7E3              mul bx
00007CB3  8BD1              mov dx,cx
00007CB5  86D6              xchg dl,dh
00007CB7  B106              mov cl,0x6
00007CB9  D2EE              shr dh,cl
00007CBB  42                inc dx      ;dx柱面数
00007CBC  F7E2              mul dx
00007CBE  39560A            cmp [bp+0xa],dx  ;分区前已用的扇区数(高2字节)
00007CC1  7723              ja 0x7ce6      ;超过了CHS访问方式所能表示的最大扇区数就采用LBA方式读取磁盘
00007CC3  7205              jc 0x7cca      ;比CHS访问方式所能表示的最大扇区数小就采用CHS方式读取磁盘,否则的话[bp+0xa]与dx相等,继续判断
00007CC5  394608            cmp [bp+0x8],ax    ;分区前已用的扇区数(低2字节)
00007CC8  731C              jnc 0x7ce6
00007CCA  B80102            mov ax,0x201    ;读取启动分区第一个扇区的数据,CHS方式读取,ah=2(功能读),al=1(一个扇区),int 13h读一个扇区
00007CCD  BB007C            mov bx,0x7c00    ;存储读取数据的内存地址0x7c00,相当于buffer
00007CD0  8B4E02            mov cx,[bp+0x2]   ;从哪个sector扇区开始读,其中低6位是扇区,高2位是柱面
00007CD3  8B5600            mov dx,[bp+0x0]   ;dl:硬盘,dh:从哪个磁头开始读
00007CD6  CD13              int 0x13
00007CD8  7351              jnc 0x7d2b      ;CF=0就跳转(CF为0代表操作成功)
00007CDA  4F                dec di
00007CDB  744E              jz 0x7d2b      ;操作失败
00007CDD  32E4              xor ah,ah      ;ah=0,磁盘系统复位
00007CDF  8A5600            mov dl,[bp+0x0]   ;要复位的磁盘驱动器号
00007CE2  CD13              int 0x13
00007CE4  EBE4              jmp short 0x7cca  ;再次读取
00007CE6  8A5600            mov dl,[bp+0x0]   ;LBA方式读取磁盘,先判断是否支持LBA方式访问磁盘
00007CE9  60                pushaw       ;寄存器组压栈
00007CEA  BBAA55            mov bx,0x55aa   
00007CED  B441              mov ah,0x41       ;检测BIOS是否已经支持扩展INT 13h功能
00007CEF  CD13              int 0x13      ;bx=0x55aa,dl=驱动器号,ah=0x41
00007CF1  7236              jc 0x7d29     ;不支持跳转
00007CF3  81FB55AA          cmp bx,0xaa55
00007CF7  7530              jnz 0x7d29     ;扩展INT 13h不可用也转
00007CF9  F6C101            test cl,0x1    ;测试扩展盘访问是否被支持
00007CFC  742B              jz 0x7d29     ;不支持跳转
00007CFE  61                popaw        ;寄存器组弹栈
00007CFF  60                pushaw       ;LAB方式访问磁盘
00007D00  6A00              push byte +0x0
00007D02  6A00              push byte +0x0
00007D04  FF760A            push word [bp+0xa]    ;启动分区前已用的扇区数(高2字节)
00007D07  FF7608            push word [bp+0x8]   ;启动区前已用的扇区数(低2字节)
00007D0A  6A00              push byte +0x0     ;存储数据目标缓冲区首址段址
00007D0C  68007C            push word 0x7c00    ;存储数据目标缓冲区首址偏移
00007D0F  6A01              push byte +0x1      ;扇区数1
00007D11  6A10              push byte +0x10     ;包长度
00007D13  B442              mov ah,0x42        ;置扩展读功能号,以LBA方式读取
00007D15  8BF4              mov si,sp
00007D17  CD13              int 0x13         ;读取数据
00007D19  61                popaw
00007D1A  61                popaw
00007D1B  730E              jnc 0x7d2b        ;CF=0跳转,说明读取成功
00007D1D  4F                dec di
00007D1E  740B              jz 0x7d2b       ;5次都没读取成功,CF=1
00007D20  32E4              xor ah,ah       ;ah=0,磁盘系统复位
00007D22  8A5600            mov dl,[bp+0x0]    ;复位的驱动器号
00007D25  CD13              int 0x13
00007D27  EBD6              jmp short 0x7cff
00007D29  61                popaw
00007D2A  F9                stc          ;设置CF=1
00007D2B  C3                ret          ;返回
后面指令略...

 5. MBR的作用是检测分区表,找到启动分区,读取其中第一个扇区的指令代码,返回到0x7c00执行。

posted @ 2019-06-07 08:15  pro_love  阅读(1498)  评论(0编辑  收藏  举报