一、回顾
上次课我们学习了进程,我们知道了进程是空间概念,最主要的功能是提供CR3,而线程才是CPU调度的最小单位;
更早的时候做SSDT HOOK FindWindow 时我们还了解到了,当3环程序向驱动发起通信时,驱动所属进程就是3环的程序;
学习了EPROCESS里的部分成员,其中 ActiveProcessLinks 是进程链表,我们可以通过对其断链实现进程隐藏,DebugPort 是调试端口,抹除它的值可以使三环调试器调试崩溃。
本次课我们来学习线程结构体 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 : UChar
KTHREAD 是 ETHREAD前 0x1c0 字节的TCB属性。下面介绍 KTHREAD 部分属性:
+0x000 Header : _DISPATCHER_HEADER
和 KPROCESS 类似,开头是一个 Header,拥有此属性的内核对象可以“被等待”(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,线程环境块。
大小4KB,位于用户地址空间。
3环可以通过 FS:[0] 找到TEB
+0x02c DebugActive : UChar
是否处于调试状态
+0x034 ApcState : _KAPC_STATE
+0x0e8 ApcQueueLock : Uint4B
+0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE
+0x14c SavedApcState : _KAPC_STATE
APC相关属性。
+0x02d State : UChar
线程状态:就绪、等待、运行。
+0x06c BasePriority : Char
其初始值是所属进程的BasePriority值(KPROCESS->BasePriority),以后可以通过KeSetBasePriorityThread()函数重新设定
+0x070 WaitBlock : [4] _KWAIT_BLOCK
等待哪个对象(WaitForSingleObject)
+0x0e0 ServiceTable : Ptr32 Void
指向系统服务表基址
+0x134 TrapFrame
进0环时保存环境
+0x140 PreviousMode : Char
某些内核函数会判断程序是0环调用还是3环调用的
+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中观察线程数量是否有变化
答案
程序仍然正常运行,OD,windbg中线程数量是0。
实验步骤
!process EPROCESS 可以查看进程里有几个线程,一般来说,第一个就是GUI线程或者主线程。
这次作业就不写代码了,直接打开一个程序,用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看看线程,发现都没了
kd> !process 82017990
PROCESS 82017990 SessionId: 0 Cid: 00b0 Peb: 7ffde000 ParentCid: 01d4
DirBase: 095002c0 ObjectTable: e1b610d0 HandleCount: 59.
Image: Dbgview.exe
VadRoot 81c4ca50 Vads 65 Clone 0 Private 339. Modified 22. Locked 0.
DeviceMap e1b8e9e8
Token e1207940
ElapsedTime 00:12:24.734
UserTime 00:00:00.078
KernelTime 00:00:00.500
QuotaPoolUsage[PagedPool] 57940
QuotaPoolUsage[NonPagedPool] 2680
Working Set Sizes (now,min,max) (3060, 50, 345) (12240KB, 200KB, 1380KB)
PeakWorkingSetSize 3060
VirtualSize 30 Mb
PeakVirtualSize 32 Mb
PageFaultCount 3198
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 403
DebugPort 81ed9ac0
TYPE mismatch for thread object at 82017830
重新用OD附加,发现附加失败:
打开任务管理器,发现线程数是0
但是!程序还在运行!!!
---------------------
作者:hambaga
来源:CSDN
原文:https://blog.csdn.net/Kwansy/article/details/109529264
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件