15

我是一名电气工程师,最近发现需要修改 MBR 中的代码。基本上我需要能够在硬盘驱动器上执行代码之前,操作系统启动并接管。

我完全理解这需要用汇编编写,并且考虑到 MBR 中大约 446 字节的代码空间,我只是希望调用 MBR 之外的其他代码。我的问题是写入 MBR 的最佳方式是什么?如果我想更改磁盘 HDD_1 的 MBR ... 将 HDD_1 从属到另一台机器然后写入它,或者在当前机器中直接写入(在 Windows 之外)是否更好。基本上,我想我会插入一个呼叫,而不要理会 MBR 的其余部分。

任何建议,将不胜感激

克里斯

我很清楚这将是困难的。我的问题是将指令放入 MBR 的最佳方式是什么?不用说,Windows 不允许直接访问磁盘。您如何建议我将指令写入 MBR ?是否可以引导 *nix 的 live CD 并从那里写入 MBR?

4

11 回答 11

20

有多种写入驱动器引导扇区的方法,我在尝试自制操作系统开发时使用了一个通用参考:http ://wiki.osdev.org/

我个人只是在linux下启动并使用dd:

  1. 先备份

    dd if=/dev/sda of=~/windows_bootloader.bin bs=512 count=1

  2. 拆卸引导加载程序

    ndisasm -b16 -o7C00h ~/windows_bootloader.bin > ~/windows_bootloader.asm

  3. 进行修改并重新组装

    nasm ~/windows_bootloader.asm -f bin ~/modified_bootloader.bin

  4. 覆盖引导加载程序

    dd if=~/modified_bootloader.bin of=/dev/sda bs=512 count=1

这假设您的“sda”是正确的块设备。请注意,步骤 4 不只是将文件复制到 /dev/sda (它可以,但是如果输出二进制 > 512 Bytes ,那么您可能会覆盖的不仅仅是第一个扇区)

显然,您不想在实时系统上调试这种方法。使用某种 x86 仿真器(如 bochs、qemu 或 VMWare Server)将为您省去很多麻烦。

然而,正如迈克尔伯尔所说,这可能是一个坏主意。修改 Windows 引导加载程序可能会让您几乎没有空间或根本没有空间供您自己的代码使用。

于 2009-02-20T09:16:02.060 回答
9

BIOS 通过读取每个引导设备的第一个扇区(512 字节)并检查一组特定的签名字节来从硬盘驱动器(或软盘驱动器)引导计算机。如果找到这些字节,则将 512 字节扇区复制到 ram(在特定位置),然后 BIOS 跳转以运行它。

除了签名字节之外,扇区中的 446 个字节可供您用作引导程序,但引导程序必须完全适合该扇区!由于 446 字节不是很大,您必须调用 BIOS 以将其他扇区从硬盘驱动器(或软盘驱动器或其他)复制到 ram 中以运行它们。

一旦你在 ram 中加载了足够的内容来运行你的程序,跳到它,你就可以开始了。

这就是操作系统如何从字面上“通过自己的引导程序将自己拉起来”

http://en.wikipedia.org/wiki/Master_boot_record

现在,您没有理由不能用 C 或 C++(或大多数其他语言)编写引导代码,除非使用汇编,您可以确切地知道将生成什么代码并且很容易进行 BIOS 调用。

我建议你写一个 512 字节的磁盘驱动器到 ram copier,将你的程序从磁盘加载到 ram 中,然后跳转到程序的起始地址。然后,您可以用您想要的任何语言编写程序。请记住,当您的启动代码开始运行时,这 512 个字节是您唯一可以依靠的,就像在 ram 中一样。(好吧,BIOS 在那里,您可以进行 BIOS 调用。BIOS 还会在 ram 中的某些位置放置一些系统信息……)自己将它们加载到ram中。

此外,测试代码的最简单方法可能是将其放在软盘上并启动。

要回答您最初的问题,您可以在某处保留旧 MBR 的备份副本,并且您的新 MBR 可以将您的功能加载到 ram 中,运行它,然后加载原始 MBR 并运行它,允许 Windows 继续启动。

此外,迈克尔·伯尔是对的,得到你想要的东西将是一场噩梦。

为了回答您关于如何在硬盘驱动器上实际写入的评论,有几个“原始写入”程序可以复制到磁盘上的扇区。此外,您可以从 linux live cd 启动并使用 dd 将数据写入您选择的块设备上您选择的扇区。——简单的那部分。

于 2009-02-20T05:15:15.507 回答
5

基本上我想我会插入一个电话,而不要管 MBR 的其余部分

这个子程序调用会调用什么?此时内存中唯一的代码是 MBR 或 ROM 中的任何代码。

在您花费太多时间之前,请仔细考虑您是否真的需要这个或那个没有更好的选择。写入 MBR(除了 OS 加载程序放入的 MBR)的第三方代码通常不被用户接受,因为:

  • 防病毒程序经常将其标记为可疑代码,因为这是病毒用来控制机器的一种技术
  • 程序使用了将自己插入 MBR 并将附加代码和数据存储在磁盘的“保留”扇区中的技术(因为在 MBR 中确实没有太多可以做的事情和存储)。不幸的是,由于没有好的、标准的方法来实际保留这些扇区,这种技术(有时用于复制保护)可能会导致磁盘上的数据结构损坏(即,驱动器上的所有数据都消失了)。用户真的很讨厌这样。我相信 Quicken 曾经使用过一种保护方案,它做了类似的事情并面临相当大的反弹。

因此,如果您决定继续走这条路,请谨慎行事并为头痛做好准备。

于 2009-02-20T05:25:46.730 回答
4

为什么不用说 Windows 不允许直接访问磁盘?CreateFile()的 MSDN 页面这样说:

对磁盘或卷的直接访问受到限制。有关详细信息,请参阅帮助和支持知识库 http://support.microsoft 中的“更改文件系统和存储堆栈以限制 Windows Vista 和 Windows Server 2008 中的直接磁盘访问和直接卷访问”。 com/kb/942448

Windows Server 2003 和 Windows XP/2000:以这种方式直接访问磁盘或卷不受限制。

KB942448解释了这些限制,它们似乎允许具有足够权限的进程写入 MBR 或分区引导扇区。

于 2009-02-20T06:48:21.010 回答
2

我发现了一个类似的问题,可能会有所帮助:

修改Windows的MBR

但是,您可能需要详细说明您打算做什么。正如我发现自己的引导加载程序代码可能非常繁琐。另外,如果可能的话,我当然会用软盘测试它。

至于实际上是从 Windows 完成这一切,我有点无能为力。到目前为止,我几乎所有的编程经验都是在 Unix 环境下进行的。

于 2009-02-20T05:18:28.340 回答
2

我认为您最好的方法是使用 linux,它可以nasm用于编译、集群复制(这也意味着 MBR),如果您不想弄乱实际分区dd,甚至可以使用引导加载程序菜单(例如)。lilo

去年我不得不制作自己的启动顺序。基本上,我有这个:

LILO boot menu:
    -> WindowsXP
    -> linux

我想在 MBR 上单独做一些事情,而不影响实际安装,所以我创建了一个新的(小)分区并将其添加到 LILO 列表(这里省略细节),它给出了这个:

LILO boot menu:
    -> WindowsXP
    -> linux
    -> TESTMBR

这样一来,由于每个分区也都有自己的 MBR,我可以将任何我想要的古怪代码放在那里,而不会有将自己锁在外面的风险(修复起来有点烦人)。

为了真正改变那个 MBR,我这样做了:

  1. 备份实际 MBR,例如dd if=/dev/sda3 of=/home/you/mbr−backup count=1
  2. 编辑文件中的代码:boot.asm
  3. 使用 nasm 编译:nasm boot.asm -o boot.bin -f bin纠正错误
  4. 将新创建的 MBR 复制到驱动器:dd if=boot.bin of=/dev/sda3
  5. 重启。
  6. 在菜单中选择 TESTMBR。
  7. 看看情况如何。

当然,您可以直接在驱动器的 MBR 而不是分区的 MBR 上执行此操作,就像我在这里所做的那样,但对于我自己的情况,它更实用。

关于实际的代码跳出 MBR,您需要使用INT 13,42中断,它将任何集群加载到磁盘上。为了我的测试目的,我只需要显示它的内容,但如果你愿意,我可以仔细看看。

希望能帮到你,抱歉回复太长了。

于 2010-04-15T12:42:56.620 回答
2

如果你可以制作一个软盘、光盘或记忆棒来引导到一个 MS 命令提示符,并且有一个匹配的 MS 调试版本,你可以像下面这样读写 MBR。运行 win95 或 win98 的机器应该能够为您创建启动软盘。只需将调试从 windows\command 目录复制到软盘。

内部调试:使用 r 命令更改寄存器值。将 ax 设置为 0201 用于读取,或 0301 用于写入。将 es:bx 设置为您希望使用的内存(缓冲区)的起始地址。0000:7C00 可能会起作用,因为这通常是在引导过程中读取下一个扇区的区域。将 cx 设置为 0001 以读取/写入一个 512 字节的扇区。将第一个物理硬盘的 dx 设置为 0080。

使用“a”命令汇编一行代码:INT 13h

使用“p”命令继续。根据您选择的 AX,将读取或写入数据。

您可以读取内存,“n”命名文件,“w”写入文件,然后在其他程序中编辑 mbr 的副本。完成后,使用调试的“n”和“L”命名并加载编辑的 MBR 文件,并使用 ax=0301h 调用 int 13h 将图像写入正确的扇区。

于 2011-06-10T18:22:55.217 回答
2

你确定你需要写MBR吗?我是带分区的磁盘,还可以修改分区的VBR(Volume Boot Record)。这可能更容易/更安全,因为您不需要触摸 MBR,即使您完全破坏了测试分区,您的机器仍然能够引导到其他分区(和操作系统)。

于 2012-10-30T10:30:10.303 回答
1

您可以查看GRUB。我绝不是 MBR 代码方面的专家,而且我已经很久没有运行 *nix 操作系统了,但我记得引导加载程序分阶段工作,并在操作系统启动之前从磁盘加载阶段。您可以编写自己的阶段以在操作系统加载之前完成您需要完成的工作,然后启动操作系统。我不确定这个选项有多实用,特别是因为代码似乎处于重写中间,因为根据文档,“旧”版本是不可维护的。

于 2009-02-20T07:18:31.747 回答
1

在 Windows(XP) 中完全可以编辑 MBR。因为这是使用 HxD 十六进制编辑器,您可以在 MBR 上复制粘贴十六进制文件,甚至在您的活动系统驱动器上(谨慎使用!:))http://mh-nexus.de/en/hxd/

作为起点,a 将获取源可用的 MBR,例如 Grub。(所以让 grub 对 Windows 进行 botoing)这样你就有了一个很好的起点来对你的 MBR 进行更改。编辑 MBR 应该不会太难,因为这个小软件非常基础。不过需要一些 16 位 (DOS) 汇编程序技能。另一种方法是让 grub 运行一些额外的有效负载而不改变 MBR,但我 100% 确定这是否可能;请参阅 Grub 手册。

于 2010-04-15T12:12:09.383 回答
0

Windows 有一个未记录的实用程序“调试”,它允许:1) 将硬盘的任何扇区(包括 mbr)加载到内存。2)将该代码视为二进制或汇编。3)在ram.4中组装一些代码)将该代码写入任何扇区(也写入mbr)。要启动此实用程序,请在命令提示符处键入调试,然后按 Enter。提示变为“-”。然后键入“帮助”。你会得到关于如何使用它的信息,

于 2015-02-15T11:53:45.320 回答