寫在前面
此係列是本人一個字一個字碼出來的,包括示例和實驗截圖。由於系統核心的複雜性,故可能有錯誤或者不全面的地方,如有錯誤,歡迎批評指正,本教程將會長期更新。 如有好的建議,歡迎反饋。碼字不易,如果本篇文章有幫助你的,如有閒錢,可以打賞支援我的創作。如想轉載,請把我的轉載資訊附在文章後面,並宣告我的個人資訊和本人部落格地址即可,但必須事先通知我。
你如果是從中間插過來看的,請仔細閱讀 羽夏看Win系統核心——簡述 ,方便學習本教程。
看此教程之前,問幾個問題,基礎知識儲備好了嗎?保護模式篇學會了嗎?系統呼叫篇學會了嗎?練習做完了嗎?沒有的話就不要繼續了。
? 華麗的分割線 ?
為了更好的學習程式與執行緒,我們需要充分了解3個結構體:EPROCESS
、EHTREAD
、KPCR
,下面將會進行詳細介紹。
EPROCESS
每個windows
程式在0環都有一個對應的結構體:EPROCESS
,這個結構體包含了程式所有重要的資訊。我們先看看裡面的成員有哪些:
kd> dt _EPROCESS
ntdll!_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_X86
+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
雖然有很多成員,我們只要知道幾個重要的成員即可,由於Windows
是閉源的,如果需要詳細瞭解就必須花費大量的時間進行逆向分析才能明白。這個結構體還巢狀了一個結構體_KPROCESS
,我們看一下:
kd> dt _KPROCESS
ntdll!_KPROCESS
+0x000 Header : _DISPATCHER_HEADER
+0x010 ProfileListHead : _LIST_ENTRY
+0x018 DirectoryTableBase : [2] Uint4B
+0x020 LdtDescriptor : _KGDTENTRY
+0x028 Int21Descriptor : _KIDTENTRY
+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
+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
Header
在3環使用API
的時候,我們都用過等待物件的函式,為什麼有的核心物件是可以等待的?是因為它有_DISPATCHER_HEADER
這個結構。
DirectoryTableBase
頁目錄表的基址,也就是所謂的CR3
。
LdtDescriptor / Int21Descriptor
歷史遺留問題,16位Windows
段選擇子不夠,每個程式都有一個LDT
表,Int21Descriptor
是DOS
下要用的。
KernelTime / UserTime
統計資訊,記錄了一個程式在核心模式/使用者模式下所花的時間,沒什麼太大的用處。
Affinity
這個成員十分重要,它有4個位元組,每一個二進位制位控制程式裡面的所有執行緒能在哪個CPU
上跑,如果值為1,那這個程式的所以執行緒只能在0號CPU
上跑;如果值為3,那這個程式的所以執行緒能在0、1號CPU
上跑;如果值為4,那這個程式的所以執行緒能在2號CPU
上跑;如果值為5,那這個程式的所以執行緒能在0,2號CPU
上跑。如果只有一個CPU
,把這個設定為4,那麼這個程式就死了。
由於4個位元組共32位,所以最多支援32核。64位的Windows
這個成員就是8個位元組了,最多支援64核。
BasePriority
基礎優先順序或最低優先順序,該程式中的所有執行緒最起碼的優先順序。
CreateTime / ExitTime
統計資訊,記錄了一個程式的建立/退出時間。
UniqueProcessId
程式的編號,也就是工作管理員中顯示的PID
。
ActiveProcessLinks
所有的活動程式都連線在一起,構成的雙向連結串列。全域性變數PsActiveProcessHead
指向這個全域性鏈的表頭。如下是示意圖:
QuotaUsage / QuotaPeak
物理頁相關的統計資訊。
CommitCharge / PeakVirtualSize / VirtualSize
虛擬記憶體相關的統計資訊。
VadRoot
這東西我們之前介紹過,是一個二叉樹,指示了程式的線性地址的使用情況和記錄。
DebugPort / ExceptionPort
除錯相關,經常有人使用DebugPort
清零實現反除錯。
ObjectTable
控制程式碼表,裝著核心物件控制程式碼,是用來標識某個核心物件的一個id
,同一個物件的該id
對於每個程式是不同的。後面的教程將會對控制程式碼表進行講解。
ImageFileName
程式映象檔名,最多16個位元組。
ActiveThreads
活動執行緒的數量。
Peb
英文全稱為Process Environment Block
,意為程式環境塊,是程式在3環的一個結構體,裡面包含了程式的模組列表、是否處於除錯狀態等資訊。
ETHREAD
每個Windows
執行緒在0環都有一個對應的結構體ETHREAD
,這個結構體我們曾在前面對某一部分進行簡略的講解,本篇將會詳細介紹重要成員,它的結構體如下所示:
kd> dt _ETHREAD
ntdll!_ETHREAD
+0x000 Tcb : _KTHREAD
+0x1c0 CreateTime : _LARGE_INTEGER
+0x1c0 NestedFaultCount : Pos 0, 2 Bits
+0x1c0 ApcNeeded : Pos 2, 1 Bit
+0x1c8 ExitTime : _LARGE_INTEGER
+0x1c8 LpcReplyChain : _LIST_ENTRY
+0x1c8 KeyedWaitChain : _LIST_ENTRY
+0x1d0 ExitStatus : Int4B
+0x1d0 OfsChain : Ptr32 Void
+0x1d4 PostBlockList : _LIST_ENTRY
+0x1dc TerminationPort : Ptr32 _TERMINATION_PORT
+0x1dc ReaperLink : Ptr32 _ETHREAD
+0x1dc KeyedWaitValue : Ptr32 Void
+0x1e0 ActiveTimerListLock : Uint4B
+0x1e4 ActiveTimerListHead : _LIST_ENTRY
+0x1ec Cid : _CLIENT_ID
+0x1f4 LpcReplySemaphore : _KSEMAPHORE
+0x1f4 KeyedWaitSemaphore : _KSEMAPHORE
+0x208 LpcReplyMessage : Ptr32 Void
+0x208 LpcWaitingOnPort : Ptr32 Void
+0x20c ImpersonationInfo : Ptr32 _PS_IMPERSONATION_INFORMATION
+0x210 IrpList : _LIST_ENTRY
+0x218 TopLevelIrp : Uint4B
+0x21c DeviceToVerify : Ptr32 _DEVICE_OBJECT
+0x220 ThreadsProcess : Ptr32 _EPROCESS
+0x224 StartAddress : Ptr32 Void
+0x228 Win32StartAddress : Ptr32 Void
+0x228 LpcReceivedMessageId : Uint4B
+0x22c ThreadListEntry : _LIST_ENTRY
+0x234 RundownProtect : _EX_RUNDOWN_REF
+0x238 ThreadLock : _EX_PUSH_LOCK
+0x23c LpcReplyMessageId : Uint4B
+0x240 ReadClusterSize : Uint4B
+0x244 GrantedAccess : Uint4B
+0x248 CrossThreadFlags : Uint4B
+0x248 Terminated : Pos 0, 1 Bit
+0x248 DeadThread : Pos 1, 1 Bit
+0x248 HideFromDebugger : Pos 2, 1 Bit
+0x248 ActiveImpersonationInfo : Pos 3, 1 Bit
+0x248 SystemThread : Pos 4, 1 Bit
+0x248 HardErrorsAreDisabled : Pos 5, 1 Bit
+0x248 BreakOnTermination : Pos 6, 1 Bit
+0x248 SkipCreationMsg : Pos 7, 1 Bit
+0x248 SkipTerminationMsg : Pos 8, 1 Bit
+0x24c SameThreadPassiveFlags : Uint4B
+0x24c ActiveExWorker : Pos 0, 1 Bit
+0x24c ExWorkerCanWaitUser : Pos 1, 1 Bit
+0x24c MemoryMaker : Pos 2, 1 Bit
+0x250 SameThreadApcFlags : Uint4B
+0x250 LpcReceivedMsgIdValid : Pos 0, 1 Bit
+0x250 LpcExitThreadCalled : Pos 1, 1 Bit
+0x250 AddressSpaceOwner : Pos 2, 1 Bit
+0x254 ForwardClusterOnly : UChar
+0x255 DisablePageFaultClustering : UChar
第一個成員還巢狀了一個結構體,我們檢視一下:
kd> dt _KTHREAD
ntdll!_KTHREAD
+0x000 Header : _DISPATCHER_HEADER
+0x010 MutantListHead : _LIST_ENTRY
+0x018 InitialStack : Ptr32 Void
+0x01c StackLimit : Ptr32 Void
+0x020 Teb : Ptr32 Void
+0x024 TlsArray : Ptr32 Void
+0x028 KernelStack : Ptr32 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 : _KAPC_STATE
+0x04c ContextSwitches : Uint4B
+0x050 IdleSwapBlock : UChar
+0x051 Spare0 : [3] UChar
+0x054 WaitStatus : Int4B
+0x058 WaitIrql : UChar
+0x059 WaitMode : Char
+0x05a WaitNext : UChar
+0x05b WaitReason : UChar
+0x05c WaitBlockList : Ptr32 _KWAIT_BLOCK
+0x060 WaitListEntry : _LIST_ENTRY
+0x060 SwapListEntry : _SINGLE_LIST_ENTRY
+0x068 WaitTime : Uint4B
+0x06c BasePriority : Char
+0x06d DecrementCount : UChar
+0x06e PriorityDecrement : Char
+0x06f Quantum : Char
+0x070 WaitBlock : [4] _KWAIT_BLOCK
+0x0d0 LegoData : Ptr32 Void
+0x0d4 KernelApcDisable : Uint4B
+0x0d8 UserAffinity : Uint4B
+0x0dc SystemAffinityActive : UChar
+0x0dd PowerState : UChar
+0x0de NpxIrql : UChar
+0x0df InitialNode : UChar
+0x0e0 ServiceTable : Ptr32 Void
+0x0e4 Queue : Ptr32 _KQUEUE
+0x0e8 ApcQueueLock : Uint4B
+0x0f0 Timer : _KTIMER
+0x118 QueueListEntry : _LIST_ENTRY
+0x120 SoftAffinity : Uint4B
+0x124 Affinity : Uint4B
+0x128 Preempted : UChar
+0x129 ProcessReadyQueue : UChar
+0x12a KernelStackResident : UChar
+0x12b NextProcessor : UChar
+0x12c CallbackStack : Ptr32 Void
+0x130 Win32Thread : Ptr32 Void
+0x134 TrapFrame : Ptr32 _KTRAP_FRAME
+0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE
+0x140 PreviousMode : Char
+0x141 EnableStackSwap : UChar
+0x142 LargeStack : UChar
+0x143 ResourceIndex : UChar
+0x144 KernelTime : Uint4B
+0x148 UserTime : Uint4B
+0x14c SavedApcState : _KAPC_STATE
+0x164 Alertable : UChar
+0x165 ApcStateIndex : UChar
+0x166 ApcQueueable : UChar
+0x167 AutoAlignment : UChar
+0x168 StackBase : Ptr32 Void
+0x16c SuspendApc : _KAPC
+0x19c SuspendSemaphore : _KSEMAPHORE
+0x1b0 ThreadListEntry : _LIST_ENTRY
+0x1b8 FreezeCount : Char
+0x1b9 SuspendCount : Char
+0x1ba IdealProcessor : UChar
+0x1bb DisableBoost : UChar
Header
和EPROCESS
一樣的,就不贅述了。
InitialStack / StackLimit / KernelStack
這三個成員十分重要,與執行緒切換相關。KernelStack
為當前切換執行緒的esp
,它們的細節將會在後面的隨筆介紹。
Teb
英文全稱為Thread Environment Block
,意為執行緒環境塊,大小4KB,位於使用者地址空間。在3環時,fs
暫存器中儲存該結構。
DebugActive
如果值為-1,則不能使用除錯暫存器Dr0
- Dr7
。
ApcState / ApcQueueLock / ApcStatePointer / SavedApcState
APC
相關,具體細節將會在後面的一個篇章進行講解。
State
指示執行緒狀態:waiting
/ready
/running
。
BasePriority
其初始值是所屬程式的BasePriority
值,以後可以通過KeSetBasePriorityThread
函式重新設定。
WaitBlock
裡面儲存了等待哪個物件,比如呼叫WaitForSingleObject
。
ServiceTable
指向系統服務表基址。
TrapFrame
儲存著進0環時儲存環境。
PreviousMode
先前模式,指示程式是0環呼叫還是3環呼叫的。
ThreadListEntry
一個程式所有的執行緒,都掛在一個雙向連結串列中,一共有兩個這樣的連結串列,KTHREAD
一個,ETHREAD
外面一個,示意圖如下:
Cid
儲存著程式ID和執行緒ID,它的結構體如下:
kd> dt _CLIENT_ID
ntdll!_CLIENT_ID
+0x000 UniqueProcess : Ptr32 Void
+0x004 UniqueThread : Ptr32 Void
ThreadsProcess
指向自己所屬程式。
KPCR
KPCR
中儲存了CPU
本身要用的一些重要資料:GDT
、IDT
以及執行緒相關的一些資訊。當執行緒進入0環時,FS:[0]
指向KPCR
,3環時FS:[0]
指向 TEB
。每個CPU
都有一個KPCR
結構體,即一個核一個。之前也略有介紹,它的結構如下:
kd> dt _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
NtTib
我們先看第一個成員,它的結構體如下:
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
ExceptionList
儲存當前執行緒核心異常連結串列,簡稱SEH
。
StackBase / StackLimit
儲存當前執行緒核心棧的基址和大小。
Self
指向自己的指標,也就是指向KPCR
結構,這樣設計的目的是為了查詢方便,只需要一個偏移就能知道自己的地址。
SelfPcr
指向自己,方便定址。
Prcb
指向擴充結構體PRCB
的地址。
IDT
指向IDT
表基址。
GDT
指向GDT
表基址。
TSS
指向TSS
的指標,每個CPU
都有一個TSS
。
Number
CPU編號,從0開始索引。
PrcbData
擴充結構體,它是結構體如下所示:
kd> dt _KPRCB
ntdll!_KPRCB
+0x000 MinorVersion : Uint2B
+0x002 MajorVersion : Uint2B
+0x004 CurrentThread : Ptr32 _KTHREAD
+0x008 NextThread : Ptr32 _KTHREAD
+0x00c IdleThread : Ptr32 _KTHREAD
+0x010 Number : Char
+0x011 Reserved : Char
+0x012 BuildType : Uint2B
+0x014 SetMember : Uint4B
+0x018 CpuType : Char
+0x019 CpuID : Char
+0x01a CpuStep : Uint2B
+0x01c ProcessorState : _KPROCESSOR_STATE
+0x33c KernelReserved : [16] Uint4B
+0x37c HalReserved : [16] Uint4B
+0x3bc PrcbPad0 : [92] UChar
+0x418 LockQueue : [16] _KSPIN_LOCK_QUEUE
+0x498 PrcbPad1 : [8] UChar
+0x4a0 NpxThread : Ptr32 _KTHREAD
+0x4a4 InterruptCount : Uint4B
+0x4a8 KernelTime : Uint4B
+0x4ac UserTime : Uint4B
+0x4b0 DpcTime : Uint4B
+0x4b4 DebugDpcTime : Uint4B
+0x4b8 InterruptTime : Uint4B
+0x4bc AdjustDpcThreshold : Uint4B
+0x4c0 PageColor : Uint4B
+0x4c4 SkipTick : Uint4B
+0x4c8 MultiThreadSetBusy : UChar
+0x4c9 Spare2 : [3] UChar
+0x4cc ParentNode : Ptr32 _KNODE
+0x4d0 MultiThreadProcessorSet : Uint4B
+0x4d4 MultiThreadSetMaster : Ptr32 _KPRCB
+0x4d8 ThreadStartCount : [2] Uint4B
+0x4e0 CcFastReadNoWait : Uint4B
+0x4e4 CcFastReadWait : Uint4B
+0x4e8 CcFastReadNotPossible : Uint4B
+0x4ec CcCopyReadNoWait : Uint4B
+0x4f0 CcCopyReadWait : Uint4B
+0x4f4 CcCopyReadNoWaitMiss : Uint4B
+0x4f8 KeAlignmentFixupCount : Uint4B
+0x4fc KeContextSwitches : Uint4B
+0x500 KeDcacheFlushCount : Uint4B
+0x504 KeExceptionDispatchCount : Uint4B
+0x508 KeFirstLevelTbFills : Uint4B
+0x50c KeFloatingEmulationCount : Uint4B
+0x510 KeIcacheFlushCount : Uint4B
+0x514 KeSecondLevelTbFills : Uint4B
+0x518 KeSystemCalls : Uint4B
+0x51c SpareCounter0 : [1] Uint4B
+0x520 PPLookasideList : [16] _PP_LOOKASIDE_LIST
+0x5a0 PPNPagedLookasideList : [32] _PP_LOOKASIDE_LIST
+0x6a0 PPPagedLookasideList : [32] _PP_LOOKASIDE_LIST
+0x7a0 PacketBarrier : Uint4B
+0x7a4 ReverseStall : Uint4B
+0x7a8 IpiFrame : Ptr32 Void
+0x7ac PrcbPad2 : [52] UChar
+0x7e0 CurrentPacket : [3] Ptr32 Void
+0x7ec TargetSet : Uint4B
+0x7f0 WorkerRoutine : Ptr32 void
+0x7f4 IpiFrozen : Uint4B
+0x7f8 PrcbPad3 : [40] UChar
+0x820 RequestSummary : Uint4B
+0x824 SignalDone : Ptr32 _KPRCB
+0x828 PrcbPad4 : [56] UChar
+0x860 DpcListHead : _LIST_ENTRY
+0x868 DpcStack : Ptr32 Void
+0x86c DpcCount : Uint4B
+0x870 DpcQueueDepth : Uint4B
+0x874 DpcRoutineActive : Uint4B
+0x878 DpcInterruptRequested : Uint4B
+0x87c DpcLastCount : Uint4B
+0x880 DpcRequestRate : Uint4B
+0x884 MaximumDpcQueueDepth : Uint4B
+0x888 MinimumDpcRate : Uint4B
+0x88c QuantumEnd : Uint4B
+0x890 PrcbPad5 : [16] UChar
+0x8a0 DpcLock : Uint4B
+0x8a4 PrcbPad6 : [28] UChar
+0x8c0 CallDpc : _KDPC
+0x8e0 ChainedInterruptList : Ptr32 Void
+0x8e4 LookasideIrpFloat : Int4B
+0x8e8 SpareFields0 : [6] Uint4B
+0x900 VendorString : [13] UChar
+0x90d InitialApicId : UChar
+0x90e LogicalProcessorsPerPhysicalProcessor : UChar
+0x910 MHz : Uint4B
+0x914 FeatureBits : Uint4B
+0x918 UpdateSignature : _LARGE_INTEGER
+0x920 NpxSaveArea : _FX_SAVE_AREA
+0xb30 PowerState : _PROCESSOR_POWER_STATE
CurrentThread
指向當前執行緒結構體指標。
NextThread
指向即將切換的下一個執行緒結構體指標。
CurrentThread
指向空閒執行緒的指標。
本節練習
本節的答案將會在下一節進行講解,務必把本節練習做完後看下一個講解內容。不要偷懶,實驗是學習本教程的捷徑。
俗話說得好,光說不練假把式,如下是本節相關的練習。如果練習沒做好,就不要看下一節教程了,越到後面,不做練習的話容易夾生了,開始還明白,後來就真的一點都不明白了。本節練習較多,請保質保量的完成。
1️⃣ 斷鏈程式結構體,實現隱藏,並思考為什麼斷鏈程式為什麼還能夠執行。
2️⃣ 使用DebugPort
清零實現反除錯。
3️⃣ 如何判斷一個程式是否為GUI
執行緒。
4️⃣ 斷鏈執行緒結構體,實現隱藏,並思考為什麼斷鏈執行緒為什麼還能夠執行。
下一篇
程式執行緒篇——執行緒切換(上)