检测 .NET 线程是否为 运行
Detect if a .NET Thread is Running
我正在使用 C++/CLI 并创建了 2 个线程。
loadedThreads = gcnew array<Thread^>(2);
len = 2;
Thread^ th1 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[0] = th1;
Thread^ th2 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[1] = th2;
th1->Start();
th2->Start();
threadsCreated = true;
两个线程都在检查对方是否还活着:
void Ping()
{
while(true)
{
if(!threadsCreated) { Thread::Sleep(25); continue; }
for(int i = 0; i < len; i++)
{
Thread^ t = loadedThreads[i];
if(!t->IsAlive())
{
_log("some thread is not running");
}
}
Thread::Sleep(25);
}
}
但是如果我用 ProcessHacker 终止线程,线程将不再 运行 但它仍将被标记为活动的 (IsAlive = true, ThreadState = 运行)
这是一个错误吗?这是 Process Hacker 使用的漏洞吗?
.NET/CLR threads 是托管线程;在应用程序的上下文中进行管理。托管线程不仅仅在 OS 中启动一个线程,它们还保持线程对象的状态,以提供一种对开发人员更友好的线程管理方式。
当你启动一个线程时,OS 必须管理这个线程(不管它是来自 .NET,Java 还是 C)并且外部程序(如 Process Hacker)可以看到这些线程很像外部程序可以看到系统上的进程 运行。 Process Hacker 和类似的可以终止线程的程序通常只需获取 OS 线程 ID 并调用 WinAPI 函数 TerminateThread
,这实际上会杀死活动线程,而其他任何用户代码都没有机会在其上执行.
对于托管线程,这意味着当您调用 Start
method, the Thread
class will keep state of the internal thread it created (e.g. the thread's ID, set thread state to 'running', call user function, etc.) and when the thread function ends, the Thread
class then cleans up and sets the appropriate flags (e.g. thread state set to 'stopped' for normal termination or 'aborted' if Abort
时被调用)。为此,如果您从外部程序(如 Process Hacker)中终止线程,Thread
class 代码就没有机会执行清理代码并因此将标志重置为有效值,即 Thread
class 仍然认为它拥有的线程是有效的。应该注意的是,在通过 Process Hacker 杀死线程对象后对其进行操作很可能会导致崩溃或未定义的行为。
还应注意,没有太多方法可以检测线程是否已在您的代码之外被强制终止。您可以加入线程或在线程代码中实现某种心跳,但这仍然不能保证(特别是如果您实现任何类型的同步锁)。如果线程被终止,您可能知道的最多的是线程已通过某种方式结束,正如您所指出的,它可能导致无效状态。
所以,直接回答:
Is it a bug?
不,这是给定上下文的预期行为。
Is it a exploit Process Hacker uses?
不,根据我上面的回答,它很可能使用 TerminateThread
函数,但它确实需要管理员权限。
希望能帮到你。
我正在使用 C++/CLI 并创建了 2 个线程。
loadedThreads = gcnew array<Thread^>(2);
len = 2;
Thread^ th1 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[0] = th1;
Thread^ th2 = gcnew Thread(gcnew ThreadStart(&Ping)); loadedThreads[1] = th2;
th1->Start();
th2->Start();
threadsCreated = true;
两个线程都在检查对方是否还活着:
void Ping()
{
while(true)
{
if(!threadsCreated) { Thread::Sleep(25); continue; }
for(int i = 0; i < len; i++)
{
Thread^ t = loadedThreads[i];
if(!t->IsAlive())
{
_log("some thread is not running");
}
}
Thread::Sleep(25);
}
}
但是如果我用 ProcessHacker 终止线程,线程将不再 运行 但它仍将被标记为活动的 (IsAlive = true, ThreadState = 运行)
这是一个错误吗?这是 Process Hacker 使用的漏洞吗?
.NET/CLR threads 是托管线程;在应用程序的上下文中进行管理。托管线程不仅仅在 OS 中启动一个线程,它们还保持线程对象的状态,以提供一种对开发人员更友好的线程管理方式。
当你启动一个线程时,OS 必须管理这个线程(不管它是来自 .NET,Java 还是 C)并且外部程序(如 Process Hacker)可以看到这些线程很像外部程序可以看到系统上的进程 运行。 Process Hacker 和类似的可以终止线程的程序通常只需获取 OS 线程 ID 并调用 WinAPI 函数 TerminateThread
,这实际上会杀死活动线程,而其他任何用户代码都没有机会在其上执行.
对于托管线程,这意味着当您调用 Start
method, the Thread
class will keep state of the internal thread it created (e.g. the thread's ID, set thread state to 'running', call user function, etc.) and when the thread function ends, the Thread
class then cleans up and sets the appropriate flags (e.g. thread state set to 'stopped' for normal termination or 'aborted' if Abort
时被调用)。为此,如果您从外部程序(如 Process Hacker)中终止线程,Thread
class 代码就没有机会执行清理代码并因此将标志重置为有效值,即 Thread
class 仍然认为它拥有的线程是有效的。应该注意的是,在通过 Process Hacker 杀死线程对象后对其进行操作很可能会导致崩溃或未定义的行为。
还应注意,没有太多方法可以检测线程是否已在您的代码之外被强制终止。您可以加入线程或在线程代码中实现某种心跳,但这仍然不能保证(特别是如果您实现任何类型的同步锁)。如果线程被终止,您可能知道的最多的是线程已通过某种方式结束,正如您所指出的,它可能导致无效状态。
所以,直接回答:
Is it a bug?
不,这是给定上下文的预期行为。
Is it a exploit Process Hacker uses?
不,根据我上面的回答,它很可能使用 TerminateThread
函数,但它确实需要管理员权限。
希望能帮到你。