首页 > 代码库 > 如何根据线程号获取模块信息

如何根据线程号获取模块信息

在得到线程之后,便可以通过openThread得到HANDLE,之后通过ZwQueryInformationThread获取线程信息。


Part1 准备:

#include <psapi.h>

#include <locale.h>

#include <iostream>

#pragma comment(lib,"psapi.lib")  


typedef enum _THREADINFOCLASS {

    ThreadBasicInformation,

    ThreadTimes,

    ThreadPriority,

    ThreadBasePriority,

    ThreadAffinityMask,

    ThreadImpersonationToken,

    ThreadDescriptorTableEntry,

    ThreadEnableAlignmentFaultFixup,

    ThreadEventPair_Reusable,

    ThreadQuerySetWin32StartAddress,

    ThreadZeroTlsCell,

    ThreadPerformanceCount,

    ThreadAmILastThread,

    ThreadIdealProcessor,

    ThreadPriorityBoost,

    ThreadSetTlsArrayAddress,

    ThreadIsIoPending,

    ThreadHideFromDebugger,

    ThreadBreakOnTermination,

    MaxThreadInfoClass

} THREADINFOCLASS;

typedef struct _CLIENT_ID {

    HANDLE UniqueProcess;

    HANDLE UniqueThread;

} CLIENT_ID;

typedef CLIENT_ID *PCLIENT_ID;

typedef struct _THREAD_BASIC_INFORMATION { // Information Class 0

    LONG     ExitStatus;

    PVOID    TebBaseAddress;

    CLIENT_ID ClientId;

    LONG AffinityMask;

    LONG Priority;

    LONG BasePriority;

} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;

extern "C" LONG (__stdcall *ZwQueryInformationThread) (

    IN HANDLE ThreadHandle,

    IN THREADINFOCLASS ThreadInformationClass,

    OUT PVOID ThreadInformation,

    IN ULONG ThreadInformationLength,

    OUT PULONG ReturnLength OPTIONAL

    ) = NULL;


主函数中需要做的准备工作:

    setlocale (LC_ALL, ".ACP");

    HINSTANCE hNTDLL = ::GetModuleHandle (TEXT ("ntdll"));

    (FARPROC&)ZwQueryInformationThread  = ::GetProcAddress (hNTDLL,   "ZwQueryInformationThread");



Part 2 获取相关信息

    THREAD_BASIC_INFORMATION    tbi;

    PVOID                       startaddr;

    LONG                        status;

    HANDLE                      thread, process;

        

    thread = ::OpenThread (THREAD_ALL_ACCESS, FALSE, dwThreadId);

    if (thread == NULL)

{

printf("cannot open thread handle\n");

        return FALSE;

}

status = ZwQueryInformationThread(thread,ThreadQuerySetWin32StartAddress, &startaddr, sizeof (startaddr), NULL);

    if (status < 0)

    {

        CloseHandle (thread);

printf("cannot get status1\n");

        return FALSE;

    };

    printf("线程 %08x 的起始地址为 %p\n", dwThreadId, startaddr);

    status = ZwQueryInformationThread (thread, 

            ThreadBasicInformation, 

            &tbi, 

            sizeof (tbi), 

            NULL);

    if (status < 0)

{

        CloseHandle (thread);

printf("cannot get status2\n");

        return FALSE;

};

printf("线程 %08x 所在进程ID为 %08x\n", dwThreadId, (DWORD)tbi.ClientId.UniqueProcess);

process = ::OpenProcess (PROCESS_ALL_ACCESS, 

FALSE, 

(DWORD)tbi.ClientId.UniqueProcess);

if (process == NULL)

{

DWORD error = ::GetLastError ();

CloseHandle (thread);

SetLastError (error);

return FALSE;

};

TCHAR modname [0x100];

::GetModuleFileNameEx (process, NULL, modname, 0x100);

printf("线程 %08x 所在进程映象为 %s\n", dwThreadId, modname);

GetMappedFileName(process, 

startaddr, 

modname, 

0x100);

        std::string stName(pName);

std::string stModName(modname);

if(stModName.find(stName) != std::string::npos)

{

printf("线程 %08x 可执行代码所在模块为 %s\n", dwThreadId, modname);

ret = TRUE;

}

CloseHandle (process);

CloseHandle (thread);




如何根据线程号获取模块信息