通过线程句柄获取线程的 TIB/TEB (2015)

Getting the TIB/TEB of a Thread by it's Thread Handle (2015)

本文关键字:线程 TEB 2015 句柄 获取 TIB      更新时间:2023-10-16

因为大多数链接到这个特定问题http://undocumented.ntinternals.net上显然已经死了,NtQueryInfoThread以及相关的THREADINFOCLASSes已经从winl .h中消失了,我现在坐在这里努力寻找一个我知道处理的进程的TEB。我试着从ntdll.dll加载方法,这是另一种解决方案,似乎工作,但遗憾的是,我仍然未能获得所需的地址。

typedef NTSTATUS(*ThreadInfoProc)(HANDLE, THREADINFOCLASS, PVOID, ULONG,  PULONG);
PVOID CProcessHelper::GetThreadStackTopAddress(HANDLE hThread)
{
HINSTANCE ntdllInstance;
ThreadInfoProc NtQueryInfoThread;
ntdllInstance = LoadLibrary("Ntdll.dll");
if (ntdllInstance != NULL)
{
    NtQueryInfoThread = (ThreadInfoProc)GetProcAddress(ntdllInstance, "NtQueryInformationThread");
    if (NtQueryInfoThread != NULL)
    {
        THREAD_BASIC_INFORMATION bi;
        NT_TIB tib;
        NTSTATUS ntstat = 0;
        NTSTATUS ntstat = (NtQueryInfoThread)(hThread, (THREADINFOCLASS)0, &bi, sizeof(THREAD_BASIC_INFORMATION),NULL);
        ReadProcessMemory(CurrentProcessHandle, bi.TebBaseAddress, &tib, sizeof(NT_TIB), 0);
        PrintHex(tib.StackBase); // output: CCCCCCCCCC
    }
}
return nullptr;
}

是否有其他方法,也许使用公共api调用来获得线程的TEB ?(正如MSDN声明的那样,这种方法不应该再使用了。)

最诚挚的问候,亚历克斯

可以正常工作:S获取线程的TEB的唯一其他方法是使用:

读取它

NT_TIB* tib = (NT_TIB*)__readfsdword(0x18);

并从中读取基址。

您的调用可能会失败,因为您可能没有正确的权限来读取内存。尝试使用VirtualProtect ?

下面的工作,但我只测试了它在当前进程..

#include <iostream>
#include <windows.h>
typedef LONG NTSTATUS;
typedef DWORD KPRIORITY;
typedef WORD UWORD;
typedef struct _CLIENT_ID
{
    PVOID UniqueProcess;
    PVOID UniqueThread;
} CLIENT_ID, *PCLIENT_ID;
typedef struct _THREAD_BASIC_INFORMATION
{
    NTSTATUS                ExitStatus;
    PVOID                   TebBaseAddress;
    CLIENT_ID               ClientId;
    KAFFINITY               AffinityMask;
    KPRIORITY               Priority;
    KPRIORITY               BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
enum THREADINFOCLASS
{
    ThreadBasicInformation,
};
void* GetThreadStackTopAddress(HANDLE hProcess, HANDLE hThread)
{
    bool loadedManually = false;
    HMODULE module = GetModuleHandle("ntdll.dll");
    if (!module)
    {
        module = LoadLibrary("ntdll.dll");
        loadedManually = true;
    }
    NTSTATUS (__stdcall *NtQueryInformationThread)(HANDLE ThreadHandle, THREADINFOCLASS ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength, PULONG ReturnLength);
    NtQueryInformationThread = reinterpret_cast<decltype(NtQueryInformationThread)>(GetProcAddress(module, "NtQueryInformationThread"));
    if (NtQueryInformationThread)
    {
        NT_TIB tib = {0};
        THREAD_BASIC_INFORMATION tbi = {0};
        NTSTATUS status = NtQueryInformationThread(hThread, ThreadBasicInformation, &tbi, sizeof(tbi), nullptr);
        if (status >= 0)
        {
            ReadProcessMemory(hProcess, tbi.TebBaseAddress, &tib, sizeof(tbi), nullptr);
            if (loadedManually)
            {
                FreeLibrary(module);
            }
            return tib.StackBase;
        }
    }

    if (loadedManually)
    {
        FreeLibrary(module);
    }
    return nullptr;
}
void __stdcall Test()
{
    for (int i = 0; i < 10; ++i)
    {
        printf("Hi. ");
        Sleep(500);
    }
}

int main()
{
    std::cout<<GetThreadStackTopAddress(GetCurrentProcess(), GetCurrentThread())<<"n";
    DWORD threadID = 0;
    HANDLE hThread = CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(Test), nullptr, 0, &threadID);
    std::cout<<GetThreadStackTopAddress(GetCurrentProcess(), hThread)<<"nn";
    CloseHandle(hThread);
    Sleep(7000);
    return 0;
}