Process Management (Kernel-Mode)

This forum contains analysis, help or questions about the Malware
Post Reply
User avatar
binhminhitc
BMITC Admin
Posts: 19
Joined: 08 May 2018 22:28
Location: Vietnam
Contact:

Introduction

This thread will be about process termination (kernel-mode), and #1 is used in the title because I may do follow-ups (not just about process termination) in the future, in which I will use #2, #3, and so forth.

Today we will briefly look into how we can terminate a process from within a kernel-mode device driver. As you may already know, in user-mode it is common to use the OpenProcess API which is provided to us through KERNEL32.DLL, and that once this is called, it will lead to the NtOpenProcess stub which is provided to use through NTDLL.DLL. At this point, a system call is performed and kernel-mode routines will handle the operations for us, and provide back the status code which represents if the operation was successful or not (however it is more than just a boolean for example because the data-type for NTSTATUS is LONG and this allows support for many different status codes - therefore if an error occurs, a comparison can be made to obtain more details about why the operation failed if necessary).

In kernel-mode, we don't have the OpenProcess function from KERNEL32.DLL. The reason for this is because in kernel-mode, we do not have access to the Win32 API, period. In kernel-mode you have to rely on the kernel-mode routines (exported ntoskrnl.exe routines, and potentially non-exported ntoskrnl.exe functions if you are capable of locating the addresses and know how to work such functions). The alternate to OpenProcess is NtOpenProcess, which means in kernel-mode we will use the Zw* variant (ZwOpenProcess). In case you're wondering why there is both Zw* and Nt* versions of the Native API routines (the ones NTDLL supports performing system calls for so they can be invoked from user-mode API calls) and the differences between them, it is because the Zw* version performs other operations when called in kernel-mode; in user-mode it does not matter whether you use Zw* or Nt* because the bytes at the stubs will be identical (unlike in kernel-mode).

In kernel-mode you could do the following:
- Call ZwOpenProcess to open a handle to the target process.
- Use the opened process handle for an operation like termination (e.g. by calling ZwTerminateProcess and using the process handle for this call).

However, you don't actually always need to open a handle in kernel-mode. Using the above example where termination for a process is required, who says you need to use ZwOpenProcess at all? There are kernel-mode only routines which are available to us due to being exported by ntoskrnl.exe, but cannot be invoked from user-mode because they do not have an entry in the System Service Dispatch Table (SSDT) thus stopping NTDLL.DLL from supporting a system call for such functions.

In kernel-mode you can do the following instead:
- PsLookupProcessByProcessId
- KeAttachProcess
- ZwTerminateProcess
- KeDetachProcess

Both scenarios will work fine, but I prefer the second method.

In both scenarios, you'll need a Process Identifier (Process ID -> PID) so you can target a specific process. In user-mode you can easily obtain a Process ID by providing a Process Name thanks to Win32 APIs such as CreateToolhelp32Snapshot (KERNEL32), Process32Next, etc. What about in kernel-mode? The truth is that when such Win32 API functions are called, a Native API function called NtQuerySystemInformation is called. This function takes in different class IDs to represent what the task is, and SystemProcessInformation (class ID of 5) is appropriate for process enumeration.

I've already written an example for using NtQuerySystemInformation from user-mode for process enumeration, but it won't be compatible with kernel-mode by default. You can find it here: Tutorial - NtQuerySystemInformation and Process IDs

The example in the thread above can easily be ported to kernel-mode by changing a few things, such as using ExAllocatePool/WithTag instead of NtAllocateVirtualMemory. ExAllocatePool/WithTag is used for local memory allocation in kernel-mode, and typically functions like VirtualAlloc are used in user-mode (however all such functions lead to NtAllocateVirtualMemory being called). ExAllocatePool/WithTag are not available in user-mode, kernel-mode only.

For process enumeration in kernel-mode, here are the broken-down steps on what is required to do it:
1. Calculate the length for the buffer (memory which will be allocated so the enumeration results can be stored within it). -> ZwQuerySystemInformation passing NULL parameters for the second and third -> get the ULONG length back.
2. Memory allocation for the buffer (via ExAllocatePool/WithTag).
3. Re-call ZwQuerySystemInformation to actually store the results this time.
4. Enumerate through the processes in the stored results within the SYSTEM_PROCESS_INFORMATION structure (pointer to it -> *)
5. Clean-up by freeing the memory with ExFreePool/WithTag when you're done with the buffer memory.

For actually obtaining the Process ID -> use structure entry for the PID.

SYSTEM_THREAD_INFORMATION

Code: Select all

typedef struct _SYSTEM_THREAD_INFORMATION {
    LARGE_INTEGER KernelTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER CreateTime;
    ULONG WaitTime;
    PVOID StartAddress;
    CLIENT_ID ClientId;
    LONG Priority;
    LONG BasePriority;
    ULONG ContextSwitches;
    ULONG ThreadState;
    ULONG WaitReason;
}SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
SYSTEM_PROCESS_INFORMATION

Code: Select all

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    LARGE_INTEGER WorkingSetPrivateSize;
    ULONG HardFaultCount;
    ULONG NumberOfThreadsHighWatermark;
    ULONGLONG CycleTime;
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER KernelTime;
    UNICODE_STRING ImageName;
    LONG BasePriority;
    PVOID UniqueProcessId;
    PVOID InheritedFromUniqueProcessId;
    ULONG HandleCount;
    ULONG SessionId;
    ULONG_PTR UniqueProcessKey;
    ULONG_PTR PeakVirtualSize;
    ULONG_PTR VirtualSize;
    ULONG PageFaultCount;
    ULONG_PTR PeakWorkingSetSize;
    ULONG_PTR WorkingSetSize;
    ULONG_PTR QuotaPeakPagedPoolUsage;
    ULONG_PTR QuotaPagedPoolUsage;
    ULONG_PTR QuotaPeakNonPagedPoolUsage;
    ULONG_PTR QuotaNonPagedPoolUsage;
    ULONG_PTR PagefileUsage;
    ULONG_PTR PeakPagefileUsage;
    ULONG_PTR PrivatePageCount;
    LARGE_INTEGER ReadOperationCount;
    LARGE_INTEGER WriteOperationCount;
    LARGE_INTEGER OtherOperationCount;
    LARGE_INTEGER ReadTransferCount;
    LARGE_INTEGER WriteTransferCount;
    LARGE_INTEGER OtherTransferCount;
    SYSTEM_THREAD_INFORMATION ProcessThreads[1];
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
SYSTEM_INFORMATION_CLASS

Code: Select all

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBasicInformation = 0,
    SystemProcessorInformation = 1,
    SystemPerformanceInformation = 2,
    SystemTimeOfDayInformation = 3,
    SystemPathInformation = 4,
    SystemProcessInformation = 5,
    SystemCallCountInformation = 6,
    SystemDeviceInformation = 7,
    SystemProcessorPerformanceInformation = 8,
    SystemFlagsInformation = 9,
    SystemCallTimeInformation = 10,
    SystemModuleInformation = 11,
    SystemLocksInformation = 12,
    SystemStackTraceInformation = 13,
    SystemPagedPoolInformation = 14,
    SystemNonPagedPoolInformation = 15,
    SystemHandleInformation = 16,
    SystemObjectInformation = 17,
    SystemPageFileInformation = 18,
    SystemVdmInstemulInformation = 19,
    SystemVdmBopInformation = 20,
    SystemFileCacheInformation = 21,
    SystemPoolTagInformation = 22,
    SystemInterruptInformation = 23,
    SystemDpcBehaviorInformation = 24,
    SystemFullMemoryInformation = 25,
    SystemLoadGdiDriverInformation = 26,
    SystemUnloadGdiDriverInformation = 27,
    SystemTimeAdjustmentInformation = 28,
    SystemSummaryMemoryInformation = 29,
    SystemMirrorMemoryInformation = 30,
    SystemPerformanceTraceInformation = 31,
    SystemObsolete0 = 32,
    SystemExceptionInformation = 33,
    SystemCrashDumpStateInformation = 34,
    SystemKernelDebuggerInformation = 35,
    SystemContextSwitchInformation = 36,
    SystemRegistryQuotaInformation = 37,
    SystemExtendedServiceTableInformation = 38,
    SystemPrioritySeparation = 39,
    SystemVerifierAddDriverInformation = 40,
    SystemVerifierRemoveDriverInformation = 41,
    SystemProcessorIdleInformation = 42,
    SystemLegacyDriverInformation = 43,
    SystemCurrentTimeZoneInformation = 44,
    SystemLookasideInformation = 45,
    SystemTimeSlipNotification = 46,
    SystemSessionCreate = 47,
    SystemSessionDetach = 48,
    SystemSessionInformation = 49,
    SystemRangeStartInformation = 50,
    SystemVerifierInformation = 51,
    SystemVerifierThunkExtend = 52,
    SystemSessionProcessInformation = 53,
    SystemLoadGdiDriverInSystemSpace = 54,
    SystemNumaProcessorMap = 55,
    SystemPrefetcherInformation = 56,
    SystemExtendedProcessInformation = 57,
    SystemRecommendedSharedDataAlignment = 58,
    SystemComPlusPackage = 59,
    SystemNumaAvailableMemory = 60,
    SystemProcessorPowerInformation = 61,
    SystemEmulationBasicInformation = 62,
    SystemEmulationProcessorInformation = 63,
    SystemExtendedHandleInformation = 64,
    SystemLostDelayedWriteInformation = 65,
    SystemBigPoolInformation = 66,
    SystemSessionPoolTagInformation = 67,
    SystemSessionMappedViewInformation = 68,
    SystemHotpatchInformation = 69,
    SystemObjectSecurityMode = 70,
    SystemWatchdogTimerHandler = 71,
    SystemWatchdogTimerInformation = 72,
    SystemLogicalProcessorInformation = 73,
    SystemWow64SharedInformationObsolete = 74,
    SystemRegisterFirmwareTableInformationHandler = 75,
    SystemFirmwareTableInformation = 76,
    SystemModuleInformationEx = 77,
    SystemVerifierTriageInformation = 78,
    SystemSuperfetchInformation = 79,
    SystemMemoryListInformation = 80,
    SystemFileCacheInformationEx = 81,
    SystemThreadPriorityClientIdInformation = 82,
    SystemProcessorIdleCycleTimeInformation = 83,
    SystemVerifierCancellationInformation = 84,
    SystemProcessorPowerInformationEx = 85,
    SystemRefTraceInformation = 86,
    SystemSpecialPoolInformation = 87,
    SystemProcessIdInformation = 88,
    SystemErrorPortInformation = 89,
    SystemBootEnvironmentInformation = 90,
    SystemHypervisorInformation = 91,
    SystemVerifierInformationEx = 92,
    SystemTimeZoneInformation = 93,
    SystemImageFileExecutionOptionsInformation = 94,
    SystemCoverageInformation = 95,
    SystemPrefetchPatchInformation = 96,
    SystemVerifierFaultsInformation = 97,
    SystemSystemPartitionInformation = 98,
    SystemSystemDiskInformation = 99,
    SystemProcessorPerformanceDistribution = 100,
    SystemNumaProximityNodeInformation = 101,
    SystemDynamicTimeZoneInformation = 102,
    SystemCodeIntegrityInformation = 103,
    SystemProcessorMicrocodeUpdateInformation = 104,
    SystemProcessorBrandString = 105,
    SystemVirtualAddressInformation = 106,
    SystemLogicalProcessorAndGroupInformation = 107,
    SystemProcessorCycleTimeInformation = 108,
    SystemStoreInformation = 109,
    SystemRegistryAppendString = 110,
    SystemAitSamplingValue = 111,
    SystemVhdBootInformation = 112,
    SystemCpuQuotaInformation = 113,
    SystemNativeBasicInformation = 114,
    SystemErrorPortTimeouts = 115,
    SystemLowPriorityIoInformation = 116,
    SystemBootEntropyInformation = 117,
    SystemVerifierCountersInformation = 118,
    SystemPagedPoolInformationEx = 119,
    SystemSystemPtesInformationEx = 120,
    SystemNodeDistanceInformation = 121,
    SystemAcpiAuditInformation = 122,
    SystemBasicPerformanceInformation = 123,
    SystemQueryPerformanceCounterInformation = 124,
    SystemSessionBigPoolInformation = 125,
    SystemBootGraphicsInformation = 126,
    SystemScrubPhysicalMemoryInformation = 127,
    SystemBadPageInformation = 128,
    SystemProcessorProfileControlArea = 129,
    SystemCombinePhysicalMemoryInformation = 130,
    SystemEntropyInterruptTimingInformation = 131,
    SystemConsoleInformation = 132,
    SystemPlatformBinaryInformation = 133,
    SystemThrottleNotificationInformation = 134,
    SystemPolicyInformation = 134,
    SystemHypervisorProcessorCountInformation = 135,
    SystemDeviceDataInformation = 136,
    SystemDeviceDataEnumerationInformation = 137,
    SystemMemoryTopologyInformation = 138,
    SystemMemoryChannelInformation = 139,
    SystemBootLogoInformation = 140,
    SystemProcessorPerformanceInformationEx = 141,
    SystemSpare0 = 142,
    SystemSecureBootPolicyInformation = 143,
    SystemPageFileInformationEx = 144,
    SystemSecureBootInformation = 145,
    SystemEntropyInterruptTimingRawInformation = 146,
    SystemPortableWorkspaceEfiLauncherInformation = 147,
    SystemFullProcessInformation = 148,
    SystemKernelDebuggerInformationEx = 149,
    SystemBootMetadataInformation = 150,
    SystemSoftRebootInformation = 151,
    SystemElamCertificateInformation = 152,
    SystemOfflineDumpConfigInformation = 153,
    SystemProcessorFeaturesInformation = 154,
    SystemRegistryReconciliationInformation = 155,
    SystemEdidInformation = 156,
    SystemManufacturingInformation = 157,
    SystemEnergyEstimationConfigInformation = 158,
    SystemHypervisorDetailInformation = 159,
    SystemProcessorCycleStatsInformation = 160,
    SystemVmGenerationCountInformation = 161,
    SystemTrustedPlatformModuleInformation = 162,
    SystemKernelDebuggerFlags = 163,
    SystemCodeIntegrityPolicyInformation = 164,
    SystemIsolatedUserModeInformation = 165,
    SystemHardwareSecurityTestInterfaceResultsInformation = 166,
    SystemSingleModuleInformation = 167,
    SystemAllowedCpuSetsInformation = 168,
    SystemDmaProtectionInformation = 169,
    SystemInterruptCpuSetsInformation = 170,
    SystemSecureBootPolicyFullInformation = 171,
    SystemCodeIntegrityPolicyFullInformation = 172,
    SystemAffinitizedInterruptProcessorInformation = 173,
    SystemRootSiloInformation = 174,
    SystemCpuSetInformation = 175,
    SystemCpuSetTagInformation = 176,
    MaxSystemInfoClass = 177
} SYSTEM_INFORMATION_CLASS;
For the record, when ZwOpenProcess is called, it will lead to another function called ObOpenObjectByPointer being called. Depending on the circumstances, that function can be used to open up a handle to a process without being caught up by any potential registered kernel-mode callbacks for ObRegisterCallbacks (used to enforce handle access checks -> restrict access rights to handles targeting a specific process, typically in Anti-Virus software as a self-protection mechanism).

Source code example​

I've created demonstration code on how you can find the Process ID of a process given its image name (e.g. "notepad.exe") thanks to ZwQuerySystemInformation, and then proceed to terminate this process using: PsLookupProcessByProcessId; KeAttachProcess; ZwTerminateProcess; and KeDetachProcess.

driver.h

Code: Select all

#pragma once
#include <ntifs.h>

#include "ntdef.h"
#include "ntexport.h"
#include "processmm.h"
ntdef.h

Code: Select all

#pragma once
#include "driver.h"

typedef struct _SYSTEM_THREAD_INFORMATION {
    LARGE_INTEGER KernelTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER CreateTime;
    ULONG WaitTime;
    PVOID StartAddress;
    CLIENT_ID ClientId;
    LONG Priority;
    LONG BasePriority;
    ULONG ContextSwitches;
    ULONG ThreadState;
    ULONG WaitReason;
}SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;

typedef struct _SYSTEM_PROCESS_INFORMATION {
    ULONG NextEntryOffset;
    ULONG NumberOfThreads;
    LARGE_INTEGER WorkingSetPrivateSize;
    ULONG HardFaultCount;
    ULONG NumberOfThreadsHighWatermark;
    ULONGLONG CycleTime;
    LARGE_INTEGER CreateTime;
    LARGE_INTEGER UserTime;
    LARGE_INTEGER KernelTime;
    UNICODE_STRING ImageName;
    LONG BasePriority;
    PVOID UniqueProcessId;
    PVOID InheritedFromUniqueProcessId;
    ULONG HandleCount;
    ULONG SessionId;
    ULONG_PTR UniqueProcessKey;
    ULONG_PTR PeakVirtualSize;
    ULONG_PTR VirtualSize;
    ULONG PageFaultCount;
    ULONG_PTR PeakWorkingSetSize;
    ULONG_PTR WorkingSetSize;
    ULONG_PTR QuotaPeakPagedPoolUsage;
    ULONG_PTR QuotaPagedPoolUsage;
    ULONG_PTR QuotaPeakNonPagedPoolUsage;
    ULONG_PTR QuotaNonPagedPoolUsage;
    ULONG_PTR PagefileUsage;
    ULONG_PTR PeakPagefileUsage;
    ULONG_PTR PrivatePageCount;
    LARGE_INTEGER ReadOperationCount;
    LARGE_INTEGER WriteOperationCount;
    LARGE_INTEGER OtherOperationCount;
    LARGE_INTEGER ReadTransferCount;
    LARGE_INTEGER WriteTransferCount;
    LARGE_INTEGER OtherTransferCount;
    SYSTEM_THREAD_INFORMATION ProcessThreads[1];
}SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;

typedef enum _SYSTEM_INFORMATION_CLASS {
    SystemBasicInformation = 0,
    SystemProcessorInformation = 1,
    SystemPerformanceInformation = 2,
    SystemTimeOfDayInformation = 3,
    SystemPathInformation = 4,
    SystemProcessInformation = 5,
    SystemCallCountInformation = 6,
    SystemDeviceInformation = 7,
    SystemProcessorPerformanceInformation = 8,
    SystemFlagsInformation = 9,
    SystemCallTimeInformation = 10,
    SystemModuleInformation = 11,
    SystemLocksInformation = 12,
    SystemStackTraceInformation = 13,
    SystemPagedPoolInformation = 14,
    SystemNonPagedPoolInformation = 15,
    SystemHandleInformation = 16,
    SystemObjectInformation = 17,
    SystemPageFileInformation = 18,
    SystemVdmInstemulInformation = 19,
    SystemVdmBopInformation = 20,
    SystemFileCacheInformation = 21,
    SystemPoolTagInformation = 22,
    SystemInterruptInformation = 23,
    SystemDpcBehaviorInformation = 24,
    SystemFullMemoryInformation = 25,
    SystemLoadGdiDriverInformation = 26,
    SystemUnloadGdiDriverInformation = 27,
    SystemTimeAdjustmentInformation = 28,
    SystemSummaryMemoryInformation = 29,
    SystemMirrorMemoryInformation = 30,
    SystemPerformanceTraceInformation = 31,
    SystemObsolete0 = 32,
    SystemExceptionInformation = 33,
    SystemCrashDumpStateInformation = 34,
    SystemKernelDebuggerInformation = 35,
    SystemContextSwitchInformation = 36,
    SystemRegistryQuotaInformation = 37,
    SystemExtendedServiceTableInformation = 38,
    SystemPrioritySeparation = 39,
    SystemVerifierAddDriverInformation = 40,
    SystemVerifierRemoveDriverInformation = 41,
    SystemProcessorIdleInformation = 42,
    SystemLegacyDriverInformation = 43,
    SystemCurrentTimeZoneInformation = 44,
    SystemLookasideInformation = 45,
    SystemTimeSlipNotification = 46,
    SystemSessionCreate = 47,
    SystemSessionDetach = 48,
    SystemSessionInformation = 49,
    SystemRangeStartInformation = 50,
    SystemVerifierInformation = 51,
    SystemVerifierThunkExtend = 52,
    SystemSessionProcessInformation = 53,
    SystemLoadGdiDriverInSystemSpace = 54,
    SystemNumaProcessorMap = 55,
    SystemPrefetcherInformation = 56,
    SystemExtendedProcessInformation = 57,
    SystemRecommendedSharedDataAlignment = 58,
    SystemComPlusPackage = 59,
    SystemNumaAvailableMemory = 60,
    SystemProcessorPowerInformation = 61,
    SystemEmulationBasicInformation = 62,
    SystemEmulationProcessorInformation = 63,
    SystemExtendedHandleInformation = 64,
    SystemLostDelayedWriteInformation = 65,
    SystemBigPoolInformation = 66,
    SystemSessionPoolTagInformation = 67,
    SystemSessionMappedViewInformation = 68,
    SystemHotpatchInformation = 69,
    SystemObjectSecurityMode = 70,
    SystemWatchdogTimerHandler = 71,
    SystemWatchdogTimerInformation = 72,
    SystemLogicalProcessorInformation = 73,
    SystemWow64SharedInformationObsolete = 74,
    SystemRegisterFirmwareTableInformationHandler = 75,
    SystemFirmwareTableInformation = 76,
    SystemModuleInformationEx = 77,
    SystemVerifierTriageInformation = 78,
    SystemSuperfetchInformation = 79,
    SystemMemoryListInformation = 80,
    SystemFileCacheInformationEx = 81,
    SystemThreadPriorityClientIdInformation = 82,
    SystemProcessorIdleCycleTimeInformation = 83,
    SystemVerifierCancellationInformation = 84,
    SystemProcessorPowerInformationEx = 85,
    SystemRefTraceInformation = 86,
    SystemSpecialPoolInformation = 87,
    SystemProcessIdInformation = 88,
    SystemErrorPortInformation = 89,
    SystemBootEnvironmentInformation = 90,
    SystemHypervisorInformation = 91,
    SystemVerifierInformationEx = 92,
    SystemTimeZoneInformation = 93,
    SystemImageFileExecutionOptionsInformation = 94,
    SystemCoverageInformation = 95,
    SystemPrefetchPatchInformation = 96,
    SystemVerifierFaultsInformation = 97,
    SystemSystemPartitionInformation = 98,
    SystemSystemDiskInformation = 99,
    SystemProcessorPerformanceDistribution = 100,
    SystemNumaProximityNodeInformation = 101,
    SystemDynamicTimeZoneInformation = 102,
    SystemCodeIntegrityInformation = 103,
    SystemProcessorMicrocodeUpdateInformation = 104,
    SystemProcessorBrandString = 105,
    SystemVirtualAddressInformation = 106,
    SystemLogicalProcessorAndGroupInformation = 107,
    SystemProcessorCycleTimeInformation = 108,
    SystemStoreInformation = 109,
    SystemRegistryAppendString = 110,
    SystemAitSamplingValue = 111,
    SystemVhdBootInformation = 112,
    SystemCpuQuotaInformation = 113,
    SystemNativeBasicInformation = 114,
    SystemErrorPortTimeouts = 115,
    SystemLowPriorityIoInformation = 116,
    SystemBootEntropyInformation = 117,
    SystemVerifierCountersInformation = 118,
    SystemPagedPoolInformationEx = 119,
    SystemSystemPtesInformationEx = 120,
    SystemNodeDistanceInformation = 121,
    SystemAcpiAuditInformation = 122,
    SystemBasicPerformanceInformation = 123,
    SystemQueryPerformanceCounterInformation = 124,
    SystemSessionBigPoolInformation = 125,
    SystemBootGraphicsInformation = 126,
    SystemScrubPhysicalMemoryInformation = 127,
    SystemBadPageInformation = 128,
    SystemProcessorProfileControlArea = 129,
    SystemCombinePhysicalMemoryInformation = 130,
    SystemEntropyInterruptTimingInformation = 131,
    SystemConsoleInformation = 132,
    SystemPlatformBinaryInformation = 133,
    SystemThrottleNotificationInformation = 134,
    SystemPolicyInformation = 134,
    SystemHypervisorProcessorCountInformation = 135,
    SystemDeviceDataInformation = 136,
    SystemDeviceDataEnumerationInformation = 137,
    SystemMemoryTopologyInformation = 138,
    SystemMemoryChannelInformation = 139,
    SystemBootLogoInformation = 140,
    SystemProcessorPerformanceInformationEx = 141,
    SystemSpare0 = 142,
    SystemSecureBootPolicyInformation = 143,
    SystemPageFileInformationEx = 144,
    SystemSecureBootInformation = 145,
    SystemEntropyInterruptTimingRawInformation = 146,
    SystemPortableWorkspaceEfiLauncherInformation = 147,
    SystemFullProcessInformation = 148,
    SystemKernelDebuggerInformationEx = 149,
    SystemBootMetadataInformation = 150,
    SystemSoftRebootInformation = 151,
    SystemElamCertificateInformation = 152,
    SystemOfflineDumpConfigInformation = 153,
    SystemProcessorFeaturesInformation = 154,
    SystemRegistryReconciliationInformation = 155,
    SystemEdidInformation = 156,
    SystemManufacturingInformation = 157,
    SystemEnergyEstimationConfigInformation = 158,
    SystemHypervisorDetailInformation = 159,
    SystemProcessorCycleStatsInformation = 160,
    SystemVmGenerationCountInformation = 161,
    SystemTrustedPlatformModuleInformation = 162,
    SystemKernelDebuggerFlags = 163,
    SystemCodeIntegrityPolicyInformation = 164,
    SystemIsolatedUserModeInformation = 165,
    SystemHardwareSecurityTestInterfaceResultsInformation = 166,
    SystemSingleModuleInformation = 167,
    SystemAllowedCpuSetsInformation = 168,
    SystemDmaProtectionInformation = 169,
    SystemInterruptCpuSetsInformation = 170,
    SystemSecureBootPolicyFullInformation = 171,
    SystemCodeIntegrityPolicyFullInformation = 172,
    SystemAffinitizedInterruptProcessorInformation = 173,
    SystemRootSiloInformation = 174,
    SystemCpuSetInformation = 175,
    SystemCpuSetTagInformation = 176,
    MaxSystemInfoClass = 177
} SYSTEM_INFORMATION_CLASS;
ntexport.h

Code: Select all

#pragma once
#include "driver.h"

typedef NTSTATUS(NTAPI *pZwQuerySystemInformation)(
    SYSTEM_INFORMATION_CLASS SystemInformationClass,
    PVOID SystemInformation,
    ULONG SystemInformationLength,
    PULONG ReturnLength OPTIONAL
    );

extern pZwQuerySystemInformation fZwQuerySystemInformation;

NTSTATUS SetupExports();
processmm.h

Code: Select all

#pragma once
#include "driver.h"

NTSTATUS ReturnProcessStruct(
    ULONG ProcessId,
    PEPROCESS *Process
);

ULONG ReturnProcessId(
    WCHAR *ProcessName
);

NTSTATUS TerminateProcess(
    PEPROCESS Process
);

NTSTATUS WrapperTerminateProcess(
    ULONG ProcessId
);
driver.c

Code: Select all

#include "driver.h"

DEVICE_OBJECT DeviceObject = { 0 };

UNICODE_STRING usDriverInfo[2] = { 
    RTL_CONSTANT_STRING(L"\\Device\\KmdfExample"), 
    RTL_CONSTANT_STRING(L"\\DosDevices\\KmdfExample")
};

VOID TerminateTest()
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    ULONG ProcessId = 0;
   
    NtStatus = SetupExports();

    if (!NT_SUCCESS(NtStatus))
    {
        return;
    }

    ProcessId = ReturnProcessId(L"notepad.exe");

    if (!ProcessId)
    {
        DbgPrint("The process could not be found\n");

        return;
    }

    DbgPrint("Process ID: %d", ProcessId);

    NtStatus = WrapperTerminateProcess(ProcessId);

    if (NT_SUCCESS(NtStatus))
    {
        DbgPrint("The process was terminated from kernel-mode\n");
    }
    else
    {
        DbgPrint("The process could not be terminated from kernel-mode\n");
    }
}

VOID DriverUnload(
    PDRIVER_OBJECT DriverObject
)
{
    IoDeleteSymbolicLink(&usDriverInfo[1]);
    IoDeleteDevice(DriverObject->DeviceObject);
}

NTSTATUS DriverEntry(
    PDRIVER_OBJECT DriverObject,
    PUNICODE_STRING RegistryPath
)
{
    UNREFERENCED_PARAMETER(RegistryPath);

    NTSTATUS NtStatus = STATUS_SUCCESS;

    NtStatus = IoCreateDevice(DriverObject,
        NULL,
        &usDriverInfo[0],
        FILE_DEVICE_UNKNOWN,
        FILE_DEVICE_SECURE_OPEN,
        FALSE,
        &DeviceObject);

    if (!NT_SUCCESS(NtStatus))
    {
        return NtStatus;
    }

    NtStatus = IoCreateSymbolicLink(&usDriverInfo[1],
        &usDriverInfo[0]);

    if (!NT_SUCCESS(NtStatus))
    {
        return NtStatus;
    }

    DriverObject->DriverUnload = DriverUnload;

    TerminateTest();

    return NtStatus;
}
ntexport.c

Code: Select all

#include "driver.h"

pZwQuerySystemInformation fZwQuerySystemInformation;

NTSTATUS SetupExports()
{
    PVOID FunctionAddress = 0;
    UNICODE_STRING usSystemRoutineName = RTL_CONSTANT_STRING(L"ZwQuerySystemInformation");

    FunctionAddress = MmGetSystemRoutineAddress(&usSystemRoutineName);

    if (!FunctionAddress)
    {
        return STATUS_UNSUCCESSFUL;
    }

    fZwQuerySystemInformation = (pZwQuerySystemInformation)FunctionAddress;

    if (!fZwQuerySystemInformation)
    {
        return STATUS_UNSUCCESSFUL;
    }

    return STATUS_SUCCESS;
}
processmm.c

Code: Select all

#include "driver.h"

NTSTATUS ReturnProcessStruct(
    ULONG ProcessId,
    PEPROCESS *Process
)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;

    NtStatus = PsLookupProcessByProcessId((HANDLE)ProcessId,
        Process);
   
    return NtStatus;
}

ULONG ReturnProcessId(
    WCHAR *ProcessName
)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    PSYSTEM_PROCESS_INFORMATION SystemProcessInfo = { 0 };
    PVOID BufferMemory = 0;
    SIZE_T RegionSize = 0;
    ULONG ReturnLength = 0, ProcessId = 0;

    NtStatus = fZwQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemProcessInformation,
        NULL,
        NULL,
        &ReturnLength);

    if (!ReturnLength)
    {
        return ProcessId;
    }

    RegionSize = (SIZE_T)ReturnLength;

    BufferMemory = ExAllocatePool(NonPagedPool,
        RegionSize);

    if (!BufferMemory)
    {
        return ProcessId;
    }

    NtStatus = fZwQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemProcessInformation,
        BufferMemory,
        ReturnLength,
        NULL);

    if (!NT_SUCCESS(NtStatus))
    {
        return ProcessId;
    }

    SystemProcessInfo = (PSYSTEM_PROCESS_INFORMATION)BufferMemory;

    while (SystemProcessInfo->NextEntryOffset)
    {
        SystemProcessInfo = (SYSTEM_PROCESS_INFORMATION*)((UCHAR*)SystemProcessInfo + SystemProcessInfo->NextEntryOffset);

        if (!wcscmp(SystemProcessInfo->ImageName.Buffer, ProcessName))
        {
            ProcessId = (ULONG)SystemProcessInfo->UniqueProcessId;
   
            break;
        }
    }

    if (BufferMemory)
    {
        ExFreePool(BufferMemory);
    }

    return ProcessId;
}

NTSTATUS TerminateProcess(
    PEPROCESS Process
)
{
    NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;

    __try {
        KeAttachProcess(Process);

        NtStatus = ZwTerminateProcess(NtCurrentProcess(),
            NULL);

        KeDetachProcess();
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
    }

    return NtStatus;
}

NTSTATUS WrapperTerminateProcess(
    ULONG ProcessId
)
{
    NTSTATUS NtStatus = STATUS_SUCCESS;
    PEPROCESS Process = { 0 };

    NtStatus = ReturnProcessStruct(ProcessId,
        &Process);

    if (!NT_SUCCESS(NtStatus))
    {
        return STATUS_UNSUCCESSFUL;
    }

    NtStatus = TerminateProcess(Process);

    return NtStatus;
}
There are many different ways to do things in kernel-mode, this thread is just for demonstration purposes to provide an example of another approach to opening a process handle with ZwOpenProcess for process termination (since you can attach to it and execute within the context of the process remotely in kernel-mode, which means you are able to call ZwTerminateProcess and pass a pseudo-handle of (HANDLE)-1 to represent the current process you're in the context of, which results in the attached-to process being terminated).

Thank you for reading.
Post Reply