C++ 获取进程主线程的句柄

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1969579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 21:43:27  来源:igfitidea点击:

Getting a handle to the process's main thread

c++windowsmultithreadingdll-injection

提问by Etan

I have created an additional thread in some small testing app and want to suspend the main thread from this additional thread. The additional thread is created via CreateRemoteThreadfrom an external process.

我在一些小型测试应用程序中创建了一个附加线程,并希望从这个附加线程挂起主线程。附加线程是通过CreateRemoteThread外部进程创建的。

Since SuspendThreadneeds a HANDLEto the thread which should be suspended, I want to know how to get this HANDLEfrom code running in my additional thread.

由于SuspendThread需要一个HANDLE应该挂起的线程,我想知道如何HANDLE从我的附加线程中运行的代码中获取它。

采纳答案by Etan

DWORD GetMainThreadId () {
    const std::tr1::shared_ptr<void> hThreadSnapshot(
        CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0), CloseHandle);
    if (hThreadSnapshot.get() == INVALID_HANDLE_VALUE) {
        throw std::runtime_error("GetMainThreadId failed");
    }
    THREADENTRY32 tEntry;
    tEntry.dwSize = sizeof(THREADENTRY32);
    DWORD result = 0;
    DWORD currentPID = GetCurrentProcessId();
    for (BOOL success = Thread32First(hThreadSnapshot.get(), &tEntry);
        !result && success && GetLastError() != ERROR_NO_MORE_FILES;
        success = Thread32Next(hThreadSnapshot.get(), &tEntry))
    {
        if (tEntry.th32OwnerProcessID == currentPID) {
            result = tEntry.th32ThreadID;
        }
    }
    return result;
}

回答by interjay

I don't think there is anything that differentiates the main thread from other threads once the process has started. However, you can enumerate all threads in the process, and use GetThreadTimesto find the thread with the earliest creation time. Call OpenThreadto get a HANDLEfrom a thread ID.

一旦进程开始,我认为没有任何东西可以将主线程与其他线程区分开来。但是,您可以枚举进程中的所有线程,并使用GetThreadTimes查找创建时间最早的线程。调用OpenThreadHANDLE从线程 ID 中获取 a 。

回答by mtx

Get the thread id with this function:

使用此函数获取线程 ID:

/* CAUTION: ONLY x86 TESTED
 * get the thread id of the main thread of a target process
 *
 * params:
 *     DWORD dwPid  process id of the target process
 *
 * return:
 *     Success      thread id
 *     Error        NULL
 */
DWORD GetMainThreadId(DWORD dwPid)
{
    LPVOID lpTid;

    _asm
    {
        mov eax, fs:[18h]
        add eax, 36
        mov [lpTid], eax
    }

    HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwPid);
    if(hProcess == NULL)
        return NULL;

    DWORD dwTid;
    if(ReadProcessMemory(hProcess, lpTid, &dwTid, sizeof(dwTid), NULL) == FALSE)
    {
        CloseHandle(hProcess);
        return NULL;
    }

    CloseHandle(hProcess);

    return dwTid;
}

Simple open the thread to get the handle:

简单打开线程获取句柄:

/*
 * get a handle to the main thread of a target process
 * if successfull, the returned handle must be closed with CloseHandle()
 *
 * params:
 *     DWORD dwPid              process id of the target process
 *     DWORD dwDesiredAccess    desired access rights to the thread
 *
 * return:
 *     Success      thread handle with desired access rights
 *     Error        NULL
 */
HANDLE GetMainThreadHandle(DWORD dwPid, DWORD dwDesiredAccess)
{
    DWORD dwTid = GetMainThreadId(dwPid);
    if(dwTid == FALSE)
        return NULL;

    return OpenThread(dwDesiredAccess, FALSE, dwTid);
}

回答by bobobobo

Why don't you just create a program-wide global (use externif you have to)

为什么不创建一个程序范围的全局变量(如果必须,请使用extern

HANDLE mainThread ;
DWORD mainThreadId ;

On the first line of main, (before any threads are created) do

在 main 的第一行,(在创建任何线程之前)做

mainThread = GetCurrentThread() ;
mainThreadId = GetCurrentThreadId() ;

You can use any form of IPCto share either the id or the HANDLE with the remote process (haven't verified sharing the HANDLE will work but it should!)

您可以使用任何形式的 IPC与远程进程共享 id 或 HANDLE(尚未验证共享 HANDLE 是否有效,但应该可以!)

回答by J.J.

A number of useful API functions of this type are under the (of course!) Tool Helpsuite. The CreateToolhelp32Snapshot()API will take a snapshot of the running threads for a specified process.

许多此类有用的 API 函数都在(当然!)工具帮助套件下。该CreateToolhelp32Snapshot()API将正在运行的线程的快照指定进程的。

// Take a snapshot of all running threads  
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); 
if( hThreadSnap == INVALID_HANDLE_VALUE ) 
  return( FALSE );

Full example code here.

完整的示例代码在这里。

The struct returned does not differentiate the primary thread from the others. I do not know a mechanism to do so; while some versions of the C runtime will all ExitProcess() at the end of the primary thread, in all recent versions the process continues to run until the last thread exits.

返回的结构不会将主线程与其他线程区分开来。我不知道这样做的机制;虽然某些版本的 C 运行时将所有 ExitProcess() 都放在主线程的末尾,但在所有最新版本中,进程会继续运行,直到最后一个线程退出。

Interjay's recommendation to use GetThreadTimes may be the best bet. If you can CreateProcess()the target process, the hThread member of the PROCESS_INFORMATIONblock contains the tid for the primary thread. Welcome any ideas from others.

Interjay 建议使用 GetThreadTimes 可能是最好的选择。如果可以CreateProcess()访问目标进程,则PROCESS_INFORMATION块的 hThread 成员包含主线程的 tid。欢迎其他人的任何想法。