C++ 通过它获取线程的TIB/TEB';s螺纹柄(2015)

C++ 通过它获取线程的TIB/TEB';s螺纹柄(2015),c++,multithreading,memory,process,handle,C++,Multithreading,Memory,Process,Handle,由于与此特定问题有关的大多数链接显然已失效,并且NtQueryInfoThread以及相关的threadinfoclass已从Winternl.h中消失,因此我现在坐在这里,努力寻找我所知道的进程的TEB。 我尝试从ntdll.dll加载该方法,这是另一个似乎有效的解决方案,但遗憾的是,我仍然无法获得所需的地址 typedef NTSTATUS(*ThreadInfoProc)(HANDLE, THREADINFOCLASS, PVOID, ULONG, PULONG); PVOID CPro

由于与此特定问题有关的大多数链接显然已失效,并且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;
}
有没有其他方法,比如使用公共api调用来获取线程的TEB?(正如MSDN所述,不应再使用这种方法。)

致以最良好的祝愿


Alex工作正常:获取线程TEB的唯一其他方法是使用以下命令读取它:

NT_-TIB*TIB=(NT_-TIB*)\u-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;
}
#包括
#包括
typedef长NTSTATUS;
typedef-DWORD-KPRIORITY;
typedef单词UWORD;
typedef结构\u客户端\u ID
{
PVOID单侧突;
PVOID单丝;
}客户ID,*P客户ID;
typedef结构线程基本信息
{
NTSTATUS存在状态;
PVOID基址;
客户ID ClientId;
亲缘关系;
KPRIORITY优先级;
KPRIORITY-BasePriority;
}线程基本信息,*PTHREAD基本信息;
枚举线程信息类
{
线状结构,
};
void*GetThreadStackTopAddress(句柄HPProcess,句柄hThread)
{
bool-loademanually=false;
HMODULE module=GetModuleHandle(“ntdll.dll”);
如果(!模块)
{
模块=加载库(“ntdll.dll”);
loadedManually=true;
}
NTSTATUS(uu stdcall*NtQueryInformationThread)(句柄ThreadHandle、THREADINFOCLASS ThreadInformationClass、PVOID ThreadInformation、ULONG ThreadInformationLength、PULONG ReturnLength);
NtQueryInformationThread=reinterpret_cast(GetProcAddress(模块,“NtQueryInformationThread”);
if(NtQueryInformationThread)
{
NT_TIB TIB={0};
线程基本信息tbi={0};
NTSTATUS status=NtQueryInformationThread(hThread,threadbasicinfo,&tbi,sizeof(tbi),nullptr);
如果(状态>=0)
{
ReadProcessMemory(hProcess、tbi.TebBaseAddress和tib、sizeof(tbi)、nullptr);
如果(手动加载)
{
免费图书馆(模块);
}
返回tib.StackBase;
}
}
如果(手动加载)
{
免费图书馆(模块);
}
返回空ptr;
}
无效uu stdcall测试()
{
对于(int i=0;i<10;++i)
{
printf(“Hi”);
睡眠(500);
}
}
int main()
{

std::coutThank you,我通读了你的代码,注意到了我自己的一些错误。我的一个不相关但至关重要的错误是,我仍然包含了winternal.h。当我再次尝试声明THREADINFOCLASS时,我收到了类型错误(因此我第一次尝试时使用了cast)我还注意到,在以前的许多情况下,NTSTATUS返回0xc000008,老实说,这应该是我检查的第一件事…因此,显然我从其他进程获取句柄的方式也有错误,这导致了一系列无效的线程句柄。谢谢!