HyperDbg/hyperdbg/libhyperdbg/code/debugger/commands/debugging-commands/s.cpp

511 lines
15 KiB
C++
Raw Permalink Normal View History

/**
* @file s.cpp
2022-01-18 22:38:56 +03:30
* @author Sina Karvandi (sina@hyperdbg.org)
* @brief s* command
* @details
* @version 0.1
* @date 2020-07-29
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
2021-05-07 02:56:34 +04:30
//
// Global Variables
//
extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee;
extern BOOLEAN g_IsKdModuleLoaded;
extern ACTIVE_DEBUGGING_PROCESS g_ActiveProcessDebuggingState;
2021-05-07 02:56:34 +04:30
2020-08-28 04:03:12 -07:00
/**
* @brief help of !s* s* commands
2021-02-10 15:19:01 -08:00
*
* @return VOID
2020-08-28 04:03:12 -07:00
*/
2021-03-22 18:19:39 +04:30
VOID
CommandSearchMemoryHelp()
{
ShowMessages("sb !sb sd !sd sq !sq : searches a contiguous memory for a "
"special byte pattern\n");
ShowMessages("sb Byte and ASCII characters\n");
ShowMessages("sd Double-word values (4 bytes)\n");
ShowMessages("sq Quad-word values (8 bytes). \n");
2021-03-22 18:19:39 +04:30
ShowMessages(
"\n If you want to search in physical (address) memory then add '!' "
"at the start of the command\n");
ShowMessages("syntax : \tsb [StartAddress (hex)] [l Length (hex)] [BytePattern (hex)] [pid ProcessId (hex)]\n");
ShowMessages("syntax : \tsd [StartAddress (hex)] [l Length (hex)] [BytePattern (hex)] [pid ProcessId (hex)]\n");
ShowMessages("syntax : \tsq [StartAddress (hex)] [l Length (hex)] [BytePattern (hex)] [pid ProcessId (hex)]\n");
2021-03-22 18:19:39 +04:30
ShowMessages("\n");
ShowMessages("\t\te.g : sb nt!ExAllocatePoolWithTag 90 85 95 l ffff \n");
ShowMessages("\t\te.g : sb nt!ExAllocatePoolWithTag+5 90 85 95 l ffff \n");
ShowMessages("\t\te.g : sb @rcx+5 90 85 95 l ffff \n");
2021-03-22 18:19:39 +04:30
ShowMessages("\t\te.g : sb fffff8077356f010 90 85 95 l ffff \n");
ShowMessages("\t\te.g : sd fffff8077356f010 90423580 l ffff pid 1c0 \n");
ShowMessages("\t\te.g : !sq 100000 9090909090909090 l ffff\n");
ShowMessages("\t\te.g : !sq @rdx+r12 9090909090909090 l ffff\n");
2021-03-22 18:19:39 +04:30
ShowMessages("\t\te.g : !sq 100000 9090909090909090 9090909090909090 "
"9090909090909090 l ffffff\n");
}
/**
* @brief Send the request of search to the kernel
*
* @param BufferToSendAsIoctl
* @param BufferToSendAsIoctlSize
* @return VOID
*/
VOID
CommandSearchSendRequest(UINT64 * BufferToSendAsIoctl, UINT32 BufferToSendAsIoctlSize)
{
BOOL Status;
DWORD BytesReturned;
UINT64 CurrentValue;
PUINT64 ResultsBuffer = NULL;
//
// Allocate a buffer to store the results
//
ResultsBuffer = (PUINT64)malloc(MaximumSearchResults * sizeof(UINT64));
//
// Also it's better to Zero the memory; however it's not necessary
// as we zero the buffer in the search routines
//
PlatformZeroMemory(ResultsBuffer, MaximumSearchResults * sizeof(UINT64));
//
// Fire the IOCTL
//
Status =
PlatformDeviceIoControl(g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_SEARCH_MEMORY, // IO Control Code (IOCTL)
BufferToSendAsIoctl, // Input Buffer to driver.
BufferToSendAsIoctlSize, // Input buffer length
ResultsBuffer, // Output Buffer from driver.
MaximumSearchResults *
2024-07-30 16:55:06 +09:00
sizeof(UINT64), // Length of output buffer in bytes.
&BytesReturned, // Bytes placed in buffer.
2024-07-30 16:55:06 +09:00
NULL // synchronous call
);
if (!Status)
{
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
free(ResultsBuffer);
return;
}
//
// Show the results (if any)
//
for (SIZE_T i = 0; i < MaximumSearchResults; i++)
{
CurrentValue = ResultsBuffer[i];
if (CurrentValue == NULL)
{
//
// We ended up the buffer, nothing else to show,
// just check whether we found anything or not
//
if (i == 0)
{
ShowMessages("not found\n");
}
break;
}
ShowMessages("%llx\n", CurrentValue);
}
//
// Free buffer
//
free(ResultsBuffer);
}
2020-08-28 04:03:12 -07:00
/**
* @brief !s* s* commands handler
2021-02-10 15:19:01 -08:00
*
2024-07-30 16:55:06 +09:00
* @param CommandTokens
* @param Command
2024-07-30 16:55:06 +09:00
*
2021-02-10 15:19:01 -08:00
* @return VOID
2020-08-28 04:03:12 -07:00
*/
2021-03-22 18:19:39 +04:30
VOID
CommandSearchMemory(vector<CommandToken> CommandTokens, string Command)
2021-03-22 18:19:39 +04:30
{
2023-07-26 15:15:16 +09:00
UINT64 Address;
vector<UINT64> ValuesToEdit;
2021-03-22 18:19:39 +04:30
BOOL SetAddress = FALSE;
BOOL SetValue = FALSE;
BOOL SetProcId = FALSE;
BOOL NextIsProcId = FALSE;
BOOL SetLength = FALSE;
BOOL NextIsLength = FALSE;
DEBUGGER_SEARCH_MEMORY SearchMemoryRequest = {0};
2023-07-26 15:15:16 +09:00
UINT64 Value = 0;
UINT64 Length = 0;
UINT32 ProcId = 0;
UINT32 CountOfValues = 0;
UINT32 FinalSize = 0;
UINT64 * FinalBuffer = NULL;
2024-07-30 16:55:06 +09:00
BOOLEAN IsFirstCommand = TRUE;
2021-03-22 18:19:39 +04:30
//
// By default if the user-debugger is active, we use these commands
// on the memory layout of the debuggee process
//
if (g_ActiveProcessDebuggingState.IsActive)
{
ProcId = g_ActiveProcessDebuggingState.ProcessId;
}
2024-07-30 16:55:06 +09:00
if (CommandTokens.size() <= 4)
2021-03-22 18:19:39 +04:30
{
2024-07-30 16:55:06 +09:00
ShowMessages("incorrect use of the '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
CommandSearchMemoryHelp();
return;
}
2024-07-30 16:55:06 +09:00
for (auto Section : CommandTokens)
2021-03-22 18:19:39 +04:30
{
2023-07-26 15:15:16 +09:00
if (IsFirstCommand == TRUE)
2021-03-22 18:19:39 +04:30
{
2024-07-30 16:55:06 +09:00
std::string FirstCommand = GetLowerStringFromCommandToken(Section);
if (!FirstCommand.compare("!sb"))
2021-03-22 18:19:39 +04:30
{
SearchMemoryRequest.MemoryType = SEARCH_PHYSICAL_MEMORY;
SearchMemoryRequest.ByteSize = SEARCH_BYTE;
}
2024-07-30 16:55:06 +09:00
else if (!FirstCommand.compare("!sd"))
2021-03-22 18:19:39 +04:30
{
SearchMemoryRequest.MemoryType = SEARCH_PHYSICAL_MEMORY;
SearchMemoryRequest.ByteSize = SEARCH_DWORD;
}
2024-07-30 16:55:06 +09:00
else if (!FirstCommand.compare("!sq"))
2021-03-22 18:19:39 +04:30
{
SearchMemoryRequest.MemoryType = SEARCH_PHYSICAL_MEMORY;
SearchMemoryRequest.ByteSize = SEARCH_QWORD;
}
2024-07-30 16:55:06 +09:00
else if (!FirstCommand.compare("sb"))
2021-03-22 18:19:39 +04:30
{
SearchMemoryRequest.MemoryType = SEARCH_VIRTUAL_MEMORY;
SearchMemoryRequest.ByteSize = SEARCH_BYTE;
}
2024-07-30 16:55:06 +09:00
else if (!FirstCommand.compare("sd"))
2021-03-22 18:19:39 +04:30
{
SearchMemoryRequest.MemoryType = SEARCH_VIRTUAL_MEMORY;
SearchMemoryRequest.ByteSize = SEARCH_DWORD;
}
2024-07-30 16:55:06 +09:00
else if (!FirstCommand.compare("sq"))
2021-03-22 18:19:39 +04:30
{
SearchMemoryRequest.MemoryType = SEARCH_VIRTUAL_MEMORY;
SearchMemoryRequest.ByteSize = SEARCH_QWORD;
}
else
{
//
// What's this? :(
//
2024-07-30 16:55:06 +09:00
ShowMessages("unknown error happened!\n\n");
2021-03-22 18:19:39 +04:30
CommandSearchMemoryHelp();
return;
}
2023-07-26 15:15:16 +09:00
IsFirstCommand = FALSE;
2021-03-22 18:19:39 +04:30
continue;
}
2021-03-22 18:19:39 +04:30
if (NextIsProcId)
{
//
// It's a process id
//
NextIsProcId = FALSE;
2024-07-30 16:55:06 +09:00
if (!ConvertTokenToUInt32(Section, &ProcId))
2021-03-22 18:19:39 +04:30
{
2024-03-17 01:01:22 +09:00
ShowMessages("please specify a correct hex process id\n\n");
2021-03-22 18:19:39 +04:30
CommandSearchMemoryHelp();
return;
}
else
{
//
// Means that the proc id is set, next we should read value
//
continue;
}
}
2021-03-22 18:19:39 +04:30
if (NextIsLength)
{
//
// It's a length
//
NextIsLength = FALSE;
2024-07-30 16:55:06 +09:00
if (!ConvertTokenToUInt64(Section, &Length))
2021-03-22 18:19:39 +04:30
{
ShowMessages("please specify a correct hex length\n\n");
CommandSearchMemoryHelp();
return;
}
else
{
//
// Means that the proc id is set, next we should read value
//
SetLength = TRUE;
continue;
}
}
2020-08-28 04:03:12 -07:00
//
2021-03-22 18:19:39 +04:30
// Check if it's a process id or not
//
2024-07-30 16:55:06 +09:00
if (!SetProcId && CompareLowerCaseStrings(Section, "pid"))
2021-03-22 18:19:39 +04:30
{
NextIsProcId = TRUE;
continue;
}
2020-08-28 04:03:12 -07:00
//
2021-03-22 18:19:39 +04:30
// Check if it's a length or not
//
2024-07-30 16:55:06 +09:00
if (!SetLength && CompareLowerCaseStrings(Section, "l"))
2021-03-22 18:19:39 +04:30
{
NextIsLength = TRUE;
continue;
}
if (!SetAddress)
{
2024-07-30 16:55:06 +09:00
if (!SymbolConvertNameOrExprToAddress(GetCaseSensitiveStringFromCommandToken(Section), &Address))
2021-03-22 18:19:39 +04:30
{
ShowMessages("err, couldn't resolve error at '%s'\n\n",
2024-07-30 16:55:06 +09:00
GetCaseSensitiveStringFromCommandToken(Section).c_str());
2021-03-22 18:19:39 +04:30
CommandSearchMemoryHelp();
return;
}
else
{
//
// Means that the address is set, next we should read value
//
SetAddress = TRUE;
continue;
}
}
if (SetAddress)
{
//
// Remove the hex notations
//
2024-07-30 16:55:06 +09:00
std::string TargetVal = GetCaseSensitiveStringFromCommandToken(Section);
if (TargetVal.rfind("0x", 0) == 0 || TargetVal.rfind("0X", 0) == 0 ||
TargetVal.rfind("\\x", 0) == 0 || TargetVal.rfind("\\X", 0) == 0)
2021-03-22 18:19:39 +04:30
{
2024-07-30 16:55:06 +09:00
TargetVal = TargetVal.erase(0, 2);
2021-03-22 18:19:39 +04:30
}
2024-07-30 16:55:06 +09:00
else if (TargetVal.rfind('x', 0) == 0 || TargetVal.rfind('X', 0) == 0)
2021-03-22 18:19:39 +04:30
{
2024-07-30 16:55:06 +09:00
TargetVal = TargetVal.erase(0, 1);
2021-03-22 18:19:39 +04:30
}
2024-07-30 16:55:06 +09:00
TargetVal.erase(remove(TargetVal.begin(), TargetVal.end(), '`'), TargetVal.end());
2021-03-22 18:19:39 +04:30
//
// Check if the value is valid based on byte counts
//
2024-07-30 16:55:06 +09:00
if (SearchMemoryRequest.ByteSize == SEARCH_BYTE && TargetVal.size() >= 3)
2021-03-22 18:19:39 +04:30
{
ShowMessages("please specify a byte (hex) value for 'sb' or '!sb'\n\n");
return;
}
2024-07-30 16:55:06 +09:00
if (SearchMemoryRequest.ByteSize == SEARCH_DWORD && TargetVal.size() >= 9)
2021-03-22 18:19:39 +04:30
{
2024-07-30 16:55:06 +09:00
ShowMessages("please specify a dword (hex) value for 'sd' or '!sd'\n\n");
2021-03-22 18:19:39 +04:30
return;
}
2024-07-30 16:55:06 +09:00
if (SearchMemoryRequest.ByteSize == SEARCH_QWORD && TargetVal.size() >= 17)
2021-03-22 18:19:39 +04:30
{
2024-07-30 16:55:06 +09:00
ShowMessages("please specify a qword (hex) value for 'sq' or '!sq'\n\n");
2021-03-22 18:19:39 +04:30
return;
}
//
// Qword is checked by the following function, no need to double
// check it above.
//
2024-07-30 16:55:06 +09:00
if (!ConvertStringToUInt64(TargetVal, &Value))
2021-03-22 18:19:39 +04:30
{
ShowMessages("please specify a correct hex value to search in the "
"memory content\n\n");
CommandSearchMemoryHelp();
return;
}
else
{
//
// Add it to the list
//
ValuesToEdit.push_back(Value);
//
// Keep track of values to modify
//
CountOfValues++;
if (!SetValue)
{
//
// At least one value is there
2021-03-22 18:19:39 +04:30
//
SetValue = TRUE;
}
continue;
}
}
}
2021-05-07 02:56:34 +04:30
//
// Check to prevent using process id in s* commands
//
if (g_IsSerialConnectedToRemoteDebuggee && ProcId != 0)
{
ShowMessages(ASSERT_MESSAGE_CANNOT_SPECIFY_PID);
2021-05-07 02:56:34 +04:30
return;
}
if (ProcId == 0)
{
ProcId = PlatformGetCurrentProcessId();
2021-05-07 02:56:34 +04:30
}
//
2021-03-22 18:19:39 +04:30
// Fill the structure
//
2021-03-22 18:19:39 +04:30
SearchMemoryRequest.ProcessId = ProcId;
SearchMemoryRequest.Address = Address;
SearchMemoryRequest.CountOf64Chunks = CountOfValues;
//
2021-03-22 18:19:39 +04:30
// Check if address and value are set or not
//
2021-03-22 18:19:39 +04:30
if (!SetAddress)
{
ShowMessages("please specify a correct hex address\n\n");
CommandSearchMemoryHelp();
return;
}
2021-03-22 18:19:39 +04:30
if (!SetValue)
{
ShowMessages(
2021-03-22 18:19:39 +04:30
"please specify a correct hex value as the content to search\n\n");
CommandSearchMemoryHelp();
return;
2021-03-22 18:19:39 +04:30
}
if (!SetLength)
{
ShowMessages("please specify a correct hex value as the length\n\n");
CommandSearchMemoryHelp();
return;
2021-03-22 18:19:39 +04:30
}
if (NextIsProcId)
{
ShowMessages("please specify a correct hex value as the process id\n\n");
CommandSearchMemoryHelp();
return;
2021-03-22 18:19:39 +04:30
}
if (NextIsLength)
{
ShowMessages("please specify a correct hex length\n\n");
CommandSearchMemoryHelp();
return;
}
2021-03-22 18:19:39 +04:30
//
// Now it's time to put everything together in one structure
//
FinalSize = (CountOfValues * sizeof(UINT64)) + SIZEOF_DEBUGGER_SEARCH_MEMORY;
//
// Set the size
//
SearchMemoryRequest.FinalStructureSize = FinalSize;
//
// Set the length
//
SearchMemoryRequest.Length = Length;
if (!g_IsSerialConnectedToRemoteDebuggee)
{
AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn);
}
2021-03-22 18:19:39 +04:30
//
// Allocate structure + buffer
//
FinalBuffer = (UINT64 *)malloc(FinalSize);
if (!FinalBuffer)
{
ShowMessages("unable to allocate memory\n\n");
return;
}
//
// Zero the buffer
//
PlatformZeroMemory(FinalBuffer, FinalSize);
2021-03-22 18:19:39 +04:30
//
// Copy the structure on top of the allocated buffer
//
memcpy(FinalBuffer, &SearchMemoryRequest, SIZEOF_DEBUGGER_SEARCH_MEMORY);
//
// Put the values in 64 bit structures
//
std::copy(ValuesToEdit.begin(), ValuesToEdit.end(), (UINT64 *)((UINT64)FinalBuffer + SIZEOF_DEBUGGER_SEARCH_MEMORY));
//
// Check if it's a connection in debugger mode
2021-03-22 18:19:39 +04:30
//
if (g_IsSerialConnectedToRemoteDebuggee)
2021-03-22 18:19:39 +04:30
{
//
// The buffer should be sent to the debugger
//
KdSendSearchRequestPacketToDebuggee(FinalBuffer, FinalSize);
2021-03-22 18:19:39 +04:30
}
else
2021-03-22 18:19:39 +04:30
{
//
// it's a local connection, send the buffer directly
//
CommandSearchSendRequest(FinalBuffer, FinalSize);
}
2021-03-22 18:19:39 +04:30
//
// Free the buffers
//
2020-08-28 04:03:12 -07:00
free(FinalBuffer);
}