inc dword ptr gs:[]在这做什么?

时间:2018-05-06 17:51:20

标签: windows assembly x86-64 windbg dword

使用WinDbg调试Windows内核时,

我发现以下行: inc dword ptr gs:[2EB8h]

有人可以解释一下这意味着什么吗? (英特尔语法,x86,Windows-10)

enter image description here

1 个答案:

答案 0 :(得分:2)

内核模式(Windows x64)中的GS段指向内核处理器控制区域( KPCR )。

您可以使用!pcr命令转储它:

kd> !pcr
KPCR for Processor 0 at fffff802fbd73000:
    Major 1 Minor 1
    NtTib.ExceptionList: fffff802fd6d8000
        NtTib.StackBase: fffff802fd6d9070
       NtTib.StackLimit: 0000000000b0e968
     NtTib.SubSystemTib: fffff802fbd73000
          NtTib.Version: 00000000fbd73180
      NtTib.UserPointer: fffff802fbd737f0
          NtTib.SelfTib: 000000007f005000

                SelfPcr: 0000000000000000
                   Prcb: fffff802fbd73180
                   Irql: 0000000000000000
                    IRR: 0000000000000000
                    IDR: 0000000000000000
          InterruptMode: 0000000000000000
                    IDT: 0000000000000000
                    GDT: 0000000000000000
                    TSS: 0000000000000000

          CurrentThread: ffffe001e41a3080
             NextThread: 0000000000000000
             IdleThread: fffff802fbde9740

              DpcQueue: Unable to read nt!_KDPC_DATA.DpcListHead.Flink @ fffff802fbd75f00

通过读取名为GS的MSR(模型特定寄存器)(值为0xc0000101),您可以确认IA32_GS_BASE段寄存器确实指向了KPCR:

kd> rdmsr 0xc0000101
msr[c0000101] = fffff802`fbd73000

正如你所看到的,在我的例子中,他们都指向0xfffff802fbd73000。

PCR由KPCR结构描述:

kd> dt nt!_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结构的最后一个字段是另一个名为KPRCB(代表内核处理器控制块)的结构(指针,但结构本身)偏移量0x180。

这是这个结构的开始:

kd> dt nt!_kprcb
   +0x000 MxCsr            : Uint4B
   +0x004 LegacyNumber     : UChar
   +0x005 ReservedMustBeZero : UChar
   +0x006 InterruptRequest : UChar
   +0x007 IdleHalt         : UChar
   +0x008 CurrentThread    : Ptr64 _KTHREAD
   +0x010 NextThread       : Ptr64 _KTHREAD
   +0x018 IdleThread       : Ptr64 _KTHREAD
   +0x020 NestingLevel     : UChar
   +0x021 ClockOwner       : UChar
   +0x022 PendingTickFlags : UChar
   +0x022 PendingTick      : Pos 0, 1 Bit
   +0x022 PendingBackupTick : Pos 1, 1 Bit
   +0x023 IdleState        : UChar
   +0x024 Number           : Uint4B
   ...

为了简洁,上面的输出被截断,因为这个结构(以及PCR)非常大:windows 10 x64中PCR的大小是0x8040字节(KPRCB为0x7EC0)。

考虑到GS中的0x2eb8偏移(指向PCR),我们可以从PCR中减去KPRCB偏移量(0x180):

kd> ? 0x2eb8 - 0x180
Evaluate expression: 11576 = 00000000`00002d38

然后检查哪个字段位于KPRCB中的偏移量0x2d38:

0: kd> .shell -ci "dt nt!_kprcb" findstr /i 0x2d38
   +0x2d38 KeSystemCalls    : Uint4B

(注意:您只需dt nt!_kprcb并查看偏移量0x2d38)。

因此,示例中的递增字段名为KeSystemCalls,是一个32位字段(Uint4B),如代码所示。

字段用法

在IDA反汇编程序(ntoskrnel.exe windows 10 - x64)中搜索,我们在0x2eb8值上有2次点击:

  • KiSystemCall64
  • VslpDispatchIumSyscall

第一个是"正常" syscall调度程序,而第二个调度程序是IUM processes(aka Trustlets)的系统调度程序。

在这两个函数中,字段的使用完全相同(KiSystemCall64中的示例):

.text:0000000140187360    call    r10 ; perform syscall
.text:0000000140187363
.text:0000000140187363 loc_140187363:
.text:0000000140187363    inc     dword ptr gs:2EB8h ; increment syscall counter

因此,该字段只是一个单调计数器,用于表示自系统启动以来发生的系统调用次数。