游戏逆向中如何不重新定义_TEB结构体就实现对它的指向?
问题:访问TEB的ThreadLocalStoragePointer时触发不完整类型错误
我正在对一款游戏进行逆向工程,该游戏通过NtCurrentTeb返回值中的ThreadLocalStoragePointer初始化指向游戏对象的指针。
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); }
上述代码编译时抛出错误:pointer or reference to incomplete type "_TEB" is not allowed,原因是winnt.h中NtCurrentTeb仅声明了_TEB结构体,未提供完整定义:
struct _TEB * NtCurrentTeb ( VOID ) { return (struct _TEB *)__readgsqword(FIELD_OFFSET(NT_TIB, Self)); }
请问是否必须完整重定义_TEB结构体才能访问其ThreadLocalStoragePointer?有没有其他方法实现相同功能?
解决方法
不需要完整重定义整个_TEB结构体,以下两种方式更简洁:
方法1:直接通过GS寄存器偏移读取
在x64系统中,TEB的基地址位于GS:[0x30],而ThreadLocalStoragePointer在TEB中的固定偏移为0x58(x86系统为0x2C)。可以跳过NtCurrentTeb()封装,直接用编译器内置函数读取:
#include <cstdint> #include <windows.h> bool AcademyWon() { int hasWon = 0; // 读取TEB基地址 uintptr_t teb_addr = __readgsqword(0x30); // 获取ThreadLocalStoragePointer的值 uintptr_t tls_ptr = *(uintptr_t*)(teb_addr + 0x58); // 计算目标游戏对象指针 uint8_t* threadPointer = *(uint8_t**)(tls_ptr + 568); // 补充后续逻辑 return hasWon; }
方法2:仅声明_TEB中需要的字段
无需定义完整的_TEB结构体,只需声明到ThreadLocalStoragePointer字段即可(需确保字段偏移与目标系统一致):
#include <cstdint> #include <windows.h> // 仅声明TEB的必要字段,保证偏移正确 struct _TEB { uintptr_t Reserved1[12]; uintptr_t* ThreadLocalStoragePointer; // 其余字段无需定义 }; bool AcademyWon() { int hasWon = 0; uint8_t* threadPointer = *(uint8_t**)(*NtCurrentTeb()->ThreadLocalStoragePointer + 568); // 补充后续逻辑 return hasWon; }
注意事项
- 务必确认
ThreadLocalStoragePointer的偏移正确性,不同Windows版本可能存在细微差异,可通过IDA或官方头文件验证。 - 直接操作TEB属于底层系统操作,兼容性受目标Windows版本影响,测试时需覆盖游戏运行的系统环境。
内容的提问来源于stack exchange,提问作者Surasia
相关产品推荐
相关产品推荐

