利用 DCI 与 Windbg 调试器调试 SMM 模式的代码 - 嘶吼 RoarTalk – 回归最本质的信息安全,互联网安全新媒体,4hou.com

利用 DCI 与 Windbg 调试器调试 SMM 模式的代码

h1apwn 技术 2021-05-07 10:30:20
收藏

导语:本文介绍了如何使用Windbg和Direct Connect Interface(DCI)调试整个操作系统,包括系统管理模式(SMM)代码 ,我将调试我报告的kernel到SMM的本地特权提升漏洞作为例子。

本文介绍了如何使用Windbg和Direct Connect Interface(DCI)调试整个操作系统,包括系统管理模式(SMM)代码 ,我将调试我报告的kernel到SMM的本地特权提升漏洞作为例子。

有关该漏洞及其影响的更多详细信息,请参考GitHub存储库,这篇文章重点介绍DCI和Windbg。

https://github.com/tandasat/SmmExploit

0x01 DCI介绍

DCI是一种用于内核/固件调试和逆向的非常强大的技术,而针对WinDbg的英特尔调试扩展程序使我们可以通过Windbg的命令和GUI使用它,这样可以加快对它的研究。

直接连接接口(DCI)是Intel硬件提供的调试接口,它使开发人员无需依赖软件提供的调试机制即可调试整个系统,例如Windows的内核调试子系统和固件(EDK2)的Debug Agent。

由于DCI由硬件实现,因此使用此接口的调试器能够调试更大范围的代码,包括复位向量和在系统管理模式(SMM)上运行的代码。例如,这使得DCI成为开发和逆向固件的强大工具。

有关DCI技术的更全面概述,我强烈建议你花些时间观看Intel的视频并阅读Slim Bootloader团队的文档:·

· 英特尔®System Studio 2018中的系统调试和跟踪介绍

· 使用英特尔(R)SVT CCA进行源代码级调试

DCI在Skylake(第6代)或更高版本以及某些Atom和Xeon型号上可用。但是,较老的一代仅支持DCI OOB的连接类型,并且需要昂贵的适配器,如下表所示。

image-20210406135330261image-20210406135330261.png

如果你的目标系统是第7代或更高版本,则支持DCI DbC,而你所需要购买的只是不需要VBus的USB电缆。购买ITPDCIAMAM1MDataPro一个,如果目标系统具有A型USB端口,或ITPDCIAMCM1M 为C型USB端口。我建议同时购买两者,因为我有一台只能与C型端口一起使用的设备。

如果你的目标系统是第六代,则不支持DbC,并且你需要购买昂贵的适配器CCA(EXIBSSBADAPTOR),允许你从复位向量中调试代码,而DbC不支持此功能。

image-20210406135349891image-20210406135349891.png

DCI连接类型 (摘自Intel使用DCI和USB 3.0调试Intel固件

对主机系统没有明显的要求,如果需要,可以使用USB-C-to-A适配器。

支持模型的完整列表可以在Intel System Debugger的发行说明中找到,我们将在稍后进行介绍。

如果设置了IA32_DEBUG_INTERFACE [0],则启用DCI。使用内核调试器或 RWEverything 进行检查。出于明显的原因,默认情况下应在市场上的系统上禁用DCI。如果不是,请向OEM报告,这是一个漏洞(请参阅CVE-2018-3652)。

image-20210406135419320image-20210406135419320.png

0x02 如何启用DCI

有两种方法可以执行此操作:更改BIOS设置或使用RU.efi修补NVRAM。

BIOS设置偶尔会提供启用DCI的选项。我已经看到了几个用于此目的的配置名称,如下所示。

· CPU运行控制

· 启用HDCIEN

我遇到的情况是该配置可用,但对IA32_DEBUG_INTERFACE没有影响。

DCI的BIOS设置通常隐藏在生产系统中,但是可以通过覆盖存储设置值的NVRAM来实现与更改设置相同的效果。这是一个有点复杂的过程,但是在下面列出的多篇文章中对此进行了解释。

1. 使用Chipsec等软件提取BIOS

2. 提取模块899407D7-99FE-43D8-9A21-79EC328CAC21UEFITool

3. 使用IFR Extractor提取可读的BISO菜单实现的表示形式

4. 查找以下设置名称的偏移量和要设置的值,用=>表示

· 调试接口=>启用(1)

· 调试接口锁定=>禁用(0)

· DCI启用(HDCIEN)=>启用(1)

· 平台调试同意=>启用(DCI OOB + [DbC])(1)

· CPU运行控制=>启用(1)

· CPU运行控制锁定=>禁用(0)

· PCH跟踪集线器启用模式=>主机调试器(2) (取决于BIOS)

1. 下载RU.efi,将系统启动到UEFI Shell中并启动RU.efi

2. Alt + =,选择“设置”,然后更改找到的偏移值,提交更改并重新启动。

· 在技嘉BKi5HA-7200上启用DCI调试

· 通过单步运行Coffee Lake-S硬件CPU调试UEFI代码

· 使用RU.EFI修改BIOS

· そうだ,Intel DCIをしよう!Intel DCI続编(资料まとめ)

有些设备没有安装程序模块,有些设备具有但未反映对IA32_DEBUG_INTERFACE的更改,而某些设备却更改了IA32_DEBUG_INTERFACE,但无论如何都不允许我连接。

Intel Flash Image Tool(FIT)是另一个可以修补固件并启用DCI的工具。

0x03 如何通过DCI连接目标

主机上需要安装Intel System Debugger才能进行连接。英特尔系统调试器是英特尔系统工作室(ISS)的一部分,可以从此链接下载。

· https://dynamicinstaller.intel.com/system-studio/

image-20210406135449704image-20210406135449704.png

选择“获取完整的System Studio软件包”,然后下载“独立脱机安装程序”。

image-20210407165746800image-20210407165746800.png

请注意,英特尔已从ISS过渡到其他产品集,并将系统调试器更名为Intel System Bring-up Toolkit,需要下载NDA。截至撰写本文时,以上下载链接仍然有效,但将来可能会关闭。

在安装时,请确保至少安装英特尔系统调试器。安装ISS后,你可以参考以下页面以通过ISS连接到目标:

· 使用英特尔®系统调试器调试基于EDK II的固件映像 (视频)

· 使用英特尔(R)SVT CCA进行源代码级调试

· 用户指南-启动和结束调试会话

为了简单起见,我建议使用旧版本。可以用 如下文件

C:\ Program Files(x86)\ IntelSWTools \ sw_dev_tools \ system_debugger_2020 \ system_debug_legacy \ xdb.bat

· 英特尔系统调试器目标指示器有助于识别可能的原因。

image-20210407165812299image-20210407165812299.png

· 并非所有端口都能正常工作。例如,只能通过C型端口调试我的设备之一,尝试其他端口,有时会重启。

0x04 WinDbg的Intel调试扩展

安装程序应该已经安装了扩展程序,该扩展程序使你可以通过DCI使用Windbg调试目标。要使用扩展,需要使用以下命令在主机上注册扩展调试接口(EXDI)IPC COM服务器:

----
> cd "C:\Program Files (x86)\IntelSWTools\sw_dev_tools\system_debugger_2020\windbg-ext\iajtagserver\intel64"
> regsvr32 ExdiIpc.dll
----

然后,重新引导主机系统,从开始菜单启动英特尔系统调试器开发人员 Shell,然后键入“ windbg_dci”

image-20210407165833606image-20210407165833606.png

成功建立连接后,键入“ windbg()”

image-20210407165915956image-20210407165915956.png

Windbg启动后,显示反汇编和注册值,并且如果成功,则接受大多数命令,例如.reload。

image-20210407220224227.png

尽管该扩展程序确实像标准的内核调试会话那样使用Windows特定位,但它并不依赖于某些Kd标志所指示的内核调试机制。如果你正在寻找隐秘的内核调试工具,那么DCI就是你的理想之选。

image-20210407220242374.png

0x05 调试SMM漏洞

通过DCI调试Windows内核是可以的,但没有太大意义,我们调试SMM漏洞利用作为示例。

漏洞是SMI 0x40允许使用0x07覆盖任意SMRAM。该漏洞利用此原语来覆盖SMST全局变量中的函数指针, 以实现SMM中的任意代码执行。

SMST的地址被设计泄漏到了SMRAM外部,Ring0代码可以从UEFI运行时代码区域中搜索 具有独特的“ smmc”签名的SMM核心私有数据,然后在其中找到泄漏的指针。

image-20210407170235970image-20210407170235970.png

SMST的地址在SMRAM外部泄漏

该利用程序利用了这一点,并在不依赖BIOS和系统版本的情况下在SMRAM中定位了函数指针的地址。有关漏洞和利用的更多详细信息,请参见GitHub

当漏洞利用在打了补丁的系统上执行时,它会调试打印SMRAM的范围,SMM内核和SMST的地址,但无法运行Shellcode。

image-20210407170310309image-20210407170310309.png

用Windbg调试漏洞并执行漏洞利用代码。

1. 加载“ dt”命令的符号,

2. 中断SMM,

3. 提取并分析SMRAM,

4. 在SMI 0x40处理程序上设置断点,

5. 调试和修改执行以模拟成功利用。

首先,进入Windbg,并为漏洞利用调用中的一个NT API设置一个断点。

----
0: kd> bp nt!ExGetSystemFirmwareTable
0: kd> g
----

然后,在目标系统上重新运行该漏洞利用程序,重新加载漏洞利用程序的符号。

----
0: kd> .reload demo.sys
...
ModLoad: fffff806`4d860000 fffff806`4d869000 \??\C:\Users\tanda\Desktop\demo.sys
Loading symbols for fffff806`4d860000 demo.sys -> demo.sys

0: kd> dt demo!SMM_CORE_PRIVATE_DATA
   +0x000 Signature : Uint8B
   ...
----

在另一个windbg_dci会话上,启用SMM入口中断并恢复系统,系统将再次进入调试器。

----
    [SKL_C0_T0] Hardware Breakpoint Execution breakpoint #0001 at [0x10:fffff8064f795b00]
    [SKL_C0_T1] HLT Instruction Break at [0x38:000000000009e1e5]
    [SKL_C1_T0] HLT Instruction Break at [0x38:000000000009e1e5]
    [SKL_C1_T1] HLT Instruction Break at [0x38:000000000009e1e5]
>>> itp.cv.smmentrybreak = 1
>>> go()
CPUs Resuming execution

>>>
    [SKL_C0_T0] Resuming
    [SKL_C0_T1] Resuming
    [SKL_C1_T0] Resuming
    [SKL_C1_T1] Resuming
>>>
    [SKL_C0_T0] SMM entry Break at [0xcb00:0000000000008000]
    [SKL_C0_T1] SMM entry Break at [0xcb80:0000000000008000]
    [SKL_C1_T0] SMM entry Break at [0xcc00:0000000000008000]
    [SKL_C1_T1] SMM entry Break at [0xcc80:0000000000008000]
>>>
----

在Windbg会话上,通过检查RIP为0x8000和AL为0x40来确认这是SMI 0x40。然后,根据先前运行的debug打印的范围转储SMRAM的内容。

----
Break instruction exception - code 80000003 (first chance)
cb00:00000000`00008000 bb9180662e      mov     ebx,2E668091h

0: kd> r
rax=0000000000000040 rbx=0000000000000000 rcx=ffff808cca4df080
rdx=00000000000000b2 rsi=ffff808cd5aff000 rdi=ffff808cd746b7d0
rip=0000000000008000 rsp=000000002c127668 rbp=0000000000000000
 r8=0000000000098367  r9=0000000000000004 r10=00000000ffffffff
r11=ffff808cd74f6040 r12=ffffffff80001998 r13=0000000000000002
r14=fffff8064d7f52f8 r15=ffff808cd5aff000
...

0: kd> .writemem C:\temp\smram_88400000_88800000.bin 0`88400000 0`88800000-1
Writing 400000 bytes.........(snip)...
----

下载并运行由Dmytro Oleksiuk(aka Cr4sh,@d_olex开发的SMRAM脚本,将显示SMI 0x40处理程序的地址。

----
$ wget https://raw.githubusercontent.com/tandasat/smram_parse/master/smram_parse.py
$ python3 smram_parse.py smram_88400000_88800000.bin
...
SW SMI HANDLERS:
...
0x88700110: SMI = 0x40, addr = 0x886e5c68, image = 0x886e5000
...
----

在Windbg会话中,还可以发现函数能指向SMRAM外部。。

----
0:kd> uf 0`886e5c68
00000000`886e5c68 4053 push rbx
00000000`886e5c6a 4883ec20 sub rsp,20h
00000000`886e5c6e 0fb704250e040000 movzx eax,word ptr [40Eh]
00000000`886e5c76 ba67000000
moveded mov byte ptr [00000000`886e6f40],1
00000000`886e5c82 c1e004 shl eax,4
00000000`886e5c85 0504010000    add eax,104h
00000000`886e5c8a 8b18       mov ebx,dword ptr [rax]

0:kd> g 0`886e5c8a
\----

在下面的反汇编中,你可以看到SMRAM外部的0x104被引用,并包含要覆盖的地址。你还可以发现后续代码会覆盖地址的内容。

----
0038:00000000`886e5c8a 8b18        mov ebx,dword ptr [rax] ds:0018:00000000`00000104=887f97fe
0038:00000000`886e5c8c 488bcb      mov rcx,rbx
0038:00000000`886e5c8f e8bc0d0000  call 00000000`886e6a50
...
0038:00000000`886e5c9e c6430207    mov byte ptr [rbx+2],7 ds:0018:00000000`887f9800=8c
0038:00000000`886e5ca2 eb10        jmp 00000000`886e5cb4
----

漏洞利用程序如何计算该地址?该漏洞利用程序能够在0x87f21390处找到SMM核心私有数据。让我们“ dt”地址以确认该地址中确实存在SMM专用核心数据,以及泄漏的SMST地址。

----
0: kd> db 0`87f21390 l10
00000000`87f21390 73 6d 6d 63 00 00 00 00-18 67 4f 84 00 00 00 00 smmc.....gO.....

0: kd> dt demo!SMM_CORE_PRIVATE_DATA 0`87f21390
   +0x000 Signature : 0x636d6d73
   +0x008 SmmIplImageHandle : 0x00000000`844f6718 Void
   +0x010 SmramRangeCount : 3
   +0x018 SmramRanges : 0x00000000`844f2d18 Void
   +0x020 SmmEntryPoint : 0x00000000`887f9d7c Void
   +0x028 SmmEntryPointRegistered : 0x1 ''
   +0x029 InSmm : 0x1 ''
   +0x030 Smst : 0x00000000`887f9730 EFI_SMM_SYSTEM_TABLE2
   +0x038 CommunicationBuffer : (null) 
   +0x040 BufferSize : 0x20
   +0x048 ReturnStatus : 0
   +0x050 PiSmmCoreImageBase : _LARGE_INTEGER 0x1
   +0x058 PiSmmCoreImageSize : 0xfffff806`53427320
   +0x060 PiSmmCoreEntryPoint : _LARGE_INTEGER 0xfffff806`53427980
----

该漏洞利用将0xd0添加到SMST的地址,因为它的布局是已知的。如下所示,偏移量0xd0是函数指针SmmLocateProtocol。

----
0: kd> db 0`887f9730 l10
00000000`887f9730 53 4d 53 54 00 00 00 00-1e 00 01 00 18 00 00 00 SMST............
0: kd> dt demo!EFI_SMM_SYSTEM_TABLE2 0`887f9730
   +0x000 Hdr : EFI_TABLE_HEADER
   +0x018 SmmFirmwareVendor : (null) 
   +0x020 SmmFirmwareRevision : 0
   +0x028 SmmInstallConfigurationTable : 0x00000000`887fa1b0 Void
   +0x030 SmmIo : EFI_SMM_CPU_IO2_PROTOCOL
   +0x050 SmmAllocatePool : 0x00000000`887fb61c Void
   +0x058 SmmFreePool : 0x00000000`887fb744 Void
   +0x060 SmmAllocatePages : 0x00000000`887fbd20 Void
   +0x068 SmmFreePages : 0x00000000`887fbe30 Void
   +0x070 SmmStartupThisAp : 0x00000000`887e0af0 Void
   +0x078 CurrentlyExecutingCpu : 0
   +0x080 NumberOfCpus : 4
   +0x088 CpuSaveStateSize : 0x00000000`887ddd50 -> 0x400
   +0x090 CpuSaveState : 0x00000000`887ddf50 -> 0x00000000`887dac00 Void
   +0x098 NumberOfTableEntries : 6
   +0x0a0 SmmConfigurationTable : 0x00000000`887e5810 Void
   +0x0a8 SmmInstallProtocolInterface : 0x00000000`887fb928 Void
   +0x0b0 SmmUninstallProtocolInterface : 0x00000000`887fbaf4 Void
   +0x0b8 SmmHandleProtocol : 0x00000000`887fbc1c Void
   +0x0c0 SmmRegisterProtocolNotify : 0x00000000`887fbf2c Void
   +0x0c8 SmmLocateHandle : 0x00000000`887fa058 Void
   +0x0d0 SmmLocateProtocol : 0x00000000`887f9f8c Void
   +0x0d8 SmiManage : 0x00000000`887fb2fc Void
   +0x0e0 SmiHandlerRegister : 0x00000000`887fb3d4 Void
   +0x0e8 SmiHandlerUnRegister : 0x00000000`887fb48c Void
----

因此,SMI 0x40将要覆盖SmmLocateProtorol字段的内容。

由于我们正在调试的代码不再容易受到攻击,因此让我们通过将RIP更改为MOV指令来模拟成功的利用。在完成该指令之后,我们可以确认地址内容已更改为0x07。

----
0: kd> dp 0`887f9800 l1
00000000`887f9800 00000000`887f9f8c

0: kd> r rip=0`886e5c9e 
0: kd> t

0: kd> dp 0`887f9800 l1
00000000`887f9800 00000000`887f9f07
----

重复此步骤4次后,该地址将被覆盖到SMRAM外部的0x07070707。

----
0: kd> dp 0`887f9800 l1
00000000`887f9800 00000000`07070707

0: kd> dt demo!EFI_SMM_SYSTEM_TABLE2 0`887f9730
...
   +0x0c8 SmmLocateHandle : 0x00000000`887fa058 Void
   +0x0d0 SmmLocateProtocol : 0x00000000`07070707 Void
   +0x0d8 SmiManage : 0x00000000`887fb2fc Void
...
----

让我们再运行一次目标,以验证利用成功。下一个SMI是0xdf,它将调用SmmLocateProtocol。

----
0: kd> g
Break instruction exception - code 80000003 (first chance)
cb00:00000000`00008000 bb9180662e mov ebx,2E668091h

0: kd> r
rax=00000000000000df rbx=0000000000000000 rcx=fffff8064d544180
rdx=ffffed842b8400b2 rsi=ffff808cd68ff000 rdi=ffff808cd521e7c0
rip=0000000000008000 rsp=000000002b8476e0 rbp=0000000000000000
r8=0000000000000001 r9=ffff808cd7345040 r10=6c6c656873204d4d
r11=ffff808ccc4901e8 r12=ffffffff80002b6c r13=0000000000000002
r14=fffff8064d8652f8 r15=ffff808cd68ff000
...

0: kd> uf 07070707
00000000`07070707 90              nop
00000000`07070708 90              nop
00000000`07070709 90              nop
00000000`0707070a 90              nop
00000000`0707070b 90              nop
00000000`0707070c 90              nop
00000000`0707070d 90              nop
00000000`0707070e 90              nop
00000000`0707070f 90              nop
00000000`07070710 4c89442418      mov     qword ptr [rsp+18h],r8
00000000`07070715 4889542410      mov     qword ptr [rsp+10h],rdx
00000000`0707071a 48894c2408      mov     qword ptr [rsp+8],rcx
00000000`0707071f 4883ec28        sub     rsp,28h
00000000`07070723 48c744240800000000 mov   qword ptr [rsp+8],0
00000000`0707072c b99e000000      mov     ecx,9Eh
00000000`07070731 0f32            rdmsr

0: kd> bp 0`07070707 
0: kd> g
Breakpoint 0 hit
0038:00000000`07070707 90 nop
----

如预期的那样,目标在0x07070707进入调试器。一旦执行了shellcode代码,就可以检查其存储在0x0的输出。

image-20210407170345674image-20210407170345674.png

----
0: kd> dx *(demo!HOOKED_SMM_LOCATE_PROTOCOL_PARAMETER_BLOCK*)0
*(demo!HOOKED_SMM_LOCATE_PROTOCOL_PARAMETER_BLOCK*)0 [Type: HOOKED_SMM_LOCATE_PROTOCOL_PARAMETER_BLOCK]
    [+0x000] Untouched        : 0x1588748418 [Type: unsigned __int64]
    [+0x008] Smbase           : 0x887cb000 [Type: unsigned __int64]
    [+0x010] SmmFeatureControl : 0x1 [Type: unsigned __int64]
    [+0x018] SmmMcaCap        : 0xc00000000000000 [Type: unsigned __int64]
    [+0x020] Eptp             : 0x0 [Type: unsigned __int64]
    [+0x028] HvPatchedAddress : 0x0 [Type: unsigned __int64]
----

0x06 参考资料

· 使用bcdedit将目标系统设为单核,我发现调试多核配置是不稳定的。

· 在调试之前,请在目标上完全禁用Hyper-V。即使禁用了VBS,Hyper-V也会通过看门狗错误检查使系统崩溃。

· DCI提供了中断VM退出/进入功能,但我无法使其正常工作。

· SMI由EDK2中的以下函数处理,你的系统可能完全相同。

· SmiRendezvous(MpService.c)

· SmmEntryPoint(PiSmmCore.c)

· SmiManage(Smi.c)

· BSPHandler(MpService.c)

· _SmiEntryPoint(SmiEntry.nasm)

· Windbg和Intel System Debugger都无法在SMM的开头正确显示16位模式代码,只需继续单步执行,直到偏移量0x90左右即可。

image-20210407170418915.pngimage-20210407170418915

· UEFI BIOS漏洞

· tapping-into-the-core

· UEFI_EXPLOITATION

· evil-maid-firmware-attacks-using-usb-debug

· open-source-firmware-explorations-using-dci-on-the-aaeon-up-squared-board

· 在UP Squared上启用DCI。该设备的最详细的分步说明。优秀的博客。

· 使用DCI EXDI会话调试Windows内核

· 使用DCI和Windbg逆向Windows

· 在Intel NUC的示例上利用AMI Aptio固件

本文翻译自:http://standa-note.blogspot.com/2021/03/debugging-system-with-dci-and-windbg.html如若转载,请注明原文地址:
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论