在Windows中使用Vagrant自动化系统内核调试工作

发布于 2020年8月    阅读 53次

所有参与过Windows内核测试的人员都知道,设置和管理用于内核调试的虚拟机可能很耗时。

vagrant是一个工具,用于创建和部署虚拟化开发环境的。拿VirtualBox举例,VirtualBox会开放一个创建虚拟机的接口,Vagrant会利用这个接口创建虚拟机,并且通过Vagrant来管理,配置和自动安装虚拟机。

总之,Vagrant是一个免费的开源工具,可自动创建和自动化VM。本文将向你介绍Vagrant,以及如何利用其功能自动执行内核调试设置。

Vagrant允许你将虚拟机视为“一次性(disposable)”,因为可以自动删除它们并重新创建它们。然后,你可以轻松地在多台计算机上设置一致的VM,与其他人共享它们,甚至将你的虚拟机部署到AWS等云提供商。

本文已假定你已经安装了Vagrant和虚拟机监视程序,你可以在此处下载Vagrant。

Vagrant支持的虚拟机监视程序包括:

  1. VirtualBox(推荐);
  2. VMware;
  3. Hyper-V。

Hyper-V提供程序在网络功能方面存在很大缺陷,因此,如果可能,建议使用其他虚拟机监视平台,我将在本文中使用VirtualBox。

准备基础镜像(base image)

简单来说,基础镜像就是没有From或者FROM scratch开头的Dockerfile所构建出来的镜像。比如alpine,这个很小的linux镜像目前只有4M左右。

Vagrant有一个“盒子”的概念,它本质上是最基本的磁盘映像,理想情况下,它只包含引导的绝对最小值,而无需安装任何其他程序。这些“盒子”构成了虚拟机模板,我们可以通过shell脚本构建这些模板。

你可以使用Vagrant Cloud中的一个框来节省大量时间。但是,如果找不到符合你规格的预制盒子,请继续。

默认情况下,Vagrant提供了一个Ubuntu盒子,但是由于我们对Windows感兴趣,因此这实际上对我们没有任何用处。Vagrant Cloud是一个由其他用户创建的可公开使用的“盒子”组成的web服务,并且有一些可用的Windows“盒子”。如果这些内容足以满足你的用例,请务必继续使用Vagrant Cloud中已准备好的“盒子”。但是,如果你需要更多控制权,那么创建自己的“盒子”是你唯一的选择。幸运的是,这并不难。

首先创建一个新的虚拟机,选择安装操作系统所需的最小RAM量,并分配适当数量的磁盘空间——大约50GB应该足够了,但要确保它是动态分配的。另外,你还需要附加一个在NAT模式下配置的虚拟网卡。本文,我选择了Windows 10 LTSC 2019 Evaluation作为我的客户操作系统,因此一旦创建了VM,就插入安装ISO的虚拟磁盘。启动VM并运行正常的安装过程,但是在创建用户帐户之后,请确保将用户名指定为“vagrant”,密码为“vagrant”。

安装完操作系统并在桌面启动后,还需要完成几项任务。根据Vagrant的官方说明,你必须:

  1. 为虚拟机监视程序安装来宾工具;
  2. 确保将虚拟网络适配器配置为专用网络;
  3. 完全禁用UAC;
  4. 禁用复杂的密码;
  5. 禁用关机跟踪程序。

此外,必须使用WinRM启用远程管理,以允许Vagrant在VM中执行脚本。为此,请在提升的命令提示符中执行以下命令:

winrm quickconfig -q

winrm set winrm/config/winrs @{MaxMemoryPerShellMB="512"}

winrm set winrm/config @{MaxTimeoutms="1800000"}

winrm set winrm/config/service @{AllowUnencrypted="true"}

winrm set winrm/config/service/auth @{Basic="true"}

sc config WinRM start= auto

完成这些任务后,你便完成了设置盒的操作,因此应关闭它。请注意,此时不应配置内核调试,因为盒子应该是可重用的基础映像,而不是出于特定目的。

现在回到你的主机,让我们实际创建一个盒子。

vagrant package --base Win10LTSCBase --output windows.box

vagrant box add invokestatic/win10ltsc windows.box

你需要更改参数以适合运行环境,包括更改VM名称(“Win10LTSCBase”)以及输出框名称(“invokestatic / win10ltsc”)。这将创建我们刚刚创建的虚拟机的“快照”,并将其封装到一个名为invokestatic / win10ltsc的盒子中。

充分利用盒子

现在我们的盒子已经设置好了,让我们充分利用它。首先,在包含以下内容的空目录中创建Vagrantfile:

你需要稍微修改一下此文件以满足你的需要,尤其是win10.vm.box名称以及可能的内核调试端口。

Vagrant.configure("2") do |config|

 config.vm.guest = :windows # tell Vagrant this is a Windows-based guest

 config.vm.communicator = "winrm" # use winrm for management instead of ssh

 config.winrm.password = "vagrant" # the credentials specified during OS install

 config.winrm.username = "vagrant"

 config.vm.define "win10" do |win10|

 win10.vm.box = "invokestatic/win10ltsc" # edit this to be the name of the box you created

 win10.vm.provision "shell", path: "guest/kdbg.bat" # this batch file will be run inside the VM

 win10.vm.network :forwarded\_port, guest: 49152, host: 49152 # expose kernel debugging port to host

 end

end

创建一个名为guest的新目录,该目录将存储将在guest内部运行的脚本。在这个目录中,使用以下内容创建文件kdbg.bat。这使我们能够在首次创建VM时在guest虚拟机内配置内核调试选项。

bcdedit /debug on

bcdedit /dbgsettings net hostip:192.168.56.1 port:49152 key:1.1.1.1

copy C:\\vagrant\\guest\\onboot.bat C:\\onboot.bat

schtasks /create /sc onstart /tr "C:\\onboot.bat" /tn vagrantonboot /ru SYSTEM /f

shutdown /r /t 0

你可以根据需要更改这些设置,但通常仅在需要时才使用网络调试。你可以更改端口和密钥,但请注意,如果更改端口,则还需要更新Vagrantfile中的端口转发。如果你需要调试Windows 7或更早版本,则需要配置COM调试,Vagrant可以实现这些调试,但这不是本文要讲的内容。

设置完成后,继续在你的项目目录中运行vagrant。这将使用Vagrantfile中指定的所有设置创建一个新的VM。

附加调试器

片刻之后,应该创建并运行你的VM,并在启用内核调试的情况下对其进行完全设置。我们可以通过按Ctrl + K并输入1.1.1.1指定端口49152来将WinDbg附加到我们的主机上。

如果一切按计划进行,你将看到一个连接的内核调试会话!

自动化驱动程序部署

如果你只想一步一步地阅读Windows代码,那就没问题了。但是,你可能需要调试内核驱动程序。幸运的是,Vagrant自动将项目目录中的所有文件映射到C:\ Vagrant中,因此你可以将驱动程序文件拖放到该目录中,并且该文件将自动可供来宾使用。

请注意,由于此映射是作为网络共享实现的,因此Windows内核无法从中加载驱动程序,因此在加载之前,必须将其复制到C: drive上的某个位置,这也可以自动化。

在来宾目录中,使用以下内容创建文件onboot.bat,s将被部署的驱动程序的名称是MyDriver.sy,它应该位于项目目录的根目录中。:

sc stop MyDriver
sc delete MyDriver
sc create MyDriver binPath= "C:\\Windows\\System32\\drivers\\MyDriver.sys" type= kernel
copy C:\\vagrant\\MyDriver.sys C:\\Windows\\System32\\drivers
sc start MyDriver

这会将驱动程序文件从项目目录复制到系统驱动程序目录,创建新服务并加载它。我们的kdbg.bat创建一个Windows任务计划程序任务,该任务将在启动时运行以执行此任务。

总结

最后,我们创建一个批处理文件以自动执行VM创建、驱动程序部署和调试器附件。在根目录中,创建一个名为start-debugger.bat的批处理文件,其中包含以下内容:

start vagrant up & vagrant powershell --command "schtasks /run /tn vagrantonboot"
"C:\\Program Files (x86)\\Windows Kits\\10\\Debuggers\\x64\\windbg.exe" -k net:port=49152,key=1.1.1.1
vagrant halt -f

执行后,此脚本将按以下顺序进行:

  1. 启动VM(如果不存在则创建它);
  2. 部署并启动驱动程序;
  3. 附加WinDbg;
  4. WinDbg关闭时停止VM。

至此,我们已经完全自动化了内核调试设置,仅需几秒钟即可进入调试器。具体视频,请点此查看

在此处查看GitHub项目以及所有项目文件,它包含本文中未介绍的其他一些有用的脚本。