利用 DCI 与 Windbg 调试器调试 SMM 模式的代码 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

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

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

导语:本文介绍了如何使用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如若转载,请注明原文地址:
  • 分享至
取消

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

扫码支持

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

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务