new blue pill在Intel系列CPU上無法卸載問題

實驗環境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);

如此就可以成功卸載了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章