/* Were we passed a process handle? */
if (ProcessHandle)
{
/* Yes we were, use it */
KillByHandle = TRUE;
}
else
{
/* We weren't... we assume this is suicide */
KillByHandle = FALSE;
ProcessHandle = NtCurrentProcess();
}
/* Get the Process Object */
Status = ObReferenceObjectByHandle(ProcessHandle,
PROCESS_TERMINATE,
PsProcessType,
KeGetPreviousMode(),
(PVOID*)&Process,
NULL);
if (!NT_SUCCESS(Status)) return(Status);
/* Check if this is a Critical Process, and Bugcheck */
if (Process->BreakOnTermination)
{
/* Break to debugger */
PspCatchCriticalBreak("Terminating critical process 0x%p (%s)\n",
Process,
Process->ImageFileName);
}
/* Lock the Process */
if (!ExAcquireRundownProtection(&Process->RundownProtect))
{
/* Failed to lock, fal */
ObDereferenceObject (Process);
return STATUS_PROCESS_IS_TERMINATING;
}
/* Set the delete flag, unless the process is comitting suicide */
if (KillByHandle) PspSetProcessFlag(Process, PSF_PROCESS_DELETE_BIT);
/* Get the first thread */
Status = STATUS_NOTHING_TO_TERMINATE;
Thread = PsGetNextProcessThread(Process, NULL);
if (Thread)
{
/* We know we have at least a thread */
Status = STATUS_SUCCESS;
/* Loop and kill the others */
do
{
/* Ensure it's not ours*/
if (Thread != CurrentThread)
{
/* Kill it */
PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
}
/* Move to the next thread */
Thread = PsGetNextProcessThread(Process, Thread);
} while (Thread);
}
/* Unlock the process */
ExReleaseRundownProtection(&Process->RundownProtect);
/* Check if we are killing ourselves */
if (Process == CurrentProcess)
{
/* Also make sure the caller gave us our handle */
if (KillByHandle)
{
/* Dereference the project */
ObDereferenceObject(Process);
/* Terminate ourselves */
PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE);
}
}
else if (ExitStatus == DBG_TERMINATE_PROCESS)
{
/* Disable debugging on this process */
DbgkClearProcessDebugObject(Process, NULL);
}
/* Check if there was nothing to terminate, or if we have a Debug Port */
if ((Status == STATUS_NOTHING_TO_TERMINATE) ||
((Process->DebugPort) && (KillByHandle)))
{
/* Clear the handle table */
ObClearProcessHandleTable(Process);
/* Return status now */
Status = STATUS_SUCCESS;
}
/* Decrease the reference count we added */
ObDereferenceObject(Process);
/* Check if this is a Critical Thread, and Bugcheck */
if (Thread->BreakOnTermination)
{
/* Break to debugger */
PspCatchCriticalBreak("Terminating critical thread 0x%p (%s)\n",
Thread,
Thread->ThreadsProcess->ImageFileName);
}
/* Check if we are already inside the thread */
if ((bSelf) || (PsGetCurrentThread() == Thread))
{
/* This should only happen at passive */
ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
/* Mark it as terminated */
PspSetCrossThreadFlag(Thread, CT_TERMINATED_BIT);
/* Directly terminate the thread */
PspExitThread(ExitStatus);
}
/* This shouldn't be a system thread */
if (Thread->SystemThread) return STATUS_ACCESS_DENIED;
/* Allocate the APC */
Apc = ExAllocatePoolWithTag(NonPagedPool, sizeof(KAPC), TAG_TERMINATE_APC);
/* Set the Terminated Flag */
Flags = Thread->CrossThreadFlags | CT_TERMINATED_BIT;
/* Set it, and check if it was already set while we were running */
if (!(InterlockedExchange((PLONG)&Thread->CrossThreadFlags, Flags) &
CT_TERMINATED_BIT))
{
/* Initialize a Kernel Mode APC to Kill the Thread */
KeInitializeApc(Apc,
&Thread->Tcb,
OriginalApcEnvironment,
PsExitSpecialApc,
PspExitApcRundown,
PspExitNormalApc,
KernelMode,
(PVOID)ExitStatus);
/* Insert it into the APC Queue */
if (!KeInsertQueueApc(Apc, Apc, NULL, 2))
{
/* The APC was already in the queue, fail */
ExFreePool(Apc);
Status = STATUS_UNSUCCESSFUL;
}
else
{
/* Forcefully resume the thread and return */
KeForceResumeThread(&Thread->Tcb);
return Status;
}
}
结果: 篮屏
分析:
经WinDbg调试发现死循环 循环代码
Thread = PsGetNextProcessThread(Process, NULL);
if (Thread)
{
/* We know we have at least a thread */
Status = STATUS_SUCCESS;
/* Loop and kill the others */
do
{
/* Ensure it's not ours*/
if (Thread != CurrentThread)
{
/* Kill it */
PspTerminateThreadByPointer(Thread, ExitStatus, FALSE);
}
/* Move to the next thread */
Thread = PsGetNextProcessThread(Process, Thread);
} while (Thread);
}
->PsGetNextProcessThread
if (Thread)
{
/* Start where we left off */
Entry = Thread->ThreadListEntry.Flink;
}
else
{
/* Start at the beginning */
Entry = Process->ThreadListHead.Flink;
}
/* Set the list head and start looping */
ListHead = &Process->ThreadListHead;
while (ListHead != Entry)
{
/* Get the Thread */
FoundThread = CONTAINING_RECORD(Entry, ETHREAD, ThreadListEntry);
/* Safe reference the thread */
if (ObReferenceObjectSafe(FoundThread)) break;
CurrentProcess = Thread->ThreadsProcess; (ShellProc)
...
FirstEntry = &CurrentProcess->ThreadListHead;
CurrentEntry = FirstEntry->Flink;
while (FirstEntry != CurrentEntry)
{
/* Get the thread on the list */
OtherThread = CONTAINING_RECORD(CurrentEntry,
ETHREAD,
ThreadListEntry);
/* Check if it's a thread that's still alive */
if ((OtherThread != Thread) &&
!(KeReadStateThread(&OtherThread->Tcb)) &&
(ObReferenceObjectSafe(OtherThread)))
{
/* It's a live thread and we referenced it, unlock process */
ExReleasePushLockExclusive(&CurrentProcess->ProcessLock);
KeLeaveCriticalRegion();
/* Wait on the thread */
KeWaitForSingleObject(OtherThread,
Executive,
KernelMode,
FALSE,
NULL);
/* Check if we had a previous thread to dereference */
if (PreviousThread) ObDereferenceObject(PreviousThread);
/* Remember the thread and re-lock the process */
PreviousThread = OtherThread;
KeEnterCriticalRegion();
ExAcquirePushLockExclusive(&CurrentProcess->ProcessLock);
}
/* Go to the next thread */
CurrentEntry = CurrentEntry->Flink;
}
原因跟前面一样, 因为线程没有闭合, 导致死循环