首页
社区
课程
招聘
[翻译]Patchguard:基于虚拟机内省检测Hypervisor
2020-5-17 10:32 8784

[翻译]Patchguard:基于虚拟机内省检测Hypervisor

2020-5-17 10:32
8784

原文链接:https://revers.engineering/patchguard-detection-of-hypervisor-based-instrospection-p1/

翻译:看雪翻译小组-OsWalker

校对:看雪翻译小组-八企鹅


勘误

在过去2-3微软在patchguard中引入了各种虚拟机内省令人耳目一新方法。随着攻击者代码运行在更高特权层,破坏内核补丁保护容易,所以微软的做法并不令人惊讶Windowshypervisor上运行效果很好,并且有开虚拟化paravirtualization)接口pacchguard在寻找vmm被篡改虚拟机必须功能以外的状态的特征。例如,尝试通过隐藏MSRs真实hook系统调用控制系统调用分发目标或者利用嵌套的分页机制在关键控制路径中获得代码执行。

Patchguard中包含的检测这些内省的机制比本文中介绍的更多,作者根据自己的兴趣选择了一些特殊的进行介绍。读者可以尝试查找更多的内容本文目标帮助安全软件、反病毒软件和内省工具与内核补丁保护机制进行交互。

第一个要介绍的是KiErrata704Present。初看这个函数的命名很规则,对不熟悉的人,看起来像是某种错误类型的合法性检查。让我们来分析一下这个函数

一些背景知识:某些古老的特权切换形式,如SYSENTER和门调用,准许调用者单步跳过操作码。这不是最佳选择,因为单步信号#DBDebug Breakpoint)在任务分发到处理代码(转移系统调用处理函数、中断门处理函数后会提交。内核需要注意这种情况,以便可以通过IRET返回调用者,最终在处理完系统调用后继续执行单步操作后来引入SYSCALL/SYSRET指令通过FMASK MSR解决系统调用的问题。这个MSR开发者对SYSCALL指令执行如何处理RFLAGS更好地控制。任何现代操作系统都会保证这个MSRIF标志位和TF标志位置为0。并且SYSRET进行特殊处理以确保如果TF置位加载了一个RFLAGS镜像,就在下一个指令边界处增加#DB信号IRET在分发的处理函数执行后边界做法相反。单步跳过SYSCALL指令时,这可提供流畅的调试体验。我们希望对此更好的理解,可以KiErrata704Present函数首先保存FMASK MSR内容,然后设置MSR值,使得TF标志位不会被SYSCALL指令修改。

之后我们看到一PUSHFQ/POPFQ它们修改追踪标志(trap flag然后将改后的MSR加载回RFLAGS寄存器可能已经意识到,这会引起前面的指令执行时将TF置位,并在执行后引起#DB信号如果指令是软件异常软件中断或特权软件异常,或者指令产生一个硬件异常。

可能意识到,一旦SYSCALL执行完成,会产生一个#DB信号,这就像在其它分支指令处执行单步跳过一样。所以,如果LSTAR的目标是下面类似的指令序列:

0x40000: SWAPGS
0x40001: MOV GS:[0x8], RSP
0x40002: MOV RSP, GS:[0x10]

#DB处理函数中断包含0x40000的堆栈段,因为这是尚未执行的syscall操作分支的目标

可能已经意识到了,patchguard可以中断处理中通过内省#DB产生IP(指令指针间接发现LSTAR MSR真实值。这是一种能发现RDMSR/WRMSR是否存在恶意的虚拟机并给操作系统预期望的值的方法

接下来是我最喜欢的,KiErrataSkx55Present。回顾CVE-2018-8897,这个函数在该脆弱性被修复后不久被加入patchguard理解这个检测如何工作,需要看一下POP SS/MOV SS vulnerability whitepaper


如果你读了这篇文章,会发现它只是在说这个漏洞。所以在上面我们给出SYSCALL处理函数,这个#DB也会在中断栈上放入0x40000.

客户代码能够获得RDMSR/WRMSR相关的更多信息时经验不多hypervisor开发者会怎么做?非常简单,设置异常位图使得在#DB异常时退出,并检查客户状态IP处理上面提到的两类指令边界#DB,如果不匹配,合适的做法是基于向量事件注入返回到客户代码检测退出条件而不检查客户状态中TF标记是明智的选择。

这里大家讲一个流行的反病毒hypervisor在这里发生错误的例子,因此它往回注入#DB客户的代码到自定义的syscall处理函数的RIPKiDebugTraps缓解做的不好,导致这个hypervisor使你的系统变得可被CVE-2018-8897攻击

最后,非但不是一个锦上添花的东西,这个可靠性检查反而使你的hypervisor#DB异常退出暴露,或者,你应该友好一点不要去检查?进入KiErrata361Present函数

这里还有一些要解释的东西。通常的指令周期中,通过POPF某个变体给RFLAGS寄存器加载TF标记,随后的SS(Stack Segment堆栈段寄存器)加载操作将引起单步在SS 加载指令后面的指令的指令边界被发现。临时被一个加载SS操作限制时,这#DB遇到被破坏的调试寄存器的情形一样。在上面的情况,一个INTn(软件中断),专门设置的INT3操作码软件异常)不关心之前通过TF挂起#DB信号并一定会被丢弃。

尽管没有被文档化,这也是ICEBP的正常行为,Intel手册中这个信号描述为特权软件异常。这种情况,#DB信号没有置DR6.BS,尽管处于挂起状态,基于这个操作码的功能这个信号将被丢弃。ICEBP引入一个#DB VMEXIT时,它实际上带有这个警告。在常规体系结构指令循环VMCS的挂起的调试异常域BS位会被置位,因为这正是当时的真实状态,但当特权软件异常引起退出时,该位将被清除。

由于这些情况下VMCS状态不可恢复将引起VMRESUME错误引起大多数hypervisors草率地中止运行。该体系结构要求,如果虚拟cpu处于中断过程中,并且启用了MOV SS/POP SS阻塞,并且设置TF标志位,那么必须存在一个基于BS的挂起的#DB,因为没有其他方法可以获得此机器状态。修复这个问题也很简单:在符合条件的退出点检测特权软件异常如果MOV SS引起阻塞TF==1就确保挂起的调试异常中BS被置位

KiErrata361Present函数的思路实际上来自于CVE-2018-1087漏洞该漏洞被大众知道前特权软件异常就是ICEBP并且这个异常会在patchguard中显示直到KVM修复Intel SDM就在那时进行了更新指明特权软件异常是什么,但仍然没有出现这种情况。

如果你觉得本文不无聊,就继续看看第二部分,我们讨论另一个Patchguard检测机制,用一些批判性思维来想出我们自己的妙招。



[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞0
打赏
分享
最新回复 (2)
雪    币: 2606
活跃值: (3708)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
syser 2020-5-17 15:26
2
0
... 确定是人翻译的么 为什么感觉是机翻....
雪    币: 695
活跃值: (708)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
大雄_RE 2020-5-18 20:31
3
0
syser ... 确定是人翻译的么 为什么感觉是机翻....
是人翻译的,只是对cpu体系结构一些底层细节和硬件虚拟化的东西不是太熟,不是太理解里面的技术点
游客
登录 | 注册 方可回帖
返回