mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-12 18:49:32 +00:00
270 lines
5.5 KiB
C
270 lines
5.5 KiB
C
/**
|
|
* @file Common.c
|
|
* @author Sina Karvandi (sina@hyperdbg.org)
|
|
* @brief Routines for common tasks in debugger
|
|
* @details
|
|
* @version 0.2
|
|
* @date 2023-01-22
|
|
*
|
|
* @copyright This project is released under the GNU Public License v3.
|
|
*
|
|
*/
|
|
#include "pch.h"
|
|
|
|
/**
|
|
* @brief Checks whether the process with ProcId exists or not
|
|
*
|
|
* @details this function should NOT be called from vmx-root mode
|
|
*
|
|
* @param UINT32 ProcId
|
|
* @return BOOLEAN Returns true if the process
|
|
* exists and false if it the process doesn't exist
|
|
*/
|
|
BOOLEAN
|
|
CommonIsProcessExist(UINT32 ProcId)
|
|
{
|
|
PEPROCESS TargetEprocess;
|
|
|
|
if (PsLookupProcessByProcessId((HANDLE)ProcId, &TargetEprocess) != STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// There was an error, probably the process id was not found
|
|
//
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
ObDereferenceObject(TargetEprocess);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get handle from Process Id
|
|
* @param Handle
|
|
* @param ProcessId
|
|
*
|
|
* @return NTSTATUS
|
|
*/
|
|
_Use_decl_annotations_
|
|
NTSTATUS
|
|
CommonGetHandleFromProcess(UINT32 ProcessId, PHANDLE Handle)
|
|
{
|
|
NTSTATUS Status;
|
|
Status = STATUS_SUCCESS;
|
|
OBJECT_ATTRIBUTES ObjAttr = {0};
|
|
CLIENT_ID Cid = {0};
|
|
InitializeObjectAttributes(&ObjAttr, NULL, 0, NULL, NULL);
|
|
|
|
Cid.UniqueProcess = (HANDLE)ProcessId;
|
|
Cid.UniqueThread = (HANDLE)0;
|
|
|
|
Status = ZwOpenProcess(Handle, PROCESS_ALL_ACCESS, &ObjAttr, &Cid);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
* @brief Get process name by eprocess
|
|
*
|
|
* @param Eprocess Process eprocess
|
|
* @return PCHAR Returns a pointer to the process name
|
|
*/
|
|
PCHAR
|
|
CommonGetProcessNameFromProcessControlBlock(PEPROCESS Eprocess)
|
|
{
|
|
PCHAR Result = 0;
|
|
|
|
//
|
|
// We can't use PsLookupProcessByProcessId as in pageable and not
|
|
// work on vmx-root
|
|
//
|
|
Result = (CHAR *)PsGetProcessImageFileName(Eprocess);
|
|
|
|
return Result;
|
|
}
|
|
|
|
/**
|
|
* @brief The undocumented way of NtOpenProcess
|
|
* @param ProcessHandle
|
|
* @param DesiredAccess
|
|
* @param ProcessId
|
|
* @param AccessMode
|
|
*
|
|
* @return NTSTATUS
|
|
*/
|
|
NTSTATUS
|
|
CommonUndocumentedNtOpenProcess(
|
|
PHANDLE ProcessHandle,
|
|
ACCESS_MASK DesiredAccess,
|
|
HANDLE ProcessId,
|
|
KPROCESSOR_MODE AccessMode)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ACCESS_STATE AccessState;
|
|
CHAR AuxData[0x200] = {0};
|
|
PEPROCESS ProcessObject = NULL;
|
|
HANDLE ProcHandle = NULL;
|
|
|
|
Status = SeCreateAccessState(
|
|
&AccessState,
|
|
AuxData,
|
|
DesiredAccess,
|
|
(PGENERIC_MAPPING)((PCHAR)*PsProcessType + 52));
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
AccessState.PreviouslyGrantedAccess |= AccessState.RemainingDesiredAccess;
|
|
AccessState.RemainingDesiredAccess = 0;
|
|
|
|
Status = PsLookupProcessByProcessId(ProcessId, &ProcessObject);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
SeDeleteAccessState(&AccessState);
|
|
return Status;
|
|
}
|
|
Status = ObOpenObjectByPointer(
|
|
ProcessObject,
|
|
0,
|
|
&AccessState,
|
|
0,
|
|
*PsProcessType,
|
|
AccessMode,
|
|
&ProcHandle);
|
|
|
|
SeDeleteAccessState(&AccessState);
|
|
|
|
ObDereferenceObject(ProcessObject);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
*ProcessHandle = ProcHandle;
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
* @brief Kill a user-mode process with different methods
|
|
* @param ProcessId
|
|
* @param KillingMethod
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
_Use_decl_annotations_
|
|
BOOLEAN
|
|
CommonKillProcess(UINT32 ProcessId, PROCESS_KILL_METHODS KillingMethod)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
HANDLE ProcessHandle = NULL;
|
|
PEPROCESS Process = NULL;
|
|
|
|
if (ProcessId == NULL_ZERO)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
switch (KillingMethod)
|
|
{
|
|
case PROCESS_KILL_METHOD_1:
|
|
|
|
Status = CommonGetHandleFromProcess(ProcessId, &ProcessHandle);
|
|
|
|
if (!NT_SUCCESS(Status) || ProcessHandle == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Call ZwTerminateProcess with NULL handle
|
|
//
|
|
Status = ZwTerminateProcess(ProcessHandle, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case PROCESS_KILL_METHOD_2:
|
|
|
|
CommonUndocumentedNtOpenProcess(
|
|
&ProcessHandle,
|
|
PROCESS_ALL_ACCESS,
|
|
(HANDLE)ProcessId,
|
|
KernelMode);
|
|
|
|
if (ProcessHandle == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Call ZwTerminateProcess with NULL handle
|
|
//
|
|
Status = ZwTerminateProcess(ProcessHandle, 0);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
break;
|
|
|
|
case PROCESS_KILL_METHOD_3:
|
|
|
|
//
|
|
// Get the base address of process's executable image and unmap it
|
|
//
|
|
Status = MmUnmapViewOfSection(Process, PsGetProcessSectionBaseAddress(Process));
|
|
|
|
//
|
|
// Dereference the target process
|
|
//
|
|
ObDereferenceObject(Process);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Unknown killing method
|
|
//
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// If we reached here, it means the functionality of
|
|
// the above codes was successful
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* @brief Validate core number
|
|
* @param CoreNumber
|
|
*
|
|
* @return BOOLEAN
|
|
*/
|
|
_Use_decl_annotations_
|
|
BOOLEAN
|
|
CommonValidateCoreNumber(UINT32 CoreNumber)
|
|
{
|
|
ULONG ProcessorsCount;
|
|
|
|
ProcessorsCount = KeQueryActiveProcessorCount(0);
|
|
|
|
if (CoreNumber >= ProcessorsCount)
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|