starsky
初级用户
积分 191
发帖 22
注册 2004-7-30
状态 离线
|
『楼 主』:
【转载】别人写的新版MBR反汇编分析
发信人: SeaPeak (登老和兮小浙大), 信区: AsmDos
标 题: mbr 反汇编分析
发信站: 飘渺水云间 (Sun Jul 4 15:55:51 2004), 转信
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 主引导记录(MBR)的反汇编分析
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MBR代码分析网上早就有了,但我找到的都是针对老版MBR的分析。这里所谓的
老版MBR,指的是早期的MBR,那时大容量硬盘还没有出现,MBR使用传统的
Int 13h接口访问硬盘。随着硬盘容量越来越大,传统的Int 13h已经无法完全
访问硬盘上所有扇区(Int 13h接口理论上可访问的最大硬盘容量约为8G)。因此,
扩展Int 13h规范出台以适应这种变化。MBR的代码也必须相应改动,必要时采
用扩展Int 13h来加载引导扇区。我称之为新版MBR。本篇分析的就是新版MBR。
MBR其实并不复杂,但要完全理解也需要一些底层的系统知识。code里的一些
技巧值得借鉴。
seapeak@88 转载时就保持完整
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; 设置栈SS:SP = 0:7C00
;
0000:7C00 xor ax, ax
0000:7C02 mov ss, ax
0000:7C04 mov sp, 7C00h
0000:7C07 sti
;
; DS = ES = 0
;
0000:7C08 push ax
0000:7C09 pop es
0000:7C0A push ax
0000:7C0B pop ds
;
; 将后面的代码复制到低端内存,为加载
; 活动分区的引导扇区腾出空间,因为引导
; 扇区也必须加载到0:7C00
;
0000:7C0C cld
0000:7C0D mov si, 7C1Bh
0000:7C10 mov di, 61Bh
0000:7C13 push ax
0000:7C14 push di
0000:7C15 mov cx, 1E5h
0000:7C18 repe movsb
;
; 跳到低端内存的代码继续执行
;
0000:7C1A retf
;
; 开始扫描分区表(Partition Table),寻找活动分区
;
0000:061B mov bp, 7BEh ; 600h+1BEh,分区表起始偏移为1BEh
0000:061E mov cl, 4 ; 分区表中有4个分区表项
loc_620:
0000:0620 cmp [bp+0], ch ; 是活动分区吗?(此时ch中的值为0)
0000:0623 jl loc_62E ; 活动分区的标志是80h,如果解释成有符号
数,则小于0
0000:0625 jnz loc_63A ; 引导标志的合法值只能是0和80h,其它的值
则出错
0000:0627 add bp, 10h ; 指向下一个表项(每一个表项的长度为10h字
节)
0000:062A loop loc_620 ; 依次扫描所有分区表项
;
; 没有发现活动分区,无法启动OS,按照规范调用Int 18h
; 早期的BIOS的Int 18h中断服务程序就是启动ROM-Basic,
; 现在的BIOS一般是打印错误信息
;
0000:062C int 18h
;
; 找到活动分区后,还要检查剩余分区的启动标志是否为0
; 不允许存在多个活动分区
;
loc_62E:
0000:062E mov si, bp
loc_630:
0000:0630 add si, 10h ; 下一个分区表项
0000:0633 dec cx
0000:0634 jz loc_64F ; 所以剩余分区都扫描完
0000:0636 cmp [si], ch ; 启动标志是否为0?
0000:0638 jz loc_630 ; 是则合法,检查下一分区
;
; 分区启动标志不合法,打印错误信息
; "Invalid partition table"
;
loc_63A:
0000:063A mov al, byte_7B5
loc_63D:
0000:063D mov ah, 7
0000:063F mov si, ax
loc_641:
0000:0641 lodsb
0000:0642
0000:0642 loc_642:
0000:0642 cmp al, 0
0000:0644 jz loc_642 ; 打印完错误信息后,进入死循环
0000:0646 mov bx, 7
0000:0649 mov ah, 0Eh
0000:064B int 10h ; 调用Int10h显示一个字符
0000:064D jmp short loc_641
;
; 开始加载活动分区的引导扇区
;
loc_64F:
;
; 将一个标志的初始值清0。这个标志表示是否尝试过备份的引导扇区
; [bp+10h]的字节肯定是没用的空间
;
0000:064F mov [bp+10h], cl
0000:0652 call sub_69B
0000:0655 jnb loc_681
loc_657:
0000:0657 inc byte ptr [bp+10h] ; 标志已经尝试过加载备份的引导扇
区
;
; 如果活动分区是FAT32分区,尝试加载备份的引导扇区
;
0000:065A cmp byte ptr [bp+4], 0Bh ;FAT32
0000:065E jz loc_66B
0000:0660 cmp byte ptr [bp+4], 0Ch ;FAT32(需用扩展Int 13h访问)
0000:0664 jz loc_66B
;
; 加载引导扇区失败,显示错误信息
; "Error loading operating system"
;
0000:0666 mov al, byte_7B6
0000:0669 jnz loc_63D
loc_66B:
;
; FAT32的备份引导扇区号=引导扇区号+6
;
0000:066B add byte ptr [bp+2], 6
0000:066F add word ptr [bp+8], 6
0000:0673 adc word ptr [bp+0Ah], 0
0000:0677 call sub_69B
0000:067A jnb loc_681
;
; 连备份的引导扇区也坏了,就没辙了!
;
0000:067C mov al, byte_7B6
0000:067F jmp short loc_63D
;
; 在把控制权交给引导扇区前,要先检查引导扇区的签名(signature)
; 防止把控制权交给已经损坏的引导扇区
;
0000:0681 loc_681:
0000:0681 cmp word ptr ds:[7DFEh], 0AA55h ;签名就是扇区最后的2个字节
0000:0687 jz loc_694
;
; 引导扇区损坏,则尝试用备份引导扇区
;
0000:0689 cmp byte ptr [bp+10h], 0 ;已经是备份的引导扇区?
0000:068D jz loc_657
;
; 备份引导扇区也坏了,死翘翘
;
0000:068F mov al, byte_7B7
0000:0692 jmp short loc_63D
;
; 交权给引导扇区,让它去完成OS的引导
;
0000:0694 loc_694:
0000:0694 mov di, sp ; di = sp = 7C00h
0000:0696 push ds
0000:0697 push di
0000:0698 mov si, bp ; 把活动分区表项指针传给引导扇区
0000:069A retf ; 跳到0:7C00
;
; 读取引导扇区的子过程
;
sub_69B proc near
0000:069B mov di, 5 ; 磁盘I/O错允许重试次数为5次
;
; 取硬盘的磁道参数
;
0000:069E mov dl, [bp+0] ; 分区的启动标志其实就是硬盘号
0000:06A1 mov ah, 8
0000:06A3 int 13h
0000:06A5 jb loc_6CA ; 如果取参数失败,认为BIOS肯定不支持扩展
Int 13h
; 只好用传统Int 13h
;
; 计算用传统Int 13h能访问的最大逻辑扇区号
; 计算公式为:(最大磁头号+1)*每道扇区数*(最大磁道号+1)
; 注意这个计算次序是有讲究的,因为(最大磁头号+1)*每道扇区数
; 的结果可以用16位寄存器就可以存放。如果先用磁道号来计算,
; 乘的结果就必须用两个寄存器来存放,导致第二步乘计算复杂化
;
0000:06A7 mov al, cl
0000:06A9 and al, 3Fh
0000:06AB cbw ; ax中为第道扇区数
0000:06AC mov bl, dh
0000:06AE mov bh, ah ; bh = 0,ah肯定为0
0000:06B0 inc bx
0000:06B1 mul bx ; (最大磁头号+1)*每道扇区数
0000:06B3 mov dx, cx
0000:06B5 xchg dl, dh
0000:06B7 mov cl, 6
0000:06B9 shr dh, cl ; dx中为(最大磁道号+1)
0000:06BB inc dx
0000:06BC mul dx ; (最大磁头号+1)*每道扇区数*(最大磁道号
+1)
;
; 判断引导扇区是否可以用传统Int 13h来访问
; 如果引导扇区的逻辑扇区号 >= 刚才算出的扇区号,必须用扩展Int
13h来读取
; 否则就用传统Int 13h来访问
;
; 注意一下双字数的比较方法!
;
0000:06BE cmp [bp+0Ah], dx
0000:06C1 ja loc_6E6
0000:06C3 jb loc_6CA
0000:06C5 cmp [bp+8], ax
0000:06C8 jnb loc_6E6
0000:06CA ;
; 用传统Int 13h来读引导扇区
;
loc_6CA:
0000:06CA mov ax, 201h
0000:06CD mov bx, 7C00h
0000:06D0 mov cx, [bp+2]
0000:06D3 mov dx, [bp+0]
0000:06D6 int 13h
0000:06D8 jnb locret_72B
;
; 读取失败可以重试,试完规定的次数后还失败就没办法了
;
0000:06DA dec di
0000:06DB jz locret_72B
;
; 重试前重置一下磁盘系统
;
0000:06DD xor ah, ah
0000:06DF mov dl, [bp+0]
0000:06E2 int 13h
0000:06E4 jmp short loc_6CA
;
; 检查BIOS是否支持扩展Int 13h
;
0000:06E6 loc_6E6:
0000:06E6 mov dl, [bp+0]
0000:06E9 pusha
0000:06EA mov bx, 55AAh
0000:06ED mov ah, 41h
0000:06EF int 13h
0000:06F1 jb loc_729
0000:06F3 cmp bx, 0AA55h
0000:06F7 jnz loc_729
0000:06F9 test cl, 1 ;必须支持Fixed disk access这个功能子集
0000:06FC jz loc_729
0000:06FE popa
;
; 扩展Int 13h读扇区
;
0000:06FF loc_6FF:
0000:06FF pusha
;
; 在栈中构造磁盘地址包(Disk Address Packet)
;
0000:0700 push 0
0000:0702 push 0
0000:0704 push word ptr [bp+0Ah]
0000:0707 push word ptr [bp+8] ; 要读扇区的LBA地址(4个word)
0000:070A push 0
0000:070C push 7C00h ; 引导扇区读到0:7C00h
0000:070F push 1 ; 读一个扇区
0000:0711 push 10h ; 包长度16个字节
0000:0713 mov ah, 42h
0000:0715 mov si, sp
0000:0717 int 13h
0000:0719 popa ; 这里用了一个小技巧,一下子从栈中弹出8
个word
; (地址包刚好是8个word)
0000:071A popa ; 这才是真正的恢复保存的通用寄存器的值
0000:071B jnb locret_72B
0000:071D dec di ; 不成功有重试的机会
; 注意这里也有个小技巧:dec指令不改变CF
的状态
0000:071E jz locret_72B ; 直到所有重试次数用完
;
; 重试前重置磁盘系统
;
0000:0720 xor ah, ah
0000:0722 mov dl, [bp+0]
0000:0725 int 13h
0000:0727 jmp short loc_6FF
loc_729:
0000:0729 popa
0000:072A stc
locret_72B:
0000:072B retn
sub_69B endp
0000:072C db 'Invalid partition table',0
0000:0744 db 'Error loading operating system',0
0000:0763 db 'Missing operating system',0
0000:07B5 byte_7B5 db 2Ch
0000:07B6 byte_7B6 db 44h
0000:07B7 byte_7B7 db 63h
0000:07FE dw 0AA55h ;MBR的signature
--------------------------------------------------------------------------------
---------
References:
* Enhanced Disk Drive Specification Ver 3.0,
http://www.phoenix.com/resources/specs-edd30.pdf.
* BIOS Boot Specification Version 1.01,
http://www.phoenix.com/resources/specs-bbs101.pdf.
------------------------------End of
file------------------------------------------------
--
实迷途其未远,觉今是而昨非
|
|