我在一些小型测试应用程序中创建了一个附加线程,并希望从这个附加线程中挂起主线程。附加线程是通过CreateRemoteThread
外部进程创建的。
由于SuspendThread
需要一个HANDLE
应该暂停的线程,我想知道如何HANDLE
从我的附加线程中运行的代码中获取它。
我在一些小型测试应用程序中创建了一个附加线程,并希望从这个附加线程中挂起主线程。附加线程是通过CreateRemoteThread
外部进程创建的。
由于SuspendThread
需要一个HANDLE
应该暂停的线程,我想知道如何HANDLE
从我的附加线程中运行的代码中获取它。
一旦进程开始,我认为没有任何东西可以将主线程与其他线程区分开来。但是,您可以枚举进程中的所有线程,并使用GetThreadTimes查找创建时间最早的线程。调用OpenThreadHANDLE
从线程 ID中获取。
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;
}
使用此函数获取线程 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);
}
许多此类有用的 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。欢迎其他人的任何想法。