QEMU安装
前往官网下载windows x86的安装程序,并在电脑上运行安装程序。
虚拟机创建与操作系统安装
创建虚拟磁盘
使用qemu-img指令创建一个虚拟磁盘test.img,默认设置为raw格式,同时指定存储空间大小为60G。(注意此时只是一个虚拟磁盘,并没有产生占用空间,所以硬盘占用为0G)
下载操作系统镜像文件
安装操作系统需要对应的镜像文件,从网上寻找到win7.iso和ubuntu_amd64.iso。
windows安装
使用qemu-system-x86_64指令启动64位机的模拟程序,设置内存大小为8G,虚拟磁盘为test.img,光驱为win7.iso,4核cpu。另外指定为从光驱启动,这样可以运行win7的安装程序。
- qemu-system-x86_64 -m 8G -hda test.img -cdrom win7.iso -smp 4 -boot d
根据提示安装win系统。另外,在安装时划分磁盘,为linux系统预留空间。
ubuntu安装以及双系统启动程序设置
使用qemu-system-x86_64指令启动64位机的模拟程序,设置内存大小为8G,虚拟磁盘为test.img,光驱为ubuntu_amd64.iso,4核cpu。另外指定为从光驱启动,这样可以运行ubuntu的安装程序。
值得注意的是:qemu-system-x86_64不支持arm64格式的镜像文件。
qemu-system-x86_64 -m 8G -hda test.img -cdrom ubuntu_amd64.iso -smp 4 -boot d
安装时,为了正确启动双系统,我们需要进行如下准备与操作:
- 查看win7系统信息可以发现为bios启动,由MBR引导。win7安装系统时会自动在C盘前划分出一块100MB大小的活动分区。该活动分区中存有MBR,相关引导文件以及windows内核。bios启动时不支持双系统。一般而言,bios会默认读取第一扇区的512字节。如果该扇区为MBR则启动成功,否则失败。
- 根据bios启动的方式我们不难发现,此方式无法启动双系统。这就是为什么我们会遇到安装完ubuntu之后再运行虚拟机,会自动进入win7系统的问题了。因为BIOS会默认读取win7的MBR,然后拉起win7。
- 要解决这个问题,我们要么得设置启动方式为UEFI启动(该启动方式支持多操作系统启动),要么让ubuntu来改写MBR,让MBR跳转到efi分区中。简单来说,UEFI不像BIOS一样把代码存在ROM中,而是在硬盘上设置了一个.efi格式的文件,该文件中存有UEFI启动代码以及多个操作系统的boot_loader(每个操作系统都有一个boot_loader,例如win7的MBR,ubuntu的GRUB_2)。启动时,可以选择由哪个boot_loader启动。
- 但是我们安装的win7为bios启动,如果我们安装了用UEFI启动的linux,很可能不兼容出问题。所以我们只能采取第二种方法:修改MBR,让它跳转至GRUB。(幸运的是这个过程ubuntu会帮我们自动完成)
- 安装ubuntu时,我们将硬盘的剩余空间进行划分,挂载\root以及设置一个.efi的分区。(当然如何硬盘够大,可以分别设置分区挂载\boot,\swap,\user,\home。这些分区具体功能不多赘述)然后进行安装。
- 完成步骤4之后,我们启动时MBR会跳转入GRUB。多亏了GRUB_2支持多级引导功能。简单而言,GRUB不仅支持ubuntu启动,同时它也可以启动winload.exe。GRUB拉起winload.exe,然后再由winload.exe拉起win7系统。所以到此为止,双系统安装已经成功了。
windows启动方式
依旧使用x86_64模拟器启动虚拟机,启动时可以使用参数来配置虚拟机。但是默认的bios-256k不支持win7,所以要指定bios.bin
qemu-system-x86_64 -m 8G -smp 4 -boot c -hda test.img -bios bios.bin
ubuntu启动方式
qemu-system-x86_64 -m 8G -smp 4 -boot c -hda test.img [-bios bios.bin]
MBR读取
MBR简介
MBR,主动引导记录,可以帮助引导操作系统启动。是boot_loader的一种。通常处于硬盘第一扇区。
拿到管理员权限
读取MBR需要管理员权限。
这是本机的硬盘分区信息,sda1,sda2是win7的分区。sda3估计是系统为了分区而划分的缓冲区。sda5是efi分区。sda6挂载了\root
sudo su root 输入密码,进入管理员模式
使用objdump反汇编MBR
反汇编就是将一份机器编码的文件翻译为汇编语言。我们首先读取磁盘的前512个字符,并保存。随后使用objdump工具,依照二进制的格式去反汇编该文件即可。
首先使用dd命令读取磁盘的前512个字符,并将其存入名为mbr的文件中。当然,可以选择用hexdump进行十六进制编码。(有时候mbr打开是乱码,无法显示。这时候用hexdummp进行十六进制编码就可以了)
可以看见,结尾为aa55,基本确定这是MBR文件了
另外,我们只需要反汇编前446个字节即可,所以我们还要重复上面操作,拿到前446个字节的数据
紧接着,安装binutils包,从而可以使用objdump工具进行反汇编。
调用objdump指令进行反汇编,注意使用-b binary参数,强制以二进制文件格式读取mbr文件。
dd if=/dev/sda of=/mbr count=512 bs=1
hexdump /mbr > /mbr.hex
apt install binutils
objdump -D -b binary -mi8086 mbr (> mbr.asm),可以选择将反汇编之后的文件进行保存
MBR结构分析
概述
MBR中主要分为三个部分:引导加载程序,硬盘分区表,结束标志。其中引导加载程序是引导操作系统启动,硬盘分区表则存储硬盘上所有分区的起始和终止位置,以及其他与分区相关的信息。结束标志则是标志MBR的结束。
硬盘分区解读
机械硬盘大致分为一个磁盘加一个磁头。磁盘用来存储数据,磁头用来读取数据。磁盘分为两面,每一面都可以存数据。同时磁盘存数据是一圈圈存的,每一圈叫做磁道。每个磁道上分了多个扇区,每个扇区大小是512字节。而MBR就在第0磁道的第一扇区,共512字节。该512字节大致可以分为三类,我们主要解读硬盘分区表,共64字节。
64字节可以分为4块,每一块记录了一个分区的信息,共16字节。
依照顺序
字节位置 | 代表含义 |
---|---|
1 | 00 代表非活动分区, 80代表活动分区 |
2 | 分区起始磁头号 |
3,4 | 分区起始扇区号 |
5 | 文件系统标志位 07代表NTFS结构 |
6 | 分区结束磁头号 |
7,8 | 分结束始扇区号 |
9,10,11,12 | 分区起始相对扇区号 |
13,14,15,16 | 分区总扇区数 |
硬盘分区表数据如图(第一行倒数为开头”2000”):
到所有的分区都是非活动分区
一共有三个分区,大小分别为:
- 0x00032000 = 204800个扇区 = 204800512个字节 = 204800512/1024/1024 = 100MB
- 0x03bcd800 = 62707712个扇区 = 29G
- 0x03bff002 = 62910466个扇区 = 29G
这些数据与上面的分区结构符合,至于为何sda3-6被计算为一个分区,是因为linux修改MBR时没有修改硬盘分区表,显示的是原本安装win7时的分区信息。
这也解释了为什么就算没有活动分区也能顺利启动,可能GRUB不需要活动分区标志吧。(好像说是根据配置文件找内核的)