以前看某些文章的時候,知道可以利用“活動進程鏈”隱藏或者檢測進程。對于如何定位活動進程鏈一直沒搞清楚,在看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 -r
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)就是我們要找的活動進程鏈了。
以上是我今天學習的一些收獲,如果大家認為有哪些不對的地方,請指正。