首先声明一下,本文所讲的内容已经是老掉牙的东西了,而且本文所涉及的代码似乎只能在 NT 内核下正常发挥作用,如有不对的地方,请各位高手给我指点,谢谢。 :)
我们先来看看本文中最重要的概念—— TEB 。
TEB(Thread Environment Block) 在 Windows 9x 系列中被称为 TIB(Thread Information Block),它记录了线程的重要信息,而且每一个线程都会对应一个 TEB 结构。 Matt Pietrek 大牛已经给我们列出了它的结构,我就不多说啦,见下:(摘自 Matt Pietrek 的 Under The Hood - MSJ 1996)
//=========================================================== // File: TIB.H // Author: Matt Pietrek // From: Microsoft Systems Journal "Under the Hood", May 1996 //=========================================================== #pragma pack(1)
typedef struct _EXCEPTION_REGISTRATION_RECORD { struct _EXCEPTION_REGISTRATION_RECORD * pNext; FARPROC pfnHandler; } EXCEPTION_REGISTRATION_RECORD, *PEXCEPTION_REGISTRATION_RECORD;
typedef struct _TIB { PEXCEPTION_REGISTRATION_RECORD pvExcept; // 00h Head of exception record list PVOID pvStackUserTop; // 04h Top of user stack PVOID pvStackUserBase; // 08h Base of user stack
union // 0Ch (NT/Win95 differences) { struct // Win95 fields { WORD pvTDB; // 0Ch TDB WORD pvThunkSS; // 0Eh SS selector used for thunking to 16 bits DWORD unknown1; // 10h } WIN95;
struct // WinNT fields { PVOID SubSystemTib; // 0Ch ULONG FiberData; // 10h } WINNT; } TIB_UNION1;
PVOID pvArbitrary; // 14h Available for application use struct _tib *ptibSelf; // 18h Linear address of TIB structure
union // 1Ch (NT/Win95 differences) { struct // Win95 fields { WORD TIBFlags; // 1Ch WORD Win16MutexCount; // 1Eh DWORD DebugContext; // 20h DWORD pCurrentPriority; // 24h DWORD pvQueue; // 28h Message Queue selector } WIN95;
struct // WinNT fields { DWORD unknown1; // 1Ch DWORD processID; // 20h DWORD threadID; // 24h DWORD unknown2; // 28h } WINNT; } TIB_UNION2;
PVOID* pvTLSArray; // 2Ch Thread Local Storage array
union // 30h (NT/Win95 differences) { struct // Win95 fields { PVOID* pProcess; // 30h Pointer to owning process database } WIN95; } TIB_UNION3;
} TIB, *PTIB; #pragma pack()
呵呵,看到那么多的结构,是不是有点头晕了?不要紧,我来给大家找出最重要的部分加以解释。
在 MASM/TASM 下编写过 SEH 代码的朋友,一定会对这三句代码非常熟悉:
push offset _SEH_Handler push fs:[0] mov fs:[0], esp
这是标准的 SEH 异常处理函数的注册方法,可是各位朋友有没有想过为什么是 fs:[0] 呢?
让我们抬头看看上面的 Matt Pietrek 的代码,其中有这么一行:
PEXCEPTION_REGISTRATION_RECORD pvExcept; // 00h Head of exception record list
注意到 PEXCEPTION_REGISTRATION_RECORD 这个定义,它表示 pvExcept 这个变量正是 exception record list 的入口,这个入口位于整个结构的 0 偏移处。同时,在 M$Content$nbsp;的 Intel i386 Windows NT/2K/XP 内核中,每当创建一个线程, OS 均会为每个线程分配 TEB ,而且 TEB 永远放在 fs 段选择器指定的数据段的 0 偏移处。
1 2 下一页 |