Windows 内核 IDT(中断描述符表)的学习总结 - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

Windows 内核 IDT(中断描述符表)的学习总结

h1apwn 技术 2020-01-04 10:30:00
1278512
收藏

导语:可以通过读取`IDTR`寄存器来检查中断描述符表在内核中的位置,过!idt转储IDT并查看给定中断的中断服务程序的地址。

0x01  概述

将中断告知系统CPU ,中断的典型示例是硬件中断,例如鼠标按钮或键盘按键按下,网络数据包活动以及硬件生成的异常,例如除零或断点-分别中断号0x00和0x03。

一旦CPU被中断,它将停止执行其正在执行的操作并响应新的中断 。

CPU通过查找在中断描述符表(IDT)中找到的中断服务例程(ISR),知道如何响应以及对新接收到的中断执行哪些内核例程。

IDT是IDT描述符条目的列表,取决于具体的体系结构,其大小为8或16个字节 。

IDT的指针存储在每个物理处理器的IDTR寄存器中,换句话说,每个处理器都有自己的IDTR寄存器,指向自己的中断描述符表。

0x02  IDT的位置

我们可以通过读取IDTR寄存器来检查中断描述符表在内核中的位置:

 r idtr

assets%2F-LFEMnER3fywgFHoroYn%2F-LvXN0L_r8czeWC_eaDR%2F-Lv__2GKIHCsDMwkNDt4%2Fimage.png?alt=media&token=a6c0fe00-d432-4c1b-969f-5f0d8bbf54ac

如稍后所述,该命令!idt允许我们dump中断描述符表的内容,并且还确认IDT位于如下所示:fffff803536dda00`

assets%2F-LFEMnER3fywgFHoroYn%2F-LvXN0L_r8czeWC_eaDR%2F-Lv_Zi6SseJOCW4Zn7xd%2Fimage.png?alt=media&token=51d818de-f84c-4d98-9e7e-2d5c969bdc7c

idtr寄存器包含与!idt dump IDT时看到的相同值

0x03  Dump IDT

我们可以转储IDT并查看给定中断的中断服务程序的地址。以下是中断描述符表的摘要:

 kd> !idt
 
 Dumping IDT: fffff80091456000
 
 00: fffff8008f37e100 nt!KiDivideErrorFaultShadow
 01: fffff8008f37e180 nt!KiDebugTrapOrFaultShadow Stack = 0xFFFFF8009145A9E0
 02: fffff8008f37e200 nt!KiNmiInterruptShadow Stack = 0xFFFFF8009145A7E0
 03: fffff8008f37e280 nt!KiBreakpointTrapShadow
 ...
 90: fffff8008f37f680 i8042prt!I8042MouseInterruptService (KINTERRUPT ffffd4816353e8c0)
 a0: fffff8008f37f700 i8042prt!I8042KeyboardInterruptService (KINTERRUPT ffffd4816353ea00)

下面显示了实际的IDT转储和ISR代码执行:

· IDT表与 !idt

· 中断a0的IRS入口点位于fffff8008f37f700

- 这是在操作系统上注册键盘事件(例如按键)时首先在内核内部执行的例程

- 最终,代码在fffff8008f37f700执行完成,就会响应例程(在实际的键盘驱动程序内部)i8042prt!I8042KeyboardInterruptService

· 设置断点

i8042prt!I8042KeyboardInterruptService

· 设置断点后,在操作系统登录提示上按一个键,然后击中断点,确认

i8042prt!I8042KeyboardInterruptService 确实可以处理键盘中断

assets%2F-LFEMnER3fywgFHoroYn%2F-Lv7T0maSgKNYOaLVofj%2F-Lv7vKNg9G9YZvVlfvP4%2Fkeyboard-interrupt.gif?alt=media&token=fd8ac60c-9fff-4d9a-93d0-62c21eae0c9f

下面是一个高度简化的示意图,说明了上述所有事件的发生:

· 键盘中断0xa0发生

· 查找使用索引的IDT表(0x0aIDT地址+ 0xa0 * 0x10),并解析ISR入口点,并将代码跳转到该表

· 经过一番努力之后,代码最终被重定向到键盘驱动程序,在 i8042prt!I8042KeyboardInterruptService中处理中断

assets%2F-LFEMnER3fywgFHoroYn%2F-Lvh-Bv7HLHlIBV-TO4E%2F-Lvh-e1dUkiXRBqNfJtA%2Fimage.png?alt=media&token=168a073a-6623-4799-a623-a60be96407d2

0x04  IDT条目

IDT由IDT条目_KIDTENTRY64组成,IDT条目是内核内存结构,其定义如下:

 kd> dt nt!_KIDTENTRY64
    +0x000 OffsetLow        : Uint2B
    +0x002 Selector         : Uint2B
    +0x004 IstIndex         : Pos 0, 3 Bits
    +0x004 Reserved0        : Pos 3, 5 Bits
    +0x004 Type             : Pos 8, 5 Bits
    +0x004 Dpl              : Pos 13, 2 Bits
    +0x004 Present          : Pos 15, 1 Bit
    +0x006 OffsetMiddle     : Uint2B
    +0x008 OffsetHigh       : Uint4B
    +0x00c Reserved1        : Uint4B
    +0x000 Alignment        : Uint8B

序号OffsetLow``OffsetMiddle``OffsetHigh在偏移量0x000,0x006和0x008的内核虚拟地址上,它是在代码执行将由CPU一旦特定中断被转移到发生-换句话说-这是中断服务程序的(ISR ) 入口点。

0x05  IDT的键盘中断

检查一下IDT条目中的键盘中断,该中断位于IDT表中的索引a0处:

 !idt a0

assets%2F-LFEMnER3fywgFHoroYn%2F-LvXN0L_r8czeWC_eaDR%2F-Lv_xl0BQZfFq11p_R47%2Fimage.png?alt=media&token=39c4a8ab-65c6-4911-930e-2ad99b1b713e

IDT位于:fffff803536dd000

 kd > r idtr  
 idtr = fffff803536dd000

可以得到a0的位置,通过0xa0*0x10增加IDT入口(中断索引a0,0x10一个描述符条目长度为16个字节)的IDT表的地址fffff803536dd000,得到:fffff803536dda00`

 kd > dq idtr + (0 xa0 * 0 x10 )L2     
 fffff803 ` 536 dda00 51568e00 ` 0010e700 00000000 ` fffff803

利用以上信息,可以将a0中断描述符条目与_KIDTENTRY64重叠并检查IDT条目a0的内容:

 kd> dt _kidtentry64 (idtr + (0xa0*0x10))
 ntdll!_KIDTENTRY64
    +0x000 OffsetLow        : 0xe700
    +0x002 Selector         : 0x10
    +0x004 IstIndex         : 0y000
    +0x004 Reserved0        : 0y00000 (0)
    +0x004 Type             : 0y01110 (0xe)
    +0x004 Dpl              : 0y00
    +0x004 Present          : 0y1
    +0x006 OffsetMiddle     : 0x5156
    +0x008 OffsetHigh       : 0xfffff803
    +0x00c Reserved1        : 0
    +0x000 Alignment        : 0x51568e00`0010e700

0x06 键盘中断a0的ISR

根据对键盘中断所述,IDT入口偏移的组合形成的中断服务程序(ISR)入口点的虚拟地址将在执行的代码a0中断由键盘触发:

assets%2F-LFEMnER3fywgFHoroYn%2F-LvXN0L_r8czeWC_eaDR%2F-LvaH9QegPcrP3xC2wFs%2Fimage.png?alt=media&token=908221d9-ec69-4bdd-8391-ec842b1acbc5

下面显示了一旦触发a0中断,CPU将在fffff8035156e700`(ISR入口点)执行指令:

· FFFFFFFFFFFFFF A0将被压入堆栈

· 跳到fffff8035156ea40`

assets%2F-LFEMnER3fywgFHoroYn%2F-LvaKDNSi0dlBmWLdJgi%2F-LvafkPn6zj0fu4G0Z-1%2Fimage.png?alt=media&token=55ad16a2-dc02-44c0-aaba-5d07e3ece182

最后,i8042prt!I8042KeyboardInterruptService将被命中,在fffff8035156e700命中了断点,立即命中:i8042prt!I8042KeyboardInterruptService`

assets%2F-LFEMnER3fywgFHoroYn%2F-Lvald6AePpkTola-xbl%2F-LvapJ9UufCkcavLFJXW%2Fimage.png?alt=media&token=5056f6b7-60e8-48c3-b8f4-7a22238a1ac4

0x07  _KINTERRUPT

_KINTERRUPT是一种内核内存结构,其中包含有关中断的信息。文章中此结构的关键成员是位于offset 0x18的成员,它是指向ServiceRoutine例程的指针(在关联的驱动程序内部),该例程负责实际处理中断:

 dt nt!_KINTERRUPT
    +0x000 Type             : Int2B
    +0x002 Size             : Int2B
    +0x008 InterruptListEntry : _LIST_ENTRY
    +0x018 ServiceRoutine   : Ptr64     unsigned char 
    ...
    +0x0f8 Padding          : [8] UChar

作为示例,从较早的时候开始,我们就知道键盘中断的ISR位于ffffd4816353ea00,因此我们可以通过在_KINTERRUPT``ffffd4816353ea00中断处覆盖内存内容来检查该中断的结构:

 dt nt !_KINTERRUPT ffffd4816353ea00

这使我们可以确认再次正确指向键盘驱动程序内部:ServiceRoutine``i8042prt!I8042KeyboardInterruptService

assets%2F-LFEMnER3fywgFHoroYn%2F-Lv7vV9cxo1ibOm0JON3%2F-Lv8-Y16fD6BhoUQ1uJF%2Fimage.png?alt=media&token=442c709e-b02e-459c-aa0c-3d30aa32302c

0x08  Finding _KINTERRUPT

为了手动找到给定中断_KINTERRUPT的位置,我们需要利用以下存储器位置和结构。

进程控制区域或PCR(_KPCR内核中的内存结构)存储有关给定处理器的信息:

 kd> dt _KPCR
 ntdll!_KPCR
    +0x000 NtTib            : _NT_TIB
    +0x000 GdtBase          : Ptr64 _KGDTENTRY64
    +0x008 TssBase          : Ptr64 _KTSS64
    +0x010 UserRsp          : Uint8B
    +0x018 Self             : Ptr64 _KPCR
    +0x020 CurrentPrcb      : Ptr64 _KPRCB
    +0x028 LockArray        : Ptr64 _KSPIN_LOCK_QUEUE
    +0x030 Used_Self        : Ptr64 Void
    +0x038 IdtBase          : Ptr64 _KIDTENTRY64
    +0x040 Unused           : [2] Uint8B
    +0x050 Irql             : UChar
    +0x051 SecondLevelCacheAssociativity : UChar
    +0x052 ObsoleteNumber   : UChar
    +0x053 Fill0            : UChar
    +0x054 Unused0          : [3] Uint4B
    +0x060 MajorVersion     : Uint2B
    +0x062 MinorVersion     : Uint2B
    +0x064 StallScaleFactor : Uint4B
    +0x068 Unused1          : [3] Ptr64 Void
    +0x080 KernelReserved   : [15] Uint4B
    +0x0bc SecondLevelCacheSize : Uint4B
    +0x0c0 HalReserved      : [16] Uint4B
    +0x100 Unused2          : Uint4B
    +0x108 KdVersionBlock   : Ptr64 Void
    +0x110 Unused3          : Ptr64 Void
    +0x118 PcrAlign1        : [24] Uint4B
    +0x180 Prcb             : _KPRCB

_KPCR的位置可以这样找到:

 kd> ? @$pcr
 Evaluate expression: -8781847822336 = fffff803`51148000
 
 kd> !pcr
 KPCR for Processor 0 at fffff80351148000:
     Major 1 Minor 1
  NtTib.ExceptionList: fffff803536dffb0
      NtTib.StackBase: fffff803536de000
     NtTib.StackLimit: 0000000000000000
 ...snip...

_KPCR内,偏移量处0x180有一个成员指向过程控制块内存结构_KPRCB,该结构包含有关处理器状态的信息。

尝试查找给定中断的_KINTERRUPT内存位置时,我们感兴趣的关键成员是InterruptObject,_KINTERRUPT包含指向对象列表的指针列表。 InterrupObject 位于0x2e80偏移处,如下所示:

 kd> dt _KPRCB
 ntdll!_KPRCB
    +0x000 MxCsr            : Uint4B
    +0x004 LegacyNumber     : UChar
    +0x005 ReservedMustBeZero : UChar
    ....
    +0x2e80 InterruptObject  : [256] Ptr64 Void //256 pointers max as noted earlier
    ....

有了以上知识,我们现在可以找到_KINTERRUPT键盘中断a0的位置:

 dt @$pcr nt!_KPCR Prcb.InterruptObject[a0]

下面是_KINTERRUPT找到的中断a0的手动匹配命令!idt给出的中断:

assets%2F-LFEMnER3fywgFHoroYn%2F-LvaKDNSi0dlBmWLdJgi%2F-LvaZGq6AV85vjZ3NpoC%2Fimage.png?alt=media&token=ee551351-c5ab-4141-9676-1bb7e5b4e72e

0x09  参考资料

https://nagareshwar.securityxploded.com/2014/03/20/code-injection-and-api-hooking-techniques/

https://en.wikipedia.org/wiki/Interrupt_handler

https://www.linux.com/tutorials/kernel-interrupt-overview/

https://relearex.wordpress.com/2017/12/27/hooking-series-part-ii-interrupt-descriptor-table-hooking/

https://resources.infosecinstitute.com/hooking-idt/#gref

0x10   学习总结

可以通过读取IDTR寄存器来检查中断描述符表在内核中的位置。

我们可以通过!idt转储IDT并查看给定中断的中断服务程序的地址。

本文翻译自:https://ired.team/miscellaneous-reversing-forensics/windows-kernel/interrupt-descriptor-table-idt如若转载,请注明原文地址:
  • 分享至
取消

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

扫码支持

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

发表评论

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