1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 活动分区的引导记录 DBR 分析

活动分区的引导记录 DBR 分析

时间:2024-07-29 21:20:15

相关推荐

活动分区的引导记录 DBR 分析

原文链接:/win7/

一、 DBR 的结构

下面来看一看 DBR 的结构,如下:

第二部分的变量区域,是 DBR 被加载到 0x7c00 执行时,由于代码中需要使用临时的地方存储数据。

因此,开辟了这部分作为局部变量区,但其中也包含了一些常量数据。

二、 DBR 代码分析

现在来看一看 DBR 的代码部分。

(1)DBR 前期准备工作

由第 1 条指令jmp short 0x54跳到 0x54 处执行。

这段代码目的是,设置 sp 为 0x7c00,并且 cs 为 0x07c0,然后继续往下执行。但此时 cs 已经变为 0x07c0,而不是之前的 0x0000

(2)检测文件系统

这里使用了变量 [0x0e],这个变量就位于前面所说的变量区域,用来放置 驱动器(硬盘)的 ID 值。

代码将检测分区是否为 NTFS 文件系统。这个 [0x03] 是常量,在本例 windows 7 中,它的值是 "NTFS" 字符串。

不是 NTFS 系统的话,将打印错误信息,然后 hlt

(3)检测是否支持 int 0x13 扩展

和 MBR 代码一样,这里也要检测 BIOS 是否支持 int 0x13 扩展功能,如果不支持的话,将打印出错信息,最终将 hlt 停机处理

(4)下一步,获取磁盘参数

这些磁盘参数,包括:

★ 磁盘的 cylinders 数量

★ 磁盘的 heads 数量

★ 每道的 sectors 数

★ 磁盘总共有多少扇区

★ 每个扇区有多少字节。

先来看一看,蓝色部分标注的代码,这里有一个巧妙之处。

这里实际上是预留了0x18 + 0x02 = 0x1A个字节,即:26 个字节。

为什么不直接用sub sp, 0x1a来预留0x1a个字节呢,下面继续解读下去。

这里使用了 int 0x13 的第 0x48 号功能来获取磁盘(硬盘)的参数,这些磁盘参数在上面已经列出。

int 0x13 的 0x48 号功能需要一个缓冲区来存放获取的参数值

那么,现在来看一看这个缓冲区结构的定义,用 c 来描述如下:

这个磁盘参数结构总共是 26 个字节,sectors 数是个 64 位值。

回到前面的代码:push word 0x1a执行完后,sp 实际上对应着的buf_size这个变量,表示 driver_parametes 这个结构体的字节数,即:sizeof(buffer)。

因此,通过 push 来定位到 buf_size 变量,实际上等于buf_size = 0x1a将 buf_size 变量赋值为 0x1a

而后面经过add sp, 0x1a修复 stack 后,代码:pop ax,正好用来取出 buffer 的最后一个 word 值,即:ax = bytes_per_sector

这段代码,玩弄了一点小技俩。

最后,ds:si 指向这块缓冲区的地址。

从上面看出,这块缓冲区就是在 stack 开辟出来的 26 个字节的空间,即:0x00:sp

执行完 int 0x13 后,恢复了 stack,如果有错,则转到 0x8a,最终是打印错误信息,然后 hlt

此时,ax 的值就是 bytes_per_sector,即:每扇区有多少字节。

[0x0b] 地址是 DBR 中存放的值,在本例中它就是 0x200,也就是 512

(5)以实例看一看,我的 bochs 上为 windows 7 分配的磁盘,它的参数是什么?

可以看出:

buf_size = 0x001a = 26 bytes

flags = 0x0000

cylinders = 0xaa553fff = 2857713663 个 cylinders

heads = 0x00000010 = 16 个 heads

sectors_per_track = 0x0000003f = 63 个 sectors

sectors = 0x00000000_013fffb0 = 20971440 个 sectors

bytes_per_sector = 0x0200 = 512 bytes

那么,这块磁盘大小为:sectors * bytes_per_sector = 209771440 * 512 = 10g

但是,cylinders 居然有 0xaa553fff 这么大的数量,这显然不对的。

(5)读分区1 剩余的扇区数

分区1 的 DBR 引导记录,由 MBR 读入,接下着 DBR 引导记录负责将其余的扇区读到内存 0x7c00 下一个扇区的位置。

0x7c00 + 512 = 0x7e00这就是下一个扇区将要读入的存放地方。

由上一篇文章中得知,分区1 位于磁盘的第 2048 扇区,即:0x800 号扇区。

因此,下一步将以 0x800 为起始,接着读 0x801 扇区到 0x7e00,以此类推:0x802 扇区读到 0x8000 ... ...

接着看代码,如下:

这个 ax 值正是 0x200 即:512 bytes, 内存 [0x0f] 是 DBR 使用的变量。

代码:shr word [0x0f], 0x4这里作用是调整为 segment 的增量,即:0x200 调整为 0x20那么,加上 0x7c0 这个 segment 值变成为 0x7e0,将作为 segment

接着,将 dx = ds,此时,dx 为 0x07c0,将要加上 0x20 作为 segment 值使用。

这段代码将要读 0x2000/0x200 也就是 16 个扇区到内存。

内存 [0x11],用于记录,扇区 offset 值,这个值就是基于 0x800(2048),而 [0x16] 用来记每次读多少次。

实际的读扇区工作交由过程 func_0x11d() 执行。 下面将看一看 func_0x11d() 是如何读取

(6)读扇区子过程 func_0x11d()

这个 func 有点长,但是逻辑很清晰:就是读 n 个扇区,这个 n 值来自 [0x16],上面已经看到 [0x16] 被初始置为 1

代码:mov eax, [0x11]这个 [0x11] 是前面说的 offset 值

而add eax, [0x1c]这个 [0x1c] 就是 0x800 值,它是随着 DBR 被一起读到内存,这是常量值。这里算出将要读哪个扇区

这段代码读入 16 个扇区到内存。

(7)接下来,看看读完扇区后,DBR 做些什么工作。

很抱歉,我并不了解 int 0x13 的 ah = 0xbb00 和 ah = 0xbb07 的用途,这里无法做出分析。如果您知道,请不吝留言赐教。

代码后面部分,是:从 0x8c28(0x7c00 + 0x1028)开始到 0x9c00 清 0

最后转到0x7c0:0x27a处继续执行。

地址 0x7c0:0x27a 实际上是分区1 的第 2 个扇区的偏移 0x7a 处。

到此为止,DBR 的工作就完成了。下一步工作将是走到 下一个扇区继续执行。

(8)下面看一看,DBR 的错误处理代码

代码根据错误的类型,选择相应的错误信息打印出来,最后是 hlt 处理。

下面是错误的信息及标志位:

三、最后总结一下 DBR 的大致工作

它的主要工作是:先判断一下磁盘的参数符不符合,然后,从下一扇区开始读 16 个扇区到 0x7e00 处。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。