可以终止线程从另一个进程终止线程
Can TerminateThread terminate a thread from another process?
在我的Windows服务应用程序中,我可能会在进程中的某些线程上调用TerminateThread API。(请注意,我这样做只是作为使用信令机制和线程同步技术以"正常方式"无法退出线程的最后措施。我在客户提交的事件日志中注意到的是,很少TerminateThread
可能会引发STATUS_INVALID_THREAD
异常,这仅在属于threadpool
的线程上调用该 API 时发生。
由于我确定我的所有线程都不是从线程池启动的,因此我调用TerminateThread
尝试关闭的线程必须来自另一个进程。这只能由于争用条件而发生,其中我的线程句柄首先关闭,然后再次传递给TerminateThread
API,而操作系统在另一个进程中将其重用于其他线程。
所以我的问题是,由于我的服务以足够高的特权运行(如localService
(,在这种情况下TerminateThread
API 是否可以无意中终止属于另一个进程的某些线程?如果是,我该如何防止这种情况(除了找到我现在正在做的竞争条件(?
文档自己说话:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms686717(v=vs.85(.aspx
请勿使用TerminateThread()
:
TerminateThread
是一个危险的功能,只应在最极端的情况下使用。仅当您确切知道目标线程正在执行的操作,并且控制目标线程在终止时可能正在运行的所有代码时,才应调用TerminateThread
。例如,TerminateThread
可能会导致以下问题:
[...]
您可以终止任何线程,只要您具有具有足够权限的句柄:
线程不能保护自己免受
TerminateThread
,除了控制对其句柄的访问。CreateThread
和CreateProcess
函数返回的线程句柄具有THREAD_TERMINATE
访问权限,因此持有这些句柄之一的任何调用方都可以终止线程。
请注意,我这样做只是在线程无法使用信令机制和线程同步技术以"正常方式"退出时的最后手段。
在这种情况下,您无法调用 TerminateThread。只有当您精确控制要终止的线程并完全合作时,您才能调用 TerminateThread。如果线程无法以正常方式退出,那么您就失去了对线程的控制,这与可以调用 TerminateThread 所需的条件完全相反。
如果进程失去了对其某个线程的控制,则无法保存该进程。这是线程的基本属性 - 它们不提供流控制之外的任何隔离。
如果你必须这样做,你可以这样做。
您只需要启动线程句柄。
使用带有 ThreadQuerySetWin32StartAddress 参数的"未记录"NtQueryInformationThread(( 函数调用第一个具有线程句柄作为输入的函数,您将获得线程的 StartAddress。 更多阅读@NTInternals。
它在通过 GetProcAddress 获取地址后按函数地址调用 NTQueryInformationThread。 然后,它使用 ThreadQuerySetWin32StartAddress 参数调用它,获取线程的 StartAddress。
然后调用第二个函数,该函数通过 CreateToolHelp32Snapshot 遍历所有线程,并与提供的 StartAddress 进行比较。 一旦找到它,它就会调用TerminateThread。
enum THREADINFOCLASS
{
ThreadQuerySetWin32StartAddress = 9,
};
typedef NTSTATUS(__stdcall * f_NtQueryInformationThread)(HANDLE, THREADINFOCLASS, void*, ULONG_PTR, ULONG_PTR*);
ULONG_PTR GetThreadStartAddress(HANDLE hThread)
{
auto NtQueryInformationThread = reinterpret_cast<f_NtQueryInformationThread>(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationThread"));
if (!NtQueryInformationThread)
return 0;
ULONG_PTR ulStartAddress = 0;
NTSTATUS Ret = NtQueryInformationThread(hThread, ThreadQuerySetWin32StartAddress, &ulStartAddress, sizeof(ULONG_PTR), nullptr);
if (NT_FAIL(Ret))
return 0;
return ulStartAddress;
}
bool TerminateThreadByStartaddress(ULONG_PTR StartAddress)
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hSnap == INVALID_HANDLE_VALUE)
return false;
THREADENTRY32 TE32 = { 0 };
TE32.dwSize = sizeof(THREADENTRY32);
BOOL Ret = Thread32First(hSnap, &TE32);
while (Ret)
{
HANDLE hTempThread = OpenThread(THREAD_ALL_ACCESS, FALSE, TE32.th32ThreadID);
if (!hTempThread)
{
Ret = Thread32Next(hSnap, &TE32);
continue;
}
if (StartAddress == GetThreadStartAddress(hTempThread))
{
TerminateThread(hTempThread, 0);
CloseHandle(hTempThread);
CloseHandle(hSnap);
return true;
}
CloseHandle(hTempThread);
Ret = Thread32Next(hSnap, &TE32);
}
CloseHandle(hSnap);
return false;
}
感谢我的朋友Broihon,我没有写这段代码,但以前用过它。
使用未记录 http://undocumented.ntinternals.net NTSYSAPI NTSTATUS NTAPI NtTerminateThread(IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus);
,其中 ThreadHandle 是由 OpenThread MS 函数生成的,并且 ExitStatus 设置为您想要的任何内容。
- 如何安全地终止线程?(使用指针)C++
- 自终止线程.使用联接或分离
- 从c/c 中终止线程中的线程,而无需线柄
- 无法终止线程(错误 6)
- 定时与终止线程使用事件不一致
- C++ WinSock Recv 在接收 0 数据时终止线程而不是返回错误代码
- 立即终止线程
- 如何在C++11中终止线程
- 在 C++11 中从外部终止线程
- 错误地终止线程
- 终止线程后的清理
- 如何在Windows线程中终止线程后获取剩余线程数?C++
- 终止线程
- 分段错误,使用 pthread_exit() 终止线程时
- 可以终止线程从另一个进程终止线程
- 正在终止线程
- 如何知道何时终止线程
- C++:如何在没有特定"interruption points"的情况下干净地终止线程
- 强制终止线程C++win32
- 想要终止线程池一旦变量达到一定的值