14

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

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

4

5 回答 5

17

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

于 2009-12-28T14:17:35.400 回答
8
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;
}
于 2009-12-30T20:10:16.163 回答
8

使用此函数获取线程 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;
}

简单打开线程获取句柄:

/*
 * 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);
}
于 2011-11-08T23:55:42.103 回答
4

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

HANDLE mainThread ;
DWORD mainThreadId ;

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

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

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

于 2011-06-05T17:25:30.173 回答
2

许多此类有用的 API 函数位于(当然!)工具帮助套件中。CreateToolhelp32Snapshot()API 将为指定进程拍摄正在运行的线程的快照。

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

完整的示例代码在这里。

返回的结构不会区分主线程和其他线程。我不知道这样做的机制;虽然某些版本的 C 运行时将在主线程结束时全部 ExitProcess(),但在所有最近的版本中,该进程将继续运行,直到最后一个线程退出。

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

于 2009-12-28T14:20:40.840 回答