RING0获取线程的TDB.
作者:陆麟
转载请征得作者同意.
2000.10.13
最近有个朋友问我如何从RING0获取TDB.
TDB是个KERNEL32数据结构,而RING0有的是THCB,TDBX.THCB是VMM的数据结构,而TDBX是VWIN32的数据结构.现在,我就针对WIN98英文版对此进行剖析.
我们通常可以从RING0获得的在MS的文档里称为THREAD HANDLE.其实,我们获得的是一个THCB指针.THCB乃是一个半公开的数据结构.为什么这么说呢?MS的95/98DDK里公开了部分的THCB的数据结构.如下:
struct tcb_s {
ULONG TCB_Flags; /* Thread status
flags */
ULONG TCB_Reserved1; /* Used internally
by VMM */
ULONG TCB_Reserved2; /* Used internally
by VMM */
ULONG TCB_Signature;
ULONG TCB_ClientPtr; /* Client registers
of thread */
ULONG TCB_VMHandle; /* VM that thread
is part of */
USHORT TCB_ThreadId; /* Unique Thread ID */
USHORT TCB_PMLockOrigSS;
/* Original SS:ESP before lock stack */
ULONG TCB_PMLockOrigESP;
ULONG TCB_PMLockOrigEIP;
/* Original CS:EIP before lock stack */
ULONG TCB_PMLockStackCount;
USHORT TCB_PMLockOrigCS;
USHORT TCB_PMPSPSelector;
ULONG TCB_ThreadType; /* dword passed
to VMMCreateThread */
USHORT TCB_pad1; /* reusable; for dword
align */
UCHAR TCB_pad2; /* reusable; for
dword align */
UCHAR TCB_extErrLocus;
/* extended error Locus */
USHORT TCB_extErr; /* extended error
Code */
UCHAR TCB_extErrAction;
/* " " Action */
UCHAR TCB_extErrClass;
/* " " Class */
ULONG TCB_extErrPtr; /* "
pointer */
};
显然,这里并没有包含95/98内的另外几个核心数据结构.为了了解VWIN32的线程数据结构,我们不得不对THCB继续探索下去.
VWIN32.VXD在线程被创建时同时创建了TDBX数据结构.用于对线程的管理.但是,VWIN32并没有在自己内部维护一个线程数据链表,取而代之的是在THCB偏移84H处填写了一个数据结构的地址.
现在取出THCB+84H处的DWORD,我们得到一个指针.但是这个指针并不是一个指向TDBX的指针,在这个指针所指向的数据结构的偏移4处,才是我们所感兴趣的TDBX结构指针.这样,我们的TDBX就得到了.我的示例代码如下:
MOV ESI,THCB
MOV EAX,[ESI+84]
ADD EAX,4
MOV EAX,[EAX];;至此,TDBX指针有了
TDBX的偏移4处则存储KERNEL32.DLL维护的TDB数据结构指针.现在,THCB,TDBX,TDB就完全从RING0串联起来了.
而TDBX/TDB的具体结构,大家可以看本主页的相关文章.
现在,如果要获取当前线程的TDB,我们更是有取巧的办法.98英文版的KERNEL32.DLL总在[BFFC9CD8]处存储当前TDB的指针.所以,
MOV EAX,[BFFC9CD8]
就可以获得当前线程的TDB.
鼓掌,收工.:)