From 2dfbf46e51b6d6923a1f2e017afd8d11eb973411 Mon Sep 17 00:00:00 2001 From: Nikzad Date: Thu, 6 Aug 2026 21:13:03 +0330 Subject: [PATCH] c/cpp files --- .../code/debugger/commands/DebuggerCommands.c | 98 +++++++++++++++ .../hyperkd/code/debugger/kernel-level/Kd.c | 40 +++++++ hyperdbg/hyperkd/code/driver/Ioctl.c | 58 +++++++++ hyperdbg/libhyperdbg/code/common/common.cpp | 113 +++++++++++++++++- .../code/debugger/core/interpreter.cpp | 3 + .../code/debugger/kernel-level/kd.cpp | 63 ++++++++++ .../kernel-level/kernel-listening.cpp | 50 ++++++++ hyperdbg/libhyperdbg/code/export/export.cpp | 30 +++++ hyperdbg/libhyperdbg/ucpuid.cpp | 7 ++ 9 files changed, 461 insertions(+), 1 deletion(-) diff --git a/hyperdbg/hyperkd/code/debugger/commands/DebuggerCommands.c b/hyperdbg/hyperkd/code/debugger/commands/DebuggerCommands.c index 2f530a49..7b62b2e9 100644 --- a/hyperdbg/hyperkd/code/debugger/commands/DebuggerCommands.c +++ b/hyperdbg/hyperkd/code/debugger/commands/DebuggerCommands.c @@ -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 * diff --git a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c index 3fdaf881..89305a12 100644 --- a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c +++ b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c @@ -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)); diff --git a/hyperdbg/hyperkd/code/driver/Ioctl.c b/hyperdbg/hyperkd/code/driver/Ioctl.c index 16817ab2..f8df9e7a 100644 --- a/hyperdbg/hyperkd/code/driver/Ioctl.c +++ b/hyperdbg/hyperkd/code/driver/Ioctl.c @@ -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: // diff --git a/hyperdbg/libhyperdbg/code/common/common.cpp b/hyperdbg/libhyperdbg/code/common/common.cpp index 09556ded..c4c8c660 100644 --- a/hyperdbg/libhyperdbg/code/common/common.cpp +++ b/hyperdbg/libhyperdbg/code/common/common.cpp @@ -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::max)()) + { + return FALSE; + } + + *Result = static_cast(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 * diff --git a/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp b/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp index f06d6dbb..ba8d96eb 100644 --- a/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp @@ -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}; diff --git a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp index fd7eba48..f13fc231 100644 --- a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp @@ -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 diff --git a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp index 81e88b30..5f5638f2 100644 --- a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp @@ -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)); diff --git a/hyperdbg/libhyperdbg/code/export/export.cpp b/hyperdbg/libhyperdbg/code/export/export.cpp index d5dc56e0..c0f984a7 100644 --- a/hyperdbg/libhyperdbg/code/export/export.cpp +++ b/hyperdbg/libhyperdbg/code/export/export.cpp @@ -1043,5 +1043,35 @@ 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) +{ + CommandUserInRequest(InRequest); + + return TRUE; +} + +/** + * @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) +{ + CommandUserOutRequest(OutRequest); + return TRUE; } \ No newline at end of file diff --git a/hyperdbg/libhyperdbg/ucpuid.cpp b/hyperdbg/libhyperdbg/ucpuid.cpp index 2c932cac..984e42e2 100644 --- a/hyperdbg/libhyperdbg/ucpuid.cpp +++ b/hyperdbg/libhyperdbg/ucpuid.cpp @@ -43,6 +43,10 @@ CommandUserCpuidHelp() /** * @brief ucpuid command show messages * + * @param FunctionId + * @param SubFunctionId + * @param CpuidRequest + * * @return VOID */ VOID @@ -2065,6 +2069,9 @@ CommandShowUserCpuidMessage(UINT32 FunctionId, /** * @brief ucpuid command handler * + * @param FunctionId + * @param SubFunctionId + * * @return VOID */ VOID