mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-10-19 01:59:00 +00:00
Merge pull request #671 from nikzad66/uin-uout-commands
Uin uout commands
This commit is contained in:
commit
80f224fa58
24 changed files with 1128 additions and 13 deletions
|
|
@ -29,4 +29,5 @@ Just so you know – the attributions listed on this credits page are acknowledg
|
|||
- unrustled.jimmies for helping us debug and fix issues, and his contributions in HyperDbg
|
||||
- Hari Mishal ([@harimishal1](https://github.com/harimishal1)) for his works on the hypertrace project for supporting Last Branch Record (LBR)
|
||||
- Masoud Rahimi Jafari ([@masoudrahimi01](https://github.com/masoudrahimi01)) for his works on the hypertrace project for supporting Intel Processor Trace (PT)
|
||||
- Abolfazl Hassani ([@FallinBinary](https://github.com/FallinBinary)) for his contributions in HyperDbg
|
||||
- Abolfazl Hassani ([@FallinBinary](https://github.com/FallinBinary)) for his contributions in HyperDbg
|
||||
- Hossein Shirdel ([@nikzad66](https://github.com/nikzad66)) for his contributions in HyperDbg
|
||||
|
|
@ -1529,6 +1529,104 @@ DebuggerCommandCpuid(PDEBUGGER_CPUID_REQUEST_RESPONSE DebuggerCpuidRequest)
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle User IN request in vmx-root mode
|
||||
*
|
||||
* @param DebuggerUserInRequest perform IN instruction (user specified)
|
||||
* @return NTSTATUS
|
||||
*/
|
||||
NTSTATUS
|
||||
DebuggerCommandUserIn(PDEBUGGER_USER_IN_REQUEST_RESPONSE DebuggerUserInRequest)
|
||||
{
|
||||
SHORT Register = DebuggerUserInRequest->UserChosenRegister;
|
||||
USHORT Port = DebuggerUserInRequest->PortAddress;
|
||||
|
||||
//
|
||||
// Zero out memory buffer
|
||||
//
|
||||
RtlZeroMemory(DebuggerUserInRequest, SIZEOF_DEBUGGER_USER_IN_REQUEST_RESPONSE);
|
||||
|
||||
//
|
||||
// we're already in kernel mode, so there is no need to check for CPL and IOPL, TSS and etc.
|
||||
//
|
||||
|
||||
//
|
||||
// handle I/O instructions
|
||||
//
|
||||
switch (Register)
|
||||
{
|
||||
//
|
||||
// store the results in the Data field
|
||||
//
|
||||
case AL_8_BIT_REGISTER:
|
||||
DebuggerUserInRequest->Data = CpuIoInByte(Port);
|
||||
|
||||
break;
|
||||
|
||||
case AX_16_BIT_REGISTER:
|
||||
DebuggerUserInRequest->Data = CpuIoInWord(Port);
|
||||
|
||||
break;
|
||||
|
||||
case EAX_32_BIT_REGISTER:
|
||||
DebuggerUserInRequest->Data = CpuIoInDword(Port);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
DebuggerUserInRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle User OUT request in vmx-root mode
|
||||
*
|
||||
* @param DebuggerUserInRequest perform OUT instruction (user specified)
|
||||
* @return NTSTATUS
|
||||
*/
|
||||
NTSTATUS
|
||||
DebuggerCommandUserOut(PDEBUGGER_USER_OUT_REQUEST_RESPONSE DebuggerUserOutRequest)
|
||||
{
|
||||
SHORT Register = DebuggerUserOutRequest->UserChosenRegister;
|
||||
USHORT Port = DebuggerUserOutRequest->PortAddress;
|
||||
UINT32 Value = DebuggerUserOutRequest->Value;
|
||||
|
||||
//
|
||||
// Zero out memory buffer
|
||||
//
|
||||
RtlZeroMemory(DebuggerUserOutRequest, SIZEOF_DEBUGGER_USER_OUT_REQUEST_RESPONSE);
|
||||
|
||||
//
|
||||
// we're already in kernel mode, so there is no need to check for CPL and IOPL, TSS and etc.
|
||||
//
|
||||
|
||||
//
|
||||
// handle I/O instructions
|
||||
//
|
||||
switch (Register)
|
||||
{
|
||||
case AL_8_BIT_REGISTER:
|
||||
__outbyte(Port, (UCHAR)Value);
|
||||
|
||||
break;
|
||||
|
||||
case AX_16_BIT_REGISTER:
|
||||
__outword(Port, (USHORT)Value);
|
||||
|
||||
break;
|
||||
|
||||
case EAX_32_BIT_REGISTER:
|
||||
__outdword(Port, Value);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
DebuggerUserOutRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform the command finished signal
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2261,6 +2261,8 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
PDEBUGGEE_STEP_PACKET SteppingPacket;
|
||||
PDEBUGGER_FLUSH_LOGGING_BUFFERS FlushPacket;
|
||||
PDEBUGGER_CPUID_REQUEST_RESPONSE CpuidPacket;
|
||||
PDEBUGGER_USER_IN_REQUEST_RESPONSE InPacket;
|
||||
PDEBUGGER_USER_OUT_REQUEST_RESPONSE OutPacket;
|
||||
PDEBUGGER_CALLSTACK_REQUEST CallstackPacket;
|
||||
PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFrameBuffer;
|
||||
PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket;
|
||||
|
|
@ -2552,6 +2554,44 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState)
|
|||
|
||||
break;
|
||||
|
||||
case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_USER_IN_INSTRUCTION:
|
||||
|
||||
InPacket = (DEBUGGER_USER_IN_REQUEST_RESPONSE *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET));
|
||||
|
||||
//
|
||||
// Receieve IN instruction result
|
||||
//
|
||||
DebuggerCommandUserIn(InPacket);
|
||||
|
||||
//
|
||||
// Send the result of IN instruction back to the debugger
|
||||
//
|
||||
KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_USER_IN_INSTRUCTION,
|
||||
(CHAR *)InPacket,
|
||||
sizeof(DEBUGGER_USER_IN_REQUEST_RESPONSE));
|
||||
|
||||
break;
|
||||
|
||||
case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_USER_OUT_INSTRUCTION:
|
||||
|
||||
OutPacket = (DEBUGGER_USER_OUT_REQUEST_RESPONSE *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET));
|
||||
|
||||
//
|
||||
// Receieve OUT instruction result
|
||||
//
|
||||
DebuggerCommandUserOut(OutPacket);
|
||||
|
||||
//
|
||||
// Send the result of OUT instruction back to the debugger
|
||||
//
|
||||
KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_USER_OUT_INSTRUCTION,
|
||||
(CHAR *)OutPacket,
|
||||
sizeof(DEBUGGER_USER_OUT_REQUEST_RESPONSE));
|
||||
|
||||
break;
|
||||
|
||||
case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_CALLSTACK:
|
||||
|
||||
CallstackPacket = (DEBUGGER_CALLSTACK_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET));
|
||||
|
|
|
|||
|
|
@ -411,6 +411,8 @@ DrvDispatchVmmIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotCh
|
|||
PDEBUGGER_MODIFY_EVENTS DebuggerModifyEventRequest;
|
||||
PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest;
|
||||
PDEBUGGER_CPUID_REQUEST_RESPONSE DebuggerCpuidRequest;
|
||||
PDEBUGGER_USER_IN_REQUEST_RESPONSE DebuggerUserInRequest;
|
||||
PDEBUGGER_USER_OUT_REQUEST_RESPONSE DebuggerUserOutRequest;
|
||||
PDEBUGGER_PREALLOC_COMMAND DebuggerReservePreallocPoolRequest;
|
||||
PDEBUGGER_PREACTIVATE_COMMAND DebuggerPreactivationRequest;
|
||||
PDEBUGGER_APIC_REQUEST DebuggerApicRequest;
|
||||
|
|
@ -864,6 +866,62 @@ DrvDispatchVmmIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN * DoNotCh
|
|||
|
||||
break;
|
||||
|
||||
case IOCTL_DEBUGGER_USER_IN:
|
||||
|
||||
//
|
||||
// Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP
|
||||
//
|
||||
if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_USER_IN_REQUEST_RESPONSE,
|
||||
(PVOID *)&DebuggerUserInRequest,
|
||||
Irp,
|
||||
IrpStack,
|
||||
&InBuffLength,
|
||||
&OutBuffLength))
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Perform IN instruction
|
||||
//
|
||||
DebuggerCommandUserIn(DebuggerUserInRequest);
|
||||
|
||||
//
|
||||
// Adjust the status and output size
|
||||
//
|
||||
DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_USER_IN_REQUEST_RESPONSE, DoNotChangeInformation, Irp, &Status);
|
||||
|
||||
break;
|
||||
|
||||
case IOCTL_DEBUGGER_USER_OUT:
|
||||
|
||||
//
|
||||
// Validate and adjust the parameters, and set the target buffer to the system buffer of the IRP
|
||||
//
|
||||
if (!DrvValidateAndAdjustIoctlParameter(SIZEOF_DEBUGGER_USER_OUT_REQUEST_RESPONSE,
|
||||
(PVOID *)&DebuggerUserOutRequest,
|
||||
Irp,
|
||||
IrpStack,
|
||||
&InBuffLength,
|
||||
&OutBuffLength))
|
||||
{
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Perform OUT instruction
|
||||
//
|
||||
DebuggerCommandUserOut(DebuggerUserOutRequest);
|
||||
|
||||
//
|
||||
// Adjust the status and output size
|
||||
//
|
||||
DrvAdjustStatusAndSetOutputSize(SIZEOF_DEBUGGER_USER_OUT_REQUEST_RESPONSE, DoNotChangeInformation, Irp, &Status);
|
||||
|
||||
break;
|
||||
|
||||
case IOCTL_DEBUGGER_ATTACH_DETACH_USER_MODE_PROCESS:
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ DebuggerCommandFlush(PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest
|
|||
NTSTATUS
|
||||
DebuggerCommandCpuid(PDEBUGGER_CPUID_REQUEST_RESPONSE DebuggerCpuidRequest);
|
||||
|
||||
NTSTATUS
|
||||
DebuggerCommandUserIn(PDEBUGGER_USER_IN_REQUEST_RESPONSE DebuggerUserInRequest);
|
||||
|
||||
NTSTATUS
|
||||
DebuggerCommandUserOut(PDEBUGGER_USER_OUT_REQUEST_RESPONSE DebuggerUserOutRequest);
|
||||
|
||||
NTSTATUS
|
||||
DebuggerCommandSignalExecutionState(PDEBUGGER_SEND_COMMAND_EXECUTION_FINISHED_SIGNAL DebuggerFinishedExecutionRequest);
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION
|
|||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_CHANGE_CORE,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_FLUSH_BUFFERS,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_USER_CPUID_REQUEST,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_USER_IN_INSTRUCTION,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_USER_OUT_INSTRUCTION,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_CALLSTACK,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_TEST_QUERY,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_CHANGE_PROCESS,
|
||||
|
|
@ -119,6 +121,8 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION
|
|||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_FORMATS,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_FLUSH,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_USER_CPUID,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_USER_IN_INSTRUCTION,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_USER_OUT_INSTRUCTION,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_CALLSTACK,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_TEST_QUERY,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_REGISTERING_EVENT,
|
||||
|
|
|
|||
|
|
@ -396,6 +396,20 @@
|
|||
#define IOCTL_DEBUGGER_CPUID \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x27, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
/**
|
||||
* @brief ioctl, to perform IN instruction
|
||||
*
|
||||
*/
|
||||
#define IOCTL_DEBUGGER_USER_IN \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x28, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
/**
|
||||
* @brief ioctl, to perform OUT instruction
|
||||
*
|
||||
*/
|
||||
#define IOCTL_DEBUGGER_USER_OUT \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_VMM_IOCTL + 0x29, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// HyperTrace IOCTLs //
|
||||
//////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1774,3 +1774,47 @@ typedef struct _DEBUGGER_CPUID_REQUEST_RESPONSE
|
|||
} DEBUGGER_CPUID_REQUEST_RESPONSE, *PDEBUGGER_CPUID_REQUEST_RESPONSE;
|
||||
|
||||
// ==============================================================================================
|
||||
|
||||
#define SIZEOF_DEBUGGER_USER_IN_REQUEST_RESPONSE \
|
||||
sizeof(DEBUGGER_USER_IN_REQUEST_RESPONSE)
|
||||
|
||||
/**
|
||||
* @brief Cpu registers for I/O instructions (related to _DEBUGGER_USER_IN_REQUEST_RESPONSE
|
||||
* and SIZEOF_DEBUGGER_USER_OUT_REQUEST_RESPONSE structs)
|
||||
*
|
||||
*/
|
||||
typedef enum _DEBUGGER_CPU_REGISTER_USER_IO
|
||||
{
|
||||
AL_8_BIT_REGISTER,
|
||||
AX_16_BIT_REGISTER,
|
||||
EAX_32_BIT_REGISTER
|
||||
} DEBUGGER_CPU_REGISTER_USER_IO;
|
||||
|
||||
/**
|
||||
* @brief Request and response for user IN instruction
|
||||
*
|
||||
*/
|
||||
typedef struct _DEBUGGER_USER_IN_REQUEST_RESPONSE
|
||||
{
|
||||
DEBUGGER_CPU_REGISTER_USER_IO UserChosenRegister; // from enum data type (_DEBUGGER_CPU_REGISTER_USER_IO)
|
||||
USHORT PortAddress; // totally 65,536 (2^16) port address (0 - 65,535)
|
||||
ULONG Data; // returned result
|
||||
|
||||
UINT32 KernelStatus;
|
||||
} DEBUGGER_USER_IN_REQUEST_RESPONSE, *PDEBUGGER_USER_IN_REQUEST_RESPONSE;
|
||||
|
||||
// ==============================================================================================
|
||||
|
||||
#define SIZEOF_DEBUGGER_USER_OUT_REQUEST_RESPONSE \
|
||||
sizeof(DEBUGGER_USER_OUT_REQUEST_RESPONSE)
|
||||
|
||||
typedef struct _DEBUGGER_USER_OUT_REQUEST_RESPONSE
|
||||
{
|
||||
DEBUGGER_CPU_REGISTER_USER_IO UserChosenRegister; // from enum data type (_DEBUGGER_CPU_REGISTER_USER_IO)
|
||||
USHORT PortAddress; // totally 65,536 (2^16) port address (0 - 65,535)
|
||||
UINT32 Value; // the value to be written to the port address
|
||||
|
||||
UINT32 KernelStatus;
|
||||
} DEBUGGER_USER_OUT_REQUEST_RESPONSE, *PDEBUGGER_USER_OUT_REQUEST_RESPONSE;
|
||||
|
||||
// ==============================================================================================
|
||||
|
|
|
|||
|
|
@ -336,6 +336,20 @@ hyperdbg_u_pt_mmap(HYPERTRACE_PT_MMAP_PACKETS * MmapRequest);
|
|||
IMPORT_EXPORT_LIBHYPERDBG BOOLEAN
|
||||
hyperdbg_u_request_cpuid(UINT32 FunctionId, UINT32 SubFunctionId);
|
||||
|
||||
//
|
||||
// IN instruction related command
|
||||
// Exported functionality of the 'uin'
|
||||
//
|
||||
IMPORT_EXPORT_LIBHYPERDBG BOOLEAN
|
||||
hyperdebg_u_in_instruction(DEBUGGER_USER_IN_REQUEST_RESPONSE InRequest);
|
||||
|
||||
//
|
||||
// OUT instruction related command
|
||||
// Exported functionality of the 'uout'
|
||||
//
|
||||
IMPORT_EXPORT_LIBHYPERDBG BOOLEAN
|
||||
hyperdebg_u_out_instruction(DEBUGGER_USER_OUT_REQUEST_RESPONSE OutRequest);
|
||||
|
||||
//
|
||||
// Transparent mode related command
|
||||
// Exported functionality of the '!hide', and '!unhide' commands
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ ConvertStringToUInt64(string TextToConvert, PUINT64 Result)
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief check and convert string to a 32 bit unsigned it and also
|
||||
* @brief check and convert string to a 32 bit unsigned int and also
|
||||
* check for special notations like 0x etc.
|
||||
* @param TextToConvert the target string
|
||||
* @param Result result will be save to the pointer
|
||||
|
|
@ -433,6 +433,95 @@ ConvertStringToUInt32(string TextToConvert, PUINT32 Result)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check and convert string to a 16 bit unsigned int and also
|
||||
* check for special notations like 0x etc.
|
||||
* @param TextToConvert the target string
|
||||
* @param Result result will be save to the pointer
|
||||
* @return BOOLEAN shows whether the conversion was successful or not
|
||||
*/
|
||||
BOOLEAN
|
||||
ConvertStringToUInt16(string TextToConvert, PUINT16 Result)
|
||||
{
|
||||
BOOLEAN IsDecimal = FALSE; // By default everything is hex
|
||||
|
||||
if (TextToConvert.rfind("0x", 0) == 0 || TextToConvert.rfind("0X", 0) == 0 ||
|
||||
TextToConvert.rfind("\\x", 0) == 0 ||
|
||||
TextToConvert.rfind("\\X", 0) == 0)
|
||||
{
|
||||
TextToConvert = TextToConvert.erase(0, 2);
|
||||
}
|
||||
else if (TextToConvert.rfind('x', 0) == 0 ||
|
||||
TextToConvert.rfind('X', 0) == 0)
|
||||
{
|
||||
TextToConvert = TextToConvert.erase(0, 1);
|
||||
}
|
||||
else if (TextToConvert.rfind("0n", 0) == 0 || TextToConvert.rfind("0N", 0) == 0 ||
|
||||
TextToConvert.rfind("\\n", 0) == 0 ||
|
||||
TextToConvert.rfind("\\N", 0) == 0)
|
||||
{
|
||||
TextToConvert = TextToConvert.erase(0, 2);
|
||||
IsDecimal = TRUE;
|
||||
}
|
||||
else if (TextToConvert.rfind('n', 0) == 0 ||
|
||||
TextToConvert.rfind('N', 0) == 0)
|
||||
{
|
||||
TextToConvert = TextToConvert.erase(0, 1);
|
||||
IsDecimal = TRUE;
|
||||
}
|
||||
|
||||
TextToConvert.erase(remove(TextToConvert.begin(), TextToConvert.end(), '`'),
|
||||
TextToConvert.end());
|
||||
|
||||
int Base = IsDecimal ? 10 : 16;
|
||||
|
||||
if (IsDecimal)
|
||||
{
|
||||
if (!IsDecimalNotation(TextToConvert))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsHexNotation(TextToConvert))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
size_t Pos = 0;
|
||||
unsigned long UL = std::stoul(TextToConvert, &Pos, Base); // use stoul (unsigned long) for 16-bit values
|
||||
|
||||
//
|
||||
// check for 16-bit overflow (0 - 65,535)
|
||||
//
|
||||
if (Pos != TextToConvert.size() || UL > (std::numeric_limits<UINT16>::max)())
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*Result = static_cast<UINT16>(UL);
|
||||
return TRUE;
|
||||
}
|
||||
catch (std::invalid_argument const &)
|
||||
{
|
||||
//
|
||||
// Bad input: std::invalid_argument thrown
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
catch (std::out_of_range const &)
|
||||
{
|
||||
//
|
||||
// Integer overflow: std::out_of_range thrown
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check and convert command token to a 64 bit unsigned integer
|
||||
*
|
||||
|
|
@ -554,6 +643,28 @@ ConvertTokenToUInt32(CommandToken TargetToken, PUINT32 Result)
|
|||
return ConvertStringToUInt32(TargetTokenValue, Result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief check and convert command token to a 16 bit unsigned integer
|
||||
*
|
||||
* @param TargetToken the target command token
|
||||
* @param Result result will be save to the pointer
|
||||
*
|
||||
* @return BOOLEAN shows whether the conversion was successful or not
|
||||
*/
|
||||
BOOLEAN
|
||||
ConvertTokenToUInt16(CommandToken TargetToken, PUINT16 Result)
|
||||
{
|
||||
//
|
||||
// Extract the token type and value from the tuple
|
||||
//
|
||||
std::string TargetTokenValue = std::get<1>(TargetToken);
|
||||
|
||||
//
|
||||
// Convert the token value to 32 bit unsigned integer
|
||||
//
|
||||
return ConvertStringToUInt16(TargetTokenValue, Result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief checks whether the string ends with a special string or not
|
||||
*
|
||||
|
|
|
|||
|
|
@ -43,6 +43,10 @@ CommandUserCpuidHelp()
|
|||
/**
|
||||
* @brief ucpuid command show messages
|
||||
*
|
||||
* @param FunctionId
|
||||
* @param SubFunctionId
|
||||
* @param CpuidRequest
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
|
|
@ -2065,9 +2069,12 @@ CommandShowUserCpuidMessage(UINT32 FunctionId,
|
|||
/**
|
||||
* @brief ucpuid command handler
|
||||
*
|
||||
* @return VOID
|
||||
* @param FunctionId
|
||||
* @param SubFunctionId
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
VOID
|
||||
BOOLEAN
|
||||
CommandCpuidRequestCpuid(UINT32 FunctionId, UINT32 SubFunctionId)
|
||||
{
|
||||
BOOL Status;
|
||||
|
|
@ -2082,15 +2089,14 @@ CommandCpuidRequestCpuid(UINT32 FunctionId, UINT32 SubFunctionId)
|
|||
//
|
||||
// It's on a debugger mode
|
||||
//
|
||||
KdSendUserCpuidPacketToDebuggee(FunctionId, SubFunctionId);
|
||||
return;
|
||||
return KdSendUserCpuidPacketToDebuggee(FunctionId, SubFunctionId);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// It's on a local debugging mode
|
||||
//
|
||||
AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn);
|
||||
AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse);
|
||||
|
||||
//
|
||||
// By the way, we don't need to send an input buffer
|
||||
|
|
@ -2113,17 +2119,19 @@ CommandCpuidRequestCpuid(UINT32 FunctionId, UINT32 SubFunctionId)
|
|||
if (!Status)
|
||||
{
|
||||
ShowMessages("ioctl failed with code 0x%x\n", PlatformGetLastError());
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (CpuidRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
|
||||
{
|
||||
CommandShowUserCpuidMessage(FunctionId, SubFunctionId, CpuidRequest);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ShowMessages("Receiving CPUID result was not successful :(\n");
|
||||
ShowMessages("Receiving CPUID result was not successful\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,251 @@
|
|||
/**
|
||||
* @file uin.cpp
|
||||
* @author Nikzad (Hossein Shirdel)
|
||||
* @brief uin command - read from i/o port address (user specified)
|
||||
* @details
|
||||
* @version 0.24
|
||||
* @date 2026-08-01
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
extern BOOLEAN g_IsKdModuleLoaded;
|
||||
extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee;
|
||||
|
||||
/**
|
||||
* @brief help of the uin command
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandUserInHelp()
|
||||
{
|
||||
ShowMessages(
|
||||
"uin : Read from I/O port (User IN)\n\n"
|
||||
"Syntax : uin <register> <port>\n\n"
|
||||
"Parameters :\n"
|
||||
" register : Destination register: AL, AX, or EAX (case-insensitive)\n"
|
||||
" port : I/O port address (hex or decimal, 0x0000 - 0xFFFF)\n\n"
|
||||
"Examples :\n"
|
||||
" uin al 0x60 Read a byte from keyboard port\n"
|
||||
" uin Ax 0x3F8 Read a word from COM1\n"
|
||||
" uin EAX 0xCF8 Read 32-bit from PCI config address\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uin command show messages
|
||||
*
|
||||
* @param UserChosenRegister
|
||||
* @param PortAddress
|
||||
* @param Data
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandShowUserInMessage(USHORT UserChosenRegister,
|
||||
USHORT PortAddress,
|
||||
ULONG Data)
|
||||
{
|
||||
const char * RegisterName = "";
|
||||
|
||||
switch (UserChosenRegister)
|
||||
{
|
||||
case AL_8_BIT_REGISTER:
|
||||
RegisterName = "AL";
|
||||
break;
|
||||
case AX_16_BIT_REGISTER:
|
||||
RegisterName = "AX";
|
||||
break;
|
||||
case EAX_32_BIT_REGISTER:
|
||||
RegisterName = "EAX";
|
||||
break;
|
||||
}
|
||||
|
||||
ShowMessages(" Port: 0x%04X (%d)\n", PortAddress, PortAddress);
|
||||
ShowMessages(" Register: %s\n", RegisterName);
|
||||
ShowMessages(" Result: 0x%08X\n", Data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uin command handler
|
||||
*
|
||||
* @param InRequest
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
CommandUserInRequest(DEBUGGER_USER_IN_REQUEST_RESPONSE InRequest)
|
||||
{
|
||||
BOOL Status;
|
||||
ULONG ReturnedLength;
|
||||
USHORT UserChosenRegister = InRequest.UserChosenRegister;
|
||||
USHORT PortAddress = InRequest.PortAddress;
|
||||
|
||||
if (g_IsSerialConnectedToRemoteDebuggee)
|
||||
{
|
||||
//
|
||||
// It's on a debugger mode
|
||||
//
|
||||
return KdSendUserInPacketToDebuggee(InRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// It's on a local debugging mode
|
||||
//
|
||||
AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse);
|
||||
|
||||
//
|
||||
// By the way, we don't need to send an input buffer
|
||||
// to the kernel, but let's keep it like this, if we
|
||||
// want to pass some other arguments to the kernel in
|
||||
// the future
|
||||
//
|
||||
Status = PlatformDeviceIoControl(
|
||||
g_DeviceHandle, // Handle to device
|
||||
IOCTL_DEBUGGER_USER_IN, // IO Control Code (IOCTL)
|
||||
&InRequest, // Input Buffer to driver.
|
||||
SIZEOF_DEBUGGER_USER_IN_REQUEST_RESPONSE, // Input buffer length
|
||||
&InRequest, // Output Buffer from driver.
|
||||
SIZEOF_DEBUGGER_USER_IN_REQUEST_RESPONSE, // 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());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (InRequest.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
|
||||
{
|
||||
//
|
||||
// The Data field is initialized to 0 before the ioctl call.
|
||||
// After the ioctl call, the Data field is populated, so we shouldn't define Data variable
|
||||
// before ioctl. Therefore, Data field must be defined after ioctl in order to be passed to
|
||||
// CommandShowUserInMessage function, because IOCTL will populate Data field.
|
||||
//
|
||||
ULONG Data = InRequest.Data;
|
||||
CommandShowUserInMessage(UserChosenRegister, PortAddress, Data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMessages("Receiving IN instruction result was not successful\n");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uin command handler
|
||||
*
|
||||
* @param CommandTokens
|
||||
* @param Command
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandUserIn(vector<CommandToken> CommandTokens, string Command)
|
||||
{
|
||||
DEBUGGER_USER_IN_REQUEST_RESPONSE InRequest = {};
|
||||
USHORT Port = 0;
|
||||
BOOL SetRegister = FALSE;
|
||||
BOOL SetPort = FALSE;
|
||||
BOOLEAN IsFirstCommand = TRUE;
|
||||
|
||||
if (CommandTokens.size() != 3)
|
||||
{
|
||||
ShowMessages("incorrect use of the '%s'\n\n",
|
||||
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
|
||||
CommandUserInHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto Section : CommandTokens)
|
||||
{
|
||||
if (IsFirstCommand == TRUE)
|
||||
{
|
||||
IsFirstCommand = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse Register (first parameter)
|
||||
//
|
||||
if (!SetRegister)
|
||||
{
|
||||
string RegisterStr = GetCaseSensitiveStringFromCommandToken(Section);
|
||||
|
||||
//
|
||||
// convert to lowercase for case-insensitive comparison
|
||||
//
|
||||
transform(RegisterStr.begin(), RegisterStr.end(), RegisterStr.begin(), ::tolower);
|
||||
|
||||
//
|
||||
// convert register string to enum
|
||||
//
|
||||
if (RegisterStr == "al")
|
||||
{
|
||||
InRequest.UserChosenRegister = AL_8_BIT_REGISTER;
|
||||
}
|
||||
else if (RegisterStr == "ax")
|
||||
{
|
||||
InRequest.UserChosenRegister = AX_16_BIT_REGISTER;
|
||||
}
|
||||
else if (RegisterStr == "eax")
|
||||
{
|
||||
InRequest.UserChosenRegister = EAX_32_BIT_REGISTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMessages("invalid cpu register, please use `al`, `ax`, or `eax` (case-insensitive)\n\n");
|
||||
}
|
||||
|
||||
SetRegister = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SetPort)
|
||||
{
|
||||
//
|
||||
// Parse Port Address (second parameter)
|
||||
//
|
||||
if (!ConvertTokenToUInt16(Section, &Port))
|
||||
{
|
||||
ShowMessages("please specify a correct hex/dec value for port address\n\n");
|
||||
CommandUserInHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
InRequest.PortAddress = Port;
|
||||
|
||||
SetPort = TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check if register and port address was provided
|
||||
//
|
||||
if (!SetRegister || !SetPort)
|
||||
{
|
||||
ShowMessages("missing required parameters\n");
|
||||
ShowMessages("Usage: uin <register> <port>\n\n");
|
||||
CommandUserInHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// use IN instruction
|
||||
//
|
||||
CommandUserInRequest(InRequest);
|
||||
}
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
/**
|
||||
* @file uout.cpp
|
||||
* @author Nikzad (Hossein Shirdel)
|
||||
* @brief uout command - write from cpu register to i/o port address (user specified)
|
||||
* @details
|
||||
* @version 0.24
|
||||
* @date 2026-08-01
|
||||
*
|
||||
* @copyright This project is released under the GNU Public License v3.
|
||||
*
|
||||
*/
|
||||
#include "pch.h"
|
||||
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
extern BOOLEAN g_IsKdModuleLoaded;
|
||||
extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee;
|
||||
|
||||
/**
|
||||
* @brief help of the uout command
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandUserOutHelp()
|
||||
{
|
||||
ShowMessages(
|
||||
"uout : Write to I/O port (User OUT)\n\n"
|
||||
"Syntax : uout <register> <port> <value>\n\n"
|
||||
"Parameters :\n"
|
||||
" register : Source register: AL, AX, or EAX (case-insensitive)\n"
|
||||
" port : I/O port address (hex or decimal, 0x0000 - 0xFFFF)\n"
|
||||
" value : Value to write (hex or decimal)\n\n"
|
||||
"Examples :\n"
|
||||
" uout al 0x60 0xED Write to keyboard controller\n"
|
||||
" uout AX 0x3F8 0x004D Write word to COM1\n"
|
||||
" uout Eax 0xCF8 0x80000000 Write 32-bit to PCI config address\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uout command show messages
|
||||
*
|
||||
* @param UserChosenRegister
|
||||
* @param PortAddress
|
||||
* @param Value
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandShowUserOutMessage(USHORT UserChosenRegister,
|
||||
USHORT PortAddress,
|
||||
UINT32 Value)
|
||||
{
|
||||
const char * RegisterName = "";
|
||||
|
||||
switch (UserChosenRegister)
|
||||
{
|
||||
case AL_8_BIT_REGISTER:
|
||||
RegisterName = "AL";
|
||||
break;
|
||||
case AX_16_BIT_REGISTER:
|
||||
RegisterName = "AX";
|
||||
break;
|
||||
case EAX_32_BIT_REGISTER:
|
||||
RegisterName = "EAX";
|
||||
break;
|
||||
}
|
||||
|
||||
ShowMessages(" Port: 0x%04X (%d)\n", PortAddress, PortAddress);
|
||||
ShowMessages(" Register: %s\n", RegisterName);
|
||||
ShowMessages(" Entered Value: 0x%08X\n", Value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uout command handler
|
||||
*
|
||||
* @param OutRequest
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
CommandUserOutRequest(DEBUGGER_USER_OUT_REQUEST_RESPONSE OutRequest)
|
||||
{
|
||||
BOOL Status;
|
||||
ULONG ReturnedLength;
|
||||
USHORT UserChosenRegister = OutRequest.UserChosenRegister;
|
||||
USHORT PortAddress = OutRequest.PortAddress;
|
||||
UINT32 Value = OutRequest.Value;
|
||||
|
||||
if (g_IsSerialConnectedToRemoteDebuggee)
|
||||
{
|
||||
//
|
||||
// It's on a debugger mode
|
||||
//
|
||||
return KdSendUserOutPacketToDebuggee(OutRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// It's on a local debugging mode
|
||||
//
|
||||
AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse);
|
||||
|
||||
//
|
||||
// By the way, we don't need to send an input buffer
|
||||
// to the kernel, but let's keep it like this, if we
|
||||
// want to pass some other arguments to the kernel in
|
||||
// the future
|
||||
//
|
||||
Status = PlatformDeviceIoControl(
|
||||
g_DeviceHandle, // Handle to device
|
||||
IOCTL_DEBUGGER_USER_OUT, // IO Control Code (IOCTL)
|
||||
&OutRequest, // Input Buffer to driver.
|
||||
SIZEOF_DEBUGGER_USER_OUT_REQUEST_RESPONSE, // Input buffer length
|
||||
&OutRequest, // Output Buffer from driver.
|
||||
SIZEOF_DEBUGGER_USER_OUT_REQUEST_RESPONSE, // 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());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (OutRequest.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
|
||||
{
|
||||
CommandShowUserOutMessage(UserChosenRegister, PortAddress, Value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ShowMessages("Receiving OUT instruction result was not successful\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uout command handler
|
||||
*
|
||||
* @param CommandTokens
|
||||
* @param Command
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandUserOut(vector<CommandToken> CommandTokens, string Command)
|
||||
{
|
||||
DEBUGGER_USER_OUT_REQUEST_RESPONSE OutRequest = {};
|
||||
USHORT Port = 0;
|
||||
UINT32 Value = 0;
|
||||
BOOL SetRegister = FALSE;
|
||||
BOOL SetPort = FALSE;
|
||||
BOOL SetValue = FALSE;
|
||||
BOOLEAN IsFirstCommand = TRUE;
|
||||
|
||||
if (CommandTokens.size() != 4)
|
||||
{
|
||||
ShowMessages("incorrect use of the '%s'\n\n",
|
||||
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
|
||||
CommandUserOutHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto Section : CommandTokens)
|
||||
{
|
||||
if (IsFirstCommand == TRUE)
|
||||
{
|
||||
IsFirstCommand = FALSE;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse Register (first parameter)
|
||||
//
|
||||
if (!SetRegister)
|
||||
{
|
||||
string RegisterStr = GetCaseSensitiveStringFromCommandToken(Section);
|
||||
|
||||
//
|
||||
// convert to lowercase for case-insensitive comparison
|
||||
//
|
||||
transform(RegisterStr.begin(), RegisterStr.end(), RegisterStr.begin(), ::tolower);
|
||||
|
||||
//
|
||||
// convert register string to enum
|
||||
//
|
||||
if (RegisterStr == "al")
|
||||
{
|
||||
OutRequest.UserChosenRegister = AL_8_BIT_REGISTER;
|
||||
}
|
||||
else if (RegisterStr == "ax")
|
||||
{
|
||||
OutRequest.UserChosenRegister = AX_16_BIT_REGISTER;
|
||||
}
|
||||
else if (RegisterStr == "eax")
|
||||
{
|
||||
OutRequest.UserChosenRegister = EAX_32_BIT_REGISTER;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowMessages("invalid cpu register, please use `al`, `ax`, or `eax` (case-insensitive)\n\n");
|
||||
}
|
||||
|
||||
SetRegister = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse Port Address (second parameter)
|
||||
//
|
||||
if (!SetPort)
|
||||
{
|
||||
if (!ConvertTokenToUInt16(Section, &Port))
|
||||
{
|
||||
ShowMessages("please specify a correct hex/dec value for port address\n\n");
|
||||
CommandUserOutHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
OutRequest.PortAddress = Port;
|
||||
|
||||
SetPort = TRUE;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse Value (third parameter)
|
||||
//
|
||||
if (!SetValue)
|
||||
{
|
||||
if (!ConvertTokenToUInt32(Section, &Value))
|
||||
{
|
||||
ShowMessages("please specify a correct hex/dec value for Value\n\n");
|
||||
CommandUserOutHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
OutRequest.Value = Value;
|
||||
|
||||
SetValue = TRUE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check if register, port address, and value was provided
|
||||
//
|
||||
if (!SetRegister || !SetPort || !SetValue)
|
||||
{
|
||||
ShowMessages("missing required parameters\n");
|
||||
ShowMessages("Usage: uout <register> <port> <value>\n\n");
|
||||
CommandUserOutHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// use OUT instruction
|
||||
//
|
||||
CommandUserOutRequest(OutRequest);
|
||||
}
|
||||
|
|
@ -1423,6 +1423,9 @@ InitializeCommandsDictionary()
|
|||
g_CommandsList["ucpuid"] = {&CommandUserCpuid, &CommandUserCpuidHelp, DEBUGGER_COMMAND_USER_CPUID_ATTRIBUTES};
|
||||
g_CommandsList["cpuid"] = {&CommandUserCpuid, &CommandUserCpuidHelp, DEBUGGER_COMMAND_USER_CPUID_ATTRIBUTES};
|
||||
|
||||
g_CommandsList["uin"] = {&CommandUserIn, &CommandUserInHelp, DEBUGGER_COMMAND_USER_IN_ATTRIBUTES};
|
||||
g_CommandsList["uout"] = {&CommandUserOut, &CommandUserOutHelp, DEBUGGER_COMMAND_USER_OUT_ATTRIBUTES};
|
||||
|
||||
g_CommandsList["pause"] = {&CommandPause, &CommandPauseHelp, DEBUGGER_COMMAND_PAUSE_ATTRIBUTES};
|
||||
g_CommandsList[".pause"] = {&CommandPause, &CommandPauseHelp, DEBUGGER_COMMAND_PAUSE_ATTRIBUTES};
|
||||
|
||||
|
|
|
|||
|
|
@ -339,6 +339,9 @@ KdSendFlushPacketToDebuggee()
|
|||
/**
|
||||
* @brief Send a CPUID request to the debuggee
|
||||
*
|
||||
* @param FunctionId
|
||||
* @param SubFunctionId
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
|
|
@ -368,6 +371,66 @@ KdSendUserCpuidPacketToDebuggee(UINT32 FunctionId, UINT32 SubFunctionId)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send IN instruction to the debuggee
|
||||
*
|
||||
* @param InRequest
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
KdSendUserInPacketToDebuggee(DEBUGGER_USER_IN_REQUEST_RESPONSE InRequest)
|
||||
{
|
||||
//
|
||||
// Send 'uin' command as packet
|
||||
//
|
||||
if (!KdCommandPacketAndBufferToDebuggee(
|
||||
DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_USER_IN_INSTRUCTION,
|
||||
(CHAR *)&InRequest,
|
||||
sizeof(DEBUGGER_USER_IN_REQUEST_RESPONSE)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until the result of IN instruction received
|
||||
//
|
||||
DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_USER_IN_RESULT);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send OUT instruction to the debuggee
|
||||
*
|
||||
* @param OutRequest
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
KdSendUserOutPacketToDebuggee(DEBUGGER_USER_OUT_REQUEST_RESPONSE OutRequest)
|
||||
{
|
||||
//
|
||||
// Send 'uout' command as packet
|
||||
//
|
||||
if (!KdCommandPacketAndBufferToDebuggee(
|
||||
DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_MODE_USER_OUT_INSTRUCTION,
|
||||
(CHAR *)&OutRequest,
|
||||
sizeof(DEBUGGER_USER_OUT_REQUEST_RESPONSE)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until the result of OUT instruction received
|
||||
//
|
||||
DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_USER_OUT_RESULT);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send a callstack request to the debuggee
|
||||
* @param BaseAddress
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ ListeningSerialPortInDebugger()
|
|||
PDEBUGGEE_DETAILS_AND_SWITCH_THREAD_PACKET ChangeThreadPacket;
|
||||
PDEBUGGER_FLUSH_LOGGING_BUFFERS FlushPacket;
|
||||
PDEBUGGER_CPUID_REQUEST_RESPONSE CpuidPacket;
|
||||
PDEBUGGER_USER_IN_REQUEST_RESPONSE InPacket;
|
||||
PDEBUGGER_USER_OUT_REQUEST_RESPONSE OutPacket;
|
||||
PDEBUGGER_CALLSTACK_REQUEST CallstackPacket;
|
||||
PDEBUGGER_SINGLE_CALLSTACK_FRAME CallstackFramePacket;
|
||||
PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket;
|
||||
|
|
@ -602,6 +604,54 @@ StartAgain:
|
|||
|
||||
break;
|
||||
|
||||
case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_USER_IN_INSTRUCTION:
|
||||
|
||||
InPacket = (DEBUGGER_USER_IN_REQUEST_RESPONSE *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET));
|
||||
|
||||
if (InPacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
|
||||
{
|
||||
USHORT UserChosenRegister = InPacket->UserChosenRegister;
|
||||
USHORT PortAddress = InPacket->PortAddress;
|
||||
ULONG Data = InPacket->Data;
|
||||
|
||||
CommandShowUserInMessage(UserChosenRegister, PortAddress, Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowErrorMessage(InPacket->KernelStatus);
|
||||
}
|
||||
|
||||
//
|
||||
// Signal the event relating to receiving result of IN instruction
|
||||
//
|
||||
DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_USER_IN_RESULT);
|
||||
|
||||
break;
|
||||
|
||||
case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_USER_OUT_INSTRUCTION:
|
||||
|
||||
OutPacket = (DEBUGGER_USER_OUT_REQUEST_RESPONSE *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET));
|
||||
|
||||
if (OutPacket->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
|
||||
{
|
||||
USHORT UserChosenRegister = OutPacket->UserChosenRegister;
|
||||
USHORT PortAddress = OutPacket->PortAddress;
|
||||
UINT32 Value = OutPacket->Value;
|
||||
|
||||
CommandShowUserOutMessage(UserChosenRegister, PortAddress, Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowErrorMessage(OutPacket->KernelStatus);
|
||||
}
|
||||
|
||||
//
|
||||
// Signal the event relating to receiving result of OUT instruction
|
||||
//
|
||||
DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_USER_OUT_RESULT);
|
||||
|
||||
break;
|
||||
|
||||
case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_CALLSTACK:
|
||||
|
||||
CallstackPacket = (DEBUGGER_CALLSTACK_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET));
|
||||
|
|
|
|||
|
|
@ -1044,4 +1044,30 @@ hyperdbg_u_request_cpuid(UINT32 FunctionId, UINT32 SubFunctionId)
|
|||
CommandCpuidRequestCpuid(FunctionId, SubFunctionId);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I/O instruction (IN)
|
||||
*
|
||||
* @param InRequest
|
||||
*
|
||||
* @return BOOLEAN TRUE if successful, FALSE otherwise
|
||||
*/
|
||||
BOOLEAN
|
||||
hyperdebg_u_in_instruction(DEBUGGER_USER_IN_REQUEST_RESPONSE InRequest)
|
||||
{
|
||||
return CommandUserInRequest(InRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I/O instruction (OUT)
|
||||
*
|
||||
* @param OutRequest
|
||||
*
|
||||
* @return BOOLEAN TRUE if successful, FALSE otherwise
|
||||
*/
|
||||
BOOLEAN
|
||||
hyperdebg_u_out_instruction(DEBUGGER_USER_OUT_REQUEST_RESPONSE OutRequest)
|
||||
{
|
||||
return CommandUserOutRequest(OutRequest);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -247,12 +247,18 @@ ConvertStringToUInt64(string TextToConvert, PUINT64 Result);
|
|||
BOOLEAN
|
||||
ConvertStringToUInt32(string TextToConvert, PUINT32 Result);
|
||||
|
||||
BOOLEAN
|
||||
ConvertStringToUInt16(string TextToConvert, PUINT16 Result);
|
||||
|
||||
BOOLEAN
|
||||
ConvertTokenToUInt64(CommandToken TargetToken, PUINT64 Result);
|
||||
|
||||
BOOLEAN
|
||||
ConvertTokenToUInt32(CommandToken TargetToken, PUINT32 Result);
|
||||
|
||||
BOOLEAN
|
||||
ConvertTokenToUInt16(CommandToken TargetToken, PUINT16 Result);
|
||||
|
||||
std::string
|
||||
GetCaseSensitiveStringFromCommandToken(CommandToken TargetToken);
|
||||
|
||||
|
|
|
|||
|
|
@ -304,6 +304,12 @@ typedef std::map<std::string, COMMAND_DETAIL> CommandType;
|
|||
#define DEBUGGER_COMMAND_USER_CPUID_ATTRIBUTES \
|
||||
DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE
|
||||
|
||||
#define DEBUGGER_COMMAND_USER_IN_ATTRIBUTES \
|
||||
DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE
|
||||
|
||||
#define DEBUGGER_COMMAND_USER_OUT_ATTRIBUTES \
|
||||
DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE
|
||||
|
||||
#define DEBUGGER_COMMAND_UNLOAD_ATTRIBUTES NULL
|
||||
|
||||
#define DEBUGGER_COMMAND_SCRIPT_ATTRIBUTES \
|
||||
|
|
@ -650,6 +656,12 @@ CommandFlush(vector<CommandToken> CommandTokens, string Command);
|
|||
VOID
|
||||
CommandUserCpuid(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
VOID
|
||||
CommandUserIn(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
VOID
|
||||
CommandUserOut(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
VOID
|
||||
CommandPause(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
|
|
|
|||
|
|
@ -174,6 +174,12 @@ CommandFlushHelp();
|
|||
VOID
|
||||
CommandUserCpuidHelp();
|
||||
|
||||
VOID
|
||||
CommandUserInHelp();
|
||||
|
||||
VOID
|
||||
CommandUserOutHelp();
|
||||
|
||||
VOID
|
||||
CommandPauseHelp();
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,8 @@
|
|||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_LBR_DUMP_RESULT 0x20
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_HYPERTRACE_PT_OPERATION_RESULT 0x21
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_USER_CPUID_RESULT 0x22
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_USER_IN_RESULT 0x23
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_USER_OUT_RESULT 0x24
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Event Details //
|
||||
|
|
@ -221,7 +223,7 @@ CommandEventsClearAllEventsAndResetTags();
|
|||
VOID
|
||||
CommandFlushRequestFlush();
|
||||
|
||||
VOID
|
||||
BOOLEAN
|
||||
CommandCpuidRequestCpuid(UINT32 FunctionId, UINT32 SubFunctionId);
|
||||
|
||||
VOID
|
||||
|
|
@ -229,6 +231,22 @@ CommandShowUserCpuidMessage(UINT32 FunctionId,
|
|||
UINT32 SubFunctionId,
|
||||
PDEBUGGER_CPUID_REQUEST_RESPONSE CpuidRequest);
|
||||
|
||||
BOOLEAN
|
||||
CommandUserInRequest(DEBUGGER_USER_IN_REQUEST_RESPONSE InRequest);
|
||||
|
||||
BOOLEAN
|
||||
CommandUserOutRequest(DEBUGGER_USER_OUT_REQUEST_RESPONSE OutRequest);
|
||||
|
||||
VOID
|
||||
CommandShowUserInMessage(USHORT UserChosenRegister,
|
||||
USHORT PortAddress,
|
||||
ULONG Data);
|
||||
|
||||
VOID
|
||||
CommandShowUserOutMessage(USHORT UserChosenRegister,
|
||||
USHORT PortAddress,
|
||||
UINT32 Value);
|
||||
|
||||
UINT64
|
||||
GetCommandAttributes(const string & FirstCommand);
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,12 @@ KdSendFlushPacketToDebuggee();
|
|||
BOOLEAN
|
||||
KdSendUserCpuidPacketToDebuggee(UINT32 FunctionId, UINT32 SubFunctionId);
|
||||
|
||||
BOOLEAN
|
||||
KdSendUserInPacketToDebuggee(DEBUGGER_USER_IN_REQUEST_RESPONSE InRequest);
|
||||
|
||||
BOOLEAN
|
||||
KdSendUserOutPacketToDebuggee(DEBUGGER_USER_OUT_REQUEST_RESPONSE OutRequest);
|
||||
|
||||
BOOLEAN
|
||||
KdSendCallStackPacketToDebuggee(UINT64 BaseAddress,
|
||||
UINT32 Size,
|
||||
|
|
|
|||
|
|
@ -199,6 +199,9 @@ msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="R
|
|||
<ClCompile Include="code\debugger\commands\debugging-commands\k.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\preactivate.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\prealloc.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\ucpuid.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\uin.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\uout.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\apic.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\crwrite.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\idt.cpp" />
|
||||
|
|
@ -247,7 +250,6 @@ msbuild "$(SolutionDir)dependencies\zydis\msvc\Zydis.sln" /m /p:Configuration="R
|
|||
<ClCompile Include="code\hwdbg\hwdbg-scripts.cpp" />
|
||||
<ClCompile Include="code\objects\objects.cpp" />
|
||||
<ClCompile Include="code\rev\rev-ctrl.cpp" />
|
||||
<ClCompile Include="ucpuid.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='release|x64'">Create</PrecompiledHeader>
|
||||
|
|
|
|||
|
|
@ -742,7 +742,13 @@
|
|||
<ClCompile Include="code\debugger\misc\pt-helper.cpp">
|
||||
<Filter>code\debugger\misc</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ucpuid.cpp">
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\ucpuid.cpp">
|
||||
<Filter>code\debugger\commands\debugging-commands</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\uin.cpp">
|
||||
<Filter>code\debugger\commands\debugging-commands</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\uout.cpp">
|
||||
<Filter>code\debugger\commands\debugging-commands</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue