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

标签 c++ multithreading memory process handle

因为 http://undocumented.ntinternals.net 上大多数链接到此特定问题显然已经死了,NtQueryInfoThread 以及相关的 THREADINFOCLASS 已经从 Winternl.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;
}

是否还有其他方法,也许使用公共(public) 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)<<"\n\n";
    CloseHandle(hThread);
    Sleep(7000);

    return 0;
}

关于c++ - 通过线程句柄获取线程的 TIB/TEB (2015),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32297431/

相关文章:

java - 确定给定数字 N 是否可以成为具有所有 3 个整数边的直角三角形的斜边的算法

c++ - std::vector 的对齐问题

c++ - JRTPLIB/header include问题

java - run() 方法的同步

java - 如何促进Java中服务器线程和多个客户端线程之间的通信

c++ - 为什么要私下继承基类,还要名字publicizing?

c++ - 在新线程中调用方法并将返回值分配给变量

c - 为什么在 C 的堆中 malloc 2GB 或更大的内存会失败?

c++ - 内存处理是否违反单一职责原则?

php - 教义刷新更改并释放内存