new blue pill在Intel系列CPU上无法卸载问题

来源:互联网 发布:c语言心形图案 编辑:程序博客网 时间:2024/04/28 05:15

实验环境win7 sp1 x64,newbluepill-0.32,VS2013,WDK8.1

NewBluePill源代码编译后,使用InstDrv成功载入生成的两个驱动:dbgclient.sys和newbp.sys。通过bpknock.exe查看运行结果,成功安装了bluepill。

但卸载时出了问题,dbgclient.sys驱动可以成功卸载,但newbp.sys已卸载系统就停下不动了。

目的是基于newbluepill做实验,但这很不方便,不能每次修改完代码都重启一次吧。不是什么高难度的工作,只是没找到有人告诉如何做,分享一下。


下面进入正文:

查阅相关资料在书《NewBluePill深入理解硬件虚拟机》的第90页中看到了解释。书中说默认情况下NewBluePill在Intel平台上是不能正常关闭的,并分析了不能关闭的原因。

按照书中分析的原因,对代码进行了一些修改,成功实现了卸载,不能卸载的具体原因,可参照书上的描述,就不重复了,下面只给出修复思路和代码。

书中分析后得出的结论是:驱动卸载函数会为每个CPU调用编号为NBP_HYPERCALL_UNLOAD的VMCALL,不能成功卸载的原因是没有对该VMMCALL进行处理。并给出了bluepill中另一个可以卸载虚拟机的函数,Hvm->ArchShutdown。

所以修复思路就是将编号为NBP_HYPERCALL_UNLOAD的VMCALL注册为处理函数为Hvm->ArchShutdown。后来发现NewBluePill实现了对vmmcall的处理函数,只是没有注册而已,该函数为hypercalls.c里的HcDispatchHypercall,所以注册为这个函数就可以,该函数里已经写好了对卸载事件的处理。

Bluepill中为各个VMM Exit事件注册处理函数的函数是VmxRegisterTraps。

原有代码中为VMCALL注册处理函数的过程为:

1.        定义一个数组:

TableOfVmxExits[]= {

    EXIT_REASON_VMCALL,

    EXIT_REASON_VMCALL,

    EXIT_REASON_VMLAUNCH,

    EXIT_REASON_VMRESUME,

    EXIT_REASON_VMPTRLD,

    EXIT_REASON_VMPTRST,

    EXIT_REASON_VMREAD,

    EXIT_REASON_VMWRITE,

    EXIT_REASON_VMXON,

    EXIT_REASON_VMXOFF

  };

2.        在之后为数组中的每一项注册处理函数:

for(i = 0; i < sizeof (TableOfVmxExits) / sizeof (ULONG32); i++) {

    if (!NT_SUCCESS (Status =TrInitializeGeneralTrap (Cpu, TableOfVmxExits[i], 0,      // length of the instruction, 0 meanslength need to be get from vmcs later.

                                                      VmxDispatchVmxInstrDummy, &Trap))) {

      _KdPrint (("VmxRegisterTraps():Failed to register VmxDispatchVmon with status 0x%08hX\n", Status));

      return Status;

    }

    TrRegisterTrap (Cpu, Trap);

  }

但注册的处理函数为VmxDispatchVmxInstrDummy。

进行的修改是:

将两个EXIT_REASON_VMCALL冲上述数组中删除。

在下面单独为其注册处理函数:

if(!NT_SUCCESS(Status = TrInitializeGeneralTrap(Cpu, EXIT_REASON_VMCALL, 0, //length of the instruction, 0 means length need to be get from vmcs later.

          HcDispatchHypercall, &Trap))) {

          _KdPrint(("VmxRegisterTraps(): Failed to register VmxDispatchCpuidwith status 0x%08hX\n", Status));

          return Status;

  }

  TrRegisterTrap(Cpu, Trap);

如此就可以成功卸载了。

0 0