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

558 lines
15 KiB
C++
Raw Normal View History

2020-07-28 05:10:27 -07:00
/**
* @file e.cpp
2022-01-18 22:38:56 +03:30
* @author Sina Karvandi (sina@hyperdbg.org)
2020-07-28 05:10:27 -07:00
* @brief e* command
* @details
* @version 0.1
* @date 2020-07-27
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
2020-07-28 05:10:27 -07:00
2021-05-07 02:56:34 +04:30
//
// Global Variables
//
extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee;
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 !e* and e* 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
CommandEditMemoryHelp()
{
2022-04-10 22:24:56 +04:30
ShowMessages("eb !eb ed !ed eq !eq : edits the memory at specific address \n");
ShowMessages("eb Byte and ASCII characters\n");
ShowMessages("ed Double-word values (4 bytes)\n");
ShowMessages("eq Quad-word values (8 bytes). \n");
2021-03-22 18:19:39 +04:30
ShowMessages("\n If you want to edit physical (address) memory then add '!' "
"at the start of the command\n");
ShowMessages("syntax : \teb [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n");
ShowMessages("syntax : \ted [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n");
ShowMessages("syntax : \teq [Address (hex)] [Contents (hex)] [pid ProcessId (hex)]\n");
ShowMessages("\n");
2021-03-22 18:19:39 +04:30
ShowMessages("\t\te.g : eb fffff8077356f010 90 \n");
2021-05-27 18:31:56 +04:30
ShowMessages("\t\te.g : eb nt!Kd_DEFAULT_Mask ff ff ff ff \n");
ShowMessages("\t\te.g : eb nt!Kd_DEFAULT_Mask+10+@rcx ff ff ff ff \n");
2021-03-22 18:19:39 +04:30
ShowMessages("\t\te.g : eb fffff8077356f010 90 90 90 90 \n");
ShowMessages("\t\te.g : !eq 100000 9090909090909090\n");
ShowMessages("\t\te.g : !eq nt!ExAllocatePoolWithTag+55 9090909090909090\n");
2021-03-22 18:19:39 +04:30
ShowMessages("\t\te.g : !eq 100000 9090909090909090 9090909090909090 "
"9090909090909090 9090909090909090 9090909090909090\n");
2020-07-28 05:10:27 -07:00
}
2024-07-10 18:36:11 +09:00
/**
* @brief Perform writing the memory content
*
* @param AddressToEdit
* @param MemoryType
* @param ByteSize
* @param Pid
* @param CountOf64Chunks
* @param BufferToEdit
*
* @return BOOLEAN
*/
BOOLEAN
WriteMemoryContent(UINT64 AddressToEdit,
DEBUGGER_EDIT_MEMORY_TYPE MemoryType,
DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize,
UINT32 Pid,
UINT32 CountOf64Chunks,
UINT64 * BufferToEdit)
{
2024-07-10 21:00:23 +09:00
BOOL Status;
DWORD BytesReturned;
2024-07-10 21:00:23 +09:00
BOOLEAN StatusReturn = FALSE;
DEBUGGER_EDIT_MEMORY * FinalBuffer;
DEBUGGER_EDIT_MEMORY EditMemoryRequest = {0};
UINT32 FinalSize = 0;
2024-07-10 18:36:11 +09:00
//
// Check if driver is loaded if it's in VMI mode
//
if (!g_IsSerialConnectedToRemoteDebuggee)
{
AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse);
}
//
// Fill the structure
//
EditMemoryRequest.ProcessId = Pid;
EditMemoryRequest.Address = AddressToEdit;
EditMemoryRequest.CountOf64Chunks = CountOf64Chunks;
EditMemoryRequest.MemoryType = MemoryType;
EditMemoryRequest.ByteSize = ByteSize;
//
// Now it's time to put everything together in one structure
//
FinalSize = (CountOf64Chunks * sizeof(UINT64)) + SIZEOF_DEBUGGER_EDIT_MEMORY;
//
// Set the size
//
EditMemoryRequest.FinalStructureSize = FinalSize;
//
// Allocate structure + buffer
//
2024-07-10 21:00:23 +09:00
FinalBuffer = (DEBUGGER_EDIT_MEMORY *)malloc(FinalSize);
2024-07-10 18:36:11 +09:00
if (!FinalBuffer)
{
ShowMessages("unable to allocate memory\n\n");
return FALSE;
}
//
// Zero the buffer
//
ZeroMemory(FinalBuffer, FinalSize);
//
// Copy the structure on top of the allocated buffer
//
2024-07-10 21:00:23 +09:00
memcpy((PVOID)FinalBuffer, &EditMemoryRequest, SIZEOF_DEBUGGER_EDIT_MEMORY);
2024-07-10 18:36:11 +09:00
//
// Copy the values to the buffer
//
memcpy((UINT64 *)((UINT64)FinalBuffer + SIZEOF_DEBUGGER_EDIT_MEMORY), BufferToEdit, (CountOf64Chunks * sizeof(UINT64)));
//
// send the request
//
if (g_IsSerialConnectedToRemoteDebuggee)
{
2024-07-10 21:00:23 +09:00
if (!KdSendEditMemoryPacketToDebuggee(FinalBuffer, FinalSize))
2024-07-10 18:36:11 +09:00
{
free(FinalBuffer);
return FALSE;
}
}
else
{
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_DEBUGGER_EDIT_MEMORY, // IO Control Code (IOCTL)
FinalBuffer, // Input Buffer to driver.
FinalSize, // Input buffer length
2024-07-10 21:00:23 +09:00
FinalBuffer, // Output Buffer from driver.
2024-07-10 18:36:11 +09:00
SIZEOF_DEBUGGER_EDIT_MEMORY, // Length of output buffer in bytes.
&BytesReturned, // Bytes placed in buffer.
2024-07-10 18:36:11 +09:00
NULL // synchronous call
);
if (!Status)
{
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
free(FinalBuffer);
return FALSE;
}
}
//
// Check the result
//
2024-07-10 21:00:23 +09:00
if (FinalBuffer->Result == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
2024-07-10 18:36:11 +09:00
{
//
// Was successful, nothing to do
//
free(FinalBuffer);
return TRUE;
}
else
{
2024-07-10 21:00:23 +09:00
ShowErrorMessage(FinalBuffer->Result);
2024-07-10 18:36:11 +09:00
free(FinalBuffer);
return FALSE;
}
}
/**
* @brief API function for writing the memory content
*
* @param AddressToEdit
* @param MemoryType
* @param ProcessId
* @param SourceAddress
* @param NumberOfBytes
*
* @return BOOLEAN
*/
BOOLEAN
2024-07-10 20:21:31 +09:00
HyperDbgWriteMemory(PVOID DestinationAddress,
DEBUGGER_EDIT_MEMORY_TYPE MemoryType,
UINT32 ProcessId,
PVOID SourceAddress,
UINT32 NumberOfBytes)
{
UINT32 RequiredBytes = 0;
DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize;
UINT64 * TargetBuffer;
UINT32 FinalSize = 0;
BOOLEAN Result = FALSE;
BYTE * BufferToEdit = (BYTE *)SourceAddress;
//
// Set the byte size to byte granularity
//
ByteSize = EDIT_BYTE;
//
// Calculate the count of 64 chunks
//
RequiredBytes = NumberOfBytes * sizeof(UINT64);
//
// Allocate structure + buffer
//
TargetBuffer = (UINT64 *)malloc(RequiredBytes);
if (!TargetBuffer)
{
return FALSE;
}
//
// Zero the buffer
//
ZeroMemory(TargetBuffer, FinalSize);
//
// Copy requested memory in 64bit chunks
//
for (SIZE_T i = 0; i < NumberOfBytes; i++)
{
TargetBuffer[i] = BufferToEdit[i];
}
//
// Perform the write operation
//
Result = WriteMemoryContent((UINT64)DestinationAddress,
MemoryType,
ByteSize,
ProcessId,
NumberOfBytes,
TargetBuffer);
//
// Free the malloc buffer
//
free(TargetBuffer);
return Result;
}
2020-08-28 04:03:12 -07:00
/**
* @brief !e* and e* commands handler
2021-02-10 15:19:01 -08:00
*
2024-07-29 19:40:24 +09:00
* @param CommandTokens
* @param Command
2024-07-29 19:40:24 +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
CommandEditMemory(vector<CommandToken> CommandTokens, string Command)
2021-03-22 18:19:39 +04:30
{
2024-07-10 18:36:11 +09:00
UINT64 Address;
UINT64 * FinalBuffer;
vector<UINT64> ValuesToEdit;
DEBUGGER_EDIT_MEMORY_TYPE MemoryType;
DEBUGGER_EDIT_MEMORY_BYTE_SIZE ByteSize;
2024-07-29 19:40:24 +09:00
BOOL SetAddress = FALSE;
BOOL SetValue = FALSE;
BOOL SetProcId = FALSE;
BOOL NextIsProcId = FALSE;
UINT64 Value = 0;
UINT32 ProcId = 0;
UINT32 CountOfValues = 0;
UINT32 FinalSize = 0;
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-29 19:40:24 +09:00
if (CommandTokens.size() <= 2)
2021-03-22 18:19:39 +04:30
{
ShowMessages("incorrect use of the '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
2020-07-28 05:10:27 -07:00
CommandEditMemoryHelp();
return;
}
2024-07-29 19:40:24 +09:00
for (auto Section : CommandTokens)
2021-03-22 18:19:39 +04:30
{
2023-07-24 01:22:28 +09:00
if (IsFirstCommand)
2021-03-22 18:19:39 +04:30
{
2024-07-29 19:40:24 +09:00
if (CompareLowerCaseStrings(Section, "!eb"))
2021-03-22 18:19:39 +04:30
{
2024-07-10 18:36:11 +09:00
MemoryType = EDIT_PHYSICAL_MEMORY;
ByteSize = EDIT_BYTE;
2021-03-22 18:19:39 +04:30
}
2024-07-29 19:40:24 +09:00
else if (CompareLowerCaseStrings(Section, "!ed"))
2021-03-22 18:19:39 +04:30
{
2024-07-10 18:36:11 +09:00
MemoryType = EDIT_PHYSICAL_MEMORY;
ByteSize = EDIT_DWORD;
2021-03-22 18:19:39 +04:30
}
2024-07-29 19:40:24 +09:00
else if (CompareLowerCaseStrings(Section, "!eq"))
2021-03-22 18:19:39 +04:30
{
2024-07-10 18:36:11 +09:00
MemoryType = EDIT_PHYSICAL_MEMORY;
ByteSize = EDIT_QWORD;
2021-03-22 18:19:39 +04:30
}
2024-07-29 19:40:24 +09:00
else if (CompareLowerCaseStrings(Section, "eb"))
2021-03-22 18:19:39 +04:30
{
2024-07-10 18:36:11 +09:00
MemoryType = EDIT_VIRTUAL_MEMORY;
ByteSize = EDIT_BYTE;
2021-03-22 18:19:39 +04:30
}
2024-07-29 19:40:24 +09:00
else if (CompareLowerCaseStrings(Section, "ed"))
2021-03-22 18:19:39 +04:30
{
2024-07-10 18:36:11 +09:00
MemoryType = EDIT_VIRTUAL_MEMORY;
ByteSize = EDIT_DWORD;
2021-03-22 18:19:39 +04:30
}
2024-07-29 19:40:24 +09:00
else if (CompareLowerCaseStrings(Section, "eq"))
2021-03-22 18:19:39 +04:30
{
2024-07-10 18:36:11 +09:00
MemoryType = EDIT_VIRTUAL_MEMORY;
ByteSize = EDIT_QWORD;
2021-03-22 18:19:39 +04:30
}
else
{
//
// What's this? :(
//
ShowMessages("unknown error happened !\n\n");
CommandEditMemoryHelp();
return;
}
2023-07-26 15:15:16 +09:00
IsFirstCommand = FALSE;
2021-03-22 18:19:39 +04:30
continue;
}
2022-10-06 17:45:07 +09:00
2021-03-22 18:19:39 +04:30
if (NextIsProcId)
{
//
// It's a process id
//
NextIsProcId = FALSE;
2024-07-29 19:40:24 +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
CommandEditMemoryHelp();
return;
}
else
{
//
// Means that the proc id is set, next we should read value
//
continue;
}
}
2021-05-07 02:56:34 +04:30
2020-07-28 05:10:27 -07:00
//
2021-03-22 18:19:39 +04:30
// Check if it's a process id or not
2020-07-28 05:10:27 -07:00
//
2024-07-29 19:40:24 +09:00
if (!SetProcId && CompareLowerCaseStrings(Section, "pid"))
2021-03-22 18:19:39 +04:30
{
NextIsProcId = TRUE;
continue;
}
if (!SetAddress)
{
2024-07-29 19:40:24 +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-29 19:40:24 +09:00
GetCaseSensitiveStringFromCommandToken(Section).c_str());
2021-03-22 18:19:39 +04:30
CommandEditMemoryHelp();
return;
}
else
{
//
// Means that the address is set, next we should read value
//
SetAddress = TRUE;
continue;
}
}
if (SetAddress)
{
//
// Remove the hex notations
//
2024-07-29 19:40:24 +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-29 19:40:24 +09:00
TargetVal = TargetVal.erase(0, 2);
2021-03-22 18:19:39 +04:30
}
2024-07-29 19:40:24 +09:00
else if (TargetVal.rfind('x', 0) == 0 || TargetVal.rfind('X', 0) == 0)
2021-03-22 18:19:39 +04:30
{
2024-07-29 19:40:24 +09:00
TargetVal = TargetVal.erase(0, 1);
2021-03-22 18:19:39 +04:30
}
2024-07-29 19:40:24 +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-29 19:40:24 +09:00
if (ByteSize == EDIT_BYTE && TargetVal.size() >= 3)
2021-03-22 18:19:39 +04:30
{
ShowMessages("please specify a byte (hex) value for 'eb' or '!eb'\n\n");
return;
}
2024-07-29 19:40:24 +09:00
if (ByteSize == EDIT_DWORD && TargetVal.size() >= 9)
2021-03-22 18:19:39 +04:30
{
ShowMessages(
"please specify a dword (hex) value for 'ed' or '!ed'\n\n");
return;
}
2024-07-29 19:40:24 +09:00
if (ByteSize == EDIT_QWORD && TargetVal.size() >= 17)
2021-03-22 18:19:39 +04:30
{
ShowMessages(
"please specify a qword (hex) value for 'eq' or '!eq'\n\n");
return;
}
//
// Qword is checked by the following function, no need to double
// check it above.
//
2024-07-29 19:40:24 +09:00
if (!ConvertStringToUInt64(TargetVal, &Value))
2021-03-22 18:19:39 +04:30
{
ShowMessages("please specify a correct hex value to change the memory "
"content\n\n");
CommandEditMemoryHelp();
return;
}
else
{
//
// Add it to the list
//
ValuesToEdit.push_back(Value);
//
// Keep track of values to modify
//
CountOfValues++;
if (!SetValue)
{
//
// At least on value is there
//
SetValue = TRUE;
}
continue;
}
}
2020-07-28 05:10:27 -07:00
}
2021-03-22 18:19:39 +04:30
2021-05-07 02:56:34 +04:30
//
// Check to prevent using process id in e* commands
//
if (g_IsSerialConnectedToRemoteDebuggee && ProcId != 0)
{
ShowMessages(ASSERT_MESSAGE_CANNOT_SPECIFY_PID);
2021-05-07 02:56:34 +04:30
return;
}
2024-07-10 21:00:23 +09:00
//
// Only valid for VMI Mode
//
2021-05-07 02:56:34 +04:30
if (ProcId == 0)
{
ProcId = GetCurrentProcessId();
}
2021-03-22 18:19:39 +04:30
//
// Check if address and value are set or not
//
if (!SetAddress)
{
ShowMessages("please specify a correct hex address\n\n");
2020-07-28 05:10:27 -07:00
CommandEditMemoryHelp();
return;
}
2021-03-22 18:19:39 +04:30
if (!SetValue)
{
2020-07-28 05:10:27 -07:00
ShowMessages(
2021-03-22 18:19:39 +04:30
"please specify a correct hex value as the content to edit\n\n");
CommandEditMemoryHelp();
2020-07-28 05:10:27 -07:00
return;
2021-03-22 18:19:39 +04:30
}
if (NextIsProcId)
{
ShowMessages("please specify a correct hex value as the process id\n\n");
2020-07-28 05:10:27 -07:00
CommandEditMemoryHelp();
return;
}
2021-03-22 18:19:39 +04:30
//
2024-07-10 18:36:11 +09:00
// Make the chunks for editing
2021-03-22 18:19:39 +04:30
//
2024-07-10 18:36:11 +09:00
FinalSize = (CountOfValues * sizeof(UINT64));
2020-07-28 05:10:27 -07:00
2021-03-22 18:19:39 +04:30
//
// Allocate structure + buffer
//
FinalBuffer = (UINT64 *)malloc(FinalSize);
2020-07-28 05:10:27 -07:00
2021-03-22 18:19:39 +04:30
if (!FinalBuffer)
{
ShowMessages("unable to allocate memory\n\n");
return;
}
2020-07-28 05:10:27 -07:00
2021-03-22 18:19:39 +04:30
//
// Zero the buffer
//
ZeroMemory(FinalBuffer, FinalSize);
2020-07-28 05:10:27 -07:00
2021-03-22 18:19:39 +04:30
//
// Put the values in 64 bit structures
//
2024-07-10 18:36:11 +09:00
std::copy(ValuesToEdit.begin(), ValuesToEdit.end(), FinalBuffer);
//
2024-07-10 18:36:11 +09:00
// Perform the write operation
//
2024-07-10 18:36:11 +09:00
WriteMemoryContent(Address,
MemoryType,
ByteSize,
ProcId,
CountOfValues,
FinalBuffer);
2020-08-28 04:03:12 -07:00
//
2021-03-22 18:19:39 +04:30
// Free the malloc buffer
//
2021-03-22 18:19:39 +04:30
free(FinalBuffer);
2020-07-28 05:10:27 -07:00
}