您的位置:首页 > 其它

ring0下的 fs:[124]

2016-01-14 11:19 357 查看
   反汇编内核函数的时候经常会看到mov eax, fs:[124].一直没弄清楚fs寄存器在ring0存放的是什么。今天查了下资料。

    fs寄存器在Ring0中指向一个称为KPCR的数据结构,即FS段的起点与KPCR结构对齐。而在Ring0中fs寄存器一般为0x30。

    这样看KPCR的数据结构:

nt!_KPCR
+0x000 NtTib            : _NT_TIB
+0x01c SelfPcr          : Ptr32 _KPCR
+0x020 Prcb             : Ptr32 _KPRCB
+0x024 Irql             : UChar
+0x028 IRR              : Uint4B
+0x02c IrrActive        : Uint4B
+0x030 IDR              : Uint4B
+0x034 KdVersionBlock   : Ptr32 Void
+0x038 IDT              : Ptr32 _KIDTENTRY
+0x03c GDT              : Ptr32 _KGDTENTRY
+0x040 TSS              : Ptr32 _KTSS
+0x044 MajorVersion     : Uint2B
+0x046 MinorVersion     : Uint2B
+0x048 SetMember        : Uint4B
+0x04c StallScaleFactor : Uint4B
+0x050 DebugActive      : UChar
+0x051 Number           : UChar
+0x052 Spare0           : UChar
+0x053 SecondLevelCacheAssociativity : UChar
+0x054 VdmAlert         : Uint4B
+0x058 KernelReserved   : [14] Uint4B
+0x090 SecondLevelCacheSize : Uint4B
+0x094 HalReserved      : [16] Uint4B
+0x0d4 InterruptMode    : Uint4B
+0x0d8 Spare1           : UChar
+0x0dc KernelReserved2  : [17] Uint4B
+0x120 PrcbData         : _KPRCB


    这样fs:[124]就指向KPRCB数据结构的第四个字节。由于KPRCB比较大,再此就不列出来了。查看其数据结构可以看到第四个字节指向CurrentThead(KTHREAD类型)。这样fs:[124]其实是指向当前线程的_KTHREAD。

===============================================================================================

应用实例:

以前看某些文章的时候,知道可以利用“活动进程链”隐藏或者检测进程。对于如何定位活动进程链一直没搞清楚,在看Rootkit那本书上说,通过PsGetCurrentProcess函数可以获得EPROCESS,但是书中解释的很模糊,一直没看明白。

今天利用WinDbg查看了各个结构,终于把疑问搞清楚了。

PsGetCurrentProcess函数反汇编后是这样:
lkd> u nt!PsGetCurrentProcess
nt!PsGetCurrentProcess:
8052b52c 64a124010000         mov          eax,dword ptr fs:[00000124h]
8052b532 8b4044                   mov          eax,dword ptr [eax+44h]
8052b535 c3                          ret

在用户模式下,FS指向TEB结构,而在内核模式下FS却指向KPCR(Kernel's Processor Control Region)结构。那么可以看到FS:[0x120]处就是KPRCB(Kernel's Processor Cotrol Block)结构(看下图红色高亮处)

lkd> dt nt!_kpcr

nt!_KPCR

        +0x000 NtTib                 : _NT_TIB

        +0x01c SelfPcr               : Ptr32 _KPCR

        +0x020 Prcb                  : Ptr32 _KPRCB

        +0x024 Irql                  : UChar

        +0x028 IRR                   : Uint4B

        +0x02c IrrActive             : Uint4B

        +0x030 IDR                   : Uint4B

        +0x034 KdVersionBlock        : Ptr32 Void

        +0x038 IDT                   : Ptr32 _KIDTENTRY

        +0x03c GDT                   : Ptr32 _KGDTENTRY

        +0x040 TSS                   : Ptr32 _KTSS

        +0x044 MajorVersion          : Uint2B

        +0x046 MinorVersion          : Uint2B

        +0x048 SetMember             : Uint4B

        +0x04c StallScaleFactor : Uint4B

        +0x050 DebugActive           : UChar

        +0x051 Number                : UChar

        +0x052 Spare0                : UChar

        +0x053 SecondLevelCacheAssociativity : UChar

        +0x054 VdmAlert              : Uint4B

        +0x058 KernelReserved        : [14] Uint4B

        +0x090 SecondLevelCacheSize : Uint4B

        +0x094 HalReserved           : [16] Uint4B

        +0x0d4 InterruptMode         : Uint4B

        +0x0d8 Spare1                : UChar

        +0x0dc KernelReserved2       : [17] Uint4B

   +0x120 PrcbData              : _KPRCB

展开KPRCB结构继续观察可以看到FS:[0x124]指向了KTHREAD结构

lkd> dt nt!_kprcb

nt!_KPRCB

        +0x000 MinorVersion          : Uint2B

        +0x002 MajorVersion          : Uint2B

   +0x004 CurrentThread         : Ptr32 _KTHREAD

        +0x008 NextThread            : Ptr32 _KTHREAD

        +0x00c IdleThread            : Ptr32 _KTHREAD

......本结构更多成员省略

继续查看KTHREAD结构可以看到KTHREAD+0x44处成员就是KPROCESS指针

lkd> dt nt!_kthread -v -r1

Matched nt!_KTHREAD

nt!_KTHREAD

struct _KTHREAD, 73 elements, 0x1c0 bytes

        +0x000 Header                : struct _DISPATCHER_HEADER, 6 elements, 0x10 bytes

           +0x000 Type                  : UChar

           +0x001 Absolute              : UChar

           +0x002 Size                  : UChar

           +0x003 Inserted              : UChar

           +0x004 SignalState           : Int4B

           +0x008 WaitListHead          : struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x000 Flink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x004 Blink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

        +0x010 MutantListHead        : struct _LIST_ENTRY, 2 elements, 0x8 bytes

           +0x000 Flink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x000 Flink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x004 Blink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

           +0x004 Blink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x000 Flink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x004 Blink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

        +0x018 InitialStack          : Ptr32 to Void

        +0x01c StackLimit            : Ptr32 to Void

        +0x020 Teb                   : Ptr32 to Void

        +0x024 TlsArray              : Ptr32 to Void

        +0x028 KernelStack           : Ptr32 to Void

        +0x02c DebugActive           : UChar

        +0x02d State                 : UChar

        +0x02e Alerted               : [2] UChar

        +0x030 Iopl                  : UChar

        +0x031 NpxState              : UChar

        +0x032 Saturation            : Char

        +0x033 Priority              : Char

  +0x034 ApcState              : struct _KAPC_STATE, 5 elements, 0x18 bytes

           +0x000 ApcListHead           : [2] struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x000 Flink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

              +0x004 Blink                 : Ptr32 to struct _LIST_ENTRY, 2 elements, 0x8 bytes

      +0x010 Process               : Ptr32 to struct _KPROCESS, 29 elements, 0x6c bytes

至此,我们已经搞清了PsGetCurrentProcess的流程

通过查DDK DOC发现MS对PsGetCurrentProcess函数是这样描述的:

PsGetCurrentProcess returns a pointer to the process of the current thread.

PEPROCESS 

       PsGetCurrentProcess(

         );

该函数的返回值是EPROCESS指针。但是我们分析的结果是函数的返回值是KPROCESS的指针。

这样的话难道PsGetCurrentProcess 函数返回值既是EPROCESS的指针又是KPROCESS的指针?

带着疑问我们继续往下看:

lkd> dt nt!_eprocess

nt!_EPROCESS

   +0x000 Pcb                   : _KPROCESS

        +0x06c ProcessLock           : _EX_PUSH_LOCK

        +0x070 CreateTime            : _LARGE_INTEGER

        +0x078 ExitTime              : _LARGE_INTEGER

        +0x080 RundownProtect        : _EX_RUNDOWN_REF

   +0x084 UniqueProcessId       : Ptr32 Void

        +0x088 ActiveProcessLinks : _LIST_ENTRY


可以看到EPROCESS的第一个成员就是KPROCESS,这样我们就明白了为什么PsGetCurrentProcess 函数返回值既是EPROCESS的地址又是KPROCESS的地址了。在EPROCESS偏移0x84是进程的PID,偏移0x88(我的系统是XP SP2)就是我们要找的活动进程链了。

补充:通过反汇编PsGetCurrentThread可以看到fs:[124h]

uf nt!PsGetCurrentThread

nt!KeGetCurrentThread:

83e8750e 64a124010000    mov     eax,dword ptr fs:[00000124h]

83e87514 c3              ret
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: