Win 8.1/10 x64平台 S3 Resume任意执行漏洞 (基于UEFI平台)
2020-04-20 15:02:56 Author: bbs.pediy.com(查看原文) 阅读量:322 收藏

[原创]Win 8.1/10 x64平台 S3 Resume任意执行漏洞 (基于UEFI平台)

14小时前 256

[原创]Win 8.1/10 x64平台 S3 Resume任意执行漏洞 (基于UEFI平台)

  • 前言:

    不知道这个漏洞之前有没有人发现并上报,我上报国家信息安全漏洞共享平台,对方要求我提供POC。我掂量了一下自己能力,觉得在驱动里实现POC难度挺高的,所以我就放弃了(当然,我已经顺手报给微软MSRC)。于是我就移步至此,记录调试过程。实验结论基于我前两篇文章:探索Windows S3唤醒函数 (一) 探索Windows S3唤醒函数 (二) 从Win7开始,x64位平台需要在测试模式下才能加载未认证的驱动,一般也没几个用户会开测试模式,所以限制了这个漏洞的利用。另外Win7可能不支持UEFI Bios,因此,这个漏洞可能在WinXp/Win7系统上不能奏效。


  • 产生原理:

前面文章里反复提到一个内核变量: HalpLowStubPhysicalAddress,漏洞的产生全在于它:

Step 1).OS在 HalpSetupAcpiPhase0阶段,调用HalpAllocPhysicalMemory分配(可执行)物理地址,并将起始地址写入 HalpLowStubPhysicalAddress;(下文会给出调试证明。随文附件中,我提供了Win10 RS5 x64 Free Build Hal.dll和对应的Hal.i64 )

Step 1.5).在之后的某个阶段(暂时没有跟踪到),OS将初始化 HalpLowStubPhysicalAddress所指的物理内存,其起始4Byte为一个JMP跳转指令; (下文亦会给出调试证明)

Step 2).进入S3 Sleep时,OS以 HalpLowStubPhysicalAddress 作为参数,调用HalpSetupRealModeResume函数,将 HalpLowStubPhysicalAddress的值写入内核变量HalpWakeVector。前面文章提过, HalpWakeVector对应UEFI S3 WakeVector;

Step 3).外部事件触发S3 Resume,UEFI Bios执行 S3ResumeBootOs,通过SwitchStack函数跳转到OS指定的S3 WakeVector,也就是 HalpLowStubPhysicalAddress的值;(下文只能提供Intel Comet Lake RVP board bios log)

  • 利用方式:

原理都写到这份上了,大家应该心知肚明了:创建驱动,仿造 Step 1)和Step 1.5)分配物理内存并在物理内存里构建JMP。然后覆盖 内核变量HalpLowStubPhysicalAddress的值为我们分配的物理地址!!!,完成后让OS进入S3,推它一把,剩下的它自己完成去吧~

2020-04-14-04:15:15.962 PROGRESS CODE: V03031006 I0
2020-04-14-04:15:15.962 
2020-04-14-04:15:16.009 Transfer to 16bit OS waking vector - 1000
2020-04-14-04:15:16.009 
2020-04-14-04:15:18.018 Froome: TaskSmmPanelPowerOnOffSequense set EC_CONF_DEV_En to 0x1

这段日志出自 Intel Comet Lake RVP board的串口输出日志,对应实现可以定位到下列UEFI源码(UEFI源码,大家可以从UDK2015项目中获得。我用的是IBV基于UDK的CodeBase,涉密不便于贴出):


这段日志表明了WakeVector的物理内存位于0x1000,这个物理地址由OS填写(确切的说是ACPI子系统填写)。

再证明Step 1):

a).首先查找OS为导出函数HalpSetupRealModeResume,根据IDA分析,我知道:HalpSetupRealModeResume距离OS导出函数hal!HalPerformEndOfInterrupt的偏移为0x2c35,所以我先定位运行时hal!HalPerformEndOfInterrupt函数的地址(注意,每次重启函数地址都会变,但函数间偏移不会变,不要随意下函数断点!)

;查找内核导出函数hal!HalPerformEndOfInterrupt
0: kd> x hal!*Halp* 
fffff800`26c0bad0 hal!HalPerformEndOfInterrupt (<no parameter info>)
fffff800`26c210b0 hal!HalProcessorIdle (<no parameter info>)

;hal!HalPerformEndOfInterrupt+偏移得到HalpSetupRealModeResume的地址
;验证一下得到的地址对应的反汇编代码是否和IDA分析的结果一致,下图为IDA HalpSetupRealModeResume的输出
;当然一致,要不然我就不贴上来了!
0: kd> u fffff800`26c210b0+2c35
hal!HalProcessorIdle+0x2c35:
fffff800`26c23ce5 488b0d64b00400  mov     rcx,qword ptr [hal!HalHandleNMI+0x20c40 (fffff800`26c6ed50)]
fffff800`26c23cec 8b15f6ae0400    mov     edx,dword ptr [hal!HalHandleNMI+0x20ad8 (fffff800`26c6ebe8)]
fffff800`26c23cf2 e829d8ffff      call    hal!HalProcessorIdle+0x470 (fffff800`26c21520)
fffff800`26c23cf7 84c0            test    al,al
fffff800`26c23cf9 0f8546a1feff    jne     hal!HalFlushCommonBuffer+0x6f5 (fffff800`26c0de45)
fffff800`26c23cff e9dca0feff      jmp     hal!HalFlushCommonBuffer+0x690 (fffff800`26c0dde0)
fffff800`26c23d04 ffc3            inc     ebx
fffff800`26c23d06 851dd0b20400    test    dword ptr [hal!HalHandleNMI+0x20ecc (fffff800`26c6efdc)],ebx


b). 从 HalpSetupRealModeResume函数中得到内核变量HalpWakeVector的地址:

根据IDA的分析, HalpWakeVector是全局变量,并且被 HalpSetupRealModeResume函数访问(即上图红框处),因此我从 HalpSetupRealModeResume函数中得到内核变量HalpWakeVector的地址:fffff800`26c6ebe8

fffff800`26c23cec 8b15f6ae0400    mov     edx,dword ptr [hal!HalHandleNMI+0x20ad8 (fffff800`26c6ebe8)]

c).对比地址fffff800`26c6ebe8的值是否和 Intel Comet Lake RVP board输出的WakeVector相同:

0: kd> dd fffff800`26c6ebe8
fffff800`26c6ebe8  00001000 00000000 00000000 00000000
fffff800`26c6ebf8  ec50d00c ffff8600 00000000 00000000

两者值一致,但需要注意地址fffff800`26c6ebe8,也就是 HalpWakeVector存储的值是物理地址,因此要用windbg扩展命令!dd查看内容:

0: kd> !dd 00001000 
#    1000 00064de9 00000001 00000001 1018003f
#    1010 00000000 00000000 00000000 00000000
#    1020 00000000 00000000 00000000 00209b00
#    1030 00000000 00000000 0000ffff 00cf9300

敏感的你看了0x1000处前4B马上能意识到这是JMP指令,是的没错,用OD试试


由此可见,UEFI代码从Facs->FirmwareWakingVector跳转到 HalpWakeVector后,又会执行一次Jmp指令跳转到指定的payload。我们的实验驱动也可以这样实现,源码我就不提供了,太麻烦!

[培训]《安卓高级研修班(网课)》6月班开始招生!一年后遇见不一样的自己!(现在进入看雪课程可以试看两节)


文章来源: https://bbs.pediy.com/thread-258998.htm
如有侵权请联系:admin#unsafe.sh