TIB & FS, GS Segment Register
TIB & FS, GS Segment Register
TIB (Thread Information Block)
TIB ← FS (x86)
← GS (x64)
typedef struct _NT_TIB
{
PVOID ExceptionList;
PVOID StackBase;
PVOID StackLimit;
PVOID SubSystemTib;
PVOID FiberData;
PVOID ArbitraryUserPointer;
struct _NT_TIB *Self;
} NT_TIB;
typedef NT_TIB *PNT_TIB;
is in WinNT.h
Address Index ?
typedef struct _NT_TIB x86 x64
{ ------------
PVOID ExceptionList; 0x000 0x000
PVOID StackBase; 0x004 0x008
PVOID StackLimit; 0x008 0x010
PVOID SubSystemTib; 0x00C 0x018
PVOID FiberData; 0x010 0x020
PVOID ArbitraryUserPointer; 0x014 0x028
struct _NT_TIB *Self; 0x018 0x030
} NT_TIB;
Real Address of TIB ?
fs:[0x018] :x86
gs:[0x030] :x64
__readfsdword()
__readgsqword()
NtCurrentTeb()
----------------------
WinNT.h
PTEB NtCurrentTeb()
_________________________________________________________________________________________
If you search the winnt.h file using the where command,
\>where \r c:\ winnt.h
typedef struct _NT_TIB {
struct _EXCEPTION_REGISTRATION_RECORD *ExceptionList;
PVOID StackBase;
PVOID StackLimit;
PVOID SubSystemTib;
#if defined(_MSC_EXTENSIONS)
union {
PVOID FiberData;
DWORD Version;
};
#else
PVOID FiberData;
#endif
PVOID ArbitraryUserPointer;
struct _NT_TIB *Self;
} NT_TIB;
typedef NT_TIB *PNT_TIB;
_________________________________________________________________________________________
______________________________________________________________________________________________
desc
When a thread is created, Windows creates a TIB(Thread Information Block) in the user memory area,
When switching threads, make the GS segment register point to TIB.
(FS in 32bit)
This means that each member of the TIB structure can be accessed by the addressing method of
GS:[offset].
------------------------------------------------------
Even if the segment register is not explicitly specified, CS is used by default in the code segment and
DS is used by default in the data segment.
(In 64-bit, it is different again. Since the register size is 64 bits, there is no need to use the expedient
method of combining with other registers to specify memory. A 64-bit size is enough to address the
entire virtual memory space used by the current operating system.)
------------------------------------------------------
Among them, the 7th member, the 7th member of the TIB structure, has the address value of the TIB
itself.
Therefore, the TIB address value of the current Thread can be obtained from GS:[0x030].
In 32-bit, you can simply access GS:[Offset] using inline assembly.
Inline assembly is not supported in 64-bit.
You can do this by coding a separate assembly source file and then creating an object file and linking
it,
An easier way is to use compiler built-in functions.
The C++ compiler provides built-in functions that correspond to assembly instructions.
The built-in function corresponding to GS:[Offset] is __readgsqword(offset).
Use the function to find the address of the TIB.
______________________________________________________________
C (C++)
unsigned
__int64 addressOfTIB;
addressOfTIB = __readgsqword(0x030);
______________________________________________________________
_____________________________________________________________________________________
__readgsqword()
unsigned __int64
__readgsqword(
unsigned long Offset
);
_____________________________________________________________________________________
related knowledge
MemoryPage (vertual memory)
\>si process
\>si mp
__readgsbyte, __readgsdword, __readgsqword, __readgsword | Microsoft Learn
x64 (amd64) intrinsics list | Microsoft Learn
Compiler intrinsics | Microsoft Learn
______________________________________________________________________________
System Internals (developer edition)
𝅇𝅇𝅇