c++cwinapintdll

How to point to _TEB without redefining it?


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?


Solution

  • 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.

    1. You could declare some different structure with the same layout which contains fields you need:
    struct MY_TEB { // or take a complete definition from Wine headers
        LPVOID Reserved[11];
        LPVOID ThreadLocalStoragePointer;
    }
    LPVOID tls = ((struct MY_TEB*)NtCurrentTeb())->ThreadLocalStoragePointer;
    
    1. In case of ThreadLocalStoragePointer specifically: It is kind of defined in SDK's _TEB definition but not named. There's still a location in the structure which corresponds to this field, it is there for all the architectures (I think), so you could still use that:
    LPVOID tls = NtCurrentTeb())->Reserved1[11];