HyperDbg/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/hide.cpp
2026-07-20 12:27:14 +02:00

492 lines
15 KiB
C++

/**
* @file hide.cpp
* @author Sina Karvandi (sina@hyperdbg.org)
* @author jtaw5649
* @brief !hide command
* @details
* @version 0.1
* @date 2020-07-07
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_IsVmmModuleLoaded;
extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState;
/**
* @brief help of the !hide command
*
* @return VOID
*/
VOID
CommandHideHelp()
{
ShowMessages("!hide : tries to make HyperDbg transparent from anti-debugging "
"and anti-hypervisor methods.\n\n");
ShowMessages("syntax : \t!hide\n");
ShowMessages("syntax : \t!hide [pid ProcessId (hex)]\n");
ShowMessages("syntax : \t!hide [name ProcessName (string)]\n");
ShowMessages("note : \tprocess names are case sensitive and you can use "
"this command multiple times.\n");
ShowMessages("\n");
ShowMessages("\t\te.g : !hide\n");
ShowMessages("\t\te.g : !hide pid b60 \n");
ShowMessages("\t\te.g : !hide name procexp.exe\n");
}
/**
* @brief This function is called when the user wants to hide the fill system calls
* in the transparent mode based on current system call numbers
*
* @param SyscallNumberDetails
* @return BOOLEAN
*/
BOOLEAN
CommandHideFillSystemCalls(SYSTEM_CALL_NUMBERS_INFORMATION * SyscallNumberDetails)
{
BOOLEAN Result = TRUE;
//
// Get the syscall number of NtQuerySystemInformation
//
SyscallNumberDetails->SysNtQuerySystemInformation = PeGetSyscallNumber("NtQuerySystemInformation");
if (SyscallNumberDetails->SysNtQuerySystemInformation == 0)
{
ShowMessages("warning, failed to get NtQuerySystemInformation syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtQuerySystemInformationEx
//
SyscallNumberDetails->SysNtQuerySystemInformationEx = PeGetSyscallNumber("NtQuerySystemInformationEx");
if (SyscallNumberDetails->SysNtQuerySystemInformationEx == 0)
{
ShowMessages("warning, failed to get NtQuerySystemInformationEx syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtSystemDebugControl
//
SyscallNumberDetails->SysNtSystemDebugControl = PeGetSyscallNumber("NtSystemDebugControl");
if (SyscallNumberDetails->SysNtSystemDebugControl == 0)
{
ShowMessages("warning, failed to get NtSystemDebugControl syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtQueryAttributesFile
//
SyscallNumberDetails->SysNtQueryAttributesFile = PeGetSyscallNumber("NtQueryAttributesFile");
if (SyscallNumberDetails->SysNtQueryAttributesFile == 0)
{
ShowMessages("warning, failed to get NtQueryAttributesFile syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtOpenDirectoryObject
//
SyscallNumberDetails->SysNtOpenDirectoryObject = PeGetSyscallNumber("NtOpenDirectoryObject");
if (SyscallNumberDetails->SysNtOpenDirectoryObject == 0)
{
ShowMessages("warning, failed to get NtOpenDirectoryObject syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtQueryDirectoryObject
//
SyscallNumberDetails->SysNtQueryDirectoryObject = PeGetSyscallNumber("NtQueryDirectoryObject");
if (SyscallNumberDetails->SysNtQueryDirectoryObject == 0)
{
ShowMessages("warning, failed to get NtQueryDirectoryObject syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtQueryInformationProcess
//
SyscallNumberDetails->SysNtQueryInformationProcess = PeGetSyscallNumber("NtQueryInformationProcess");
if (SyscallNumberDetails->SysNtQueryInformationProcess == 0)
{
ShowMessages("warning, failed to get NtQueryInformationProcess syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtSetInformationProcess
//
SyscallNumberDetails->SysNtSetInformationProcess = PeGetSyscallNumber("NtSetInformationProcess");
if (SyscallNumberDetails->SysNtSetInformationProcess == 0)
{
ShowMessages("warning, failed to get NtSetInformationProcess syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtQueryInformationThread
//
SyscallNumberDetails->SysNtQueryInformationThread = PeGetSyscallNumber("NtQueryInformationThread");
if (SyscallNumberDetails->SysNtQueryInformationThread == 0)
{
ShowMessages("warning, failed to get NtQueryInformationThread syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtSetInformationThread
//
SyscallNumberDetails->SysNtSetInformationThread = PeGetSyscallNumber("NtSetInformationThread");
if (SyscallNumberDetails->SysNtSetInformationThread == 0)
{
ShowMessages("warning, failed to get NtSetInformationThread syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtOpenFile
//
SyscallNumberDetails->SysNtOpenFile = PeGetSyscallNumber("NtOpenFile");
if (SyscallNumberDetails->SysNtOpenFile == 0)
{
ShowMessages("warning, failed to get NtOpenFile syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtOpenKey
//
SyscallNumberDetails->SysNtOpenKey = PeGetSyscallNumber("NtOpenKey");
if (SyscallNumberDetails->SysNtOpenKey == 0)
{
ShowMessages("warning, failed to get NtOpenKey syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtOpenKeyEx
//
SyscallNumberDetails->SysNtOpenKeyEx = PeGetSyscallNumber("NtOpenKeyEx");
if (SyscallNumberDetails->SysNtOpenKeyEx == 0)
{
ShowMessages("warning, failed to get NtOpenKeyEx syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtQueryValueKey
//
SyscallNumberDetails->SysNtQueryValueKey = PeGetSyscallNumber("NtQueryValueKey");
if (SyscallNumberDetails->SysNtQueryValueKey == 0)
{
ShowMessages("warning, failed to get NtQueryValueKey syscall number for transparent-mode\n");
Result = FALSE;
}
//
// Get the syscall number of NtEnumerateKey
//
SyscallNumberDetails->SysNtEnumerateKey = PeGetSyscallNumber("NtEnumerateKey");
if (SyscallNumberDetails->SysNtEnumerateKey == 0)
{
ShowMessages("warning, failed to get NtEnumerateKey syscall number for transparent-mode\n");
Result = FALSE;
}
return Result;
}
/**
* @brief Enable transparent mode
* @param ProcessId
* @param ProcessName
* @param IsProcessId
* @param EvadeMask
*
* @return BOOLEAN
*/
BOOLEAN
HyperDbgEnableTransparentModeEx(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId, UINT32 EvadeMask)
{
BOOLEAN Status;
ULONG ReturnedLength;
DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE HideRequest = {0};
PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE FinalRequestBuffer = 0;
SIZE_T RequestBufferSize = 0;
UINT32 EffectiveEvadeMask = EvadeMask == 0 ? TRANSPARENT_EVADE_MASK_DEFAULT : EvadeMask;
//
// Check if debugger is loaded or not
//
// AssertShowMessageReturnStmt(g_IsVmmModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_VMM_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse);
//
// We wanna hide the debugger and make transparent vm-exits
//
if ((EffectiveEvadeMask & ~TRANSPARENT_EVADE_MASK_ALL) != 0)
{
ShowMessages("unknown transparent-mode evade mask bits\n");
return FALSE;
}
HideRequest.IsHide = TRUE;
HideRequest.EvadeMask = EffectiveEvadeMask;
HideRequest.TrueIfProcessIdAndFalseIfProcessName = IsProcessId;
if (IsProcessId)
{
//
// It's a process id
//
HideRequest.ProcId = (UINT32)ProcessId;
RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE);
}
else
{
//
// It's a process name
//
HideRequest.LengthOfProcessName = (UINT32)strlen(ProcessName) + 1;
RequestBufferSize = sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE) + HideRequest.LengthOfProcessName;
}
if ((EffectiveEvadeMask & TRANSPARENT_EVADE_MASK_SYSCALL_HOOK) != 0 &&
!CommandHideFillSystemCalls(&HideRequest.SystemCallNumbersInformation))
{
ShowMessages("warning, failed to resolve one or more syscall numbers for transparent-mode\n");
return FALSE;
}
//
// Allocate the requested buffer
//
FinalRequestBuffer = (PDEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE)malloc(RequestBufferSize);
if (FinalRequestBuffer == NULL)
{
ShowMessages("insufficient space\n");
return FALSE;
}
//
// Zero the memory
//
PlatformZeroMemory(FinalRequestBuffer, RequestBufferSize);
//
// Copy the buffer on the top of the final buffer
// to send the kernel
//
memcpy(FinalRequestBuffer, &HideRequest, sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE));
//
// If it's a name then we should add it to the end of the buffer
//
if (!IsProcessId)
{
CHAR * ProcName = ProcessName;
memcpy(((UINT64 *)((UINT64)FinalRequestBuffer + sizeof(DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE))),
ProcName,
HideRequest.LengthOfProcessName);
}
//
// Send the request to the kernel
//
Status = PlatformDeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_HIDE_AND_UNHIDE_TO_TRANSPARENT_THE_DEBUGGER, // IO Control
// code
FinalRequestBuffer, // Input Buffer to driver.
(DWORD)RequestBufferSize, // Input buffer length
FinalRequestBuffer, // Output Buffer from driver.
SIZEOF_DEBUGGER_HIDE_AND_TRANSPARENT_DEBUGGER_MODE, // Length of output
// buffer in bytes.
&ReturnedLength, // Bytes placed in buffer.
NULL // synchronous call
);
if (!Status)
{
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
free(FinalRequestBuffer);
return FALSE;
}
if (FinalRequestBuffer->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
{
ShowMessages("transparent debugging successfully enabled :)\n");
}
else if (FinalRequestBuffer->KernelStatus == DEBUGGER_ERROR_UNABLE_TO_HIDE_OR_UNHIDE_DEBUGGER)
{
ShowMessages("unable to hide the debugger (transparent-debugging) :(\n");
free(FinalRequestBuffer);
return FALSE;
}
else
{
ShowMessages("unknown error occurred :(\n");
free(FinalRequestBuffer);
return FALSE;
}
//
// free the buffer
//
free(FinalRequestBuffer);
//
// It means the transparent mode enabled successfully
//
return TRUE;
}
/**
* @brief Enable transparent mode
* @param ProcessId
* @param ProcessName
* @param IsProcessId
*
* @return BOOLEAN
*/
BOOLEAN
HyperDbgEnableTransparentMode(UINT32 ProcessId, CHAR * ProcessName, BOOLEAN IsProcessId)
{
return HyperDbgEnableTransparentModeEx(ProcessId, ProcessName, IsProcessId, 0);
}
/**
* @brief !hide command handler
*
* @param CommandTokens
* @param Command
* @return VOID
*/
VOID
CommandHide(vector<CommandToken> CommandTokens, string Command)
{
UINT32 TargetPid;
BOOLEAN TrueIfProcessIdAndFalseIfProcessName;
#if ActivateHyperEvadeProject != TRUE
ShowMessages("warning, the !hide command (hyperevade project) is in the Beta phase and is not yet well-tested, "
"so it is disabled in this version. If you want to test, you can enable it "
"from the configuration file (set ActivateHyperEvadeProject to TRUE) and recompile HyperDbg\n\n");
return;
#endif
if (CommandTokens.size() != 1 && CommandTokens.size() != 3)
{
ShowMessages("incorrect use of the '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
CommandHideHelp();
return;
}
//
// Find out whether the user enters pid or name
//
if (CommandTokens.size() == 1)
{
if (g_ActiveProcessDebuggingState.IsActive)
{
TrueIfProcessIdAndFalseIfProcessName = TRUE;
TargetPid = g_ActiveProcessDebuggingState.ProcessId;
}
else
{
//
// There is no user-debugging process
//
ShowMessages("you're not attached to any user-mode process, "
"please explicitly specify the process id or process name\n\n");
CommandHideHelp();
return;
}
}
else if (CompareLowerCaseStrings(CommandTokens.at(1), "pid"))
{
TrueIfProcessIdAndFalseIfProcessName = TRUE;
//
// Check for the user to not add extra arguments
//
if (CommandTokens.size() != 3)
{
ShowMessages("incorrect use of the '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
CommandHideHelp();
return;
}
//
// It's just a pid for the process
//
if (!ConvertTokenToUInt32(CommandTokens.at(2), &TargetPid))
{
ShowMessages("incorrect process id\n\n");
return;
}
}
else if (CompareLowerCaseStrings(CommandTokens.at(1), "name"))
{
TrueIfProcessIdAndFalseIfProcessName = FALSE;
}
else
{
//
// Invalid argument for the second parameter to the command
//
ShowMessages("incorrect use of the '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
CommandHideHelp();
return;
}
//
// Enable the transparent mode
//
if (TrueIfProcessIdAndFalseIfProcessName)
{
HyperDbgEnableTransparentMode(TargetPid,
NULL,
TRUE);
}
else
{
HyperDbgEnableTransparentMode(NULL,
(CHAR *)GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str(),
FALSE);
}
}