进程与线程 -- 进程线程概念(一)

c++

Posted by YiMiTuMi on May 26, 2021

进程与线程 – 进程线程概念(一)

创建进程:

<1> 任何进程都是别的进程创建的: CreateProcess() 

<2> 进程的创建过程

	1)映射EXE文件

	2)创建内核对象EPROCESS

	3)映射系统DLL(ntdll.dll)

	4)创建线程内核对象ETHREAD

	5)系统启动线程

		 (1)映射DLL(通过函数 ntdll.LdrInitializeThunk -> LdrpInitializeProcess函数)

		 (2)线程开始执行

当操作系统想创建一个进程或者线程时,本质上就是分配一块内存,创建一个结构体,并为结构体赋值。

每个进程都有4GB的虚拟空间,进程主要决定了哪些物理页当前进程能用,所以进程主要就提供了一个CR3。

mov dword ptr ds:[0x12345678], 1

其中 0x12345678 是一个有效地址,向它里面赋值实际上是通过当前的有效地址去解析成物理地址保存值,为了找到具体的物理页要通过CR3去寻找,CR3由进程提供,所以进程主要决定了哪些物理页当前进程能用。

切换进程实际上就是切换CR3,当CR3切换后,页目录表就不相同了,所以即使相同的有效地址访问的物理页也不相同。(一个核只有一个CR3,更换的只是CR3里面的值)

进程切换一定会换CR3,线程切换不一定会。实际上在操作系统上运行的都是线程,操作系统并没有进程的概念,所以也没有进程切换的概念,只有线程切换的概念。当操作系统切换线程时发现要切换的线程和当前线程不是在同一个进程中,这时操作系统就会切换CR3,即所谓的进程切换。若切换的线程和当前线程是在同一个进程中,则不会切换CR3,即线程切换。

进程结构体 EPROCESS

每个Windows进程在0环都有一个对应的结构体:EPROCESS 这个结构体包含了进程所有重要的信息。EPROCESS和PEB(进程环境块)不同,PEB也是描述进程信息的但是PEB是3环的给应用层使用的。每当进程创建就会生成一个EPROCESS,即使一个相同的exe打开两次也会创建2个EPROCESS

FS:[124]->_EPROCESS //内核获取_EPROCESS,简单办法,FS:[124]获取_ETHREAD,_EPROCESS在_ETHREAD+0x220的位置(win XP)

EPROCESS结构体结构(win7 32):

kd> dt _EPROCESS
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x098 ProcessLock      : _EX_PUSH_LOCK
   +0x0a0 CreateTime       : _LARGE_INTEGER
   +0x0a8 ExitTime         : _LARGE_INTEGER
   +0x0b0 RundownProtect   : _EX_RUNDOWN_REF
   +0x0b4 UniqueProcessId  : Ptr32 Void
   +0x0b8 ActiveProcessLinks : _LIST_ENTRY
   +0x0c0 ProcessQuotaUsage : [2] Uint4B
   +0x0c8 ProcessQuotaPeak : [2] Uint4B
   +0x0d0 CommitCharge     : Uint4B
   +0x0d4 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK
   +0x0d8 CpuQuotaBlock    : Ptr32 _PS_CPU_QUOTA_BLOCK
   +0x0dc PeakVirtualSize  : Uint4B
   +0x0e0 VirtualSize      : Uint4B
   +0x0e4 SessionProcessLinks : _LIST_ENTRY
   +0x0ec DebugPort        : Ptr32 Void
   +0x0f0 ExceptionPortData : Ptr32 Void
   +0x0f0 ExceptionPortValue : Uint4B
   +0x0f0 ExceptionPortState : Pos 0, 3 Bits
   +0x0f4 ObjectTable      : Ptr32 _HANDLE_TABLE
   +0x0f8 Token            : _EX_FAST_REF
   +0x0fc WorkingSetPage   : Uint4B
   +0x100 AddressCreationLock : _EX_PUSH_LOCK
   +0x104 RotateInProgress : Ptr32 _ETHREAD
   +0x108 ForkInProgress   : Ptr32 _ETHREAD
   +0x10c HardwareTrigger  : Uint4B
   +0x110 PhysicalVadRoot  : Ptr32 _MM_AVL_TABLE
   +0x114 CloneRoot        : Ptr32 Void
   +0x118 NumberOfPrivatePages : Uint4B
   +0x11c NumberOfLockedPages : Uint4B
   +0x120 Win32Process     : Ptr32 Void
   +0x124 Job              : Ptr32 _EJOB
   +0x128 SectionObject    : Ptr32 Void
   +0x12c SectionBaseAddress : Ptr32 Void
   +0x130 Cookie           : Uint4B
   +0x134 Spare8           : Uint4B
   +0x138 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY
   +0x13c Win32WindowStation : Ptr32 Void
   +0x140 InheritedFromUniqueProcessId : Ptr32 Void
   +0x144 LdtInformation   : Ptr32 Void
   +0x148 VdmObjects       : Ptr32 Void
   +0x14c ConsoleHostProcess : Uint4B
   +0x150 DeviceMap        : Ptr32 Void
   +0x154 EtwDataSource    : Ptr32 Void
   +0x158 FreeTebHint      : Ptr32 Void
   +0x160 PageDirectoryPte : _HARDWARE_PTE_X86
   +0x160 Filler           : Uint8B
   +0x168 Session          : Ptr32 Void
   +0x16c ImageFileName    : [15] UChar
   +0x17b PriorityClass    : UChar
   +0x17c JobLinks         : _LIST_ENTRY
   +0x184 LockedPagesList  : Ptr32 Void
   +0x188 ThreadListHead   : _LIST_ENTRY
   +0x190 SecurityPort     : Ptr32 Void
   +0x194 PaeTop           : Ptr32 Void
   +0x198 ActiveThreads    : Uint4B
   +0x19c ImagePathHash    : Uint4B
   +0x1a0 DefaultHardErrorProcessing : Uint4B
   +0x1a4 LastThreadExitStatus : Int4B
   +0x1a8 Peb              : Ptr32 _PEB
   +0x1ac PrefetchTrace    : _EX_FAST_REF
   +0x1b0 ReadOperationCount : _LARGE_INTEGER
   +0x1b8 WriteOperationCount : _LARGE_INTEGER
   +0x1c0 OtherOperationCount : _LARGE_INTEGER
   +0x1c8 ReadTransferCount : _LARGE_INTEGER
   +0x1d0 WriteTransferCount : _LARGE_INTEGER
   +0x1d8 OtherTransferCount : _LARGE_INTEGER
   +0x1e0 CommitChargeLimit : Uint4B
   +0x1e4 CommitChargePeak : Uint4B
   +0x1e8 AweInfo          : Ptr32 Void
   +0x1ec SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x1f0 Vm               : _MMSUPPORT
   +0x25c MmProcessLinks   : _LIST_ENTRY
   +0x264 HighestUserAddress : Ptr32 Void
   +0x268 ModifiedPageCount : Uint4B
   +0x26c Flags2           : Uint4B
   +0x26c JobNotReallyActive : Pos 0, 1 Bit
   +0x26c AccountingFolded : Pos 1, 1 Bit
   +0x26c NewProcessReported : Pos 2, 1 Bit
   +0x26c ExitProcessReported : Pos 3, 1 Bit
   +0x26c ReportCommitChanges : Pos 4, 1 Bit
   +0x26c LastReportMemory : Pos 5, 1 Bit
   +0x26c ReportPhysicalPageChanges : Pos 6, 1 Bit
   +0x26c HandleTableRundown : Pos 7, 1 Bit
   +0x26c NeedsHandleRundown : Pos 8, 1 Bit
   +0x26c RefTraceEnabled  : Pos 9, 1 Bit
   +0x26c NumaAware        : Pos 10, 1 Bit
   +0x26c ProtectedProcess : Pos 11, 1 Bit
   +0x26c DefaultPagePriority : Pos 12, 3 Bits
   +0x26c PrimaryTokenFrozen : Pos 15, 1 Bit
   +0x26c ProcessVerifierTarget : Pos 16, 1 Bit
   +0x26c StackRandomizationDisabled : Pos 17, 1 Bit
   +0x26c AffinityPermanent : Pos 18, 1 Bit
   +0x26c AffinityUpdateEnable : Pos 19, 1 Bit
   +0x26c PropagateNode    : Pos 20, 1 Bit
   +0x26c ExplicitAffinity : Pos 21, 1 Bit
   +0x270 Flags            : Uint4B
   +0x270 CreateReported   : Pos 0, 1 Bit
   +0x270 NoDebugInherit   : Pos 1, 1 Bit
   +0x270 ProcessExiting   : Pos 2, 1 Bit
   +0x270 ProcessDelete    : Pos 3, 1 Bit
   +0x270 Wow64SplitPages  : Pos 4, 1 Bit
   +0x270 VmDeleted        : Pos 5, 1 Bit
   +0x270 OutswapEnabled   : Pos 6, 1 Bit
   +0x270 Outswapped       : Pos 7, 1 Bit
   +0x270 ForkFailed       : Pos 8, 1 Bit
   +0x270 Wow64VaSpace4Gb  : Pos 9, 1 Bit
   +0x270 AddressSpaceInitialized : Pos 10, 2 Bits
   +0x270 SetTimerResolution : Pos 12, 1 Bit
   +0x270 BreakOnTermination : Pos 13, 1 Bit
   +0x270 DeprioritizeViews : Pos 14, 1 Bit
   +0x270 WriteWatch       : Pos 15, 1 Bit
   +0x270 ProcessInSession : Pos 16, 1 Bit
   +0x270 OverrideAddressSpace : Pos 17, 1 Bit
   +0x270 HasAddressSpace  : Pos 18, 1 Bit
   +0x270 LaunchPrefetched : Pos 19, 1 Bit
   +0x270 InjectInpageErrors : Pos 20, 1 Bit
   +0x270 VmTopDown        : Pos 21, 1 Bit
   +0x270 ImageNotifyDone  : Pos 22, 1 Bit
   +0x270 PdeUpdateNeeded  : Pos 23, 1 Bit
   +0x270 VdmAllowed       : Pos 24, 1 Bit
   +0x270 CrossSessionCreate : Pos 25, 1 Bit
   +0x270 ProcessInserted  : Pos 26, 1 Bit
   +0x270 DefaultIoPriority : Pos 27, 3 Bits
   +0x270 ProcessSelfDelete : Pos 30, 1 Bit
   +0x270 SetTimerResolutionLink : Pos 31, 1 Bit
   +0x274 ExitStatus       : Int4B
   +0x278 VadRoot          : _MM_AVL_TABLE
   +0x298 AlpcContext      : _ALPC_PROCESS_CONTEXT
   +0x2a8 TimerResolutionLink : _LIST_ENTRY
   +0x2b0 RequestedTimerResolution : Uint4B
   +0x2b4 ActiveThreadsHighWatermark : Uint4B
   +0x2b8 SmallestTimerResolution : Uint4B
   +0x2bc TimerResolutionStackRecord : Ptr32 _PO_DIAG_STACK_RECORD

+0x000 Pcb : _KPROCESS:

kd> dt _KPROCESS
ntdll!_KPROCESS
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 ProfileListHead  : _LIST_ENTRY
   +0x018 DirectoryTableBase : Uint4B
   +0x01c LdtDescriptor    : _KGDTENTRY
   +0x024 Int21Descriptor  : _KIDTENTRY
   +0x02c ThreadListHead   : _LIST_ENTRY
   +0x034 ProcessLock      : Uint4B
   +0x038 Affinity         : _KAFFINITY_EX
   +0x044 ReadyListHead    : _LIST_ENTRY
   +0x04c SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x050 ActiveProcessors : _KAFFINITY_EX
   +0x05c AutoAlignment    : Pos 0, 1 Bit
   +0x05c DisableBoost     : Pos 1, 1 Bit
   +0x05c DisableQuantum   : Pos 2, 1 Bit
   +0x05c ActiveGroupsMask : Pos 3, 1 Bit
   +0x05c ReservedFlags    : Pos 4, 28 Bits
   +0x05c ProcessFlags     : Int4B
   +0x060 BasePriority     : Char
   +0x061 QuantumReset     : Char
   +0x062 Visited          : UChar
   +0x063 Unused3          : UChar
   +0x064 ThreadSeed       : [1] Uint4B
   +0x068 IdealNode        : [1] Uint2B
   +0x06a IdealGlobalNode  : Uint2B
   +0x06c Flags            : _KEXECUTE_OPTIONS
   +0x06d Unused1          : UChar
   +0x06e IopmOffset       : Uint2B
   +0x070 Unused4          : Uint4B
   +0x074 StackCount       : _KSTACK_COUNT
   +0x078 ProcessListEntry : _LIST_ENTRY
   +0x080 CycleTime        : Uint8B
   +0x088 KernelTime       : Uint4B
   +0x08c UserTime         : Uint4B
   +0x090 VdmTrapcHandler  : Ptr32 Void

第一个成员 Header : _DISPATCHER_HEADER 为可等待对象,比如Mutex互斥体、Event事件等(WaitForSingleObject),可以通过 WaitForSingleObject 等待一个事件、互斥体还可以等待进程、线程等。只要R0的这个结构体是以 _DISPATCHER_HEADER 开头的我们成为“可等待对象”。

+0x018 DirectoryTableBase : Uint4B:(重要)

页目录表(PDT)基址。进程切换实际上就是将要切换进程的 DirectoryTableBase 写到 CR3中,简单点说进程切换就是切换 CR3。

+0x088 KernelTime : Uint4B:

当前进程在0环运行时间。

+0x08c UserTime : Uint4B:

当前进程在3环运行时间。

+0x038 Affinity : _KAFFINITY_EX:

规定进程里面所有线程能在哪个CPU上跑。

如果值为1,那么这个进程里面所有线程只能在0号CPU上跑(00000001)。 如果值为3,那么这个进程里面所有线程只能在0、1号CPU上跑(00000011)。

4个字节共32位,所以最多32核,64位就64核。如果只有一个CPU把这个值设置为4,那么这个进程就死了。

+0x060 BasePriority : Char:

基础优先级或最低优先级,该进程中的所有线程最起始的创建优先级。

+0x0a0 CreateTime : _LARGE_INTEGER:

进程的创建时间。

+0x0a8 ExitTime : _LARGE_INTEGER:

进程的退出时间。

+0x0b4 UniqueProcessId : Ptr32 Void:

进程的编号:PID 和任务管理器的PID是同一个。

+0x0b8 ActiveProcessLinks : _LIST_ENTRY:

活动进程链表:双向链表,所有活动的进程都连接在一起,构成了一个链表。

PsActiveProcessHead(全局变量)指向了链表的头节点。

kd> dd PsActiveProcessHead
83f88f18  855c9ba0 86a66be8 00000000 00000000
83f88f28  83efc48c 00000000 00000000 89001150
83f88f38  00000000 8000001c 00000101 800002e8
83f88f48  80000024 00000000 00000000 00000000
83f88f58  00000000 00000000 00000113 00000000
83f88f68  00000000 83f3935a 00000000 00000000
83f88f78  00000000 00000000 00000008 00000000
83f88f88  83f88f88 83f88f88 00000000 00000000


							第一个节点              _EPROCESS              _EPROCESS
		 
PsActiveProcessHead  →   :0x0 : 下一个    →     	  下一个0x0b8    →       下一个
		                 :0x4 : 前一个          	  前一个(指向上一个)   前一个(指向上一个)

PsActiveProcessHead 中指向的是0x0b8或者是0x0CC的位置,也就是ActiveProcessLinks的位置,所以** _EPROCESS 的位置要在此基础上减去 **ActiveProcessLinks 的偏移。

任务管理器通过查询这个链表来显示进程,可以隐藏进程。

物理页相关的统计信息:

	+0x0d4 QuotaBlock : Ptr32 \_EPROCESS\_QUOTA\_BLOCK 

	+0x0d8 CpuQuotaBlock : Ptr32 \_PS\_CPU\_QUOTA\_BLOCK

虚拟内存相关的统计信息:

	+0x0d0 CommitCharge : Uint4B

    +0x0dc PeakVirtualSize  : Uint4B

    +0x0e0 VirtualSize      : Uint4B

+0x278 VadRoot : _MM_AVL_TABLE:

标识 0-2G(低2g,用户空间)哪些地址是否被占用、分配,该成员指向一个平衡二叉树。

当申请一个内存时,会查找当前二叉树。(模块隐藏)

windbg: !Vad + 地址  //查看

调试相关:

   +0x0ec DebugPort        : Ptr32 Void

   +0x0f0 ExceptionPortData : Ptr32 Void

+0x0f4 ObjectTable : Ptr32 _HANDLE_TABLE:

句柄表。当前进程可能会用到其他的内核对象,句柄表保存其他内核对象的地址。

如果查找其他进程的句柄表时,发现了自己 _EPROCESS 的地址,说明哪个进程打开了当前进程,说明进程被调试。

+0x16c ImageFileName : [15] UChar:

进程镜像文件名(进程名):任务管理器显示的那个。

+0x198 ActiveThreads : Uint4B:

活动线程的数量。

+0x1a8 Peb : Ptr32 _PEB:

PEB(进程环境块):进程在3环的一个结构体,里面包含了进程的模块列表、是否处于调试状态等信息。

kd> dt _PEB
ntdll!_PEB
   +0x000 InheritedAddressSpace : UChar
   +0x001 ReadImageFileExecOptions : UChar
   +0x002 BeingDebugged    : UChar
   +0x003 BitField         : UChar
   +0x003 ImageUsesLargePages : Pos 0, 1 Bit
   +0x003 IsProtectedProcess : Pos 1, 1 Bit
   +0x003 IsLegacyProcess  : Pos 2, 1 Bit
   +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit
   +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit
   +0x003 SpareBits        : Pos 5, 3 Bits
   +0x004 Mutant           : Ptr32 Void
   +0x008 ImageBaseAddress : Ptr32 Void
   +0x00c Ldr              : Ptr32 _PEB_LDR_DATA
   +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS
   +0x014 SubSystemData    : Ptr32 Void
   +0x018 ProcessHeap      : Ptr32 Void
   +0x01c FastPebLock      : Ptr32 _RTL_CRITICAL_SECTION
   +0x020 AtlThunkSListPtr : Ptr32 Void
   +0x024 IFEOKey          : Ptr32 Void
   +0x028 CrossProcessFlags : Uint4B
   +0x028 ProcessInJob     : Pos 0, 1 Bit
   +0x028 ProcessInitializing : Pos 1, 1 Bit
   +0x028 ProcessUsingVEH  : Pos 2, 1 Bit
   +0x028 ProcessUsingVCH  : Pos 3, 1 Bit
   +0x028 ProcessUsingFTH  : Pos 4, 1 Bit
   +0x028 ReservedBits0    : Pos 5, 27 Bits
   +0x02c KernelCallbackTable : Ptr32 Void
   +0x02c UserSharedInfoPtr : Ptr32 Void
   +0x030 SystemReserved   : [1] Uint4B
   +0x034 AtlThunkSListPtr32 : Uint4B
   +0x038 ApiSetMap        : Ptr32 Void
   +0x03c TlsExpansionCounter : Uint4B
   +0x040 TlsBitmap        : Ptr32 Void
   +0x044 TlsBitmapBits    : [2] Uint4B
   +0x04c ReadOnlySharedMemoryBase : Ptr32 Void
   +0x050 HotpatchInformation : Ptr32 Void
   +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void
   +0x058 AnsiCodePageData : Ptr32 Void
   +0x05c OemCodePageData  : Ptr32 Void
   +0x060 UnicodeCaseTableData : Ptr32 Void
   +0x064 NumberOfProcessors : Uint4B
   +0x068 NtGlobalFlag     : Uint4B
   +0x070 CriticalSectionTimeout : _LARGE_INTEGER
   +0x078 HeapSegmentReserve : Uint4B
   +0x07c HeapSegmentCommit : Uint4B
   +0x080 HeapDeCommitTotalFreeThreshold : Uint4B
   +0x084 HeapDeCommitFreeBlockThreshold : Uint4B
   +0x088 NumberOfHeaps    : Uint4B
   +0x08c MaximumNumberOfHeaps : Uint4B
   +0x090 ProcessHeaps     : Ptr32 Ptr32 Void
   +0x094 GdiSharedHandleTable : Ptr32 Void
   +0x098 ProcessStarterHelper : Ptr32 Void
   +0x09c GdiDCAttributeList : Uint4B
   +0x0a0 LoaderLock       : Ptr32 _RTL_CRITICAL_SECTION
   +0x0a4 OSMajorVersion   : Uint4B
   +0x0a8 OSMinorVersion   : Uint4B
   +0x0ac OSBuildNumber    : Uint2B
   +0x0ae OSCSDVersion     : Uint2B
   +0x0b0 OSPlatformId     : Uint4B
   +0x0b4 ImageSubsystem   : Uint4B
   +0x0b8 ImageSubsystemMajorVersion : Uint4B
   +0x0bc ImageSubsystemMinorVersion : Uint4B
   +0x0c0 ActiveProcessAffinityMask : Uint4B
   +0x0c4 GdiHandleBuffer  : [34] Uint4B
   +0x14c PostProcessInitRoutine : Ptr32     void 
   +0x150 TlsExpansionBitmap : Ptr32 Void
   +0x154 TlsExpansionBitmapBits : [32] Uint4B
   +0x1d4 SessionId        : Uint4B
   +0x1d8 AppCompatFlags   : _ULARGE_INTEGER
   +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER
   +0x1e8 pShimData        : Ptr32 Void
   +0x1ec AppCompatInfo    : Ptr32 Void
   +0x1f0 CSDVersion       : _UNICODE_STRING
   +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA
   +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP
   +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA
   +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP
   +0x208 MinimumStackCommit : Uint4B
   +0x20c FlsCallback      : Ptr32 _FLS_CALLBACK_INFO
   +0x210 FlsListHead      : _LIST_ENTRY
   +0x218 FlsBitmap        : Ptr32 Void
   +0x21c FlsBitmapBits    : [4] Uint4B
   +0x22c FlsHighIndex     : Uint4B
   +0x230 WerRegistrationData : Ptr32 Void
   +0x234 WerShipAssertPtr : Ptr32 Void
   +0x238 pContextData     : Ptr32 Void
   +0x23c pImageHeaderHash : Ptr32 Void
   +0x240 TracingFlags     : Uint4B
   +0x240 HeapTracingEnabled : Pos 0, 1 Bit
   +0x240 CritSecTracingEnabled : Pos 1, 1 Bit
   +0x240 SpareTracingBits : Pos 2, 30 Bits

+0x002 BeingDebugged : UChar:

当前进程如果被调试器打开,BeingDebugged 会被置1。

+0x00c Ldr : Ptr32 _PEB_LDR_DATA:

kd> dt _PEB_LDR_DATA
ntdll!_PEB_LDR_DATA
   +0x000 Length           : Uint4B
   +0x004 Initialized      : UChar
   +0x008 SsHandle         : Ptr32 Void
   +0x00c InLoadOrderModuleList : _LIST_ENTRY  
   +0x014 InMemoryOrderModuleList : _LIST_ENTRY
   +0x01c InInitializationOrderModuleList : _LIST_ENTRY
   +0x024 EntryInProgress  : Ptr32 Void
   +0x028 ShutdownInProgress : UChar
   +0x02c ShutdownThreadId : Ptr32 Void

记录当前进程有多少个模块(将该链表断链可以实现模块隐藏):

	+0x00c InLoadOrderModuleList : _LIST_ENTRY  //模块加载的顺序

	+0x014 InMemoryOrderModuleList : _LIST_ENTRY //模块在内存中的顺序

	+0x01c InInitializationOrderModuleList : _LIST_ENTRY //模块初始化的顺序

_LIST_ENTRY 链表保存了指向了 _LDR_DATA_TABLE_ENTRY 结构体:

kd> dt _LDR_DATA_TABLE_ENTRY
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x008 InMemoryOrderLinks : _LIST_ENTRY
   +0x010 InInitializationOrderLinks : _LIST_ENTRY
   +0x018 DllBase          : Ptr32 Void
   +0x01c EntryPoint       : Ptr32 Void
   +0x020 SizeOfImage      : Uint4B
   +0x024 FullDllName      : _UNICODE_STRING
   +0x02c BaseDllName      : _UNICODE_STRING
   +0x034 Flags            : Uint4B
   +0x038 LoadCount        : Uint2B
   +0x03a TlsIndex         : Uint2B
   +0x03c HashLinks        : _LIST_ENTRY
   +0x03c SectionPointer   : Ptr32 Void
   +0x040 CheckSum         : Uint4B
   +0x044 TimeDateStamp    : Uint4B
   +0x044 LoadedImports    : Ptr32 Void
   +0x048 EntryPointActivationContext : Ptr32 _ACTIVATION_CONTEXT
   +0x04c PatchInformation : Ptr32 Void
   +0x050 ForwarderLinks   : _LIST_ENTRY
   +0x058 ServiceTagLinks  : _LIST_ENTRY
   +0x060 StaticLinks      : _LIST_ENTRY
   +0x068 ContextInformation : Ptr32 Void
   +0x06c OriginalBase     : Uint4B
   +0x070 LoadTime         : _LARGE_INTEGER

PEB的使用

线程结构体 ETHREAD (win7 32)

和进程相同,每有一个线程在0环会有一个对应的结构体。

kd> dt _ETHREAD
ntdll!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   +0x200 CreateTime       : _LARGE_INTEGER
   +0x208 ExitTime         : _LARGE_INTEGER
   +0x208 KeyedWaitChain   : _LIST_ENTRY
   +0x210 ExitStatus       : Int4B
   +0x214 PostBlockList    : _LIST_ENTRY
   +0x214 ForwardLinkShadow : Ptr32 Void
   +0x218 StartAddress     : Ptr32 Void
   +0x21c TerminationPort  : Ptr32 _TERMINATION_PORT
   +0x21c ReaperLink       : Ptr32 _ETHREAD
   +0x21c KeyedWaitValue   : Ptr32 Void
   +0x220 ActiveTimerListLock : Uint4B
   +0x224 ActiveTimerListHead : _LIST_ENTRY
   +0x22c Cid              : _CLIENT_ID
   +0x234 KeyedWaitSemaphore : _KSEMAPHORE
   +0x234 AlpcWaitSemaphore : _KSEMAPHORE
   +0x248 ClientSecurity   : _PS_CLIENT_SECURITY_CONTEXT
   +0x24c IrpList          : _LIST_ENTRY
   +0x254 TopLevelIrp      : Uint4B
   +0x258 DeviceToVerify   : Ptr32 _DEVICE_OBJECT
   +0x25c CpuQuotaApc      : Ptr32 _PSP_CPU_QUOTA_APC
   +0x260 Win32StartAddress : Ptr32 Void
   +0x264 LegacyPowerObject : Ptr32 Void
   +0x268 ThreadListEntry  : _LIST_ENTRY
   +0x270 RundownProtect   : _EX_RUNDOWN_REF
   +0x274 ThreadLock       : _EX_PUSH_LOCK
   +0x278 ReadClusterSize  : Uint4B
   +0x27c MmLockOrdering   : Int4B
   +0x280 CrossThreadFlags : Uint4B
   +0x280 Terminated       : Pos 0, 1 Bit
   +0x280 ThreadInserted   : Pos 1, 1 Bit
   +0x280 HideFromDebugger : Pos 2, 1 Bit
   +0x280 ActiveImpersonationInfo : Pos 3, 1 Bit
   +0x280 Reserved         : Pos 4, 1 Bit
   +0x280 HardErrorsAreDisabled : Pos 5, 1 Bit
   +0x280 BreakOnTermination : Pos 6, 1 Bit
   +0x280 SkipCreationMsg  : Pos 7, 1 Bit
   +0x280 SkipTerminationMsg : Pos 8, 1 Bit
   +0x280 CopyTokenOnOpen  : Pos 9, 1 Bit
   +0x280 ThreadIoPriority : Pos 10, 3 Bits
   +0x280 ThreadPagePriority : Pos 13, 3 Bits
   +0x280 RundownFail      : Pos 16, 1 Bit
   +0x280 NeedsWorkingSetAging : Pos 17, 1 Bit
   +0x284 SameThreadPassiveFlags : Uint4B
   +0x284 ActiveExWorker   : Pos 0, 1 Bit
   +0x284 ExWorkerCanWaitUser : Pos 1, 1 Bit
   +0x284 MemoryMaker      : Pos 2, 1 Bit
   +0x284 ClonedThread     : Pos 3, 1 Bit
   +0x284 KeyedEventInUse  : Pos 4, 1 Bit
   +0x284 RateApcState     : Pos 5, 2 Bits
   +0x284 SelfTerminate    : Pos 7, 1 Bit
   +0x288 SameThreadApcFlags : Uint4B
   +0x288 Spare            : Pos 0, 1 Bit
   +0x288 StartAddressInvalid : Pos 1, 1 Bit
   +0x288 EtwPageFaultCalloutActive : Pos 2, 1 Bit
   +0x288 OwnsProcessWorkingSetExclusive : Pos 3, 1 Bit
   +0x288 OwnsProcessWorkingSetShared : Pos 4, 1 Bit
   +0x288 OwnsSystemCacheWorkingSetExclusive : Pos 5, 1 Bit
   +0x288 OwnsSystemCacheWorkingSetShared : Pos 6, 1 Bit
   +0x288 OwnsSessionWorkingSetExclusive : Pos 7, 1 Bit
   +0x289 OwnsSessionWorkingSetShared : Pos 0, 1 Bit
   +0x289 OwnsProcessAddressSpaceExclusive : Pos 1, 1 Bit
   +0x289 OwnsProcessAddressSpaceShared : Pos 2, 1 Bit
   +0x289 SuppressSymbolLoad : Pos 3, 1 Bit
   +0x289 Prefetching      : Pos 4, 1 Bit
   +0x289 OwnsDynamicMemoryShared : Pos 5, 1 Bit
   +0x289 OwnsChangeControlAreaExclusive : Pos 6, 1 Bit
   +0x289 OwnsChangeControlAreaShared : Pos 7, 1 Bit
   +0x28a OwnsPagedPoolWorkingSetExclusive : Pos 0, 1 Bit
   +0x28a OwnsPagedPoolWorkingSetShared : Pos 1, 1 Bit
   +0x28a OwnsSystemPtesWorkingSetExclusive : Pos 2, 1 Bit
   +0x28a OwnsSystemPtesWorkingSetShared : Pos 3, 1 Bit
   +0x28a TrimTrigger      : Pos 4, 2 Bits
   +0x28a Spare1           : Pos 6, 2 Bits
   +0x28b PriorityRegionActive : UChar
   +0x28c CacheManagerActive : UChar
   +0x28d DisablePageFaultClustering : UChar
   +0x28e ActiveFaultCount : UChar
   +0x28f LockOrderState   : UChar
   +0x290 AlpcMessageId    : Uint4B
   +0x294 AlpcMessage      : Ptr32 Void
   +0x294 AlpcReceiveAttributeSet : Uint4B
   +0x298 AlpcWaitListEntry : _LIST_ENTRY
   +0x2a0 CacheManagerCount : Uint4B
   +0x2a4 IoBoostCount     : Uint4B
   +0x2a8 IrpListLock      : Uint4B
   +0x2ac ReservedForSynchTracking : Ptr32 Void
   +0x2b0 CmCallbackListHead : _SINGLE_LIST_ENTRY

+0x000 Tcb : _KTHREAD:

kd> dt _KTHREAD
ntdll!_KTHREAD
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 CycleTime        : Uint8B
   +0x018 HighCycleTime    : Uint4B
   +0x020 QuantumTarget    : Uint8B
   +0x028 InitialStack     : Ptr32 Void
   +0x02c StackLimit       : Ptr32 Void
   +0x030 KernelStack      : Ptr32 Void
   +0x034 ThreadLock       : Uint4B
   +0x038 WaitRegister     : _KWAIT_STATUS_REGISTER
   +0x039 Running          : UChar
   +0x03a Alerted          : [2] UChar
   +0x03c KernelStackResident : Pos 0, 1 Bit
   +0x03c ReadyTransition  : Pos 1, 1 Bit
   +0x03c ProcessReadyQueue : Pos 2, 1 Bit
   +0x03c WaitNext         : Pos 3, 1 Bit
   +0x03c SystemAffinityActive : Pos 4, 1 Bit
   +0x03c Alertable        : Pos 5, 1 Bit
   +0x03c GdiFlushActive   : Pos 6, 1 Bit
   +0x03c UserStackWalkActive : Pos 7, 1 Bit
   +0x03c ApcInterruptRequest : Pos 8, 1 Bit
   +0x03c ForceDeferSchedule : Pos 9, 1 Bit
   +0x03c QuantumEndMigrate : Pos 10, 1 Bit
   +0x03c UmsDirectedSwitchEnable : Pos 11, 1 Bit
   +0x03c TimerActive      : Pos 12, 1 Bit
   +0x03c SystemThread     : Pos 13, 1 Bit
   +0x03c Reserved         : Pos 14, 18 Bits
   +0x03c MiscFlags        : Int4B
   +0x040 ApcState         : _KAPC_STATE
   +0x040 ApcStateFill     : [23] UChar
   +0x057 Priority         : Char
   +0x058 NextProcessor    : Uint4B
   +0x05c DeferredProcessor : Uint4B
   +0x060 ApcQueueLock     : Uint4B
   +0x064 ContextSwitches  : Uint4B
   +0x068 State            : UChar
   +0x069 NpxState         : Char
   +0x06a WaitIrql         : UChar
   +0x06b WaitMode         : Char
   +0x06c WaitStatus       : Int4B
   +0x070 WaitBlockList    : Ptr32 _KWAIT_BLOCK
   +0x074 WaitListEntry    : _LIST_ENTRY
   +0x074 SwapListEntry    : _SINGLE_LIST_ENTRY
   +0x07c Queue            : Ptr32 _KQUEUE
   +0x080 WaitTime         : Uint4B
   +0x084 KernelApcDisable : Int2B
   +0x086 SpecialApcDisable : Int2B
   +0x084 CombinedApcDisable : Uint4B
   +0x088 Teb              : Ptr32 Void
   +0x090 Timer            : _KTIMER
   +0x0b8 AutoAlignment    : Pos 0, 1 Bit
   +0x0b8 DisableBoost     : Pos 1, 1 Bit
   +0x0b8 EtwStackTraceApc1Inserted : Pos 2, 1 Bit
   +0x0b8 EtwStackTraceApc2Inserted : Pos 3, 1 Bit
   +0x0b8 CalloutActive    : Pos 4, 1 Bit
   +0x0b8 ApcQueueable     : Pos 5, 1 Bit
   +0x0b8 EnableStackSwap  : Pos 6, 1 Bit
   +0x0b8 GuiThread        : Pos 7, 1 Bit
   +0x0b8 UmsPerformingSyscall : Pos 8, 1 Bit
   +0x0b8 VdmSafe          : Pos 9, 1 Bit
   +0x0b8 UmsDispatched    : Pos 10, 1 Bit
   +0x0b8 ReservedFlags    : Pos 11, 21 Bits
   +0x0b8 ThreadFlags      : Int4B
   +0x0bc ServiceTable     : Ptr32 Void
   +0x0c0 WaitBlock        : [4] _KWAIT_BLOCK
   +0x120 QueueListEntry   : _LIST_ENTRY
   +0x128 TrapFrame        : Ptr32 _KTRAP_FRAME
   +0x12c FirstArgument    : Ptr32 Void
   +0x130 CallbackStack    : Ptr32 Void
   +0x130 CallbackDepth    : Uint4B
   +0x134 ApcStateIndex    : UChar
   +0x135 BasePriority     : Char
   +0x136 PriorityDecrement : Char
   +0x136 ForegroundBoost  : Pos 0, 4 Bits
   +0x136 UnusualBoost     : Pos 4, 4 Bits
   +0x137 Preempted        : UChar
   +0x138 AdjustReason     : UChar
   +0x139 AdjustIncrement  : Char
   +0x13a PreviousMode     : Char
   +0x13b Saturation       : Char
   +0x13c SystemCallNumber : Uint4B
   +0x140 FreezeCount      : Uint4B
   +0x144 UserAffinity     : _GROUP_AFFINITY
   +0x150 Process          : Ptr32 _KPROCESS
   +0x154 Affinity         : _GROUP_AFFINITY
   +0x160 IdealProcessor   : Uint4B
   +0x164 UserIdealProcessor : Uint4B
   +0x168 ApcStatePointer  : [2] Ptr32 _KAPC_STATE
   +0x170 SavedApcState    : _KAPC_STATE
   +0x170 SavedApcStateFill : [23] UChar
   +0x187 WaitReason       : UChar
   +0x188 SuspendCount     : Char
   +0x189 Spare1           : Char
   +0x18a OtherPlatformFill : UChar
   +0x18c Win32Thread      : Ptr32 Void
   +0x190 StackBase        : Ptr32 Void
   +0x194 SuspendApc       : _KAPC
   +0x194 SuspendApcFill0  : [1] UChar
   +0x195 ResourceIndex    : UChar
   +0x194 SuspendApcFill1  : [3] UChar
   +0x197 QuantumReset     : UChar
   +0x194 SuspendApcFill2  : [4] UChar
   +0x198 KernelTime       : Uint4B
   +0x194 SuspendApcFill3  : [36] UChar
   +0x1b8 WaitPrcb         : Ptr32 _KPRCB
   +0x194 SuspendApcFill4  : [40] UChar
   +0x1bc LegoData         : Ptr32 Void
   +0x194 SuspendApcFill5  : [47] UChar
   +0x1c3 LargeStack       : UChar
   +0x1c4 UserTime         : Uint4B
   +0x1c8 SuspendSemaphore : _KSEMAPHORE
   +0x1c8 SuspendSemaphorefill : [20] UChar
   +0x1dc SListFaultCount  : Uint4B
   +0x1e0 ThreadListEntry  : _LIST_ENTRY
   +0x1e8 MutantListHead   : _LIST_ENTRY
   +0x1f0 SListFaultAddress : Ptr32 Void
   +0x1f4 ThreadCounters   : Ptr32 _KTHREAD_COUNTERS
   +0x1f8 XStateSave       : Ptr32 _XSTATE_SAVE

第一个成员 Header : _DISPATCHER_HEADER 为可等待对象,比如Mutex互斥体、Event事件等(WaitForSingleObject),可以通过 WaitForSingleObject 等待一个事件、互斥体还可以等待进程、线程等。只要R0的这个结构体是以 _DISPATCHER_HEADER 开头的我们成为“可等待对象”。

线程切换相关:

与0环线程堆栈有关系,当提权时我们要把堆栈切换到到0环的堆栈,0环的堆栈保存在TSS中,每个线程都有一个0环的结构体和0环的栈,但TSS只有一份,所以TSS保存的是当前正在运行线程的堆栈,当线程切换时会用到下面的值。

   +0x028 InitialStack     : Ptr32 Void
   +0x02c StackLimit       : Ptr32 Void
   +0x030 KernelStack      : Ptr32 Void

每个线程都有一个ESP0,从 KernelStack 中获取,从其他线程切换到当前线程时会将该值写到TSS中,当从当前线程切换到其他线程时,它就会更新 KernelStack 保存新的栈顶。

InitialStack:0环栈初始的位置。

+0x280 CrossThreadFlags : Uint4B:

线程标志位,可以用于防止进程结束,在插入APC中也有判断:

 mov     eax, [ebp+ThreadHandle]       //获取线程句柄
 xor     ebx, ebx                      //清空ebx
 test    byte ptr [eax+248h], 10h      // eax + 248 =  _ETHREAD.ThreadListEntry.CrossThreadFlags 
 jnz     loc_523983                    //判断 _ETHREAD.ThreadListEntry.CrossThreadFlags 标志位是否为 10H

+0x0b8 ApcQueueable : Pos 5, 1 Bit:

ApcQueueable 用于表示是否可以向线程的APC队列中插入APC。

当线程正在执行退出的代码时,会将这个值设置为0,如果此时执行插入APC的代码(KeInsertQueueApc),在插入函数中会判断这个值的状态,如果为0,则插入失败。

+0x168 ApcStatePointer : [2] Ptr32 _KAPC_STATE

为了操作方便,_KTHREAD 结构体中定义了一个指针数组 ApcStatePointer,长度为2。

正常情况下:

ApcStatePointer[0] 指向 ApcState

ApcStatePointer[1] 指向 SavedApcState (此时 ApcState == SavedApcState)

挂靠情况下:

ApcStatePointer[0] 指向 SavedApcState

ApcStatePointer[1] 指向 ApcState     (此时的ApcState是挂靠的进程的APC队列)

+0x06b WaitMode : Char:

判断线程是用户还是内核导致的等待。

WaitMode = 0 //内核

WaitMode = 1 //用户

+0x03c Alertable : Pos 5, 1 Bit:

判断线程是否可以被APC唤醒。

Alertable = 0 //不可以被APC唤醒

Alertable = 1 //可以被APC唤醒

在APC中:

1.Alertable = 0 当前插入的APC函数未必有机会执行:UserApcPending = 0

2.Alertable = 1时,UserApcPending = 1,则将目标线程唤醒。

+0x088 Teb : Ptr32 Void:

TEB(线程环境块),大小4KB,位于用户地址空间:

FS:[0]->TEB //3环时,0环时FS执行KPCR

TEB:
kd> dt _TEB
ntdll!_TEB
   +0x000 NtTib            : _NT_TIB
   +0x01c EnvironmentPointer : Ptr32 Void
   +0x020 ClientId         : _CLIENT_ID
   +0x028 ActiveRpcHandle  : Ptr32 Void
   +0x02c ThreadLocalStoragePointer : Ptr32 Void
   +0x030 ProcessEnvironmentBlock : Ptr32 _PEB
   +0x034 LastErrorValue   : Uint4B
   +0x038 CountOfOwnedCriticalSections : Uint4B
   +0x03c CsrClientThread  : Ptr32 Void
   +0x040 Win32ThreadInfo  : Ptr32 Void
   +0x044 User32Reserved   : [26] Uint4B
   +0x0ac UserReserved     : [5] Uint4B
   +0x0c0 WOW32Reserved    : Ptr32 Void
   +0x0c4 CurrentLocale    : Uint4B
   +0x0c8 FpSoftwareStatusRegister : Uint4B
   +0x0cc SystemReserved1  : [54] Ptr32 Void
   +0x1a4 ExceptionCode    : Int4B
   +0x1a8 ActivationContextStackPointer : Ptr32 _ACTIVATION_CONTEXT_STACK
   +0x1ac SpareBytes       : [36] UChar
   +0x1d0 TxFsContext      : Uint4B
   +0x1d4 GdiTebBatch      : _GDI_TEB_BATCH
   +0x6b4 RealClientId     : _CLIENT_ID
   +0x6bc GdiCachedProcessHandle : Ptr32 Void
   +0x6c0 GdiClientPID     : Uint4B
   +0x6c4 GdiClientTID     : Uint4B
   +0x6c8 GdiThreadLocalInfo : Ptr32 Void
   +0x6cc Win32ClientInfo  : [62] Uint4B
   +0x7c4 glDispatchTable  : [233] Ptr32 Void
   +0xb68 glReserved1      : [29] Uint4B
   +0xbdc glReserved2      : Ptr32 Void
   +0xbe0 glSectionInfo    : Ptr32 Void
   +0xbe4 glSection        : Ptr32 Void
   +0xbe8 glTable          : Ptr32 Void
   +0xbec glCurrentRC      : Ptr32 Void
   +0xbf0 glContext        : Ptr32 Void
   +0xbf4 LastStatusValue  : Uint4B
   +0xbf8 StaticUnicodeString : _UNICODE_STRING
   +0xc00 StaticUnicodeBuffer : [261] Wchar
   +0xe0c DeallocationStack : Ptr32 Void
   +0xe10 TlsSlots         : [64] Ptr32 Void
   +0xf10 TlsLinks         : _LIST_ENTRY
   +0xf18 Vdm              : Ptr32 Void
   +0xf1c ReservedForNtRpc : Ptr32 Void
   +0xf20 DbgSsReserved    : [2] Ptr32 Void
   +0xf28 HardErrorMode    : Uint4B
   +0xf2c Instrumentation  : [9] Ptr32 Void
   +0xf50 ActivityId       : _GUID
   +0xf60 SubProcessTag    : Ptr32 Void
   +0xf64 EtwLocalData     : Ptr32 Void
   +0xf68 EtwTraceData     : Ptr32 Void
   +0xf6c WinSockData      : Ptr32 Void
   +0xf70 GdiBatchCount    : Uint4B
   +0xf74 CurrentIdealProcessor : _PROCESSOR_NUMBER
   +0xf74 IdealProcessorValue : Uint4B
   +0xf74 ReservedPad0     : UChar
   +0xf75 ReservedPad1     : UChar
   +0xf76 ReservedPad2     : UChar
   +0xf77 IdealProcessor   : UChar
   +0xf78 GuaranteedStackBytes : Uint4B
   +0xf7c ReservedForPerf  : Ptr32 Void
   +0xf80 ReservedForOle   : Ptr32 Void
   +0xf84 WaitingOnLoaderLock : Uint4B
   +0xf88 SavedPriorityState : Ptr32 Void
   +0xf8c SoftPatchPtr1    : Uint4B
   +0xf90 ThreadPoolData   : Ptr32 Void
   +0xf94 TlsExpansionSlots : Ptr32 Ptr32 Void
   +0xf98 MuiGeneration    : Uint4B
   +0xf9c IsImpersonating  : Uint4B
   +0xfa0 NlsCache         : Ptr32 Void
   +0xfa4 pShimData        : Ptr32 Void
   +0xfa8 HeapVirtualAffinity : Uint4B
   +0xfac CurrentTransactionHandle : Ptr32 Void
   +0xfb0 ActiveFrame      : Ptr32 _TEB_ACTIVE_FRAME
   +0xfb4 FlsData          : Ptr32 Void
   +0xfb8 PreferredLanguages : Ptr32 Void
   +0xfbc UserPrefLanguages : Ptr32 Void
   +0xfc0 MergedPrefLanguages : Ptr32 Void
   +0xfc4 MuiImpersonation : Uint4B
   +0xfc8 CrossTebFlags    : Uint2B
   +0xfc8 SpareCrossTebBits : Pos 0, 16 Bits
   +0xfca SameTebFlags     : Uint2B
   +0xfca SafeThunkCall    : Pos 0, 1 Bit
   +0xfca InDebugPrint     : Pos 1, 1 Bit
   +0xfca HasFiberData     : Pos 2, 1 Bit
   +0xfca SkipThreadAttach : Pos 3, 1 Bit
   +0xfca WerInShipAssertCode : Pos 4, 1 Bit
   +0xfca RanProcessInit   : Pos 5, 1 Bit
   +0xfca ClonedThread     : Pos 6, 1 Bit
   +0xfca SuppressDebugMsg : Pos 7, 1 Bit
   +0xfca DisableUserStackWalk : Pos 8, 1 Bit
   +0xfca RtlExceptionAttached : Pos 9, 1 Bit
   +0xfca InitialThread    : Pos 10, 1 Bit
   +0xfca SpareSameTebBits : Pos 11, 5 Bits
   +0xfcc TxnScopeEnterCallback : Ptr32 Void
   +0xfd0 TxnScopeExitCallback : Ptr32 Void
   +0xfd4 TxnScopeContext  : Ptr32 Void
   +0xfd8 LockCount        : Uint4B
   +0xfdc SpareUlong0      : Uint4B
   +0xfe0 ResourceRetValue : Ptr32 Void

kd> dt _NT_TIB
ntdll!_NT_TIB
   +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD //异常链表
   +0x004 StackBase        : Ptr32 Void  //R3 栈底
   +0x008 StackLimit       : Ptr32 Void  //R3 栈范围
   +0x00c SubSystemTib     : Ptr32 Void
   +0x010 FiberData        : Ptr32 Void
   +0x010 Version          : Uint4B
   +0x014 ArbitraryUserPointer : Ptr32 Void
   +0x018 Self             : Ptr32 _NT_TIB

APC相关:

   +0x040 ApcState         : _KAPC_STATE
   +0x060 ApcQueueLock     : Uint4B
   +0x168 ApcStatePointer  : [2] Ptr32 _KAPC_STATE
   +0x170 SavedApcState    : _KAPC_STATE

+0x068 State : UChar:

线程状态:就绪、等待还是运行。

State = 5 //等待

+0x135 BasePriority : Char:

线程优先级,其初始值是所属进程的BasePriority值(即进程的优先级KPROCESS->BasePriority),以后可以通过函数 KeSetBasePriorityThread() 重新设定。

+0x070 WaitBlockList : Ptr32 _KWAIT_BLOCK:

等待哪个对象(WaitForSingleObject)

+0x0bc ServiceTable : Ptr32 Void:

指向系统服务表基址(不是SSTD)

一个普通线程调用任何一个界面函数就会变成GUI线程。 之后就会将 ServiceTable换成SHADOW。

+0x128 TrapFrame : Ptr32 _KTRAP_FRAME:

进入0环时,保存3环的环境。KTRAP FRAME

一个线程一个 TrapFrame

+0x13a PreviousMode : Char:

先前模式:某些内核函数会判断程序是0环调用还是3环调用。

+0x1e0 ThreadListEntry : _LIST_ENTRY:

双向链表,一个进程所有的线程都挂在一个链表中,挂的就是这个位置。一共有两个这样的链表。遍历时注意,获取 ETHREAD 时要减去自身ThreadListEntry的偏移。

+0x22c Cid : _CLIENT_ID:

kd> dt _CLIENT_ID
ntdll!_CLIENT_ID
   +0x000 UniqueProcess    : Ptr32 Void  //当前进程ID
   +0x004 UniqueThread     : Ptr32 Void  //当前线程ID

+0x268 ThreadListEntry : _LIST_ENTRY:

双向链表,一个进程所有的线程都挂在一个链表中,挂的就是这个位置。一共有两个这样的链表。遍历时注意,获取 ETHREAD 时要减去自身ThreadListEntry的偏移。 和 0x1e0处 一样的只是位置不一样。

KPCR(CPU控制区)

1)当线程进入0环时,FS:[0]指向KPCR(3环时FS:[0] -> TEB),并清空异常链表。

2)每个CPU都有一个KPCR结构体(一个核一个)

3)KPCR中存储了CPU本身要用的一些重要数据:GDT、IDT以及线程相关的一些信息。

CPU在同一时刻只能运行一个线程,所以一些通用的数据为了方便查找可以直接保存在KPCR中。(即线程相关信息的一个副本)

KPCR保存的是当前线程的数据,所以KPCR是在线程切换时被赋值的。

FS:[124] 当前线程的结构体 ETHREAD。

KPCR 结构体

kd> dt _KPCR
ntdll!_KPCR
   +0x000 NtTib            : _NT_TIB
   +0x000 Used_ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 Used_StackBase   : Ptr32 Void
   +0x008 Spare2           : Ptr32 Void
   +0x00c TssCopy          : Ptr32 Void
   +0x010 ContextSwitches  : Uint4B
   +0x014 SetMemberCopy    : Uint4B
   +0x018 Used_Self        : Ptr32 Void
   +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 SpareUnused      : 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

+0x000 NtTib : _NT_TIB:

kd> dt _NT_TIB
ntdll!_NT_TIB
   +0x000 ExceptionList    : Ptr32 _EXCEPTION_REGISTRATION_RECORD
   +0x004 StackBase        : Ptr32 Void
   +0x008 StackLimit       : Ptr32 Void
   +0x00c SubSystemTib     : Ptr32 Void
   +0x010 FiberData        : Ptr32 Void
   +0x010 Version          : Uint4B
   +0x014 ArbitraryUserPointer : Ptr32 Void
   +0x018 Self             : Ptr32 _NT_TIB

+0x000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD:

异常处理链表:保存0环的异常处理程序。

进入0环后,当前异常处理链表和三环的不同。

栈相关:

   +0x004 StackBase        : Ptr32 Void 
   +0x008 StackLimit       : Ptr32 Void

保存当前线程的栈低和栈边界,因为CPU在同一时刻只能运行一个线程,所以保存的是当前线程的栈。

+0x01c SelfPcr : Ptr32 _KPCR:

指向当前KPCR自己的指针。

+0x020 Prcb : Ptr32 _KPRCB:

保存一个指向 +0x120 PrcbData : _KPRCB 的指针,如果 PrcbData 位置发生变化可以通过 Prcb 找到。

+0x038 IDT : Ptr32 _KIDTENTRY:

保存 IDT 表的基址。

+0x03c GDT : Ptr32 _KGDTENTRY:

保存 GDT 表的基址。

+0x040 TSS : Ptr32 _KTSS:

保存 TSS 的基址。

+0x051 Number : UChar:

保存当前CPU编号。

+0x120 PrcbData : _KPRCB:

拓展结构体:_KPRCB

kd> dt _KPRCB
ntdll!_KPRCB
   +0x000 MinorVersion     : Uint2B
   +0x002 MajorVersion     : Uint2B
   +0x004 CurrentThread    : Ptr32 _KTHREAD
   +0x008 NextThread       : Ptr32 _KTHREAD
   +0x00c IdleThread       : Ptr32 _KTHREAD
   +0x010 LegacyNumber     : UChar
   +0x011 NestingLevel     : UChar
   +0x012 BuildType        : Uint2B
   +0x014 CpuType          : Char
   +0x015 CpuID            : Char
   +0x016 CpuStep          : Uint2B
   +0x016 CpuStepping      : UChar
   +0x017 CpuModel         : UChar
   +0x018 ProcessorState   : _KPROCESSOR_STATE
   +0x338 KernelReserved   : [16] Uint4B
   +0x378 HalReserved      : [16] Uint4B
   +0x3b8 CFlushSize       : Uint4B
   +0x3bc CoresPerPhysicalProcessor : UChar
   +0x3bd LogicalProcessorsPerCore : UChar
   +0x3be PrcbPad0         : [2] UChar
   +0x3c0 MHz              : Uint4B
   +0x3c4 CpuVendor        : UChar
   +0x3c5 GroupIndex       : UChar
   +0x3c6 Group            : Uint2B
   +0x3c8 GroupSetMember   : Uint4B
   +0x3cc Number           : Uint4B
   +0x3d0 PrcbPad1         : [72] UChar
   +0x418 LockQueue        : [17] _KSPIN_LOCK_QUEUE
   +0x4a0 NpxThread        : Ptr32 _KTHREAD
   +0x4a4 InterruptCount   : Uint4B
   +0x4a8 KernelTime       : Uint4B
   +0x4ac UserTime         : Uint4B
   +0x4b0 DpcTime          : Uint4B
   +0x4b4 DpcTimeCount     : Uint4B
   +0x4b8 InterruptTime    : Uint4B
   +0x4bc AdjustDpcThreshold : Uint4B
   +0x4c0 PageColor        : Uint4B
   +0x4c4 DebuggerSavedIRQL : UChar
   +0x4c5 NodeColor        : UChar
   +0x4c6 PrcbPad20        : [2] UChar
   +0x4c8 NodeShiftedColor : Uint4B
   +0x4cc ParentNode       : Ptr32 _KNODE
   +0x4d0 SecondaryColorMask : Uint4B
   +0x4d4 DpcTimeLimit     : Uint4B
   +0x4d8 PrcbPad21        : [2] Uint4B
   +0x4e0 CcFastReadNoWait : Uint4B
   +0x4e4 CcFastReadWait   : Uint4B
   +0x4e8 CcFastReadNotPossible : Uint4B
   +0x4ec CcCopyReadNoWait : Uint4B
   +0x4f0 CcCopyReadWait   : Uint4B
   +0x4f4 CcCopyReadNoWaitMiss : Uint4B
   +0x4f8 MmSpinLockOrdering : Int4B
   +0x4fc IoReadOperationCount : Int4B
   +0x500 IoWriteOperationCount : Int4B
   +0x504 IoOtherOperationCount : Int4B
   +0x508 IoReadTransferCount : _LARGE_INTEGER
   +0x510 IoWriteTransferCount : _LARGE_INTEGER
   +0x518 IoOtherTransferCount : _LARGE_INTEGER
   +0x520 CcFastMdlReadNoWait : Uint4B
   +0x524 CcFastMdlReadWait : Uint4B
   +0x528 CcFastMdlReadNotPossible : Uint4B
   +0x52c CcMapDataNoWait  : Uint4B
   +0x530 CcMapDataWait    : Uint4B
   +0x534 CcPinMappedDataCount : Uint4B
   +0x538 CcPinReadNoWait  : Uint4B
   +0x53c CcPinReadWait    : Uint4B
   +0x540 CcMdlReadNoWait  : Uint4B
   +0x544 CcMdlReadWait    : Uint4B
   +0x548 CcLazyWriteHotSpots : Uint4B
   +0x54c CcLazyWriteIos   : Uint4B
   +0x550 CcLazyWritePages : Uint4B
   +0x554 CcDataFlushes    : Uint4B
   +0x558 CcDataPages      : Uint4B
   +0x55c CcLostDelayedWrites : Uint4B
   +0x560 CcFastReadResourceMiss : Uint4B
   +0x564 CcCopyReadWaitMiss : Uint4B
   +0x568 CcFastMdlReadResourceMiss : Uint4B
   +0x56c CcMapDataNoWaitMiss : Uint4B
   +0x570 CcMapDataWaitMiss : Uint4B
   +0x574 CcPinReadNoWaitMiss : Uint4B
   +0x578 CcPinReadWaitMiss : Uint4B
   +0x57c CcMdlReadNoWaitMiss : Uint4B
   +0x580 CcMdlReadWaitMiss : Uint4B
   +0x584 CcReadAheadIos   : Uint4B
   +0x588 KeAlignmentFixupCount : Uint4B
   +0x58c KeExceptionDispatchCount : Uint4B
   +0x590 KeSystemCalls    : Uint4B
   +0x594 AvailableTime    : Uint4B
   +0x598 PrcbPad22        : [2] Uint4B
   +0x5a0 PPLookasideList  : [16] _PP_LOOKASIDE_LIST
   +0x620 PPNPagedLookasideList : [32] _GENERAL_LOOKASIDE_POOL
   +0xf20 PPPagedLookasideList : [32] _GENERAL_LOOKASIDE_POOL
   +0x1820 PacketBarrier    : Uint4B
   +0x1824 ReverseStall     : Int4B
   +0x1828 IpiFrame         : Ptr32 Void
   +0x182c PrcbPad3         : [52] UChar
   +0x1860 CurrentPacket    : [3] Ptr32 Void
   +0x186c TargetSet        : Uint4B
   +0x1870 WorkerRoutine    : Ptr32     void 
   +0x1874 IpiFrozen        : Uint4B
   +0x1878 PrcbPad4         : [40] UChar
   +0x18a0 RequestSummary   : Uint4B
   +0x18a4 SignalDone       : Ptr32 _KPRCB
   +0x18a8 PrcbPad50        : [56] UChar
   +0x18e0 DpcData          : [2] _KDPC_DATA
   +0x1908 DpcStack         : Ptr32 Void
   +0x190c MaximumDpcQueueDepth : Int4B
   +0x1910 DpcRequestRate   : Uint4B
   +0x1914 MinimumDpcRate   : Uint4B
   +0x1918 DpcLastCount     : Uint4B
   +0x191c PrcbLock         : Uint4B
   +0x1920 DpcGate          : _KGATE
   +0x1930 ThreadDpcEnable  : UChar
   +0x1931 QuantumEnd       : UChar
   +0x1932 DpcRoutineActive : UChar
   +0x1933 IdleSchedule     : UChar
   +0x1934 DpcRequestSummary : Int4B
   +0x1934 DpcRequestSlot   : [2] Int2B
   +0x1934 NormalDpcState   : Int2B
   +0x1936 DpcThreadActive  : Pos 0, 1 Bit
   +0x1936 ThreadDpcState   : Int2B
   +0x1938 TimerHand        : Uint4B
   +0x193c LastTick         : Uint4B
   +0x1940 MasterOffset     : Int4B
   +0x1944 PrcbPad41        : [2] Uint4B
   +0x194c PeriodicCount    : Uint4B
   +0x1950 PeriodicBias     : Uint4B
   +0x1958 TickOffset       : Uint8B
   +0x1960 TimerTable       : _KTIMER_TABLE
   +0x31a0 CallDpc          : _KDPC
   +0x31c0 ClockKeepAlive   : Int4B
   +0x31c4 ClockCheckSlot   : UChar
   +0x31c5 ClockPollCycle   : UChar
   +0x31c6 PrcbPad6         : [2] UChar
   +0x31c8 DpcWatchdogPeriod : Int4B
   +0x31cc DpcWatchdogCount : Int4B
   +0x31d0 ThreadWatchdogPeriod : Int4B
   +0x31d4 ThreadWatchdogCount : Int4B
   +0x31d8 KeSpinLockOrdering : Int4B
   +0x31dc PrcbPad70        : [1] Uint4B
   +0x31e0 WaitListHead     : _LIST_ENTRY
   +0x31e8 WaitLock         : Uint4B
   +0x31ec ReadySummary     : Uint4B
   +0x31f0 QueueIndex       : Uint4B
   +0x31f4 DeferredReadyListHead : _SINGLE_LIST_ENTRY
   +0x31f8 StartCycles      : Uint8B
   +0x3200 CycleTime        : Uint8B
   +0x3208 HighCycleTime    : Uint4B
   +0x320c PrcbPad71        : Uint4B
   +0x3210 PrcbPad72        : [2] Uint8B
   +0x3220 DispatcherReadyListHead : [32] _LIST_ENTRY
   +0x3320 ChainedInterruptList : Ptr32 Void
   +0x3324 LookasideIrpFloat : Int4B
   +0x3328 MmPageFaultCount : Int4B
   +0x332c MmCopyOnWriteCount : Int4B
   +0x3330 MmTransitionCount : Int4B
   +0x3334 MmCacheTransitionCount : Int4B
   +0x3338 MmDemandZeroCount : Int4B
   +0x333c MmPageReadCount  : Int4B
   +0x3340 MmPageReadIoCount : Int4B
   +0x3344 MmCacheReadCount : Int4B
   +0x3348 MmCacheIoCount   : Int4B
   +0x334c MmDirtyPagesWriteCount : Int4B
   +0x3350 MmDirtyWriteIoCount : Int4B
   +0x3354 MmMappedPagesWriteCount : Int4B
   +0x3358 MmMappedWriteIoCount : Int4B
   +0x335c CachedCommit     : Uint4B
   +0x3360 CachedResidentAvailable : Uint4B
   +0x3364 HyperPte         : Ptr32 Void
   +0x3368 PrcbPad8         : [4] UChar
   +0x336c VendorString     : [13] UChar
   +0x3379 InitialApicId    : UChar
   +0x337a LogicalProcessorsPerPhysicalProcessor : UChar
   +0x337b PrcbPad9         : [5] UChar
   +0x3380 FeatureBits      : Uint4B
   +0x3388 UpdateSignature  : _LARGE_INTEGER
   +0x3390 IsrTime          : Uint8B
   +0x3398 RuntimeAccumulation : Uint8B
   +0x33a0 PowerState       : _PROCESSOR_POWER_STATE
   +0x3468 DpcWatchdogDpc   : _KDPC
   +0x3488 DpcWatchdogTimer : _KTIMER
   +0x34b0 WheaInfo         : Ptr32 Void
   +0x34b4 EtwSupport       : Ptr32 Void
   +0x34b8 InterruptObjectPool : _SLIST_HEADER
   +0x34c0 HypercallPageList : _SLIST_HEADER
   +0x34c8 HypercallPageVirtual : Ptr32 Void
   +0x34cc VirtualApicAssist : Ptr32 Void
   +0x34d0 StatisticsPage   : Ptr32 Uint8B
   +0x34d4 RateControl      : Ptr32 Void
   +0x34d8 Cache            : [5] _CACHE_DESCRIPTOR
   +0x3514 CacheCount       : Uint4B
   +0x3518 CacheProcessorMask : [5] Uint4B
   +0x352c PackageProcessorSet : _KAFFINITY_EX
   +0x3538 PrcbPad91        : [1] Uint4B
   +0x353c CoreProcessorSet : Uint4B
   +0x3540 TimerExpirationDpc : _KDPC
   +0x3560 SpinLockAcquireCount : Uint4B
   +0x3564 SpinLockContentionCount : Uint4B
   +0x3568 SpinLockSpinCount : Uint4B
   +0x356c IpiSendRequestBroadcastCount : Uint4B
   +0x3570 IpiSendRequestRoutineCount : Uint4B
   +0x3574 IpiSendSoftwareInterruptCount : Uint4B
   +0x3578 ExInitializeResourceCount : Uint4B
   +0x357c ExReInitializeResourceCount : Uint4B
   +0x3580 ExDeleteResourceCount : Uint4B
   +0x3584 ExecutiveResourceAcquiresCount : Uint4B
   +0x3588 ExecutiveResourceContentionsCount : Uint4B
   +0x358c ExecutiveResourceReleaseExclusiveCount : Uint4B
   +0x3590 ExecutiveResourceReleaseSharedCount : Uint4B
   +0x3594 ExecutiveResourceConvertsCount : Uint4B
   +0x3598 ExAcqResExclusiveAttempts : Uint4B
   +0x359c ExAcqResExclusiveAcquiresExclusive : Uint4B
   +0x35a0 ExAcqResExclusiveAcquiresExclusiveRecursive : Uint4B
   +0x35a4 ExAcqResExclusiveWaits : Uint4B
   +0x35a8 ExAcqResExclusiveNotAcquires : Uint4B
   +0x35ac ExAcqResSharedAttempts : Uint4B
   +0x35b0 ExAcqResSharedAcquiresExclusive : Uint4B
   +0x35b4 ExAcqResSharedAcquiresShared : Uint4B
   +0x35b8 ExAcqResSharedAcquiresSharedRecursive : Uint4B
   +0x35bc ExAcqResSharedWaits : Uint4B
   +0x35c0 ExAcqResSharedNotAcquires : Uint4B
   +0x35c4 ExAcqResSharedStarveExclusiveAttempts : Uint4B
   +0x35c8 ExAcqResSharedStarveExclusiveAcquiresExclusive : Uint4B
   +0x35cc ExAcqResSharedStarveExclusiveAcquiresShared : Uint4B
   +0x35d0 ExAcqResSharedStarveExclusiveAcquiresSharedRecursive : Uint4B
   +0x35d4 ExAcqResSharedStarveExclusiveWaits : Uint4B
   +0x35d8 ExAcqResSharedStarveExclusiveNotAcquires : Uint4B
   +0x35dc ExAcqResSharedWaitForExclusiveAttempts : Uint4B
   +0x35e0 ExAcqResSharedWaitForExclusiveAcquiresExclusive : Uint4B
   +0x35e4 ExAcqResSharedWaitForExclusiveAcquiresShared : Uint4B
   +0x35e8 ExAcqResSharedWaitForExclusiveAcquiresSharedRecursive : Uint4B
   +0x35ec ExAcqResSharedWaitForExclusiveWaits : Uint4B
   +0x35f0 ExAcqResSharedWaitForExclusiveNotAcquires : Uint4B
   +0x35f4 ExSetResOwnerPointerExclusive : Uint4B
   +0x35f8 ExSetResOwnerPointerSharedNew : Uint4B
   +0x35fc ExSetResOwnerPointerSharedOld : Uint4B
   +0x3600 ExTryToAcqExclusiveAttempts : Uint4B
   +0x3604 ExTryToAcqExclusiveAcquires : Uint4B
   +0x3608 ExBoostExclusiveOwner : Uint4B
   +0x360c ExBoostSharedOwners : Uint4B
   +0x3610 ExEtwSynchTrackingNotificationsCount : Uint4B
   +0x3614 ExEtwSynchTrackingNotificationsAccountedCount : Uint4B
   +0x3618 Context          : Ptr32 _CONTEXT
   +0x361c ContextFlags     : Uint4B
   +0x3620 ExtendedState    : Ptr32 _XSAVE_AREA

+0x004 CurrentThread : Ptr32 _KTHREAD:

CPU正在执行的线程。

(结构体指针)

+0x008 NextThread : Ptr32 _KTHREAD:

CPU下一个要切换的线程。

(结构体指针)

+0x00c IdleThread : Ptr32 _KTHREAD:

没有下一个可切换的线程,CPU索要跑的空闲线程。

(结构体指针)

断链

进程结构体 EPROCESS 中的两个链表,里面圈着当前进程所有的线程。对进程断链,程序可以正常运行,原因是CPU执行与调度是基于线程的,进程断链只是影响一些遍历系统的API,并不会影响程序执行。

对进程断链也是一样的,断链后在Windbg或者OD中无法看到被断掉的线程,但并不影响其执行。(依然再跑)

33个链表

线程三种状态:挂起(等待)、执行、就绪(wait、 running、 ready)

正在运行中的线程存储在KPCR中,就绪和等待的线程全在另外的33个链表中。一个等待链表,32个就绪链表。

这些链表都使用了 _KTHREAD 的线程链表,也就是说,线程在某一时刻,只能属于其中一个圈。

等待链表

线程调用了 Sleep() 或者 WaitForSingleObject()等待函数时,就挂到这个等待链表。

全局变量:

KiWaitListHead   //指向等待链表(双向链表)

等待链表挂在 _KTHREAD WaitListEntry的位置,所以 _ETHREAD 的基址为查找到的地址减去WaitListEntry的位置。

_KTREAD:

 +0x074 WaitListEntry    : _LIST_ENTRY  //等待链
 +0x074 SwapListEntry    : _SINGLE_LIST_ENTRY //就绪链

因为一个线程同时只会处于一个状态,所以这两个值在同一个位置。

调度链表

调度链表有32个圈(双向链表),就是优先级 0 - 31(0最低,31最高),默认优先级一般时8,改变优先级就是从一个圈(双向链表)里面卸下来挂到另外一个圈上。

这32个圈(双向链表)是正在调度的线程,准备运行的。

如:只有一个CPU但有10个线程在运行,那么某一时刻,正在运行的线程在KPCR中,其他9个在这32个圈中。

KiDispatcherReadyListHead 一个指向调度链表(32个)的全局变量。(XP以上可能没有导出)

查看调度链表:

既然有32个链表,就要有32个链表头。

kd> dd KiDispatcherReadyListHead L70

在 Windbg 中可以看到这32个链表的地址,若其中一个链表地址等于后面一个链表地址则说明当前链表为空。

调试时看到所有链表为空,因为调试时所有线程都被挂起。

之所以断掉之前的线程链表,但线程仍在执行,是因为CPU调度时用的是这个调度链表而并非之前保存链表。

版本差异

XP只有一套33个链表,也就是说这个数组只有一个,多核也只有一个。

Win7也是一样的只有一套33个链表,如果是64位的,就有有一套64个链表。即一个等待链表,64个调度链表。

服务器版本:

KiWaitListHead整个系统只有一个,但KiDispatcherReadyListHead这个数组有几个CPU就有几组。

PS:

一个操作系统所有的线程数 = 32个调度链表中的进程数 + 等待链表中的进程数 + N个核中的线程数(正在运行中的线程)。

一个核只有一个 KPCR 一个 KPCR 保存一个正在运行的线程。多个核就有多个正在运行的线程。

总结

CPU的调度单位是线程,也就是说即使将进程从链表中删掉也不影响正常执行。

调用:

int 20  可以获取当前进程的ESP0

操作系统没有使用TSS做任务切换,但使用了其中的值。

windows的线程切换一定发生在0环。

一个普通线程调用任何一个界面函数就会变成GUI线程。 之后就会将 ServiceTable换成SHADOW。

CPU调度线程和进程时用的并不是 EPROCESS 和 ETHREAD 中线程和进程列表。所以从中断开也不会使线程和进程停止。

线程三种状态:挂起、执行、就绪(wait、 running、 ready)

蓝色妖姬 – 相守