(54)线程结构体 ETHREAD,线程断链
一、回顧
上次課我們學習了進程,我們知道了進程是空間概念,最主要的功能是提供CR3,而線程才是CPU調(diào)度的最小單位;
更早的時候做SSDT HOOK FindWindow 時我們還了解到了,當3環(huán)程序向驅(qū)動發(fā)起通信時,驅(qū)動所屬進程就是3環(huán)的程序;
學習了EPROCESS里的部分成員,其中 ActiveProcessLinks 是進程鏈表,我們可以通過對其斷鏈實現(xiàn)進程隱藏,DebugPort 是調(diào)試端口,抹除它的值可以使三環(huán)調(diào)試器調(diào)試崩潰。
本次課我們來學習線程結(jié)構(gòu)體 ETHREAD,了解其部分成員,完成線程鏈表斷鏈的課后練習。
二、KTHREAD
nt!_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 : UCharKTHREAD 是 ETHREAD前 0x1c0 字節(jié)的TCB屬性。下面介紹 KTHREAD 部分屬性:
+0x000 Header : _DISPATCHER_HEADER
和 KPROCESS 類似,開頭是一個 Header,擁有此屬性的內(nèi)核對象可以“被等待”(WaitForSingleObject)
+0x018 InitialStack : Ptr32 Void
+0x01c StackLimit : Ptr32 Void
+0x028 KernelStack : Ptr32 Void
InitialStack 初始棧頂,也可以理解成ebp0
StackLimit 棧的大小
KernelStack 線程切換時,舊線程的esp0存到它的KernelStack,然后把新線程的KernelStack寫到TSS
+0x020 Teb : Ptr32 Void
TEB,Thread Environment Block,線程環(huán)境塊。
大小4KB,位于用戶地址空間。
3環(huán)可以通過 FS:[0] 找到TEB
+0x02c DebugActive : UChar
是否處于調(diào)試狀態(tài)
+0x034 ApcState : _KAPC_STATE
+0x0e8 ApcQueueLock : Uint4B
+0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE
+0x14c SavedApcState : _KAPC_STATE
APC相關(guān)屬性。
+0x02d State : UChar
線程狀態(tài):就緒、等待、運行。
+0x06c BasePriority : Char
其初始值是所屬進程的BasePriority值(KPROCESS->BasePriority),以后可以通過KeSetBasePriorityThread()函數(shù)重新設(shè)定
+0x070 WaitBlock : [4] _KWAIT_BLOCK
等待哪個對象(WaitForSingleObject)
+0x0e0 ServiceTable : Ptr32 Void
指向系統(tǒng)服務(wù)表基址
+0x134 TrapFrame
進0環(huán)時保存環(huán)境
+0x140 PreviousMode : Char
某些內(nèi)核函數(shù)會判斷程序是0環(huán)調(diào)用還是3環(huán)調(diào)用的
+0x1b0 ThreadListEntry : _LIST_ENTRY
雙向鏈表,一個進程所有的線程都掛在一個鏈表中,掛的就是這個位置,有兩個這樣的鏈表
三、ETHREAD
nt!_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+0x1ec Cid : _CLIENT_ID
進程ID、線程ID
+0x220 ThreadsProcess : Ptr32 _EPROCESS
指向自己所屬進程
+0x22c ThreadListEntry : _LIST_ENTRY
雙向鏈表,一個進程所有的線程都掛在一個鏈表中,掛的就是這個位置,有兩個這樣的鏈表
四、將線程鏈表中的某個線程進行斷鏈(兩個雙向鏈表都要斷)
問題
答案
程序仍然正常運行,OD,windbg中線程數(shù)量是0。
實驗步驟
!process EPROCESS 可以查看進程里有幾個線程,一般來說,第一個就是GUI線程或者主線程。
這次作業(yè)就不寫代碼了,直接打開一個程序,用windbg斷鏈,我這里打開的是dbgview.exe,它有兩個線程
然后在windbg里找到dbgview的EPROCESS(82017990),把 +50 和 +190 兩個鏈表斷掉:
kd> ed 82017990+194 82017990+194 kd> ed 82017990+190 82017990+190 kd> ed 82017990+50 82017990+50 kd> ed 82017990+54 82017990+54然后用windbg看看線程,發(fā)現(xiàn)都沒了
kd> !process 82017990 PROCESS 82017990 SessionId: 0 Cid: 00b0 Peb: 7ffde000 ParentCid: 01d4DirBase: 095002c0 ObjectTable: e1b610d0 HandleCount: 59.Image: Dbgview.exeVadRoot 81c4ca50 Vads 65 Clone 0 Private 339. Modified 22. Locked 0.DeviceMap e1b8e9e8Token e1207940ElapsedTime 00:12:24.734UserTime 00:00:00.078KernelTime 00:00:00.500QuotaPoolUsage[PagedPool] 57940QuotaPoolUsage[NonPagedPool] 2680Working Set Sizes (now,min,max) (3060, 50, 345) (12240KB, 200KB, 1380KB)PeakWorkingSetSize 3060VirtualSize 30 MbPeakVirtualSize 32 MbPageFaultCount 3198MemoryPriority BACKGROUNDBasePriority 8CommitCharge 403DebugPort 81ed9ac0TYPE mismatch for thread object at 82017830重新用OD附加,發(fā)現(xiàn)附加失敗:
打開任務(wù)管理器,發(fā)現(xiàn)線程數(shù)是0
但是!程序還在運行!!!
總結(jié)
以上是生活随笔為你收集整理的(54)线程结构体 ETHREAD,线程断链的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (53)进程结构体EPROCESS,擦除
- 下一篇: (55)_KPCR, _NT_TIB,