Windows Process内存组织结构及重要域解析

最近恶补操作系统和一些底层的知识。遂写篇文章来说说从操作系统的角度来研究Process的一些结构,实现,Porcess的初始化,重要的结构体域的定义,代表的含义,如何组织起来的,等。还有在前段时间研究托管的static字段到底在内存中如何组织的时候,遇到的handle table不熟悉的问题。

       一个xp里面的Process,是由几个Eprocess,执行体进程块来表示的。这个Eprocess里面不仅包含了进程相关的一些重要的数据结构,同时还包含了进程一些重要的环境变量之内的东西。EPROCESS块位于操作系统的进程空间里面。不过PEB块是在用户空间里面的。因为PEB块包含了一些需要用户来修改的数据,放在操作系统空间中会导致不安全和频繁的操作模式的切换。

       从网上c了一个图过来说明,这个图是windows internal第六章里面的。一个完整的Process的东西分别放在了SYSTEM ADDRESSPROCESS ADDRESS里面。用来适应不同的操作模式。

       在内核调试模式下,可以dtProcess的内核执行块的结构:

    



lkd> dt 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

   +0x090 QuotaUsage       : [3] Uint4B

   +0x09c QuotaPeak        : [3] Uint4B

   +0x0a8 CommitCharge     : Uint4B

   +0x0ac PeakVirtualSize  : Uint4B

   +0x0b0 VirtualSize      : Uint4B

   +0x0b4 SessionProcessLinks : _LIST_ENTRY

   +0x0bc DebugPort        : Ptr32 Void

   +0x0c0 ExceptionPort    : Ptr32 Void

   +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE

   +0x0c8 Token            : _EX_FAST_REF

   +0x0cc WorkingSetLock   : _FAST_MUTEX

   +0x0ec WorkingSetPage   : Uint4B

   +0x0f0 AddressCreationLock : _FAST_MUTEX

   +0x110 HyperSpaceLock   : Uint4B

   +0x114 ForkInProgress   : Ptr32 _ETHREAD

   +0x118 HardwareTrigger  : Uint4B

   +0x11c VadRoot          : Ptr32 Void

   +0x120 VadHint          : Ptr32 Void

   +0x124 CloneRoot        : Ptr32 Void

   +0x128 NumberOfPrivatePages : Uint4B

   +0x12c NumberOfLockedPages : Uint4B

   +0x130 Win32Process     : Ptr32 Void

   +0x134 Job              : Ptr32 _EJOB

   +0x138 SectionObject    : Ptr32 Void

   +0x13c SectionBaseAddress : Ptr32 Void

   +0x140 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK

   +0x144 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY

   +0x148 Win32WindowStation : Ptr32 Void

   +0x14c InheritedFromUniqueProcessId : Ptr32 Void

   +0x150 LdtInformation   : Ptr32 Void

   +0x154 VadFreeHint      : Ptr32 Void

   +0x158 VdmObjects       : Ptr32 Void

   +0x15c DeviceMap        : Ptr32 Void

   +0x160 PhysicalVadList  : _LIST_ENTRY

   +0x168 PageDirectoryPte : _HARDWARE_PTE

   +0x168 Filler           : Uint8B

   +0x170 Session          : Ptr32 Void

   +0x174 ImageFileName    : [16] UChar

   +0x184 JobLinks         : _LIST_ENTRY

   +0x18c LockedPagesList  : Ptr32 Void

   +0x190 ThreadListHead   : _LIST_ENTRY

   +0x198 SecurityPort     : Ptr32 Void

   +0x19c PaeTop           : Ptr32 Void

   +0x1a0 ActiveThreads    : Uint4B

   +0x1a4 GrantedAccess    : Uint4B

   +0x1a8 DefaultHardErrorProcessing : Uint4B

   +0x1ac LastThreadExitStatus : Int4B

   +0x1b0 Peb              : Ptr32 _PEB

   +0x1b4 PrefetchTrace    : _EX_FAST_REF

   +0x1b8 ReadOperationCount : _LARGE_INTEGER

   +0x1c0 WriteOperationCount : _LARGE_INTEGER

   +0x1c8 OtherOperationCount : _LARGE_INTEGER

   +0x1d0 ReadTransferCount : _LARGE_INTEGER

   +0x1d8 WriteTransferCount : _LARGE_INTEGER

   +0x1e0 OtherTransferCount : _LARGE_INTEGER

   +0x1e8 CommitChargeLimit : Uint4B

   +0x1ec CommitChargePeak : Uint4B

   +0x1f0 AweInfo          : Ptr32 Void

   +0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO

   +0x1f8 Vm               : _MMSUPPORT

   +0x238 LastFaultCount   : Uint4B

   +0x23c ModifiedPageCount : Uint4B

   +0x240 NumberOfVads     : Uint4B

   +0x244 JobStatus        : Uint4B

   +0x248 Flags            : Uint4B

   +0x248 CreateReported   : Pos 0, 1 Bit

   +0x248 NoDebugInherit   : Pos 1, 1 Bit

   +0x248 ProcessExiting   : Pos 2, 1 Bit

   +0x248 ProcessDelete    : Pos 3, 1 Bit

   +0x248 Wow64SplitPages  : Pos 4, 1 Bit

   +0x248 VmDeleted        : Pos 5, 1 Bit

   +0x248 OutswapEnabled   : Pos 6, 1 Bit

   +0x248 Outswapped       : Pos 7, 1 Bit

   +0x248 ForkFailed       : Pos 8, 1 Bit

   +0x248 HasPhysicalVad   : Pos 9, 1 Bit

   +0x248 AddressSpaceInitialized : Pos 10, 2 Bits

   +0x248 SetTimerResolution : Pos 12, 1 Bit

   +0x248 BreakOnTermination : Pos 13, 1 Bit

   +0x248 SessionCreationUnderway : Pos 14, 1 Bit

   +0x248 WriteWatch       : Pos 15, 1 Bit

   +0x248 ProcessInSession : Pos 16, 1 Bit

   +0x248 OverrideAddressSpace : Pos 17, 1 Bit

   +0x248 HasAddressSpace  : Pos 18, 1 Bit

   +0x248 LaunchPrefetched : Pos 19, 1 Bit

   +0x248 InjectInpageErrors : Pos 20, 1 Bit

   +0x248 VmTopDown        : Pos 21, 1 Bit

   +0x248 Unused3          : Pos 22, 1 Bit

   +0x248 Unused4          : Pos 23, 1 Bit

   +0x248 VdmAllowed       : Pos 24, 1 Bit

   +0x248 Unused           : Pos 25, 5 Bits

   +0x248 Unused1          : Pos 30, 1 Bit

   +0x248 Unused2          : Pos 31, 1 Bit

   +0x24c ExitStatus       : Int4B

   +0x250 NextPageColor    : Uint2B

   +0x252 SubSystemMinorVersion : UChar

   +0x253 SubSystemMajorVersion : UChar

   +0x252 SubSystemVersion : Uint2B

   +0x254 PriorityClass    : UChar

   +0x255 WorkingSetAcquiredUnsafe : UChar

   +0x258 Cookie           : Uint4B

      

       也可以用dt nt!_Kprocess –r1命令来展开成为一级的形式,在输出中显示结构体的定义。

 

       首先看看_LIST_ENTRY表示的几个域:

+0x160 PhysicalVadList  : _LIST_ENTRY

+0x184 JobLinks         : _LIST_ENTRY

+0x190 ThreadListHead   : _LIST_ENTRY

+0x0b4 SessionProcessLinks : _LIST_ENTRY

+0x088 ActiveProcessLinks : _LIST_ENTRY

 

首先给看看_LIST_ENTRY的定义:
typedef struct _LIST_ENTRY {

   struct _LIST_ENTRY *Flink;

   struct _LIST_ENTRY *Blink;

} LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

 

使用这个结构体,就可以把许多同类型的数据组成一个链表。譬如有一种隐藏进程的方法,就是通过截断EPROCESSActiveProcessLinks链表来隐藏进程。

具体的做法,就是通过PsGetCurrentProcess函数,来获取当前的KPROCESS的地址,而KPROCESS就是进程执行体,就是上面的EPROCESS的第一项。然后根据不同的操作系统的版本的偏移位置的不同,来得到_LIST_ENTRY链表,然后通过修改链表来达到隐藏进程的目的。

同时,根据PsGetCurrentProcess返回的KPROCESS的地址得到了EPROCESS执行体之后,具体分析不同版本操作系统的EPROCESS结构体的不同,还可以做很多事情。

 

       从给起的变量的名字上面,可以大致的知道这些链表都把啥东西链接了起来。

 

       整个EPROCESS的大小和包含的结构体的定义,可以使用!strct _EPROCESS这个命令来获取到:

       lkd> !strct _eprocess

struct _EPROCESS (sizeof=648)

+000 struct   _KPROCESS Pcb

+070 struct   _KEVENT LockEvent

+090 union    _LARGE_INTEGER ExitTime

+098 struct   _KTHREAD *LockOwner

+0a0 struct   _LIST_ENTRY ActiveProcessLinks

+0d0 struct   _MMSUPPORT Vm

+118 struct   _LIST_ENTRY SessionProcessLinks

+128 struct   _HANDLE_TABLE *ObjectTable

+130 struct   _FAST_MUTEX WorkingSetLock

+158 struct   _FAST_MUTEX AddressCreationLock

+17c struct   _ETHREAD *ForkInProgress

+184 struct   _KEVENT *VmOperationEvent

+1b0 struct   _PEB *Peb

+1b8 struct   _EPROCESS_QUOTA_BLOCK *QuotaBlock

+1c0 struct   _PAGEFAULT_HISTORY *WorkingSetWatch

+1e8 struct   _LIST_ENTRY PhysicalVadList

+1f0 struct   _HARDWARE_PTE_X86 PageDirectoryPte

+218 struct   _EJOB *Job

+220 struct   _LIST_ENTRY JobLinks

+230 struct   _WOW64_PROCESS *Wow64Process

+238 union    _LARGE_INTEGER ReadOperationCount

+240 union    _LARGE_INTEGER WriteOperationCount

+248 union    _LARGE_INTEGER OtherOperationCount

+250 union    _LARGE_INTEGER ReadTransferCount

+258 union    _LARGE_INTEGER WriteTransferCount

+260 union    _LARGE_INTEGER OtherTransferCount

+270 struct   _LIST_ENTRY ThreadListHead

+278 struct   _RTL_BITMAP *VadPhysicalPagesBitMap

这里只留下structunion,区域的数据类型全部去掉了。

每个EPROCESS的第一个域,都是一个KPROCESS域。KPROCESS包含了公共的分发器对象头,指向进程页面目录的指针,KTHREAD的内核线程块的列表,线程的内核时间和用户时间等等。简单的瞅瞅:

lkd> dt _KPROCESS

ntdll!_KPROCESS

   +0x000 Header           : _DISPATCHER_HEADER

   +0x010 ProfileListHead  : _LIST_ENTRY

//进程的页目录

   +0x018 DirectoryTableBase : [2] Uint4B

   +0x020 LdtDescriptor    : _KGDTENTRY

       //GDT的入口

   +0x028 Int21Descriptor  : _KIDTENTRY

       //IDT的入口

   +0x030 IopmOffset       : Uint2B

   +0x032 Iopl             : UChar

   +0x033 Unused           : UChar

   +0x034 ActiveProcessors : Uint4B

   +0x038 KernelTime       : Uint4B

   +0x03c UserTime         : Uint4B

   +0x040 ReadyListHead    : _LIST_ENTRY

   +0x048 SwapListEntry    : _SINGLE_LIST_ENTRY

   +0x04c VdmTrapcHandler  : Ptr32 Void

   +0x050 ThreadListHead   : _LIST_ENTRY

       //KTHREAD的链

   +0x058 ProcessLock      : Uint4B

   +0x05c Affinity         : Uint4B

   +0x060 StackCount       : Uint2B

   +0x062 BasePriority     : Char

   +0x063 ThreadQuantum    : Char

   +0x064 AutoAlignment    : UChar

   +0x065 State            : UChar

   +0x066 ThreadSeed       : UChar

   +0x067 DisableBoost     : UChar

   +0x068 PowerState       : UChar

   +0x069 DisableQuantum   : UChar

   +0x06a IdealNode        : UChar

   +0x06b Flags            : _KEXECUTE_OPTIONS

       //运行的标识位

   +0x06b ExecuteOptions   : Uchar

      

       可以用!process 0 0来获取系统里面正在运行的所有线程的EPROCESS的地址:

       lkd> !process 0 0

PROCESS 821b77c0  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000

    DirBase: 02ac0020  ObjectTable: e1001e10  HandleCount: 277.

    Image: System

 

PROCESS 8207c740  SessionId: none  Cid: 0180    Peb: 7ffd5000  ParentCid: 0004

    DirBase: 02ac0040  ObjectTable: e13ad948  HandleCount:  21.

    Image: SMSS.EXE

 

PROCESS 820ee020  SessionId: 0  Cid: 027c    Peb: 7ffdf000  ParentCid: 0180

    DirBase: 02ac0060  ObjectTable: e1401eb0  HandleCount: 309.

Image: CSRSS.EXE

 

如果不带参数的话,就直接获取当前正在运行的进程的情况:

 

lkd> !process

PROCESS 81fe15c8  SessionId: 0  Cid: 0604    Peb: 7ffd4000  ParentCid: 05c4

    DirBase: 02ac0320  ObjectTable: e1ae43e8  HandleCount: 635.

    Image: windbg.exe

    VadRoot 81dc61b0 Vads 792 Clone 0 Private 43397. Modified 74582. Locked 1.

    DeviceMap e1a2c530

    Token                             e2343bd0

    ElapsedTime                       3 Days 00:51:45.656

    UserTime                          00:02:52.656

    KernelTime                        00:01:08.937

    QuotaPoolUsage[PagedPool]         140124

    QuotaPoolUsage[NonPagedPool]      32200

    Working Set Sizes (now,min,max)  (35983, 50, 345) (143932KB, 200KB, 1380KB)

    PeakWorkingSetSize                45310

    VirtualSize                       293 Mb

    PeakVirtualSize                   424 Mb

    PageFaultCount                    210305

    MemoryPriority                    BACKGROUND

    BasePriority                      8

    CommitCharge                      44348

 

THREAD 81da02e8  Cid 0604.04fc  Teb: 7ffdf000 Win32Thread: e2329eb0 WAIT: (WrUserRequest) UserMode Non-Alertable

82133d30  SynchronizationEvent

略去几条线程的信息。

 

对比KPROCESS的结构和上面Process命令得到的输出结果,可以看到,Process命令只是输出了一部分的Process的信息。如果采用!Process 0 0来获取到某特特定进程的Eprocess的地址做为Process命令的参数,就可以得到特定的Process的信息。

 

同理,对PEB的查看也是一样:

lkd> !strct peb

struct   _PEB (sizeof=488)

+000 byte     InheritedAddressSpace

+001 byte     ReadImageFileExecOptions

+002 byte     BeingDebugged

+003 byte     SpareBool

+004 void     *Mutant

+008 void     *ImageBaseAddress

+00c struct   _PEB_LDR_DATA *Ldr

+010 struct   _RTL_USER_PROCESS_PARAMETERS *ProcessParameters

+014 void     *SubSystemData

+018 void     *ProcessHeap

+01c void     *FastPebLock

+020 void     *FastPebLockRoutine

+024 void     *FastPebUnlockRoutine

+028 uint32   EnvironmentUpdateCount

+02c void     *KernelCallbackTable

+030 uint32   SystemReserved[2]

+038 struct   _PEB_FREE_BLOCK *FreeList

+03c uint32   TlsExpansionCounter

+040 void     *TlsBitmap

+044 uint32   TlsBitmapBits[2]

+04c void     *ReadOnlySharedMemoryBase

+050 void     *ReadOnlySharedMemoryHeap

+054 void     **ReadOnlyStaticServerData

+058 void     *AnsiCodePageData

+05c void     *OemCodePageData

+060 void     *UnicodeCaseTableData

+064 uint32   NumberOfProcessors

+068 uint32   NtGlobalFlag

+070 union    _LARGE_INTEGER CriticalSectionTimeout

+070    uint32   LowPart

+074    int32    HighPart

+070    struct   __unnamed3 u

+070       uint32   LowPart

+074       int32    HighPart

+070    int64    QuadPart

+078 uint32   HeapSegmentReserve

+07c uint32   HeapSegmentCommit

+080 uint32   HeapDeCommitTotalFreeThreshold

+084 uint32   HeapDeCommitFreeBlockThreshold

+088 uint32   NumberOfHeaps

+08c uint32   MaximumNumberOfHeaps

+090 void     **ProcessHeaps

+094 void     *GdiSharedHandleTable

+098 void     *ProcessStarterHelper

+09c uint32   GdiDCAttributeList

+0a0 void     *LoaderLock

+0a4 uint32   OSMajorVersion

+0a8 uint32   OSMinorVersion

+0ac uint16   OSBuildNumber

+0ae uint16   OSCSDVersion

+0b0 uint32   OSPlatformId

+0b4 uint32   ImageSubsystem

+0b8 uint32   ImageSubsystemMajorVersion

+0bc uint32   ImageSubsystemMinorVersion

+0c0 uint32   ImageProcessAffinityMask

+0c4 uint32   GdiHandleBuffer[34]

+14c function *PostProcessInitRoutine

+150 void     *TlsExpansionBitmap

+154 uint32   TlsExpansionBitmapBits[32]

+1d4 uint32   SessionId

+1d8 void     *AppCompatInfo

+1dc struct   _UNICODE_STRING CSDVersion

+1dc    uint16   Length

+1de    uint16   MaximumLength

+1e0    uint16   *Buffer

 

本来还准备说说handle table,上面的废话太多了,下篇再说了。

 

7/22/2008 2:35:05 PM   首发sscli.cnblogs.com   lbq1221119@jl

posted on 2008-07-22 14:45  lbq1221119  阅读(4394)  评论(11编辑  收藏  举报

导航