Zero-Tang / NoirVisor

The Grimoire Hypervisor solution for x86 Processors with experimental nested virtualization support. Remastering with Rust in progress.
MIT License
474 stars 81 forks source link

Exit vt :Init #32

Closed progromyang closed 1 year ago

progromyang commented 1 year ago

您好前辈,之前向您请教过Exit vt退出时,触发了Init这个信号。(那个时候是在 tandasat 的项目中遇到的) 最近在学习您写的代码时 依然遇到了此问题。(我没有修改您的代码,直接编译运行的) 后来我尝试在msr 定义 0x40000071 尝试拦截 Interrupt Command Register 想通过观察 msr 看看是谁在发送INIT 但是在 msr处理中并没有拦截到 Interrupt Command Register 信号,这让我感到困惑。 因为您之前说过 触发 INIT 信号以后 guest context 已经不可信。 我尝试在 win10 win11,i5-9400f i7-13000k 上运行,但是依然会init 这个来说应该不是处理器的问题? 但是我在Win7上运行,就不会遇到此问题。不知道是否是系统问题?

Zero-Tang commented 1 year ago

你应该配置EPT来拦截APIC页的写入操作,或者是x2APIC的MSR。 在真机Windows驱动环境里拦截0x40000071这个MSR没啥意义,若是有用,你用过的vt框架早就拦到了。

progromyang commented 1 year ago

按照您说的 我尝试在MSR 拦截 通过查阅intel手册 The Interrupt Command Register (ICR): The two 32-bit registers in xAPIC mode (at offsets 300H and 310H) are merged into a single 64-bit MSR in x2APIC mode (with MSR address 830H). There is no MSR with address 831H. INIT的信号是 写ecx=0x830,低位=5来发送的。 我在Exit Vt 陷入时处理Msr的写。拦截 0x830,和83f (0x83f 自己向自己发送IPI)。触发INIT后 ,MSR依然没有拦截到。 我只能尝试下拦截HalpApicWiteCommand函数或者分割[[HalpLocalApic]+0x300] 来看看能不能拦截到。

Zero-Tang commented 1 year ago

除了CPU这一侧还有外设那里。特定的外部中断请求可能会被I/O APIC或者IOMMU转译为INIT信号。 0x830那个MSR是x2APIC,使用前应该先看x2APIC是否启用。 拦截APIC用EPT拦截并模拟APIC物理页的写入即可。方法很多,你可以用反汇编器,也可以替换页然后单步。

progromyang commented 1 year ago

确实是我没有Enable x2Apic。我将分割apic的物理页 按照您说的方法,我将APIC 物理页分割。(HalpLocalApicPhysical == Apic.Base),将这个页除去了write权限。 我对偏移+0x300这里地方进行监控。通过 Interrupt Command Register ,INIT信号是 8 10 bit ==1 来发送的。

` if (BYTE_OFFSET(fault_pa) == 0x300)

  {
      Ia32Icr Init;
      GpRegisters* Reg = (GpRegisters*)context;
      Init.all = Reg->dx;
      if (Init.fields.Value == 5)
      {
          CheckDebug
      }
}

` 但是这里依然没有拦截到INIT的写入,,依然是Exit-Vt陷入后收到了INIT信号

Zero-Tang commented 1 year ago

你怎么能肯定写入的时候值一定来自rdx寄存器。。。 前文说了,要么用反汇编器解析指令,要么用EPT替换APIC页了之后再用MTF单步。

progromyang commented 1 year ago

我使用的是EPT +MTF来拦截的。 经过反复测试, 我把写HalpLocalApic+300这个地方的guest rip尝试保存,只有 HalpApic1WaitForIcr函数 在写300这个偏移。 我过滤掉了 HalpApic1WaitForIcr guest rip,直到INIT触发 发现没有别的rip 写HalpLocalApic+300。 我甚至把所有的寄存器都保存了下来做对比,都没有拦截到 INIT信号。这很诡异。 我自己模拟了INIT信号的发出 (我自己写HalpLocalApic+300),EPT成功拦截到了。所以排除了拦截的问题。 但是系统自己触发INIT,ept就没有拦截到。

Zero-Tang commented 1 year ago

说明一下你买的什么机器吧,越详细越好。

progromyang commented 1 year ago

Windows10 19042.1706 CPU: Intel(R) Core(TM) i5-9400F CPU @ 2.90GHz 2.90 GHz 显卡 GeForce GTX1660, 内存16G金士顿 2666Mhz 硬盘是固态m.2 这个INIT触发的情况需要一个条件: 在电脑启动时3-5分钟内加载驱动 然后让cpu使用率飙升,比如开启很多程序。 测试发现。如果电脑启动后静置5分钟以后,再加载VT驱动,几乎不会出现INIT的问题。 您之前告诉我触发INIT信号 1:其他处理器对APIC进行写入,2:外部硬件通过IO APIC 发送了IRQ。 通过这几天测试我觉得可以排除其他处理器对APIC的写入? 您说的Q群号可以告知一下么?

Zero-Tang commented 1 year ago

我其实最想知道的是主板,你反而没说。 加群的话:769616136

progromyang commented 1 year ago

第一款CPU:E3-1231 v3 品牌 | 技嘉 GIGABYTE 型号 | B85-HD3-A

第二款CPU:i5-9400f 华硕 B365

Zero-Tang commented 1 year ago

Reason of this issue, as discovered by issue raiser, is a stealthy hook. In other words, it was caused by deprecated feature.