I'm working on reverse engineering a game, which uses the Thread Local Storage Pointer from NTCurrentTeb to initialize a pointer to a game object.
The IDA output looks like this:
bool sub_51C3CC()
{
int v0; // eax
_BYTE *v1; // rdx
v0 = 0;
v1 = *(_BYTE **)(*(_QWORD *)NtCurrentTeb()->ThreadLocalStoragePointer + 568i64);
...
Currently, I've implemented it as
#include <cstdint>
#include <windows.h>
bool AcademyWon()
{
int hasWon;
uint8_t *threadPointer;
hasWon = 0;
threadPointer = *(uint8_t **)(*(intptr_t *)NtCurrentTeb()->ThreadLocalStoragePointer + 568);
}
The code above throws the error of "pointer or reference to incomplete type "_TEB" is not allowed", as _TEB is defined like this in winnt.h:
struct _TEB *
NtCurrentTeb (
VOID
)
{
return (struct _TEB *)__readgsqword(FIELD_OFFSET(NT_TIB, Self));
}
Do I need to redefine _TEB in its entirety to point to it? Or is there any way to achieve the same result without touching it?
Unfortunately you cannot simply access _TEB::ThreadLocalStoragePointer
because this field is not documented and not provided in Windows SDK. And you cannot redefine _TEB since it is probably already defined (and you don't really want to).
I can see two general approaches here.
struct MY_TEB { // or take a complete definition from Wine headers
LPVOID Reserved[11];
LPVOID ThreadLocalStoragePointer;
}
LPVOID tls = ((struct MY_TEB*)NtCurrentTeb())->ThreadLocalStoragePointer;
LPVOID tls = NtCurrentTeb())->Reserved1[11];