Как указать на _TEB, не переопределяя его?

Я работаю над обратным проектированием игры, которая использует указатель локального хранилища потока из NTCurrentTeb для инициализации указателя на игровой объект.

Вывод IDA выглядит следующим образом:

bool sub_51C3CC()
{
  int v0; // eax
  _BYTE *v1; // rdx

  v0 = 0;
  v1 = *(_BYTE **)(*(_QWORD *)NtCurrentTeb()->ThreadLocalStoragePointer + 568i64);
...

В настоящее время я реализовал это как

#include <cstdint>
#include <windows.h>


bool AcademyWon()
{
    int hasWon;
    uint8_t *threadPointer;

    hasWon = 0;
    threadPointer = *(uint8_t **)(*(intptr_t *)NtCurrentTeb()->ThreadLocalStoragePointer + 568);
}

Приведенный выше код выдает ошибку «указатель или ссылка на неполный тип «_TEB» не разрешен», поскольку _TEB определен следующим образом в winnt.h:

struct _TEB *
NtCurrentTeb (
    VOID
    )

{
    return (struct _TEB *)__readgsqword(FIELD_OFFSET(NT_TIB, Self));
}

Нужно ли мне полностью переопределить _TEB, чтобы он указывал на него? Или есть ли способ добиться того же результата, не прикасаясь к нему?

Нет необходимости определять тип структуры для создания/возврата указателей на этот тип (например, нулевые указатели). Однако необходимо определить этот тип, чтобы разыменовать такой указатель или создать экземпляр этого типа. Ваша функция AcademyWon() выполняет разыменование с помощью NtCurrentTeb()->ThreadLocalStoragePointer + 568). Оператор -> — это оператор разыменования указателя. Обычный способ обработки таких вещей — поместить определение структуры в заголовок (а не просто прямое объявление) и #include этот заголовок, чтобы разыменовать такие указатели.

Peter 28.05.2024 14:43

C или C++ здесь имеют значение. Это следует общей схеме введения псевдонима типа для struct: typedef struct _TEB { ... } TEB;. В C++ вы можете использовать либо _TEB, либо TEB. В C вам нужно использовать struct _TEB или TEB. Это определено в Winternl.h. Включенный вами код не определяет структуру. Он определяет функцию NtCurrentTeb(), которая возвращает struct _TEB, то есть TEB.

IInspectable 28.05.2024 14:48

Спасибо! Кажется, я неправильно понял функцию, думая, что она определяет структуру, а не возвращает ее. Итак, теоретически определение структуры _TEB до ThreadLocalStoragePointer в файле заголовка, а затем ее включение должно решить эту проблему?

Surasia 28.05.2024 15:08

Или вместо того, чтобы переходить на низкий уровень, просто используйте TlsAlloc и связанные с ним функции (TlsFree, TlsGetValue, TlsSetValue) или даже реализацию компилятора. Есть большая вероятность, что исходный код не затрагивал TEB напрямую.

Neitsa 28.05.2024 15:28

Это абсолютно не касалось ТЭБ напрямую. Это стандартный способ доступа к статически выделенному значению TLS, и весь этот код был сгенерирован компилятором. В исходном коде это был просто стандартный доступ к глобальной переменной thread_local. Проблема в том, что ОП, вероятно, хочет сохранить функциональность на 100%, чтобы некоторые части исходного кода можно было заменить новым кодом, и все это по-прежнему работало.

Andrey Turkin 28.05.2024 16:07
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
121
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

К сожалению, вы не можете просто получить доступ к _TEB::ThreadLocalStoragePointer, поскольку это поле не задокументировано и не предусмотрено в Windows SDK. И вы не можете переопределить _TEB, поскольку он, вероятно, уже определен (а вам это не очень-то и хочется).

Я вижу здесь два общих подхода.

  1. Вы можете объявить другую структуру с тем же макетом, содержащую нужные вам поля:
struct MY_TEB { // or take a complete definition from Wine headers
    LPVOID Reserved[11];
    LPVOID ThreadLocalStoragePointer;
}
LPVOID tls = ((struct MY_TEB*)NtCurrentTeb())->ThreadLocalStoragePointer;
  1. В частности, в случае ThreadLocalStoragePointer: он как бы определен в определении SDK _TEB, но не назван. В структуре все еще есть место, соответствующее этому полю, оно есть для всех архитектур (я думаю), так что вы все равно можете его использовать:
LPVOID tls = NtCurrentTeb())->Reserved1[11];

Другие вопросы по теме