上一篇我们介绍了进程结构体,这节我们介绍下线程结构体:ETHREAD。还是去windbg里面去看一下这个结构体的长相:
依旧是一大堆成员,我们只关注一些比较重要的结构体成员。在进程结构体中的第一个成员是一个子结构体Pcb,在线程结构体中,第一个成员依然是一个子结构体叫Tcb.我们还是跟进去看一下这个子结构体有哪些重要的成员:
第一个成员依然是Header。上一节讲进程结构体的时候,我没有介绍这个成员。其实这个成员是一个可等待对象。只要后面标注是一个 _DISPATCHER_HEADER,那他就是一个可等待对象。(这个我也不是很会)有兴趣可以查下资料。
+0x018 InitialStack : Ptr32 Void
+0x01c StackLimit : Ptr32 Void
+0x028 KernelStack : Ptr32 Void
这三个成员是和堆栈切换相关的。也就是线程切换。我们知道在线程切换的时候,一定是伴随着堆栈切换的。
+0x020 Teb : Ptr32 Void
用于描述线程的线程环境块,存在于用户态。类似于PEB。如果进不了0环如何知道TEB在哪呢。在用户态下FS:[0]->TEB,内核态时FS执行KPCR。
+0x034 ApcState : _KAPC_STATE
+0x0e8 ApcQueueLock : Uint4B
+0x138 ApcStatePointer : [2] Ptr32 _KAPC_STATE
+0x14c SavedApcState : _KAPC_STATE
这四个成员都和APC有关,异步过程调用。
+0x02d State : UChar
这个成员描述当前线程的状态,是就绪态,还是运行态,还是阻塞态。
+0x0e0 ServiceTable : Ptr32 Void
指向系统服务表的基地址。
+0x134 TrapFrame : Ptr32 _KTRAP_FRAME
进入0环的时候保存环境。进入前的寄存器等值会存储在这个结构体里。
+0x1b0 ThreadListEntry : _LIST_ENTRY
这也是一个双向链表。一个进程的所有线程,都用这个链表串起来了。
上述都是Tcb里面的重要成员,我们再看看ETHREAD里面的重要成员还有哪些:
+0x1ec Cid : _CLIENT_ID
线程的编号,类似PID。
+0x220 ThreadsProcess : Ptr32 _EPROCESS
指向当前线程所属的进程。
+0x22c ThreadListEntry : _LIST_ENTRY
这依然是一个双向链表,和上面存在于_KTHREAD的ThreadListEntry是一样的值。只是为了方便遍历。
以上就是比较重要的成员了。