From 9d239ccdfd7901cad197a4b49327efbf322cd116 Mon Sep 17 00:00:00 2001 From: Sinaei Date: Thu, 20 Jul 2023 15:52:34 +0900 Subject: [PATCH] query for process type (32-bit or 64-bit) from VMX-root and IOCTL --- .../kernel-level/kernel-listening.cpp | 8 +- .../hprdbgctrl/code/debugger/misc/readmem.cpp | 13 ++ .../code/debugger/commands/DebuggerCommands.c | 114 +++++++++++++++++- .../hprdbgkd/code/debugger/kernel-level/Kd.c | 4 +- .../code/debugger/user-level/UserAccess.c | 47 +++++--- hyperdbg/hprdbgkd/code/driver/Ioctl.c | 3 + .../header/debugger/user-level/UserAccess.h | 3 + hyperdbg/include/SDK/Headers/DataTypes.h | 4 +- .../include/SDK/Headers/RequestStructures.h | 2 + 9 files changed, 171 insertions(+), 27 deletions(-) diff --git a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kernel-listening.cpp b/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kernel-listening.cpp index 30c7a22b5..c8b6913bb 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kernel-listening.cpp +++ b/hyperdbg/hprdbgctrl/code/debugger/kernel-level/kernel-listening.cpp @@ -214,7 +214,7 @@ ListeningSerialPortInDebugger() RtlZeroMemory(g_CurrentRunningInstruction, MAXIMUM_INSTR_SIZE); memcpy(g_CurrentRunningInstruction, &PausePacket->InstructionBytesOnRip, MAXIMUM_INSTR_SIZE); - g_IsRunningInstruction32Bit = PausePacket->Is32BitAddress; + g_IsRunningInstruction32Bit = PausePacket->IsProcessorOn32BitMode; // // Show additional messages before showing assembly and pausing @@ -283,13 +283,13 @@ ListeningSerialPortInDebugger() // if (HyperDbgLengthDisassemblerEngine(PausePacket->InstructionBytesOnRip, MAXIMUM_INSTR_SIZE, - PausePacket->Is32BitAddress ? FALSE : TRUE) > PausePacket->ReadInstructionLen) + PausePacket->IsProcessorOn32BitMode ? FALSE : TRUE) > PausePacket->ReadInstructionLen) { ShowMessages("oOh, no! there might be a misinterpretation in disassembling the current instruction\n"); } } - if (!PausePacket->Is32BitAddress) + if (!PausePacket->IsProcessorOn32BitMode) { // // Show diassembles @@ -338,7 +338,7 @@ ListeningSerialPortInDebugger() // CommandTrackHandleReceivedInstructions(&PausePacket->InstructionBytesOnRip[0], MAXIMUM_INSTR_SIZE, - PausePacket->Is32BitAddress ? FALSE : TRUE, + PausePacket->IsProcessorOn32BitMode ? FALSE : TRUE, PausePacket->Rip); // diff --git a/hyperdbg/hprdbgctrl/code/debugger/misc/readmem.cpp b/hyperdbg/hprdbgctrl/code/debugger/misc/readmem.cpp index 1df79e641..2e5129062 100644 --- a/hyperdbg/hprdbgctrl/code/debugger/misc/readmem.cpp +++ b/hyperdbg/hprdbgctrl/code/debugger/misc/readmem.cpp @@ -53,6 +53,19 @@ HyperDbgReadMemoryAndDisassemble(DEBUGGER_SHOW_MEMORY_STYLE Style, ReadMem.Style = Style; ReadMem.DtDetails = DtDetails; + // + // Check if this is used for disassembler or not + // + if (Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE64 || + Style == DEBUGGER_SHOW_COMMAND_DISASSEMBLE32) + { + ReadMem.IsForDisasm = TRUE; + } + else + { + ReadMem.IsForDisasm = FALSE; + } + // // send the request // diff --git a/hyperdbg/hprdbgkd/code/debugger/commands/DebuggerCommands.c b/hyperdbg/hprdbgkd/code/debugger/commands/DebuggerCommands.c index 31c276ac1..644a7bc58 100644 --- a/hyperdbg/hprdbgkd/code/debugger/commands/DebuggerCommands.c +++ b/hyperdbg/hprdbgkd/code/debugger/commands/DebuggerCommands.c @@ -28,7 +28,11 @@ DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer UINT32 Size; UINT64 Address; DEBUGGER_READ_MEMORY_TYPE MemType; + BOOLEAN Is32BitProcess = FALSE; + // + // Adjust the parameters + // Pid = ReadMemRequest->Pid; Size = ReadMemRequest->Size; Address = ReadMemRequest->Address; @@ -36,11 +40,73 @@ DebuggerCommandReadMemory(PDEBUGGER_READ_MEMORY ReadMemRequest, PVOID UserBuffer if (Size && Address != NULL) { - return MemoryManagerReadProcessMemoryNormal((HANDLE)Pid, Address, MemType, (PVOID)UserBuffer, Size, ReturnSize); + if (MemoryManagerReadProcessMemoryNormal((HANDLE)Pid, Address, MemType, (PVOID)UserBuffer, Size, ReturnSize)) + { + // + // Reading memory was successful + // + + // + // *** Now, we check whether this a disassembly request for a virtual address + // or not, if so, we'll detect whether the target process is 32-bit or 64-bit *** + // + + // + // Check if the address is on a 32-bit mode process or not (just in case of disassembling) + // + if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->IsForDisasm) + { + // + // Check if the address is in the canonical range for kernel space + // + if (ReadMemRequest->Address >= 0xFFFF800000000000 && ReadMemRequest->Address <= 0xFFFFFFFFFFFFFFFF) + { + // + // The address is in the range of canonical kernel space, so it's 64-bit process + // + ReadMemRequest->Is32BitAddress = FALSE; + } + else + { + // + // The address is in the user-mode and the memory type is a virtual address + // for disassembly, so we have to query whether the target process is a + // 32-bit process or a 64-bit process + // + if (UserAccessIsWow64Process(ReadMemRequest->Pid, &Is32BitProcess)) + { + ReadMemRequest->Is32BitAddress = Is32BitProcess; + } + else + { + // + // We couldn't determine the type of process, let's assume that it's a + // 64-bit process by default + // + ReadMemRequest->Is32BitAddress = FALSE; + } + } + } + + // + // Anyway, the read was successful + // + return TRUE; + } + else + { + // + // Reading memory was not successful + // + return FALSE; + } } else { - return STATUS_UNSUCCESSFUL; + // + // Parameters are invalid + // + return FALSE; } } @@ -60,7 +126,8 @@ DebuggerCommandReadMemoryVmxRoot(PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR * U UINT64 Address; UINT64 OffsetInUserBuffer; DEBUGGER_READ_MEMORY_TYPE MemType; - PLIST_ENTRY TempList = 0; + BOOLEAN Is32BitProcess = FALSE; + PLIST_ENTRY TempList = 0; Pid = ReadMemRequest->Pid; Size = ReadMemRequest->Size; @@ -131,6 +198,47 @@ DebuggerCommandReadMemoryVmxRoot(PDEBUGGER_READ_MEMORY ReadMemRequest, UCHAR * U ReadMemRequest->KernelStatus = DEBUGGER_ERROR_MEMORY_TYPE_INVALID; return FALSE; } + + // + // Check if the address is on a 32-bit mode process or not (just in case of disassembling) + // + if (ReadMemRequest->MemoryType == DEBUGGER_READ_VIRTUAL_ADDRESS && ReadMemRequest->IsForDisasm) + { + // + // Check if the address is in the canonical range for kernel space + // + if (ReadMemRequest->Address >= 0xFFFF800000000000 && ReadMemRequest->Address <= 0xFFFFFFFFFFFFFFFF) + { + // + // The address is in the range of canonical kernel space, so it's 64-bit process + // + ReadMemRequest->Is32BitAddress = FALSE; + } + else + { + // + // The address is in the user-mode and the memory type is a virtual address + // for disassembly, so we have to query whether the target process is a + // 32-bit process or a 64-bit process + // + if (UserAccessIsWow64ProcessByEprocess(PsGetCurrentProcess(), &Is32BitProcess)) + { + ReadMemRequest->Is32BitAddress = Is32BitProcess; + } + else + { + // + // We couldn't determine the type of process, let's assume that it's a + // 64-bit process by default + // + ReadMemRequest->Is32BitAddress = FALSE; + } + } + } + + // + // Set the final status of memory read as it was successful + // ReadMemRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; *ReturnSize = Size; diff --git a/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c b/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c index a386d1df7..84adfa286 100644 --- a/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c +++ b/hyperdbg/hprdbgkd/code/debugger/kernel-level/Kd.c @@ -2760,8 +2760,8 @@ KdManageSystemHaltOnVmxRoot(PROCESSOR_DEBUGGING_STATE * DbgState, // // Set the RIP and mode of execution // - PausePacket.Rip = LastVmexitRip; - PausePacket.Is32BitAddress = KdIsGuestOnUsermode32Bit(); + PausePacket.Rip = LastVmexitRip; + PausePacket.IsProcessorOn32BitMode = KdIsGuestOnUsermode32Bit(); // // Set disassembly state diff --git a/hyperdbg/hprdbgkd/code/debugger/user-level/UserAccess.c b/hyperdbg/hprdbgkd/code/debugger/user-level/UserAccess.c index 13660eca4..74bb8f4e3 100644 --- a/hyperdbg/hprdbgkd/code/debugger/user-level/UserAccess.c +++ b/hyperdbg/hprdbgkd/code/debugger/user-level/UserAccess.c @@ -702,30 +702,17 @@ UserAccessPrintLoadedModulesX86_2(PEPROCESS Proc) } /** - * @brief Detects whether process is 32-bit or 64-bit + * @brief Detects whether process is 32-bit or 64-bit by using EPROCESS pointer * @details This function should be called in vmx non-root * - * @param ProcessId + * @param SourceProcess * @param Is32Bit * * @return BOOLEAN */ BOOLEAN -UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit) +UserAccessIsWow64ProcessByEprocess(PEPROCESS SourceProcess, PBOOLEAN Is32Bit) { - PEPROCESS SourceProcess; - KAPC_STATE State = {0}; - - if (PsLookupProcessByProcessId(ProcessId, &SourceProcess) != STATUS_SUCCESS) - { - // - // if the process not found - // - return FALSE; - } - - ObDereferenceObject(SourceProcess); - if (g_PsGetProcessWow64Process == NULL || g_PsGetProcessPeb == NULL) { return FALSE; @@ -756,6 +743,34 @@ UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit) } } +/** + * @brief Detects whether process is 32-bit or 64-bit + * @details This function should be called in vmx non-root + * + * @param ProcessId + * @param Is32Bit + * + * @return BOOLEAN + */ +BOOLEAN +UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit) +{ + PEPROCESS SourceProcess; + KAPC_STATE State = {0}; + + if (PsLookupProcessByProcessId(ProcessId, &SourceProcess) != STATUS_SUCCESS) + { + // + // if the process not found + // + return FALSE; + } + + ObDereferenceObject(SourceProcess); + + return UserAccessIsWow64ProcessByEprocess(SourceProcess, Is32Bit); +} + /** * @brief Get details about loaded modules * @details This function should be called in vmx non-root diff --git a/hyperdbg/hprdbgkd/code/driver/Ioctl.c b/hyperdbg/hprdbgkd/code/driver/Ioctl.c index faa03e583..1e61f6cf8 100644 --- a/hyperdbg/hprdbgkd/code/driver/Ioctl.c +++ b/hyperdbg/hprdbgkd/code/driver/Ioctl.c @@ -105,6 +105,7 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) Status = STATUS_INVALID_PARAMETER; break; } + break; case IOCTL_RETURN_IRP_PENDING_PACKETS_AND_DISALLOW_IOCTL: @@ -123,6 +124,7 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) TRUE); Status = STATUS_SUCCESS; + break; case IOCTL_TERMINATE_VMX: @@ -544,6 +546,7 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) DoNotChangeInformation = TRUE; break; + case IOCTL_DEBUGGER_SEARCH_MEMORY: // diff --git a/hyperdbg/hprdbgkd/header/debugger/user-level/UserAccess.h b/hyperdbg/hprdbgkd/header/debugger/user-level/UserAccess.h index 2127541f8..cb2c8c40d 100644 --- a/hyperdbg/hprdbgkd/header/debugger/user-level/UserAccess.h +++ b/hyperdbg/hprdbgkd/header/debugger/user-level/UserAccess.h @@ -212,6 +212,9 @@ UserAccessGetLoadedModules(PUSERMODE_LOADED_MODULE_DETAILS ProcessLoadedModuleRe BOOLEAN UserAccessIsWow64Process(HANDLE ProcessId, PBOOLEAN Is32Bit); +BOOLEAN +UserAccessIsWow64ProcessByEprocess(PEPROCESS SourceProcess, PBOOLEAN Is32Bit); + BOOLEAN UserAccessCheckForLoadedModuleDetails(UINT32 CoreId); diff --git a/hyperdbg/include/SDK/Headers/DataTypes.h b/hyperdbg/include/SDK/Headers/DataTypes.h index 98887d795..4c3fb7e87 100644 --- a/hyperdbg/include/SDK/Headers/DataTypes.h +++ b/hyperdbg/include/SDK/Headers/DataTypes.h @@ -156,8 +156,8 @@ typedef struct _DEBUGGER_PAUSE_PACKET_RECEIVED typedef struct _DEBUGGEE_KD_PAUSED_PACKET { UINT64 Rip; - BOOLEAN Is32BitAddress; // if true shows that the address should be interpreted in 32-bit mode - BOOLEAN IgnoreDisassembling; // if check if diassembling should be ignored or not + BOOLEAN IsProcessorOn32BitMode; // if true shows that the address should be interpreted in 32-bit mode + BOOLEAN IgnoreDisassembling; // if check if diassembling should be ignored or not DEBUGGEE_PAUSING_REASON PausingReason; ULONG CurrentCore; UINT64 EventTag; diff --git a/hyperdbg/include/SDK/Headers/RequestStructures.h b/hyperdbg/include/SDK/Headers/RequestStructures.h index 55062ce56..fe85bad70 100644 --- a/hyperdbg/include/SDK/Headers/RequestStructures.h +++ b/hyperdbg/include/SDK/Headers/RequestStructures.h @@ -233,6 +233,8 @@ typedef struct _DEBUGGER_READ_MEMORY UINT32 Pid; // Read from cr3 of what process UINT64 Address; UINT32 Size; + BOOLEAN IsForDisasm; // Debugger sets whether the read memory is for diassembler or not + BOOLEAN Is32BitAddress; // Debuggee sets the status of address DEBUGGER_READ_MEMORY_TYPE MemoryType; DEBUGGER_READ_READING_TYPE ReadingType; PDEBUGGER_DT_COMMAND_OPTIONS DtDetails;