mirror of
https://github.com/HyperDbg/HyperDbg
synced 2026-08-15 06:29:09 -04:00
492 lines
15 KiB
C++
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);
|
|
}
|
|
}
|