系统启动过程主要由一下几步组成(以硬盘启动为例):

1. 开机 :-)
    2. BIOS 加电自检 ( Power On Self Test -- POST )
       内存地址为 0ffff:0000
    3. 将硬盘第一个扇区 (0头0道1扇区, 也就是Boot Sector)
       读入内存地址 0000:7c00 处.
    4. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于
       则转去尝试其他启动介质, 如果没有其他启动介质则显示
       "No ROM BASIC" 然后死机.
    5. 跳转到 0000:7c00 处执行 MBR 中的程序.
    6. MBR 首先将自己复制到 0000:0600 处, 然后继续执行.
    7. 在主分区表中搜索标志为活动的分区. 如果发现没有活动
       分区或有不止一个活动分区, 则转停止.
    8. 将活动分区的第一个扇区读入内存地址 0000:7c00 处.
    9. 检查 (WORD) 0000:7dfe 是否等于 0xaa55, 若不等于则

显示 "Missing Operating System" 然后停止, 或尝试
       软盘启动.
    10. 跳转到 0000:7c00 处继续执行特定系统的启动程序.
    11. 启动系统 ...
以上步骤中 2,3,4,5 步是由 BIOS 的引导程序完成. 6,7,8,9,10
步由MBR中的引导程序完成.

1.主引导扇区结构

  硬盘的0柱面0磁道1扇区称为主引导扇区,其大小为512bytes.由主引导记录MBR(Master Boot Record)和4个分区表DPT(Disk Partition Table)以及2字节的结束标志"55h,AAh"构成.

; MBR( Master Boot Record )主引导记录包含两部分的内容,前446字节为启动代码及数据,而
; 从446(0x1BE)开始则是分区表,分区表由四个分区项组成,每个分区项数据为16字节,记录了
; 启动时需要的分区参数。
;
; 在CPU上电之后,若由硬盘启动,则BIOS将硬盘的主引导记录(位于0柱面、0磁道、1扇区)读
; 入7C00处,然后将控制权交给主引导代码。主引导代码的任务包括:
; (1) 扫描分区表,找到一个激活(可引导)分区;
; (2) 找到激活分区的起始扇区;
; (3) 将激活分区的引导扇区装载到内存7C00处;
; (4) 将控制权交给引导扇区代码;
;  
; 如果主引导代码无法完成上述任务,它将显示以下错误信息之一:
; No active partition.
; Invalid partition table.
; Error loading operating system.
; Missing operating system.

具体结构如下:

+---------+-------+-------------------+

+  Offset  +  Size  +          描述           +

+---------+-------+-------------------+

+  0h       +   446  + MBR的代码和数据  +

+---------+-------+-------------------+

+  1BEh   +   16    + 分区表1的入口地址 +

+---------+-------+-------------------+

+  1CEh   +   16    + 分区表2的入口地址 +

+---------+-------+-------------------+

+  1DEh   +   16    + 分区表3的入口地址 +

+---------+-------+-------------------+

+  1EEh   +   16    + 分区表4的入口地址 +

+---------+-------+-------------------+

+  1FEh   +     2    +  结束标志"55AAh" +

+---------+-------+-------------------+

2.MBR的具体实现代码

参考网上的"主引导扇区代码(MBR)"

http://blog.21ic.com/user1/1425/archives/2008/51135.html

;====================================================================
;
; FlyingDragon MBR ( Master Boot Record )
;
; Author : Jack
; History:
; 0.01 - 2005-08-13 19:34 采用传统的CHS磁盘调用
; 0.02 - 2005-08-23 19:44 优先采用扩展磁盘调用
;
; Build  : nasm -f bin MBR.ASM -oMBR.BIN 
;  
;====================================================================================
;
; MBR( Master Boot Record )主引导记录包含两部分的内容,前446字节为启动代码及数据,而
; 从446(0x1BE)开始则是分区表,分区表由四个分区项组成,每个分区项数据为16字节,记录了
; 启动时需要的分区参数。
;
; 在CPU上电之后,若由硬盘启动,则BIOS将硬盘的主引导记录(位于0柱面、0磁道、1扇区)读
; 入7C00处,然后将控制权交给主引导代码。主引导代码的任务包括:
; (1) 扫描分区表,找到一个激活(可引导)分区;
; (2) 找到激活分区的起始扇区;
; (3) 将激活分区的引导扇区装载到内存7C00处;
; (4) 将控制权交给引导扇区代码;
;  
; 如果主引导代码无法完成上述任务,它将显示以下错误信息之一:
; No active partition.
; Invalid partition table.
; Error loading operating system.
; Missing operating system.
;
;====================================================================================
; FAT16分区尺寸与LBA
;====================================================================================
; LBA   HeadsPerCylinder SectorsPerTrack  Maximum Size for Boot Partition
; Disabled 64     32     1GB
; Enabled  255     63     4GB
;
; 为了适应超过8G的硬盘,Windows2000忽略了Start CHS和End CHS,而使用StartLBA和TotalSector    
; 来确定分区在整个磁盘中的位置和大小。
;  
;====================================================================================
;     分区表项结构(16字节)
;====================================================================================
;
; typedef struct _PARTITION_ENTRY
; {
;  UCHAR BootIndicator;  // 能否启动标志
;  UCHAR StartHead;   // 该分区起始磁头号
;  UCHAR StartSector;  // 起始柱面号高2位:6位起始扇区号
;  UCHAR StartCylinder;  // 起始柱面号低8位
;  UCHAR PartitionType;  // 分区类型
;  UCHAR EndHead;   // 该分区终止磁头号
;  UCHAR EndSector;   // 终止柱面号高2位:6位终止扇区号
;  UCHAR EndCylinder;  // 终止柱面号低8位
;  ULONG StartLBA;   // 起始扇区号
;  ULONG TotalSector;  // 分区尺寸(总扇区数)
; }PARTITION_ENTRY,*PPARTITION_ENTRY;
;
;====================================================================================
;    主引导记录(MBR)结构
;====================================================================================
; typedef struct _MASTER_BOOT_RECORD
; {
;  UCHAR    BootCode[446];
;  PARTITION_ENTRY  Partition[4];
;  USHORT    Signature;
; }MASTER_BOOT_RECORD,*PMASTER_BOOT_RECORD;
;
;====================================================================================

BITS   16   ; 生成16位代码而不是32位代码
SECTION  .text   ; 代码段
ORG   0600H  ; 指定程序被装入内存的起始位置

;====================================================================
;
; 宏和常量定义
;
;====================================================================
?     EQU  0  ; NASM不支持DW ?这样的语法,可以使用这样的定义
        ; 模拟,以使代码的可读性更强
ACTIVE_FLAG  EQU  80H  ; 激活(可引导)分区标志
NOT_ACTIVE_FLAG EQU  00H  ; 不激活标志
MBR_MOVE_ADDR EQU  0600H ; MBR先移动自身到该位置然后再运行
BOOT_SIGNATURE EQU  0AA55H ; 启动标志
SEC_SIG_OFF  EQU  01FEH ; 启动扇区的标志位置

;====================================================================
; 分区表项结构偏移
;====================================================================
BootIndicator EQU  0  ; 能否启动标志
StartHead  EQU  1  ; 该分区起始磁头号
StartSector  EQU  2  ; 起始柱面号高2位:6位起始扇区号
StartCylinder EQU  3  ; 起始柱面号低8位
PartitionType EQU  4  ; 分区类型
EndHead   EQU  5  ; 该分区终止磁头号
EndSector  EQU  6  ; 终止柱面号高2位:6位终止扇区号
EndCylinder  EQU  7  ; 终止柱面号低8位
StartLBA  EQU  8  ; 起始扇区号
TotalSector  EQU  12  ; 分区尺寸(总扇区数)

;====================================================================
; 常用的分区类型
;====================================================================
PARTITION_TYPE_EMPTY  EQU  00H ; 空分区
PARTITION_TYPE_FAT12  EQU  01H ; FAT12 ( < 32680 sectors )
PARTITION_TYPE_FAT16  EQU  04H ; FAT16 ( 32680 - 65535 sectors )
PARTITION_TYPE_EXTENDED  EQU  05H ; DOS EXTENDED
PARTITION_TYPE_BIGDOS_FAT16 EQU  06H ; FAT16 ( 33MB - 4GB )
PARTITION_TYPE_NTFS   EQU  07H ; NTFS
PARTITION_TYPE_FAT32  EQU  0BH ; FAT32
PARTITION_TYPE_FAT32_LBA EQU  0CH ; FAT32 LBA
PARTITION_TYPE_FAT16_LBA EQU  0EH ; FAT16 LBA
PARTITION_TYPE_EXTENDED_LBA EQU  0FH ; LBA EXTENDED
PARTITION_TYPE_DYNAMIC_DISK EQU  42H ; Dynamic Disk Volume

;====================================================================
; 主引导记录的入口
;====================================================================
_ENTRY_POINT:
 
 ; 初始化相关寄存器及标志位
 CLI      ; 先关掉中断
 CLD      ; 方向为向前递增
 XOR  AX,AX   ; AX = 0
 MOV  DS,AX   ; 设置数据段寄存器 DS:SI
 MOV  ES,AX   ; 设置附加段寄存器 ES:DI
 MOV  SS,AX   ; 设置堆栈段寄存器
 MOV  BP,7C00H  ; 设置基址寄存器
 MOV  SP,BP   ; 设置堆栈栈顶
 
 ; 将MBR代码移动到0600H处
 MOV  SI,BP   ; SI = 7C00H
 MOV  DI,MBR_MOVE_ADDR; DI = 0600H
 MOV  CX,512   ; 待移动的字节数
 REP  MOVSB 
 JMP  0:.RealStart

; 真正开始   
.RealStart:

; 保存引导驱动器号
 MOV  BYTE [ DriveNumber ] , DL
 
 ;====================================================================  
 ; 检查是否支持磁盘中断INT 13H的扩展
 ;====================================================================
 MOV  AH,41H
 MOV  BX,055AAH
 INT  13H
 JC  .LookupActive   ; 如果失败,进位标志为1
 MOV  BYTE[DiskExtension],01H ; 设置支持磁盘扩展标志

.LookupActive:
 
 ; 查找激活分区
 MOV  BP,PartitionTable   ; 指向分区表
 MOV  BL,4      ; 最多4个分区

;检查激活分区 
.CheckNext:

CMP  BYTE [BP+BootIndicator],ACTIVE_FLAG  ; 检查该分区是否激活
 JZ  .FoundActive       ; 找到激活分区
 CMP  BYTE [BP+BootIndicator],NOT_ACTIVE_FLAG ; 检查该分区是否激活 
 JNZ  .InvalidTable       ; 无效值
 ADD  BP,10H         ; 指向下一个分区表项
 DEC  BL
 JZ  .NoActive        ; 没有找到激活分区
 JMP  .CheckNext

;找到了激活分区
.FoundActive:

; 保存分区表项
 MOV  AL,4
 SUB  AL,BL      ; AL = 4-BL = 第一个激活分区表项索引(0-3)
 MOV  BYTE [ActivePartition],AL ; 保存激活分区表项索引
 MOV  DI,BP      ; DI = 激活分区项
 MOV  DH,BYTE[BP+StartHead]  ; 该分区起始磁头号
 MOV  CL,BYTE[BP+StartSector]  ; 起始柱面号高2位:6位起始扇区号
 MOV  CH,BYTE[BP+StartCylinder] ; 起始柱面号低8位
 
 ; 保存起始扇区号
 MOV  AX,WORD[BP+StartLBA+2]
 MOV  WORD[DAP_SECTOR_LOW+2],AX 
 MOV  AX,WORD[BP+StartLBA]  
 MOV  WORD[DAP_SECTOR_LOW],AX 
 
; 检查确信只有一个激活分区 
.Recheck:     
 ADD  BP,10H      ; 指向下一个分区项
 DEC  BL
 JZ  .LoadBootSector    ; 装载该分区的引导扇区
 CMP  BYTE [BP+BootIndicator],NOT_ACTIVE_FLAG ; 检查该分区是否激活 
 JNZ  .InvalidTable    ; 无效值
 JMP  .Recheck

; 装载激活分区的引导扇区 
.LoadBootSector:
 
 ; 设置驱动器号
 MOV  DL,BYTE [DriveNumber]
 
 ; 检查是否支持扩展磁盘调用
 CMP  BYTE [DiskExtension],01H
 JNZ  .NoDiskExtension
 
 ; 使用扩展磁盘调用读取引导扇区
 ; 
 ; INT 13H 
 ;  AH = 42H
 ;  DL = Drive Number
 ;  DS:SI = 指向磁盘地址包的指针
 ;
 MOV  SI,DAP_PACKET_SIZE
 MOV  AH,42H
 INT  13H
 JC  .ErrorLoadOS
 JMP  .CheckBootSector

.NoDiskExtension: 
 ;====================================================================
 ; 
 ; INT 13H 
 ;  AH = 2        柱面号:0 - 1023
 ;  AL = 要读取的扇区数     磁头号:0 - 255   
 ;  CH = 柱面号低8位     扇区号:1 - 63 
 ;  CL = 柱面号高2位 : 6位扇区号  
 ;  DH = 磁头号
 ;  DL = 驱动器号
 ;  ES:BX = 缓冲区
 ;
 ;====================================================================

; 读取引导扇区 
 MOV  BX,7C00H
 MOV  AX,0201H
 INT  13H
 JC  .ErrorLoadOS
 
; 检查引导扇区是否合法 
.CheckBootSector: 
 
 ; 装载引导扇区成功,检查引导标志
 MOV  BX,7C00H
 CMP  WORD [BX+SEC_SIG_OFF], BOOT_SIGNATURE  ; 检查引导标志
 JNZ  .MissingOS     
 
 ; 准备跳转到激活扇区的引导扇区代码
 ; DL = 磁盘驱动器号
 ; DH = 激活分区号
 ; DI = 激活分区项
 MOV  DL,BYTE [DriveNumber]
 MOV  DH,BYTE [ActivePartition]
 JMP  0:7C00H

; 没有激活分区
.NoActive: 
 MOV  SI,MsgNoActive
 CALL ShowMessage
 JMP  .Hang
 
; 无效分区表
.InvalidTable:
 MOV  SI,MsgPartitionTable
 CALL ShowMessage
 JMP  .Hang
 
; 装载引导扇区失败
.ErrorLoadOS:
 MOV  SI,MsgLoadingOS
 CALL ShowMessage
 JMP  .Hang
 
; 引导扇区不合法
.MissingOS:
 MOV  SI,MsgMissingOS
 CALL ShowMessage

.Hang:
 JMP  .Hang

;====================================================================
;
; 显示一个字符串
; 输入:
;   DS:SI  = 字符串的起始地址(以NULL结束)
;   
;====================================================================
ShowMessage:
 LODSB    ; AL = DS:[SI] SI = SI+1
 OR  AL,AL    ; 检测是否遇到NULL字符串
 JZ  .ShowEnd
 MOV  AH,0EH
 MOV  BX,07H
 INT  10H
 JMP  ShowMessage

.ShowEnd:
 RET 
 
 
;====================================================================
; 调试例程
;====================================================================

%IFDEF DEBUG 
 
;====================================================================
;
; 显示一个字符
; 输入: AL = 待显示字符
;
;====================================================================
PrintChar:
 PUSH AX
 PUSH BX
 MOV  AH,0EH
 MOV  BX,7
 INT  10H
 POP  BX
 POP  AX
 RET

;====================================================================
;
; 显示16进制的值(将一个BYTE变为两个ASCII字符打印出来,用于调试)
; 输入: AL = 待显示的字节
;
;====================================================================
PrintByte:
 PUSH BX
 MOV  BH,AL
 
 ; 显示高4位
 SHR  AL,4
 AND  AL,0FH
 ADD  AL,30H
 CMP  AL,39H
 JLE  .PrintIt
 ADD  AL,07H
.PrintIt: 
 CALL PrintChar

; 显示低4位 
 MOV  AL,BH
 AND  AL,0FH
 ADD  AL,30H
 CMP  AL,39H
 JLE  .PrintItAgain
 ADD  AL,07H
.PrintItAgain 
 CALL PrintChar
 POP  BX
 RET

%ENDIF ; DEBUG

;====================================================================
; 数据区
;====================================================================
MsgNoActive     DB  "No active partition.",00H
MsgPartitionTable   DB "Invalid partition table.",00H   
MsgLoadingOS    DB "Error loading operating system.",00H
MsgMissingOS    DB "Missing operating system.",00H

;====================================================================
;临时数据
;====================================================================
DriveNumber     DB 00H ; 启动磁盘启动器号
ActivePartition    DB 00H ; 激活分区表索引(0-3)
DiskExtension    DB 00H ; 是否支持磁盘扩展调用

;====================================================================  
; 扩展磁盘服务所使用的地址包
;====================================================================
DAP_PACKET_SIZE    DB 10H  ; 包的大小为16字节
DAP_RESERVED1    DB 00H  ; 保留字节
DAP_READ_SECTORS   DB 01H  ; 要处理的扇区数(1 - 127 )
DAP_RESERVED2    DB 00H  ; 保留字节
DAP_BUFFER_OFF    DW 7C00H ; 缓冲区偏移
DAP_BUFFER_SEG    DW 0000H ; 缓冲区段地址
DAP_SECTOR_LOW    DD 0000H ; 起始扇区号的低32位
DAP_SECTOR_HIGH    DD 0000H ; 起始扇区号的高32位

;====================================================================
; 填充字节
Padding TIMES 440-($-$$) db  00H
;====================================================================

;====================================================================
; 标志字节
;====================================================================
UniqueMbrSignature   DD 4B43414AH
UnknownWord     DW 00H

;====================================================================
; 分区表(偏移为446)
;====================================================================
PartitionTable TIMES 64  DB 00H

;====================================================================
; 扇区最后的标记字节(NASM不支持重复ORG)
;====================================================================
BootSignature    dw 0AA55H

;====================================================================
; 代码结束
;====================================================================

3.MBR病毒感染

从上面可以看出.

MBR的作用就是检查分区表是否正确以及确定哪个分区为引导分区,并在程序结束时把该分区的启动程序(也就是操作系统引导扇区)调入内存加以执行.

并且通过检测某些标志位,来确定是否显示一些错误的信息.

其实这部分MBR的代码,我们也可以自己编写,只要完成上述功能即可.某些多余的字节码,可以用来实现更多邪恶的思想.比如 stoned bootkit;

DOS时代需要通过软盘启动系统,那个时候一个被感染MBR病毒的软盘,插入软驱,启动系统时,执行的过程大概如下:

1.用户从一个被感染了的软盘启动,然后病毒得到执行.

2.病毒将保存原来的MBR,然后将MBR部分替换为病毒自身.

3.然后病毒会跳转到 original MBR部分,系统继续运行,而病毒就存留在系统中了..

所以MBR病毒感染的基本思想,首先是读取主引导记录和把分区表从主引导记录中复制出来。然后,MBR病毒把自己的包含恶意二进制数据的主引导记录放到主引导扇区,并复制新的分区表到它。但是,并非只有分区表需要保留,还有微软公司原来的主引导记录也需要保存下来。为此,MBR病毒复制原始主引导记录到其它64个未用到的扇区。到MBR病毒执行完自己的操作后在读取原始的主引导记录并跳到0x7c00处执行来引导开机。

那这样检测和恢复MBR其实也很简单了,只要dump出系统硬盘的MBR,然后和正确的MBR对比,若符合之,则没有被感染,若不符合,不匹配,则认为其MBR是被病毒修改过了.要恢复MBR,可以使用dos下的fdisk,也可以自己实现,将正确的MBR写入.

转载于:https://www.cnblogs.com/Tbit/archive/2010/10/28/1863654.html

[1.0]剖析MBR相关推荐

  1. 一起谈.NET技术,NHibernate3.0剖析:Query篇之NHibernate.Linq标准查询

    系列引入 NHibernate3.0剖析系列分别从Configuration篇.Mapping篇.Query篇.Session策略篇.应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种 ...

  2. NHibernate3.0剖析:Query篇之NHibernate.Linq标准查询

    系列引入 NHibernate3.0剖析系列分别从Configuration篇.Mapping篇.Query篇.Session策略篇.应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种 ...

  3. 《操作系统真象还原》——0.28 MBR、EBR、DBR和OBR各是什么

    本节书摘来自异步社区<操作系统真象还原>一书中的第0章,第0.28节,作者:郑钢著,更多章节内容可以访问云栖社区"异步社区"公众号查看 0.28 MBR.EBR.DBR ...

  4. 拼一个自己的操作系统(SnailOS 0.03的实现)

    拼一个自己的操作系统 SnailOS 0.03的实现 拼一个自己的操作系统SnailOS0.03源代码-Linux文档类资源-CSDN下载 操作系统SnailOS学习拼一个自己的操作系统-Linux文 ...

  5. NHibernate3剖析:Query篇之NHibernate.Linq标准查询

    本节内容 系列引入 NHibernate.Linq概述 标准查询运算符 结语 系列引入 NHibernate3.0剖析系列分别从Configuration篇.Mapping篇.Query篇.Sessi ...

  6. uefi+guid分区与legacy+mbr分区_WIN10下如何将 MBR 分区转换为 GPT

    MBR2GPT.EXE 可将磁盘从主启动记录 (MBR) 转换为 GUID 分区表 (GPT) 分区形式,无需修改或删除磁盘上的数据. 该工具旨在从 Windows 预安装环境 (Windows PE ...

  7. 计算机数据恢复报告单,计算机数据恢复第三章MBR引导分析篇

    摘要: 主引导记录(MBR,Main Boot Record)是位于磁盘最前边的一段引导(Loader)代码.它负责磁盘操作系统(DOS)对磁盘进行读写时分区合法性的判别.分区引导信息的定位,它由磁盘 ...

  8. spark1.0和2.0的区别_Spark2.1.0——Spark初体验

    学习一个工具的最好途径,就是使用它.这就好比<极品飞车>玩得好的同学,未必真的会开车,要学习车的驾驶技能,就必须用手触摸方向盘.用脚感受刹车与油门的力道.在IT领域,在深入了解一个系统的原 ...

  9. Legacy BIOS MBR 安装黑苹果 High sierra

    编辑中: 首先看看机器配置,史前时代 2007--2008年的机器,和 UEFI + GPT 没有半毛钱的关系,够老了.应该很少人比这个还老了. 搞错了.这个CPU最多安装 10.13 High Si ...

最新文章

  1. PHP for循环中的sql语句,php – 在foreach循环中使用SQL结果
  2. 学python可以做什么职业好-学了那么多年python到底可以找什么工作?
  3. 无缓冲channel
  4. golang unrecognized import path golang.org/x/net 完美解决方案
  5. 微信5.0安卓内测版下载
  6. 灵悟礼品网上专卖店——画出E-R图
  7. TTL、CMOS和RS232电平的区别和联系
  8. video.h5.player.js视频播放器
  9. 【百度网盘】电脑版百度网盘二维码无法加载的问题
  10. electron编写我们第一个hello world程序和文件引入
  11. smartsvn学习(-)
  12. 一套牛逼哄哄的开源的监控系统(附源码)
  13. 商家分账使用场景流程
  14. vue的组件通信方式
  15. 最新会声会影2023旗舰版更新了哪些功能?
  16. easyexcel实现代码生成xlsx文件并保存到云端
  17. 固件avr usb驱动程序_在AVR固件上使用Z3定理
  18. std::this_thread::sleep_for 使用
  19. 视频号带货玩法拆解,无私分享给有需要的你「视频教程」
  20. html格式自动出现乱码,HTML页面乱码怎么解决?

热门文章

  1. exls下载后显示jsp_jsp利用POI直接生成Excel并在页面提示打开下载
  2. python队列中替换某元素_如何打印队列中的元素(Python)
  3. 一层循环时间复杂度_数据结构与算法系列——时间、空间复杂度
  4. 2022-03-23 转载C++中std::auto_ptr被废弃,由std::unique_ptr代替的原因
  5. Web请求响应编码问题详解
  6. PhoneGap在Android上的插件开发方法介绍
  7. 一种软阴影的实现方法
  8. RPG Maker的引擎分析(一)(二)
  9. VC.dll相关及其C#交互
  10. dao generator for php and mysql_mybatis generator 自动生成dao层映射代码