• kernel 获取ntoskrnl.exe基址


    标题: kernel shellcode之寻找ntoskrnl.exe基址

    http://scz.617.cn:8/windows/201704171416.txt

    以64-bits为例,这是Eternalblue所用函数:

    --------------------------------------------------------------------------
    0000000000000961                         Private_find_MZ proc near
    0000000000000961 53                                      push    rbx
    /*
     * 起始位置
     */
    0000000000000962 65 48 8B 04 25 38 00 00+                mov     rax, gs:qword_38 ; KPCR.IdtBase
    000000000000096B 48 8B 40 04                             mov     rax, [rax+4]
    000000000000096F 48 C1 E8 0C                             shr     rax, 0Ch        ; 右移左移目的是对齐在页边界上(0x1000)
    0000000000000973 48 C1 E0 0C                             shl     rax, 0Ch
    0000000000000977
    0000000000000977                         loop_977:
    0000000000000977 48 8B 18                                mov     rbx, [rax]
    /*
     * 寻找"MZ"
     */
    000000000000097A 66 81 FB 4D 5A                          cmp     bx, 5A4Dh
    000000000000097F 74 08                                   jz      short ok_989
    0000000000000981 48 2D 00 10 00 00                       sub     rax, 1000h      ; 以页为单位递减
    0000000000000987 EB EE                                   jmp     short loop_977
    0000000000000989
    0000000000000989                         ok_989:
    0000000000000989 5B                                      pop     rbx
    000000000000098A C3                                      retn
    000000000000098A                         Private_find_MZ endp
    --------------------------------------------------------------------------
    

    x64内核态GS:0指向nt!_KPCR。对于x64,必须从相应的MSR中读取GS段基址:

    kd> rdmsr 0xC0000101
    msr[c0000101] = fffff800`019f9d00
    
    

    在kd中有个办法变相获取GS段基址:

    kd> !cpuinfo
    CP  F/M/S Manufacturer  MHz PRCB Signature    MSR 8B Signature Features
     0  6,42,7 GenuineIntel 3392 0000002300000000  0000002300000000 21193ffe
                          Cached Update Signature 0000002300000000
                         Initial Update Signature 0000002300000000
    
    kd> !pcr 0
    KPCR for Processor 0 at fffff800019f9d00:
    ...
    
    kd> dt -v nt!_KPCR fffff800`019f9d00
    struct _KPCR, 27 elements, 0x4e80 bytes
       +0x000 NtTib            : struct _NT_TIB, 8 elements, 0x38 bytes
       +0x000 GdtBase          : 0xfffff800`02cae000 union _KGDTENTRY64, 7 elements, 0x10 bytes
       +0x008 TssBase          : 0xfffff800`02caf080 struct _KTSS64, 8 elements, 0x68 bytes
       +0x010 UserRsp          : 0x2ef398
       +0x018 Self             : 0xfffff800`019f9d00 struct _KPCR, 27 elements, 0x4e80 bytes
       +0x020 CurrentPrcb      : 0xfffff800`019f9e80 struct _KPRCB, 242 elements, 0x4d00 bytes
       +0x028 LockArray        : 0xfffff800`019fa4f0 struct _KSPIN_LOCK_QUEUE, 2 elements, 0x10 bytes
       +0x030 Used_Self        : 0x000007ff`fffdd000 Void
       +0x038 IdtBase          : 0xfffff800`02cae080 union _KIDTENTRY64, 11 elements, 0x10 bytes
       +0x040 Unused           : [2] 0
       +0x050 Irql             : 0 ''
       +0x051 SecondLevelCacheAssociativity : 0x10 ''
       +0x052 ObsoleteNumber   : 0 ''
       +0x053 Fill0            : 0 ''
       +0x054 Unused0          : [3] 0
       +0x060 MajorVersion     : 1
       +0x062 MinorVersion     : 1
       +0x064 StallScaleFactor : 0xd40
       +0x068 Unused1          : [3] (null)
       +0x080 KernelReserved   : [15] 0
       +0x0bc SecondLevelCacheSize : 0x800000
       +0x0c0 HalReserved      : [16] 0xca337550
       +0x100 Unused2          : 0
       +0x108 KdVersionBlock   : (null)
       +0x110 Unused3          : (null)
       +0x118 PcrAlign1        : [24] 0
       +0x180 Prcb             : struct _KPRCB, 242 elements, 0x4d00 bytes
    

    GS:[0x38]是IdtBase,等于0xfffff800`02cae080,指向nt!_KIDTENTRY64:

    kd> dt -v nt!_KIDTENTRY64
    union _KIDTENTRY64, 11 elements, 0x10 bytes
       +0x000 OffsetLow        : Uint2B
       +0x002 Selector         : Uint2B
       +0x004 IstIndex         : Bitfield Pos 0, 3 Bits
       +0x004 Reserved0        : Bitfield Pos 3, 5 Bits
       +0x004 Type             : Bitfield Pos 8, 5 Bits
       +0x004 Dpl              : Bitfield Pos 13, 2 Bits
       +0x004 Present          : Bitfield Pos 15, 1 Bit
       +0x006 OffsetMiddle     : Uint2B
       +0x008 OffsetHigh       : Uint4B
       +0x00c Reserved1        : Uint4B
       +0x000 Alignment        : Uint8B
    
    kd> db 0xfffff800`02cae080 l 0x10
    fffff800`02cae080  00 81 10 00 00 8e 87 01-00 f8 ff ff 00 00 00 00  ................
    
    kd> dt -v nt!_KIDTENTRY64 0xfffff800`02cae080
    union _KIDTENTRY64, 11 elements, 0x10 bytes
       +0x000 OffsetLow        : 0x8100
       +0x002 Selector         : 0x10
       +0x004 IstIndex         : Bitfield 0y000
       +0x004 Reserved0        : Bitfield 0y00000 (0)
       +0x004 Type             : Bitfield 0y01110 (0xe)
       +0x004 Dpl              : Bitfield 0y00
       +0x004 Present          : Bitfield 0y1
       +0x006 OffsetMiddle     : 0x187
       +0x008 OffsetHigh       : 0xfffff800
       +0x00c Reserved1        : 0
       +0x000 Alignment        : 0x1878e00`00108100
    

    Offset是ISR的入口地址,在中断描述符中被分成三部分,上例中Offset实际值是:

    ( OffsetHigh << 32 ) | ( OffsetMiddle << 16 ) | OffsetLow = 0xfffff80001878100

    对比下面的命令输出:

    kd> !idt 0
    
    Dumping IDT:
    
    00:     fffff80001878100 nt!KiDivideErrorFault
    
    

    Private_find_MZ()从IDT[0]的偏移0x4处取8字节指针:

    kd> ? poi(0xfffff800`02cae080+4)
    Evaluate expression: -8796067361280 = fffff800`01878e00
    
    

    0xfffff80001878e00本身没有意义,因为低16位跟Offset没关系。但是,该值对齐在
    页边界(0x1000)上后将位于nt模块中。考虑两个事实,一是高48位对应OffsetHigh、
    OffsetMiddle,二是bit-15是KIDTENTRY64.Present,一般等于1。

    kd> u 0xfffff80001878000
    nt!KiUnexpectedInterrupt+0x1e0:
    
    

    Private_find_MZ()从0xfffff80001878000开始向低址方向寻找"MZ",以页为单位递
    减,以此定位nt模块基址。其实际值是:

    kd> lm m nt
    start             end                 module name
    fffff800`0180b000 fffff800`01df2000   nt
    
    

    显然,这个算法是经验性的。

  • 相关阅读:
    bzoj1724[Usaco2006 Nov]Fence Repair 切割木板*
    vue-cli脚手架和webpack-simple模板项目
    Vue-router 进阶
    前端路由vue-router介绍
    vue的一些特殊特性
    生命周期钩子
    过滤器
    RSA加密算法
    欧几里得算法
    动态规划
  • 原文地址:https://www.cnblogs.com/iBinary/p/11984305.html
Copyright © 2020-2023  润新知