12 ways to terminate a process

TerminateProcess or NtTerminateProcess

Everyone knows about TerminateProcess. You simply open a handle to the target process and call TerminateProcess. In case TerminateProcess is hooked, you can call the equivalent Native API function NtTerminateProcess.

CreateRemoteThread, ExitProcess

For this method you will have to find the address of ExitProcess within the target process. It is usually the same as ExitProcess for your process, so you can use GetModuleHandle and GetProcAddress. You can then create a thread inside the target process which executes ExitProcess, killing the target process.

NtQuerySystemInformation or toolhelp32, TerminateThread or NtTerminateThread

Simply loop through the threads of the target process and terminate each one using TerminateThread. If it’s hooked, call NtTerminateThread.

NtQuerySystemInformation or toolhelp32, SetThreadContext

Loop through the threads of the target process and set their contexts using SetThreadContext; modify their contexts so that eip points to ExitProcess.

DuplicateHandle

Loop from 0 to 4096 and call DuplicateHandle with Options = 1, leaving TargetProcess and TargetProcessHandle null. This will close most, if not all handles opened by the target process. This method works best for complex applications like security software – it doesn’t crash Notepad, for example.

CreateJobObject, AssignProcessToJobObject, TerminateJobObject (and their Native API equivalents)

Create a job object using CreateJobObject, assign the target process to it using AssignProcessToJobObject, and terminate it using TerminateJobObject. This only works if the process is not already associated with a job object. This technique works well if NtAssignProcessToJobObject and NtTerminateJobObject are not hooked because NtTerminateJobObject calls PsTerminateProcess directly.

NtCreateDebugObject, NtDebugActiveProcess, CloseHandle

People usually implement this technique by using DebugActiveProcess and then exiting the current process. They do this because they don’t know how DebugActiveProcess works. Behind the scenes kernel32 is calling ntdll which calls NtDebugActiveProcess with an already-created debug object. You don’t have to exit the current process for the debuggee to get killed; you just need to close the debug object. When it is closed, the kernel will kill the debuggee using PsTerminateProcess.

To implement this technique, you can create a debug object using NtCreateDebugObject (specifying the kill-on-close flag), debug the process using NtDebugActiveProcess (the process handle needs PROCESS_SUSPEND_RESUME access), and close the handle to the debug object using CloseHandle. Here are the definitions:

#define DEBUG_OBJECT_READEVENT 0x1
#define DEBUG_OBJECT_PROCESSASSIGN 0x2
#define DEBUG_OBJECT_SETINFORMATION 0x4
#define DEBUG_OBJECT_QUERYINFORMATION 0x8

#define DEBUG_OBJECT_KILLONCLOSE 0x1

NTSTATUS NTAPI NtCreateDebugObject(
    PHANDLE DebugObjectHandle,
    ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    ULONG Flags
    );

NTSTATUS NTAPI NtDebugActiveProcess(
    HANDLE ProcessHandle,
    HANDLE DebugObjectHandle
    );

VirtualQueryEx, VirtualProtectEx

Loop through the memory regions of the target process using VirtualQueryEx and set their protections to PAGE_NOACCESS. The program will crash as soon as it context-switches into user-mode code because it will be unable to read any code from memory.

VirtualQueryEx, WriteProcessMemory

Loop through the memory regions of the target process and write random data to it using WriteProcessMemory.

VirtualAllocEx

Call VirtualAllocEx in a loop until you can’t reserve any more memory in the target process. It will crash when it is unable to allocate any more memory.

PsTerminateProcess

PsTerminateProcess is an internal kernel-mode function which is not exported by ntoskrnl. You will need to locate it by scanning kernel-mode memory for a specific signature, which I will not post here. WARNING: On XP you should locate PspTerminateProcess instead, which is stdcall. On Vista PsTerminateProcess is thiscall (first argument goes in ecx), so you will need some hand-coded assembly.

typedef NTSTATUS (*_PsTerminateProcess)(
    PEPROCESS Process,
    NTSTATUS ExitStatus
    );

PspTerminateThreadByPointer

This function is not exported either. WARNING: On XP, there are two arguments. On Vista, there are three.

/* XP */
typedef NTSTATUS (NTAPI *_PspTerminateThreadByPointer51)(
    PETHREAD Thread,
    NTSTATUS ExitStatus
    );

/* Vista */
typedef NTSTATUS (NTAPI *_PspTerminateThreadByPointer60)(
    PETHREAD Thread,
    NTSTATUS ExitStatus,
    BOOLEAN DirectTerminate
    );

A note about process handles

Before you get started on these methods, you will need to know the ways of getting a handle to the victim process. Surely, the only way to do this is by calling OpenProcess/NtOpenProcess, right? Wrong. If you can’t get a handle with the right access because of a hooked function (such as with security software), you can open the target process with SYNCHRONIZE access (or whatever access you think will be granted) and call DuplicateHandle to get new access rights. This won’t always work though because security software vendors are starting to hook ZwDuplicateObject to prevent this.

On Windows Vista there are two Native API functions named NtGetNextProcess and NtGetNextThread. Almost no one knows about this and almost no one hooks these two functions. Here are their definitions:

NTSTATUS NTAPI NtGetNextProcess(
    HANDLE ProcessHandle,
    ACCESS_MASK DesiredAccess,
    ULONG HandleAttributes,
    ULONG Flags,
    PHANDLE NewProcessHandle
    );

NTSTATUS NTAPI NtGetNextThread(
    HANDLE ProcessHandle,
    HANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    ULONG HandleAttributes,
    ULONG Flags,
    PHANDLE NewThreadHandle
    );
This entry was posted in Programming. Bookmark the permalink.

5 Responses to 12 ways to terminate a process

  1. GM says:

    Nice info wj32 ;)

    ————

    #13 : Queuing APC to process threads

    1- Loop through the threads of the target process .

    2- For each thread we mark it as SystemThread and set the ApcQueueable flag/field .

    3- We Queue a kernel-mode APC to the thread, ApcRoutine calls PsTerminateSystemThreads to kill the current thread .

    4- Forcibly resume the thread if it’s suspened by setting KTHREAD.SuspendCount & KTHREAD.FreezeCount to zero and signalling the thread suspend semaphore .

    Additional work :
    Implementing our own APC manager to avoid hooks .

    –GM

  2. Ashish says:

    I need to know more about DebugActiveProcess.. How do i kill process using DebugActiveProcess??? Can you provide detailed explanation?

  3. Ashish says:

    NtDebugActiveProcess failed in my case :(

  4. Tigzy says:

    Hello

    Don’t know why, that code won’t works.
    The handles are duplicated successfully, but the program still works…

    //************************
    void KillWithDuplicateHandle (DWORD pid)
    {
    HANDLE hProc = OpenProcess(PROCESS_DUP_HANDLE,FALSE, pid);
    if(hProc != NULL)
    {
    for (ULONG i = 0 ; i <= 4096 ; i++)
    {
    HANDLE hdl;

    if (DuplicateHandle( hProc, (HANDLE)i , NULL, &hdl, 0, FALSE, DUPLICATE_CLOSE_SOURCE))
    printf ("Handle [%d] duplicated and terminatedn", i);
    //else printf ("Unable to kill %dn", pid);
    }
    }
    //else printf ("Unable to kill %dn", pid);
    }
    //**************************

  5. Pingback: Need Some Help In Hooking Plz

Leave a Reply