From ac87707a0b1a1989fb0806ed909c521eb14c9283 Mon Sep 17 00:00:00 2001 From: SinaKarvandi Date: Fri, 8 Nov 2024 15:14:12 +0100 Subject: [PATCH 1/7] add support to read Local APIC in xAPIC and x2APIC modes --- hyperdbg/hyperhv/code/devices/Apic.c | 354 +++++++++++++++++- hyperdbg/hyperhv/code/interface/Export.c | 11 + hyperdbg/hyperhv/header/devices/Apic.h | 5 +- .../hyperkd/code/debugger/kernel-level/Kd.c | 5 + .../SDK/imports/kernel/HyperDbgVmmImports.h | 3 + 5 files changed, 376 insertions(+), 2 deletions(-) diff --git a/hyperdbg/hyperhv/code/devices/Apic.c b/hyperdbg/hyperhv/code/devices/Apic.c index 1711213b..8877cdd0 100644 --- a/hyperdbg/hyperhv/code/devices/Apic.c +++ b/hyperdbg/hyperhv/code/devices/Apic.c @@ -11,6 +11,103 @@ */ #include "pch.h" +#define LAPIC_LVT_FLAG_ENTRY_MASKED (1UL << 16) +#define LAPIC_LVT_DELIVERY_MODE_EXT_INT (7UL << 8) +#define LAPIC_SVR_FLAG_SW_ENABLE (1UL << 8) + +/// @brief LAPIC structure size +#define LAPIC_SIZE 0x400 + +typedef struct _LAPIC_PAGE +{ + UINT8 __reserved_000[0x10]; + UINT8 __reserved_010[0x10]; + + UINT32 Id; // offset 0x020 + UINT8 __reserved_024[0x0C]; + + UINT32 Version; // offset 0x030 + UINT8 __reserved_034[0x0C]; + + UINT8 __reserved_040[0x40]; + + UINT32 TPR; // offset 0x080 + UINT8 __reserved_084[0x0C]; + + UINT32 ArbitrationPriority; // offset 0x090 + UINT8 __reserved_094[0x0C]; + + UINT32 ProcessorPriority; // offset 0x0A0 + UINT8 __reserved_0A4[0x0C]; + + UINT32 EOI; // offset 0x0B0 + UINT8 __reserved_0B4[0x0C]; + + UINT32 RemoteRead; // offset 0x0C0 + UINT8 __reserved_0C4[0x0C]; + + UINT32 LogicalDestination; // offset 0x0D0 + UINT8 __reserved_0D4[0x0C]; + + UINT32 DestinationFormat; // offset 0x0E0 + UINT8 __reserved_0E4[0x0C]; + + UINT32 SpuriousInterruptVector; // offset 0x0F0 + UINT8 __reserved_0F4[0x0C]; + + UINT32 ISR[32]; // offset 0x100 + + UINT32 TMR[32]; // offset 0x180 + + UINT32 IRR[32]; // offset 0x200 + + UINT32 ErrorStatus; // offset 0x280 + UINT8 __reserved_284[0x0C]; + + UINT8 __reserved_290[0x60]; + + UINT32 LvtCmci; // offset 0x2F0 + UINT8 __reserved_2F4[0x0C]; + + UINT32 IcrLow; // offset 0x300 + UINT8 __reserved_304[0x0C]; + + UINT32 IcrHigh; // offset 0x310 + UINT8 __reserved_314[0x0C]; + + UINT32 LvtTimer; // offset 0x320 + UINT8 __reserved_324[0x0C]; + + UINT32 LvtThermalSensor; // offset 0x330 + UINT8 __reserved_334[0x0C]; + + UINT32 LvtPerfMonCounters; // offset 0x340 + UINT8 __reserved_344[0x0C]; + + UINT32 LvtLINT0; // offset 0x350 + UINT8 __reserved_354[0x0C]; + + UINT32 LvtLINT1; // offset 0x360 + UINT8 __reserved_364[0x0C]; + + UINT32 LvtError; // offset 0x370 + UINT8 __reserved_374[0x0C]; + + UINT32 InitialCount; // offset 0x380 + UINT8 __reserved_384[0x0C]; + + UINT32 CurrentCount; // offset 0x390 + UINT8 __reserved_394[0x0C]; + + UINT8 __reserved_3A0[0x40]; // offset 0x3A0 + + UINT32 DivideConfiguration; // offset 0x3E0 + UINT8 __reserved_3E4[0x0C]; + + UINT32 SelfIpi; // offset 0x3F0 + UINT8 __reserved_3F4[0x0C]; // valid only for X2APIC +} LAPIC_PAGE; + /** * @brief Trigger NMI on XAPIC * @param Low @@ -38,6 +135,241 @@ X2ApicIcrWrite(UINT32 Low, UINT32 High) __writemsr(X2_MSR_BASE + TO_X2(ICROffset), ((UINT64)High << 32) | Low); } +/** + * @brief Read x2APIC mode + * @param Offset + * + * @return UINT64 + */ +UINT64 +X2ApicRead(UINT32 Offset) +{ + LogInfo("Read offset at: %llx", Offset); + return __readmsr(X2_MSR_BASE + TO_X2(Offset)); +} + +VOID +LapicPrintPlatformXApicMode( + void) +{ + UINT8 i = 0, j = 0; + UINT32 k = 0; + UINT32 reg = 0; + IA32_APIC_BASE_REGISTER ia32ApicBaseMsr; + UINT64 basePa = 0; + + volatile LAPIC_PAGE * lapicVa = g_ApicBase; + + if (!g_ApicBase) + { + return; + } + + ia32ApicBaseMsr.AsUInt = __readmsr(IA32_APIC_BASE); + basePa = ia32ApicBaseMsr.ApicBase; + + LogInfo("*** (xAPIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" + " -> TPR = 0x%08x, APR = 0x%08x, PPR = 0x%08x, RRD = 0x%08x\n" + " -> LDR = 0x%08x, DFR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" + " -> ICR_LOW = 0x%08x , ICR_HIGH = 0x%08x\n" + " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" + " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" + " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" + " -> LVT_ERR = 0x%08x\n" + " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", + lapicVa->Id >> 24, + lapicVa->Version, + (lapicVa->Version & 0xFF0000) >> 16, + (lapicVa->Version >> 24) & 1, + (lapicVa->SpuriousInterruptVector >> 12) & 1, + (lapicVa->SpuriousInterruptVector & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", + ia32ApicBaseMsr, + lapicVa->TPR, + lapicVa->ArbitrationPriority, + lapicVa->ProcessorPriority, + lapicVa->RemoteRead, + lapicVa->LogicalDestination, + lapicVa->DestinationFormat, + lapicVa->SpuriousInterruptVector, + lapicVa->ErrorStatus, + lapicVa->IcrLow, + lapicVa->IcrHigh, + lapicVa->LvtLINT0, + lapicVa->LvtLINT1, + lapicVa->LvtCmci, + lapicVa->LvtPerfMonCounters, + lapicVa->LvtTimer, + lapicVa->LvtThermalSensor, + lapicVa->LvtError, + lapicVa->InitialCount, + lapicVa->CurrentCount, + lapicVa->DivideConfiguration); + + // print the ISR, TMR and IRR + LogInfo("ISR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + reg = (UINT32)lapicVa->ISR[i * 4]; + for (j = 0; j < 32; j++) + { + if (0 != (reg & k)) + { + LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + LogInfo("\n"); + + LogInfo("TMR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + reg = (UINT32)lapicVa->TMR[i * 4]; + for (j = 0; j < 32; j++) + { + if (reg & k) + { + LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + LogInfo("\n"); + + LogInfo("IRR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + reg = (UINT32)lapicVa->IRR[i * 4]; + for (j = 0; j < 32; j++) + { + if (reg & k) + { + LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + LogInfo("\n"); + + return; +} + +VOID +LapicPrintPlatformX2ApicMode( + void) +{ + UINT8 i = 0, j = 0; + UINT32 k = 0; + UINT32 reg = 0; + IA32_APIC_BASE_REGISTER ia32ApicBaseMsr; + + ia32ApicBaseMsr.AsUInt = __readmsr(IA32_APIC_BASE); + + LogInfo("*** (x2APIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" + " -> TPR = 0x%08x, APR = 0x%08x, PPR = 0x%08x, RRD = 0x%08x\n" + " -> LDR = 0x%08x, DFR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" + " -> ICR_LOW = 0x%08x , ICR_HIGH = 0x%08x\n" + " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" + " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" + " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" + " -> LVT_ERR = 0x%08x\n" + " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", + X2ApicRead(APIC_ID) >> 24, + X2ApicRead(APIC_VERSION), + (X2ApicRead(APIC_VERSION) & 0xFF0000) >> 16, + (X2ApicRead(APIC_VERSION) >> 24) & 1, + (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) >> 12) & 1, + (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", + ia32ApicBaseMsr, + X2ApicRead(APIC_TASK_PRIORITY), + 0, // X2ApicRead(APIC_ARBITRATION_PRIORITY), + X2ApicRead(APIC_PROCESSOR_PRIORITY), + 0, // X2ApicRead(APIC_REMOTE_READ), + X2ApicRead(APIC_LOGICAL_DESTINATION), + 0, // X2ApicRead(APIC_DESTINATION_FORMAT), + X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR), + X2ApicRead(APIC_ERROR_STATUS), + 0, // X2ApicRead(APIC_INTERRUPT_COMMAND_BITS_0_31), + 0, // X2ApicRead(APIC_INTERRUPT_COMMAND_BITS_32_63), + X2ApicRead(APIC_LVT_LINT0), + X2ApicRead(APIC_LVT_LINT1), + X2ApicRead(APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT), + X2ApicRead(APIC_LVT_PERFORMANCE_MONITORING_COUNTERS), + X2ApicRead(APIC_LVT_TIMER), + X2ApicRead(APIC_LVT_THERMAL_SENSOR), + X2ApicRead(APIC_LVT_ERROR), + X2ApicRead(APIC_INITIAL_COUNT), + X2ApicRead(APIC_CURRENT_COUNT), + X2ApicRead(APIC_DIVIDE_CONFIGURATION)); + + // + // print the ISR, TMR and IRR + // + + LogInfo("ISR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + reg = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i)); + for (j = 0; j < 32; j++) + { + if (0 != (reg & k)) + { + LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + LogInfo("\n"); + + LogInfo("TMR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + reg = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i)); + + for (j = 0; j < 32; j++) + { + if (reg & k) + { + LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + LogInfo("\n"); + + LogInfo("IRR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + reg = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i)); + + for (j = 0; j < 32; j++) + { + if (reg & k) + { + LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + LogInfo("\n"); +} + /** * @brief Trigger NMI on X2APIC or APIC based on Current system * @@ -56,6 +388,24 @@ ApicTriggerGenericNmi() } } +/** + * @brief Show the details of APIC in xAPIC and x2APIC mode + * + * @return VOID + */ +VOID +ApicShowDetails() +{ + if (g_CompatibilityCheck.IsX2Apic) + { + LapicPrintPlatformX2ApicMode(); + } + else + { + LapicPrintPlatformXApicMode(); + } +} + /** * @brief Initialize APIC * @@ -67,13 +417,14 @@ ApicInitialize() UINT64 ApicBaseMSR; PHYSICAL_ADDRESS PaApicBase; - ApicBaseMSR = __readmsr(0x1B); + ApicBaseMSR = __readmsr(IA32_APIC_BASE); if (!(ApicBaseMSR & (1 << 11))) return FALSE; if (ApicBaseMSR & (1 << 10)) { g_CompatibilityCheck.IsX2Apic = TRUE; + return FALSE; } else @@ -86,6 +437,7 @@ ApicInitialize() g_CompatibilityCheck.IsX2Apic = FALSE; } + return TRUE; } diff --git a/hyperdbg/hyperhv/code/interface/Export.c b/hyperdbg/hyperhv/code/interface/Export.c index 3c2132af..f01014bd 100644 --- a/hyperdbg/hyperhv/code/interface/Export.c +++ b/hyperdbg/hyperhv/code/interface/Export.c @@ -813,3 +813,14 @@ VmFuncEnableAndCheckForPreviousExternalInterrupts(UINT32 CoreId) { HvEnableAndCheckForPreviousExternalInterrupts(&g_GuestState[CoreId]); } + +/** + * @brief Show details of xapic or x2apic + * + * @return VOID + */ +VOID +VmFuncApicShowDetails() +{ + ApicShowDetails(); +} diff --git a/hyperdbg/hyperhv/header/devices/Apic.h b/hyperdbg/hyperhv/header/devices/Apic.h index 341d2b96..07e10fa1 100644 --- a/hyperdbg/hyperhv/header/devices/Apic.h +++ b/hyperdbg/hyperhv/header/devices/Apic.h @@ -26,7 +26,7 @@ #define APIC_LVR 0x30 #define APIC_LVR_MASK 0xFF00FF -#define GET_APIC_VERSION(x) ((x)&0xFFu) +#define GET_APIC_VERSION(x) ((x) & 0xFFu) #define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFFu) #define APIC_INTEGRATED(x) (1) @@ -153,6 +153,9 @@ ApicInitialize(); VOID ApicUninitialize(); +VOID +ApicShowDetails(); + VOID ApicSelfIpi(UINT32 Vector); diff --git a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c index fa25a297..1fd0fae6 100644 --- a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c +++ b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c @@ -1763,6 +1763,11 @@ KdQuerySystemState() { ULONG ProcessorsCount; + // + // Show APIC details (test should be removed) + // + VmFuncApicShowDetails(); + ProcessorsCount = KeQueryActiveProcessorCount(0); // diff --git a/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h index 8effa78a..99265b12 100644 --- a/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h @@ -215,6 +215,9 @@ VmFuncVmxCompatibleWcsncmp(const wchar_t * Address1, const wchar_t * Address2, S IMPORT_EXPORT_VMM INT32 VmFuncVmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count); +IMPORT_EXPORT_VMM VOID +VmFuncApicShowDetails(); + ////////////////////////////////////////////////// // Configuration Functions // ////////////////////////////////////////////////// From a73b6d66f2aadd344b0bb4e1a2678e6ffe729ba3 Mon Sep 17 00:00:00 2001 From: SinaKarvandi Date: Fri, 8 Nov 2024 15:54:02 +0100 Subject: [PATCH 2/7] refactor APIC support codes --- hyperdbg/hyperhv/code/devices/Apic.c | 343 +++++++++---------------- hyperdbg/hyperhv/header/devices/Apic.h | 102 ++++++++ 2 files changed, 226 insertions(+), 219 deletions(-) diff --git a/hyperdbg/hyperhv/code/devices/Apic.c b/hyperdbg/hyperhv/code/devices/Apic.c index 8877cdd0..ac0efef3 100644 --- a/hyperdbg/hyperhv/code/devices/Apic.c +++ b/hyperdbg/hyperhv/code/devices/Apic.c @@ -2,7 +2,10 @@ * @file Apic.h * @author Sina Karvandi (sina@hyperdbg.org) * @brief Routines for Advanced Programmable Interrupt Controller (APIC) - * @details The code is derived from (https://www.cpl0.com/blog/?p=46) + * @details The code is derived from (https://www.cpl0.com/blog/?p=46) and the code + * for showing the APIC details in the XAPIC is derived from bitdefender/napoca project + * which is enhanced to support X2APIC mode in HyperDbg + * * @version 0.1 * @date 2020-12-31 * @@ -11,103 +14,6 @@ */ #include "pch.h" -#define LAPIC_LVT_FLAG_ENTRY_MASKED (1UL << 16) -#define LAPIC_LVT_DELIVERY_MODE_EXT_INT (7UL << 8) -#define LAPIC_SVR_FLAG_SW_ENABLE (1UL << 8) - -/// @brief LAPIC structure size -#define LAPIC_SIZE 0x400 - -typedef struct _LAPIC_PAGE -{ - UINT8 __reserved_000[0x10]; - UINT8 __reserved_010[0x10]; - - UINT32 Id; // offset 0x020 - UINT8 __reserved_024[0x0C]; - - UINT32 Version; // offset 0x030 - UINT8 __reserved_034[0x0C]; - - UINT8 __reserved_040[0x40]; - - UINT32 TPR; // offset 0x080 - UINT8 __reserved_084[0x0C]; - - UINT32 ArbitrationPriority; // offset 0x090 - UINT8 __reserved_094[0x0C]; - - UINT32 ProcessorPriority; // offset 0x0A0 - UINT8 __reserved_0A4[0x0C]; - - UINT32 EOI; // offset 0x0B0 - UINT8 __reserved_0B4[0x0C]; - - UINT32 RemoteRead; // offset 0x0C0 - UINT8 __reserved_0C4[0x0C]; - - UINT32 LogicalDestination; // offset 0x0D0 - UINT8 __reserved_0D4[0x0C]; - - UINT32 DestinationFormat; // offset 0x0E0 - UINT8 __reserved_0E4[0x0C]; - - UINT32 SpuriousInterruptVector; // offset 0x0F0 - UINT8 __reserved_0F4[0x0C]; - - UINT32 ISR[32]; // offset 0x100 - - UINT32 TMR[32]; // offset 0x180 - - UINT32 IRR[32]; // offset 0x200 - - UINT32 ErrorStatus; // offset 0x280 - UINT8 __reserved_284[0x0C]; - - UINT8 __reserved_290[0x60]; - - UINT32 LvtCmci; // offset 0x2F0 - UINT8 __reserved_2F4[0x0C]; - - UINT32 IcrLow; // offset 0x300 - UINT8 __reserved_304[0x0C]; - - UINT32 IcrHigh; // offset 0x310 - UINT8 __reserved_314[0x0C]; - - UINT32 LvtTimer; // offset 0x320 - UINT8 __reserved_324[0x0C]; - - UINT32 LvtThermalSensor; // offset 0x330 - UINT8 __reserved_334[0x0C]; - - UINT32 LvtPerfMonCounters; // offset 0x340 - UINT8 __reserved_344[0x0C]; - - UINT32 LvtLINT0; // offset 0x350 - UINT8 __reserved_354[0x0C]; - - UINT32 LvtLINT1; // offset 0x360 - UINT8 __reserved_364[0x0C]; - - UINT32 LvtError; // offset 0x370 - UINT8 __reserved_374[0x0C]; - - UINT32 InitialCount; // offset 0x380 - UINT8 __reserved_384[0x0C]; - - UINT32 CurrentCount; // offset 0x390 - UINT8 __reserved_394[0x0C]; - - UINT8 __reserved_3A0[0x40]; // offset 0x3A0 - - UINT32 DivideConfiguration; // offset 0x3E0 - UINT8 __reserved_3E4[0x0C]; - - UINT32 SelfIpi; // offset 0x3F0 - UINT8 __reserved_3F4[0x0C]; // valid only for X2APIC -} LAPIC_PAGE; - /** * @brief Trigger NMI on XAPIC * @param Low @@ -144,230 +50,229 @@ X2ApicIcrWrite(UINT32 Low, UINT32 High) UINT64 X2ApicRead(UINT32 Offset) { - LogInfo("Read offset at: %llx", Offset); return __readmsr(X2_MSR_BASE + TO_X2(Offset)); } +/** + * @brief Print local APIC in XAPIC mode + * + * @return VOID + */ VOID -LapicPrintPlatformXApicMode( - void) +ApicPrintLocalApicInXApicMode() { UINT8 i = 0, j = 0; UINT32 k = 0; - UINT32 reg = 0; - IA32_APIC_BASE_REGISTER ia32ApicBaseMsr; - UINT64 basePa = 0; + UINT32 Reg = 0; + IA32_APIC_BASE_REGISTER Ia32ApicBase; + UINT64 BasePa = 0; - volatile LAPIC_PAGE * lapicVa = g_ApicBase; + volatile LAPIC_PAGE * LocalApicVa = g_ApicBase; + // + // Check if the base virtual address of local APIC is valid or not + // if (!g_ApicBase) { return; } - ia32ApicBaseMsr.AsUInt = __readmsr(IA32_APIC_BASE); - basePa = ia32ApicBaseMsr.ApicBase; + Ia32ApicBase.AsUInt = __readmsr(IA32_APIC_BASE); + BasePa = Ia32ApicBase.ApicBase; - LogInfo("*** (xAPIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" - " -> TPR = 0x%08x, APR = 0x%08x, PPR = 0x%08x, RRD = 0x%08x\n" - " -> LDR = 0x%08x, DFR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" - " -> ICR_LOW = 0x%08x , ICR_HIGH = 0x%08x\n" - " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" - " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" - " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" - " -> LVT_ERR = 0x%08x\n" - " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", - lapicVa->Id >> 24, - lapicVa->Version, - (lapicVa->Version & 0xFF0000) >> 16, - (lapicVa->Version >> 24) & 1, - (lapicVa->SpuriousInterruptVector >> 12) & 1, - (lapicVa->SpuriousInterruptVector & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", - ia32ApicBaseMsr, - lapicVa->TPR, - lapicVa->ArbitrationPriority, - lapicVa->ProcessorPriority, - lapicVa->RemoteRead, - lapicVa->LogicalDestination, - lapicVa->DestinationFormat, - lapicVa->SpuriousInterruptVector, - lapicVa->ErrorStatus, - lapicVa->IcrLow, - lapicVa->IcrHigh, - lapicVa->LvtLINT0, - lapicVa->LvtLINT1, - lapicVa->LvtCmci, - lapicVa->LvtPerfMonCounters, - lapicVa->LvtTimer, - lapicVa->LvtThermalSensor, - lapicVa->LvtError, - lapicVa->InitialCount, - lapicVa->CurrentCount, - lapicVa->DivideConfiguration); + Log("*** (x2APIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" + " -> TPR = 0x%08x, PPR = 0x%08x\n" + " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" + " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" + " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" + " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" + " -> LVT_ERR = 0x%08x\n" + " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", + LocalApicVa->Id >> 24, + LocalApicVa->Version, + (LocalApicVa->Version & 0xFF0000) >> 16, + (LocalApicVa->Version >> 24) & 1, + (LocalApicVa->SpuriousInterruptVector >> 12) & 1, + (LocalApicVa->SpuriousInterruptVector & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", + Ia32ApicBase, + LocalApicVa->TPR, + LocalApicVa->ProcessorPriority, + LocalApicVa->LogicalDestination, + LocalApicVa->SpuriousInterruptVector, + LocalApicVa->ErrorStatus, + LocalApicVa->LvtLINT0, + LocalApicVa->LvtLINT1, + LocalApicVa->LvtCmci, + LocalApicVa->LvtPerfMonCounters, + LocalApicVa->LvtTimer, + LocalApicVa->LvtThermalSensor, + LocalApicVa->LvtError, + LocalApicVa->InitialCount, + LocalApicVa->CurrentCount, + LocalApicVa->DivideConfiguration); - // print the ISR, TMR and IRR - LogInfo("ISR : "); + // + // Print the ISR, TMR and IRR + // + Log("ISR : "); for (i = 0; i < 8; i++) { k = 1; - reg = (UINT32)lapicVa->ISR[i * 4]; + Reg = (UINT32)LocalApicVa->ISR[i * 4]; for (j = 0; j < 32; j++) { - if (0 != (reg & k)) + if (0 != (Reg & k)) { - LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + Log("0x%02hhx ", (UINT8)(i * 32 + j)); } k = k << 1; } } - LogInfo("\n"); + Log("\n"); - LogInfo("TMR : "); + Log("TMR : "); for (i = 0; i < 8; i++) { k = 1; - reg = (UINT32)lapicVa->TMR[i * 4]; + Reg = (UINT32)LocalApicVa->TMR[i * 4]; for (j = 0; j < 32; j++) { - if (reg & k) + if (Reg & k) { - LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + Log("0x%02hhx ", (UINT8)(i * 32 + j)); } k = k << 1; } } - LogInfo("\n"); + Log("\n"); - LogInfo("IRR : "); + Log("IRR : "); for (i = 0; i < 8; i++) { k = 1; - reg = (UINT32)lapicVa->IRR[i * 4]; + Reg = (UINT32)LocalApicVa->IRR[i * 4]; for (j = 0; j < 32; j++) { - if (reg & k) + if (Reg & k) { - LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + Log("0x%02hhx ", (UINT8)(i * 32 + j)); } k = k << 1; } } - LogInfo("\n"); + Log("\n"); return; } +/** + * @brief Print local APIC in X2APIC mode + * + * @return VOID + */ VOID -LapicPrintPlatformX2ApicMode( - void) +ApicPrintLocalApicInX2ApicMode() { UINT8 i = 0, j = 0; UINT32 k = 0; - UINT32 reg = 0; - IA32_APIC_BASE_REGISTER ia32ApicBaseMsr; + UINT32 Reg = 0; + IA32_APIC_BASE_REGISTER Ia32ApicBase; - ia32ApicBaseMsr.AsUInt = __readmsr(IA32_APIC_BASE); + Ia32ApicBase.AsUInt = __readmsr(IA32_APIC_BASE); - LogInfo("*** (x2APIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" - " -> TPR = 0x%08x, APR = 0x%08x, PPR = 0x%08x, RRD = 0x%08x\n" - " -> LDR = 0x%08x, DFR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" - " -> ICR_LOW = 0x%08x , ICR_HIGH = 0x%08x\n" - " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" - " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" - " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" - " -> LVT_ERR = 0x%08x\n" - " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", - X2ApicRead(APIC_ID) >> 24, - X2ApicRead(APIC_VERSION), - (X2ApicRead(APIC_VERSION) & 0xFF0000) >> 16, - (X2ApicRead(APIC_VERSION) >> 24) & 1, - (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) >> 12) & 1, - (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", - ia32ApicBaseMsr, - X2ApicRead(APIC_TASK_PRIORITY), - 0, // X2ApicRead(APIC_ARBITRATION_PRIORITY), - X2ApicRead(APIC_PROCESSOR_PRIORITY), - 0, // X2ApicRead(APIC_REMOTE_READ), - X2ApicRead(APIC_LOGICAL_DESTINATION), - 0, // X2ApicRead(APIC_DESTINATION_FORMAT), - X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR), - X2ApicRead(APIC_ERROR_STATUS), - 0, // X2ApicRead(APIC_INTERRUPT_COMMAND_BITS_0_31), - 0, // X2ApicRead(APIC_INTERRUPT_COMMAND_BITS_32_63), - X2ApicRead(APIC_LVT_LINT0), - X2ApicRead(APIC_LVT_LINT1), - X2ApicRead(APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT), - X2ApicRead(APIC_LVT_PERFORMANCE_MONITORING_COUNTERS), - X2ApicRead(APIC_LVT_TIMER), - X2ApicRead(APIC_LVT_THERMAL_SENSOR), - X2ApicRead(APIC_LVT_ERROR), - X2ApicRead(APIC_INITIAL_COUNT), - X2ApicRead(APIC_CURRENT_COUNT), - X2ApicRead(APIC_DIVIDE_CONFIGURATION)); + Log("*** (x2APIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" + " -> TPR = 0x%08x, PPR = 0x%08x\n" + " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" + " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" + " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" + " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" + " -> LVT_ERR = 0x%08x\n" + " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", + X2ApicRead(APIC_ID) >> 24, + X2ApicRead(APIC_VERSION), + (X2ApicRead(APIC_VERSION) & 0xFF0000) >> 16, + (X2ApicRead(APIC_VERSION) >> 24) & 1, + (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) >> 12) & 1, + (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", + Ia32ApicBase, + X2ApicRead(APIC_TASK_PRIORITY), + X2ApicRead(APIC_PROCESSOR_PRIORITY), + X2ApicRead(APIC_LOGICAL_DESTINATION), + X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR), + X2ApicRead(APIC_ERROR_STATUS), + X2ApicRead(APIC_LVT_LINT0), + X2ApicRead(APIC_LVT_LINT1), + X2ApicRead(APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT), + X2ApicRead(APIC_LVT_PERFORMANCE_MONITORING_COUNTERS), + X2ApicRead(APIC_LVT_TIMER), + X2ApicRead(APIC_LVT_THERMAL_SENSOR), + X2ApicRead(APIC_LVT_ERROR), + X2ApicRead(APIC_INITIAL_COUNT), + X2ApicRead(APIC_CURRENT_COUNT), + X2ApicRead(APIC_DIVIDE_CONFIGURATION)); // - // print the ISR, TMR and IRR + // Print the ISR, TMR and IRR // - - LogInfo("ISR : "); + Log("ISR : "); for (i = 0; i < 8; i++) { k = 1; - reg = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i)); + Reg = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i)); for (j = 0; j < 32; j++) { - if (0 != (reg & k)) + if (0 != (Reg & k)) { - LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + Log("0x%02hhx ", (UINT8)(i * 32 + j)); } k = k << 1; } } - LogInfo("\n"); + Log("\n"); - LogInfo("TMR : "); + Log("TMR : "); for (i = 0; i < 8; i++) { k = 1; - reg = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i)); + Reg = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i)); for (j = 0; j < 32; j++) { - if (reg & k) + if (Reg & k) { - LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + Log("0x%02hhx ", (UINT8)(i * 32 + j)); } k = k << 1; } } - LogInfo("\n"); + Log("\n"); - LogInfo("IRR : "); + Log("IRR : "); for (i = 0; i < 8; i++) { k = 1; - reg = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i)); + Reg = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i)); for (j = 0; j < 32; j++) { - if (reg & k) + if (Reg & k) { - LogInfo("0x%02hhx ", (UINT8)(i * 32 + j)); + Log("0x%02hhx ", (UINT8)(i * 32 + j)); } k = k << 1; } } - LogInfo("\n"); + Log("\n"); } /** @@ -398,11 +303,11 @@ ApicShowDetails() { if (g_CompatibilityCheck.IsX2Apic) { - LapicPrintPlatformX2ApicMode(); + ApicPrintLocalApicInX2ApicMode(); } else { - LapicPrintPlatformXApicMode(); + ApicPrintLocalApicInXApicMode(); } } diff --git a/hyperdbg/hyperhv/header/devices/Apic.h b/hyperdbg/hyperhv/header/devices/Apic.h index 07e10fa1..e5fc1323 100644 --- a/hyperdbg/hyperhv/header/devices/Apic.h +++ b/hyperdbg/hyperhv/header/devices/Apic.h @@ -143,6 +143,108 @@ #define APIC_BASE_MSR 0x800 +#define LAPIC_LVT_FLAG_ENTRY_MASKED (1UL << 16) +#define LAPIC_LVT_DELIVERY_MODE_EXT_INT (7UL << 8) +#define LAPIC_SVR_FLAG_SW_ENABLE (1UL << 8) + +/** + * @brief LAPIC structure size + */ +#define LAPIC_SIZE 0x400 + +/** + * @brief LAPIC structure and offsets + */ +typedef struct _LAPIC_PAGE +{ + UINT8 Reserved000[0x10]; + UINT8 Reserved010[0x10]; + + UINT32 Id; // offset 0x020 + UINT8 Reserved024[0x0C]; + + UINT32 Version; // offset 0x030 + UINT8 Reserved034[0x0C]; + + UINT8 Reserved040[0x40]; + + UINT32 TPR; // offset 0x080 + UINT8 Reserved084[0x0C]; + + UINT32 ArbitrationPriority; // offset 0x090 + UINT8 Reserved094[0x0C]; + + UINT32 ProcessorPriority; // offset 0x0A0 + UINT8 Reserved0A4[0x0C]; + + UINT32 EOI; // offset 0x0B0 + UINT8 Reserved0B4[0x0C]; + + UINT32 RemoteRead; // offset 0x0C0 + UINT8 Reserved0C4[0x0C]; + + UINT32 LogicalDestination; // offset 0x0D0 + UINT8 Reserved0D4[0x0C]; + + UINT32 DestinationFormat; // offset 0x0E0 + UINT8 Reserved0E4[0x0C]; + + UINT32 SpuriousInterruptVector; // offset 0x0F0 + UINT8 Reserved0F4[0x0C]; + + UINT32 ISR[32]; // offset 0x100 + + UINT32 TMR[32]; // offset 0x180 + + UINT32 IRR[32]; // offset 0x200 + + UINT32 ErrorStatus; // offset 0x280 + UINT8 Reserved284[0x0C]; + + UINT8 Reserved290[0x60]; + + UINT32 LvtCmci; // offset 0x2F0 + UINT8 Reserved2F4[0x0C]; + + UINT32 IcrLow; // offset 0x300 + UINT8 Reserved304[0x0C]; + + UINT32 IcrHigh; // offset 0x310 + UINT8 Reserved314[0x0C]; + + UINT32 LvtTimer; // offset 0x320 + UINT8 Reserved324[0x0C]; + + UINT32 LvtThermalSensor; // offset 0x330 + UINT8 Reserved334[0x0C]; + + UINT32 LvtPerfMonCounters; // offset 0x340 + UINT8 Reserved344[0x0C]; + + UINT32 LvtLINT0; // offset 0x350 + UINT8 Reserved354[0x0C]; + + UINT32 LvtLINT1; // offset 0x360 + UINT8 Reserved364[0x0C]; + + UINT32 LvtError; // offset 0x370 + UINT8 Reserved374[0x0C]; + + UINT32 InitialCount; // offset 0x380 + UINT8 Reserved384[0x0C]; + + UINT32 CurrentCount; // offset 0x390 + UINT8 Reserved394[0x0C]; + + UINT8 Reserved3A0[0x40]; // offset 0x3A0 + + UINT32 DivideConfiguration; // offset 0x3E0 + UINT8 Reserved3E4[0x0C]; + + UINT32 SelfIpi; // offset 0x3F0 + UINT8 Reserved3F4[0x0C]; // valid only for X2APIC +} LAPIC_PAGE, *PLAPIC_PAGE; + ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// From f09fc83643efaa41f3997c738f34e1d0a2a41522 Mon Sep 17 00:00:00 2001 From: SinaKarvandi Date: Fri, 8 Nov 2024 18:46:52 +0100 Subject: [PATCH 3/7] store APIC fields in user-mode constructed structures --- hyperdbg/hyperhv/code/devices/Apic.c | 267 +++++------------- hyperdbg/hyperhv/code/interface/Export.c | 9 +- hyperdbg/hyperhv/header/devices/Apic.h | 106 +------ .../hyperkd/code/debugger/kernel-level/Kd.c | 5 - hyperdbg/include/SDK/headers/Connection.h | 1 + hyperdbg/include/SDK/headers/Ioctls.h | 7 + .../include/SDK/headers/RequestStructures.h | 132 +++++++++ .../SDK/imports/kernel/HyperDbgVmmImports.h | 4 +- .../commands/extension-commands/apic.cpp | 258 +++++++++++++++++ .../code/debugger/kernel-level/kd.cpp | 36 +++ hyperdbg/libhyperdbg/header/debugger.h | 1 + hyperdbg/libhyperdbg/header/kd.h | 3 + hyperdbg/libhyperdbg/libhyperdbg.vcxproj | 1 + .../libhyperdbg/libhyperdbg.vcxproj.filters | 3 + 14 files changed, 529 insertions(+), 304 deletions(-) create mode 100644 hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp diff --git a/hyperdbg/hyperhv/code/devices/Apic.c b/hyperdbg/hyperhv/code/devices/Apic.c index ac0efef3..8380a0c3 100644 --- a/hyperdbg/hyperhv/code/devices/Apic.c +++ b/hyperdbg/hyperhv/code/devices/Apic.c @@ -1,5 +1,5 @@ /** - * @file Apic.h + * @file Apic.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Routines for Advanced Programmable Interrupt Controller (APIC) * @details The code is derived from (https://www.cpl0.com/blog/?p=46) and the code @@ -54,19 +54,13 @@ X2ApicRead(UINT32 Offset) } /** - * @brief Print local APIC in XAPIC mode + * @brief Store the local APIC in XAPIC mode * - * @return VOID + * @return BOOLEAN */ -VOID -ApicPrintLocalApicInXApicMode() +BOOLEAN +ApicStoretLocalApicInXApicMode(PLAPIC_PAGE LApicBuffer) { - UINT8 i = 0, j = 0; - UINT32 k = 0; - UINT32 Reg = 0; - IA32_APIC_BASE_REGISTER Ia32ApicBase; - UINT64 BasePa = 0; - volatile LAPIC_PAGE * LocalApicVa = g_ApicBase; // @@ -74,205 +68,99 @@ ApicPrintLocalApicInXApicMode() // if (!g_ApicBase) { - return; + return FALSE; } - Ia32ApicBase.AsUInt = __readmsr(IA32_APIC_BASE); - BasePa = Ia32ApicBase.ApicBase; - - Log("*** (x2APIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" - " -> TPR = 0x%08x, PPR = 0x%08x\n" - " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" - " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" - " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" - " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" - " -> LVT_ERR = 0x%08x\n" - " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", - LocalApicVa->Id >> 24, - LocalApicVa->Version, - (LocalApicVa->Version & 0xFF0000) >> 16, - (LocalApicVa->Version >> 24) & 1, - (LocalApicVa->SpuriousInterruptVector >> 12) & 1, - (LocalApicVa->SpuriousInterruptVector & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", - Ia32ApicBase, - LocalApicVa->TPR, - LocalApicVa->ProcessorPriority, - LocalApicVa->LogicalDestination, - LocalApicVa->SpuriousInterruptVector, - LocalApicVa->ErrorStatus, - LocalApicVa->LvtLINT0, - LocalApicVa->LvtLINT1, - LocalApicVa->LvtCmci, - LocalApicVa->LvtPerfMonCounters, - LocalApicVa->LvtTimer, - LocalApicVa->LvtThermalSensor, - LocalApicVa->LvtError, - LocalApicVa->InitialCount, - LocalApicVa->CurrentCount, - LocalApicVa->DivideConfiguration); - // - // Print the ISR, TMR and IRR + // Store fields // - Log("ISR : "); + LApicBuffer->Id = LocalApicVa->Id; + LApicBuffer->Version = LocalApicVa->Version; + LApicBuffer->SpuriousInterruptVector = LocalApicVa->SpuriousInterruptVector; + LApicBuffer->TPR = LocalApicVa->TPR; + LApicBuffer->ProcessorPriority = LocalApicVa->ProcessorPriority; + LApicBuffer->LogicalDestination = LocalApicVa->LogicalDestination; + LApicBuffer->ErrorStatus = LocalApicVa->ErrorStatus; + LApicBuffer->LvtLINT0 = LocalApicVa->LvtLINT0; + LApicBuffer->LvtLINT1 = LocalApicVa->LvtLINT1; + LApicBuffer->LvtCmci = LocalApicVa->LvtCmci; + LApicBuffer->LvtPerfMonCounters = LocalApicVa->LvtPerfMonCounters; + LApicBuffer->LvtTimer = LocalApicVa->LvtTimer; + LApicBuffer->LvtThermalSensor = LocalApicVa->LvtThermalSensor; + LApicBuffer->LvtError = LocalApicVa->LvtError; + LApicBuffer->InitialCount = LocalApicVa->InitialCount; + LApicBuffer->CurrentCount = LocalApicVa->CurrentCount; + LApicBuffer->DivideConfiguration = LocalApicVa->DivideConfiguration; - for (i = 0; i < 8; i++) + // + // Save the ISR, TMR and IRR + // + for (UINT32 i = 0; i < 8; i++) { - k = 1; - Reg = (UINT32)LocalApicVa->ISR[i * 4]; - for (j = 0; j < 32; j++) - { - if (0 != (Reg & k)) - { - Log("0x%02hhx ", (UINT8)(i * 32 + j)); - } - k = k << 1; - } - } - Log("\n"); - - Log("TMR : "); - - for (i = 0; i < 8; i++) - { - k = 1; - Reg = (UINT32)LocalApicVa->TMR[i * 4]; - for (j = 0; j < 32; j++) - { - if (Reg & k) - { - Log("0x%02hhx ", (UINT8)(i * 32 + j)); - } - k = k << 1; - } + LApicBuffer->ISR[i * 4] = LocalApicVa->ISR[i * 4]; } - Log("\n"); - - Log("IRR : "); - - for (i = 0; i < 8; i++) + for (UINT32 i = 0; i < 8; i++) { - k = 1; - Reg = (UINT32)LocalApicVa->IRR[i * 4]; - for (j = 0; j < 32; j++) - { - if (Reg & k) - { - Log("0x%02hhx ", (UINT8)(i * 32 + j)); - } - k = k << 1; - } + LApicBuffer->TMR[i * 4] = LocalApicVa->TMR[i * 4]; } - Log("\n"); + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->IRR[i * 4] = LocalApicVa->IRR[i * 4]; + } - return; + return TRUE; } /** - * @brief Print local APIC in X2APIC mode + * @brief Store the local APIC in X2APIC mode * - * @return VOID + * @return BOOLEAN */ -VOID -ApicPrintLocalApicInX2ApicMode() +BOOLEAN +ApicStoreLocalApicInX2ApicMode(PLAPIC_PAGE LApicBuffer) { - UINT8 i = 0, j = 0; - UINT32 k = 0; - UINT32 Reg = 0; - IA32_APIC_BASE_REGISTER Ia32ApicBase; - - Ia32ApicBase.AsUInt = __readmsr(IA32_APIC_BASE); - - Log("*** (x2APIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s'). ApicBase=0x%x\n" - " -> TPR = 0x%08x, PPR = 0x%08x\n" - " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" - " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" - " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" - " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" - " -> LVT_ERR = 0x%08x\n" - " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", - X2ApicRead(APIC_ID) >> 24, - X2ApicRead(APIC_VERSION), - (X2ApicRead(APIC_VERSION) & 0xFF0000) >> 16, - (X2ApicRead(APIC_VERSION) >> 24) & 1, - (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) >> 12) & 1, - (X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR) & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", - Ia32ApicBase, - X2ApicRead(APIC_TASK_PRIORITY), - X2ApicRead(APIC_PROCESSOR_PRIORITY), - X2ApicRead(APIC_LOGICAL_DESTINATION), - X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR), - X2ApicRead(APIC_ERROR_STATUS), - X2ApicRead(APIC_LVT_LINT0), - X2ApicRead(APIC_LVT_LINT1), - X2ApicRead(APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT), - X2ApicRead(APIC_LVT_PERFORMANCE_MONITORING_COUNTERS), - X2ApicRead(APIC_LVT_TIMER), - X2ApicRead(APIC_LVT_THERMAL_SENSOR), - X2ApicRead(APIC_LVT_ERROR), - X2ApicRead(APIC_INITIAL_COUNT), - X2ApicRead(APIC_CURRENT_COUNT), - X2ApicRead(APIC_DIVIDE_CONFIGURATION)); + // + // Store fields + // + LApicBuffer->Id = (UINT32)X2ApicRead(APIC_ID); + LApicBuffer->Version = (UINT32)X2ApicRead(APIC_VERSION); + LApicBuffer->SpuriousInterruptVector = (UINT32)X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR); + LApicBuffer->TPR = (UINT32)X2ApicRead(APIC_TASK_PRIORITY); + LApicBuffer->ProcessorPriority = (UINT32)X2ApicRead(APIC_PROCESSOR_PRIORITY); + LApicBuffer->LogicalDestination = (UINT32)X2ApicRead(APIC_LOGICAL_DESTINATION); + LApicBuffer->ErrorStatus = (UINT32)X2ApicRead(APIC_ERROR_STATUS); + LApicBuffer->LvtLINT0 = (UINT32)X2ApicRead(APIC_LVT_LINT0); + LApicBuffer->LvtLINT1 = (UINT32)X2ApicRead(APIC_LVT_LINT1); + LApicBuffer->LvtCmci = (UINT32)X2ApicRead(APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT); + LApicBuffer->LvtPerfMonCounters = (UINT32)X2ApicRead(APIC_LVT_PERFORMANCE_MONITORING_COUNTERS); + LApicBuffer->LvtTimer = (UINT32)X2ApicRead(APIC_LVT_TIMER); + LApicBuffer->LvtThermalSensor = (UINT32)X2ApicRead(APIC_LVT_THERMAL_SENSOR); + LApicBuffer->LvtError = (UINT32)X2ApicRead(APIC_LVT_ERROR); + LApicBuffer->InitialCount = (UINT32)X2ApicRead(APIC_INITIAL_COUNT); + LApicBuffer->CurrentCount = (UINT32)X2ApicRead(APIC_CURRENT_COUNT); + LApicBuffer->DivideConfiguration = (UINT32)X2ApicRead(APIC_DIVIDE_CONFIGURATION); // - // Print the ISR, TMR and IRR + // Save the ISR, TMR and IRR // - Log("ISR : "); - - for (i = 0; i < 8; i++) + for (UINT32 i = 0; i < 8; i++) { - k = 1; - Reg = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i)); - for (j = 0; j < 32; j++) - { - if (0 != (Reg & k)) - { - Log("0x%02hhx ", (UINT8)(i * 32 + j)); - } - k = k << 1; - } - } - Log("\n"); - - Log("TMR : "); - - for (i = 0; i < 8; i++) - { - k = 1; - Reg = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i)); - - for (j = 0; j < 32; j++) - { - if (Reg & k) - { - Log("0x%02hhx ", (UINT8)(i * 32 + j)); - } - k = k << 1; - } + LApicBuffer->ISR[i * 4] = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i)); } - Log("\n"); - - Log("IRR : "); - - for (i = 0; i < 8; i++) + for (UINT32 i = 0; i < 8; i++) { - k = 1; - Reg = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i)); - - for (j = 0; j < 32; j++) - { - if (Reg & k) - { - Log("0x%02hhx ", (UINT8)(i * 32 + j)); - } - k = k << 1; - } + LApicBuffer->TMR[i * 4] = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i)); } - Log("\n"); + for (UINT32 i = 0; i < 8; i++) + { + LApicBuffer->IRR[i * 4] = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i)); + } + + return TRUE; } /** @@ -294,20 +182,21 @@ ApicTriggerGenericNmi() } /** - * @brief Show the details of APIC in xAPIC and x2APIC mode + * @brief Stire the details of APIC in xAPIC and x2APIC mode + * @param LApicBuffer * - * @return VOID + * @return BOOLEAN */ -VOID -ApicShowDetails() +BOOLEAN +ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer) { if (g_CompatibilityCheck.IsX2Apic) { - ApicPrintLocalApicInX2ApicMode(); + return ApicStoreLocalApicInX2ApicMode(LApicBuffer); } else { - ApicPrintLocalApicInXApicMode(); + return ApicStoretLocalApicInXApicMode(LApicBuffer); } } diff --git a/hyperdbg/hyperhv/code/interface/Export.c b/hyperdbg/hyperhv/code/interface/Export.c index f01014bd..3ff107b0 100644 --- a/hyperdbg/hyperhv/code/interface/Export.c +++ b/hyperdbg/hyperhv/code/interface/Export.c @@ -815,12 +815,13 @@ VmFuncEnableAndCheckForPreviousExternalInterrupts(UINT32 CoreId) } /** - * @brief Show details of xapic or x2apic + * @brief Store the details Local APIC in xapic or x2apic modes + * @param LocalApicBuffer * * @return VOID */ -VOID -VmFuncApicShowDetails() +BOOLEAN +VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer) { - ApicShowDetails(); + return ApicStoreLocalApicFields(LocalApicBuffer); } diff --git a/hyperdbg/hyperhv/header/devices/Apic.h b/hyperdbg/hyperhv/header/devices/Apic.h index e5fc1323..41cfbb76 100644 --- a/hyperdbg/hyperhv/header/devices/Apic.h +++ b/hyperdbg/hyperhv/header/devices/Apic.h @@ -143,108 +143,6 @@ #define APIC_BASE_MSR 0x800 -#define LAPIC_LVT_FLAG_ENTRY_MASKED (1UL << 16) -#define LAPIC_LVT_DELIVERY_MODE_EXT_INT (7UL << 8) -#define LAPIC_SVR_FLAG_SW_ENABLE (1UL << 8) - -/** - * @brief LAPIC structure size - */ -#define LAPIC_SIZE 0x400 - -/** - * @brief LAPIC structure and offsets - */ -typedef struct _LAPIC_PAGE -{ - UINT8 Reserved000[0x10]; - UINT8 Reserved010[0x10]; - - UINT32 Id; // offset 0x020 - UINT8 Reserved024[0x0C]; - - UINT32 Version; // offset 0x030 - UINT8 Reserved034[0x0C]; - - UINT8 Reserved040[0x40]; - - UINT32 TPR; // offset 0x080 - UINT8 Reserved084[0x0C]; - - UINT32 ArbitrationPriority; // offset 0x090 - UINT8 Reserved094[0x0C]; - - UINT32 ProcessorPriority; // offset 0x0A0 - UINT8 Reserved0A4[0x0C]; - - UINT32 EOI; // offset 0x0B0 - UINT8 Reserved0B4[0x0C]; - - UINT32 RemoteRead; // offset 0x0C0 - UINT8 Reserved0C4[0x0C]; - - UINT32 LogicalDestination; // offset 0x0D0 - UINT8 Reserved0D4[0x0C]; - - UINT32 DestinationFormat; // offset 0x0E0 - UINT8 Reserved0E4[0x0C]; - - UINT32 SpuriousInterruptVector; // offset 0x0F0 - UINT8 Reserved0F4[0x0C]; - - UINT32 ISR[32]; // offset 0x100 - - UINT32 TMR[32]; // offset 0x180 - - UINT32 IRR[32]; // offset 0x200 - - UINT32 ErrorStatus; // offset 0x280 - UINT8 Reserved284[0x0C]; - - UINT8 Reserved290[0x60]; - - UINT32 LvtCmci; // offset 0x2F0 - UINT8 Reserved2F4[0x0C]; - - UINT32 IcrLow; // offset 0x300 - UINT8 Reserved304[0x0C]; - - UINT32 IcrHigh; // offset 0x310 - UINT8 Reserved314[0x0C]; - - UINT32 LvtTimer; // offset 0x320 - UINT8 Reserved324[0x0C]; - - UINT32 LvtThermalSensor; // offset 0x330 - UINT8 Reserved334[0x0C]; - - UINT32 LvtPerfMonCounters; // offset 0x340 - UINT8 Reserved344[0x0C]; - - UINT32 LvtLINT0; // offset 0x350 - UINT8 Reserved354[0x0C]; - - UINT32 LvtLINT1; // offset 0x360 - UINT8 Reserved364[0x0C]; - - UINT32 LvtError; // offset 0x370 - UINT8 Reserved374[0x0C]; - - UINT32 InitialCount; // offset 0x380 - UINT8 Reserved384[0x0C]; - - UINT32 CurrentCount; // offset 0x390 - UINT8 Reserved394[0x0C]; - - UINT8 Reserved3A0[0x40]; // offset 0x3A0 - - UINT32 DivideConfiguration; // offset 0x3E0 - UINT8 Reserved3E4[0x0C]; - - UINT32 SelfIpi; // offset 0x3F0 - UINT8 Reserved3F4[0x0C]; // valid only for X2APIC -} LAPIC_PAGE, *PLAPIC_PAGE; - ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// @@ -255,8 +153,8 @@ ApicInitialize(); VOID ApicUninitialize(); -VOID -ApicShowDetails(); +BOOLEAN +ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer); VOID ApicSelfIpi(UINT32 Vector); diff --git a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c index 1fd0fae6..fa25a297 100644 --- a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c +++ b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c @@ -1763,11 +1763,6 @@ KdQuerySystemState() { ULONG ProcessorsCount; - // - // Show APIC details (test should be removed) - // - VmFuncApicShowDetails(); - ProcessorsCount = KeQueryActiveProcessorCount(0); // diff --git a/hyperdbg/include/SDK/headers/Connection.h b/hyperdbg/include/SDK/headers/Connection.h index 65df4c72..36e8c299 100644 --- a/hyperdbg/include/SDK/headers/Connection.h +++ b/hyperdbg/include/SDK/headers/Connection.h @@ -96,6 +96,7 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_SET_SHORT_CIRCUITING_STATE, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_INJECT_PAGE_FAULT, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_WRITE_REGISTER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_ACTIONS_ON_APIC, // // Debuggee to debugger diff --git a/hyperdbg/include/SDK/headers/Ioctls.h b/hyperdbg/include/SDK/headers/Ioctls.h index 9acd0c9b..f27fe8f3 100644 --- a/hyperdbg/include/SDK/headers/Ioctls.h +++ b/hyperdbg/include/SDK/headers/Ioctls.h @@ -288,3 +288,10 @@ */ #define IOCTL_PREACTIVATE_FUNCTIONALITY \ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/** + * @brief ioctl, to perform actions related to APIC + * + */ +#define IOCTL_PERFROM_ACTIONS_ON_APIC \ + CTL_CODE(FILE_DEVICE_UNKNOWN, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS) diff --git a/hyperdbg/include/SDK/headers/RequestStructures.h b/hyperdbg/include/SDK/headers/RequestStructures.h index aba89607..1a72c7f5 100644 --- a/hyperdbg/include/SDK/headers/RequestStructures.h +++ b/hyperdbg/include/SDK/headers/RequestStructures.h @@ -1022,6 +1022,138 @@ typedef struct _DEBUGGEE_STEP_PACKET */ #define DEBUGGER_REMOTE_TRACKING_DEFAULT_COUNT_OF_STEPPING 0xffffffff +/* ============================================================================================== + +/** + * @brief Perform actions related to APIC + * + */ +typedef enum _DEBUGGER_APIC_REQUEST_TYPE +{ + DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC, + +} DEBUGGER_APIC_REQUEST_TYPE; + +/** + * @brief The structure of actions for APIC + * + */ +typedef struct _DEBUGGER_APIC_REQUEST +{ + DEBUGGER_APIC_REQUEST_TYPE ApicType; + UINT32 KernelStatus; + +} DEBUGGER_APIC_REQUEST, *PDEBUGGER_APIC_REQUEST; + +/** + * @brief Debugger size of DEBUGGER_APIC_REQUEST + * + */ +#define SIZEOF_DEBUGGER_APIC_REQUEST \ + sizeof(DEBUGGER_APIC_REQUEST) + +/** + * @brief LAPIC structure size + */ +#define LAPIC_SIZE 0x400 + +#define LAPIC_LVT_FLAG_ENTRY_MASKED (1UL << 16) +#define LAPIC_LVT_DELIVERY_MODE_EXT_INT (7UL << 8) +#define LAPIC_SVR_FLAG_SW_ENABLE (1UL << 8) + +/** + * @brief LAPIC structure and offsets + */ +typedef struct _LAPIC_PAGE +{ + UINT8 Reserved000[0x10]; + UINT8 Reserved010[0x10]; + + UINT32 Id; // offset 0x020 + UINT8 Reserved024[0x0C]; + + UINT32 Version; // offset 0x030 + UINT8 Reserved034[0x0C]; + + UINT8 Reserved040[0x40]; + + UINT32 TPR; // offset 0x080 + UINT8 Reserved084[0x0C]; + + UINT32 ArbitrationPriority; // offset 0x090 + UINT8 Reserved094[0x0C]; + + UINT32 ProcessorPriority; // offset 0x0A0 + UINT8 Reserved0A4[0x0C]; + + UINT32 EOI; // offset 0x0B0 + UINT8 Reserved0B4[0x0C]; + + UINT32 RemoteRead; // offset 0x0C0 + UINT8 Reserved0C4[0x0C]; + + UINT32 LogicalDestination; // offset 0x0D0 + UINT8 Reserved0D4[0x0C]; + + UINT32 DestinationFormat; // offset 0x0E0 + UINT8 Reserved0E4[0x0C]; + + UINT32 SpuriousInterruptVector; // offset 0x0F0 + UINT8 Reserved0F4[0x0C]; + + UINT32 ISR[32]; // offset 0x100 + + UINT32 TMR[32]; // offset 0x180 + + UINT32 IRR[32]; // offset 0x200 + + UINT32 ErrorStatus; // offset 0x280 + UINT8 Reserved284[0x0C]; + + UINT8 Reserved290[0x60]; + + UINT32 LvtCmci; // offset 0x2F0 + UINT8 Reserved2F4[0x0C]; + + UINT32 IcrLow; // offset 0x300 + UINT8 Reserved304[0x0C]; + + UINT32 IcrHigh; // offset 0x310 + UINT8 Reserved314[0x0C]; + + UINT32 LvtTimer; // offset 0x320 + UINT8 Reserved324[0x0C]; + + UINT32 LvtThermalSensor; // offset 0x330 + UINT8 Reserved334[0x0C]; + + UINT32 LvtPerfMonCounters; // offset 0x340 + UINT8 Reserved344[0x0C]; + + UINT32 LvtLINT0; // offset 0x350 + UINT8 Reserved354[0x0C]; + + UINT32 LvtLINT1; // offset 0x360 + UINT8 Reserved364[0x0C]; + + UINT32 LvtError; // offset 0x370 + UINT8 Reserved374[0x0C]; + + UINT32 InitialCount; // offset 0x380 + UINT8 Reserved384[0x0C]; + + UINT32 CurrentCount; // offset 0x390 + UINT8 Reserved394[0x0C]; + + UINT8 Reserved3A0[0x40]; // offset 0x3A0 + + UINT32 DivideConfiguration; // offset 0x3E0 + UINT8 Reserved3E4[0x0C]; + + UINT32 SelfIpi; // offset 0x3F0 + UINT8 Reserved3F4[0x0C]; // valid only for X2APIC +} LAPIC_PAGE, *PLAPIC_PAGE; + /* ============================================================================================== */ diff --git a/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h index 99265b12..9603fa32 100644 --- a/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h @@ -215,8 +215,8 @@ VmFuncVmxCompatibleWcsncmp(const wchar_t * Address1, const wchar_t * Address2, S IMPORT_EXPORT_VMM INT32 VmFuncVmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count); -IMPORT_EXPORT_VMM VOID -VmFuncApicShowDetails(); +IMPORT_EXPORT_VMM BOOLEAN +VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer); ////////////////////////////////////////////////// // Configuration Functions // diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp new file mode 100644 index 00000000..398ca549 --- /dev/null +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp @@ -0,0 +1,258 @@ +/** + * @file apic.cpp + * @author Sina Karvandi (sina@hyperdbg.org) + * @brief !apic command + * @details + * @version 0.11 + * @date 2024-11-08 + * + * @copyright This project is released under the GNU Public License v3. + * + */ +#include "pch.h" + +// +// Global Variables +// +extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee; + +/** + * @brief help of the !apic command + * + * @return VOID + */ +VOID +CommandApicHelp() +{ + ShowMessages("!apic : shows the details of Local APIC in both xAPIC and x2APIC modes.\n\n"); + + ShowMessages("syntax : \t!apic\n"); + + ShowMessages("\n"); + ShowMessages("\t\te.g : !apic\n"); +} + +/** + * @brief Send APIC requests + * + * @param ApicType + * @param ApicBuffer + * @param ExpectedRequestSize + * + * @return VOID + */ +BOOLEAN +CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, PVOID ApicBuffer, UINT32 ExpectedRequestSize) +{ + BOOL Status; + ULONG ReturnedLength; + PDEBUGGER_APIC_REQUEST ApicRequest; + UINT32 RequestSize = 0; + + RequestSize = SIZEOF_DEBUGGER_APIC_REQUEST + ExpectedRequestSize; + + // + // Allocate buffer to fill the request + // + ApicRequest = (PDEBUGGER_APIC_REQUEST)malloc(RequestSize); + + if (ApicRequest == NULL) + { + // + // Unable to allocate buffer + // + return FALSE; + } + + RtlZeroMemory(ApicRequest, RequestSize); + + // + // Set the APIC type to local apic + // Note that the APIC mode (xAPIC and x2APIC) is determined in the debugger + // + ApicRequest->ApicType = ApicType; + + if (g_IsSerialConnectedToRemoteDebuggee) + { + // + // Send the request over serial kernel debugger + // + return KdSendApicActionPacketsToDebuggee(ApicRequest, RequestSize); + } + else + { + AssertShowMessageReturnStmt(g_DeviceHandle, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturnFalse); + + // + // Send IOCTL + // + Status = DeviceIoControl( + g_DeviceHandle, // Handle to device + IOCTL_PERFROM_ACTIONS_ON_APIC, // IO Control Code (IOCTL) + &ApicRequest, // Input Buffer to driver. + SIZEOF_DEBUGGER_APIC_REQUEST, // Input buffer length + &ApicBuffer, // Output Buffer from driver. + RequestSize, // Length of output + // buffer in bytes. + &ReturnedLength, // Bytes placed in buffer. + NULL // synchronous call + ); + + if (!Status) + { + ShowMessages("ioctl failed with code 0x%x\n", GetLastError()); + return FALSE; + } + + if (ApicRequest->KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL) + { + // + // Fill the request buffer + // + RtlCopyMemory(ApicBuffer, ApicRequest, ExpectedRequestSize); + return TRUE; + } + else + { + // + // An err occurred, no results + // + ShowErrorMessage(ApicRequest->KernelStatus); + return FALSE; + } + } +} + +/** + * @brief !apic command handler + * + * @return BOOLEAN + */ +BOOLEAN +CommandGetLocalApic(PLAPIC_PAGE LocalApic) +{ + return CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC, LocalApic, sizeof(LAPIC_PAGE)); +} + +/** + * @brief !apic command handler + * + * @param CommandTokens + * @param Command + * + * @return VOID + */ +VOID +CommandApic(vector CommandTokens, string Command) +{ + UINT8 i = 0, j = 0; + UINT32 k = 0; + UINT32 Reg = 0; + LAPIC_PAGE LocalApic = {0}; + + if (CommandTokens.size() != 1) + { + ShowMessages("incorrect use of the '%s'\n\n", + GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str()); + + CommandApicHelp(); + return; + } + + // + // Get the local APIC results + // + if (CommandGetLocalApic(&LocalApic) == FALSE) + { + return; + } + + // + // Show different fields of the Local APIC + // + ShowMessages("*** (xAPIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s')\n" + " -> TPR = 0x%08x, PPR = 0x%08x\n" + " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" + " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" + " -> LVT_CMCI = 0x%08x, LVT_PMCR = 0x%08x\n" + " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" + " -> LVT_ERR = 0x%08x\n" + " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", + LocalApic.Id >> 24, + LocalApic.Version, + (LocalApic.Version & 0xFF0000) >> 16, + (LocalApic.Version >> 24) & 1, + (LocalApic.SpuriousInterruptVector >> 12) & 1, + (LocalApic.SpuriousInterruptVector & LAPIC_SVR_FLAG_SW_ENABLE) != 0 ? "Enabled" : "Disabled", + LocalApic.TPR, + LocalApic.ProcessorPriority, + LocalApic.LogicalDestination, + LocalApic.SpuriousInterruptVector, + LocalApic.ErrorStatus, + LocalApic.LvtLINT0, + LocalApic.LvtLINT1, + LocalApic.LvtCmci, + LocalApic.LvtPerfMonCounters, + LocalApic.LvtTimer, + LocalApic.LvtThermalSensor, + LocalApic.LvtError, + LocalApic.InitialCount, + LocalApic.CurrentCount, + LocalApic.DivideConfiguration); + + // + // Print the ISR, TMR and IRR + // + ShowMessages("ISR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + Reg = (UINT32)LocalApic.ISR[i * 4]; + for (j = 0; j < 32; j++) + { + if (0 != (Reg & k)) + { + ShowMessages("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + ShowMessages("\n"); + + ShowMessages("TMR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + Reg = (UINT32)LocalApic.TMR[i * 4]; + for (j = 0; j < 32; j++) + { + if (Reg & k) + { + ShowMessages("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + ShowMessages("\n"); + + ShowMessages("IRR : "); + + for (i = 0; i < 8; i++) + { + k = 1; + Reg = (UINT32)LocalApic.IRR[i * 4]; + for (j = 0; j < 32; j++) + { + if (Reg & k) + { + ShowMessages("0x%02hhx ", (UINT8)(i * 32 + j)); + } + k = k << 1; + } + } + + ShowMessages("\n"); +} diff --git a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp index 7b1fb649..cd58c51a 100644 --- a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kd.cpp @@ -984,6 +984,42 @@ KdSendVa2paAndPa2vaPacketToDebuggee(PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paAndP return TRUE; } +/** + * @brief Send requests for APIC packet to the debuggee + * @param ApicPage + * @param ExpectedRequestSize + * + * @return BOOLEAN + */ +BOOLEAN +KdSendApicActionPacketsToDebuggee(PDEBUGGER_APIC_REQUEST ApicRequest, UINT32 ExpectedRequestSize) +{ + // + // Set the request data + // + DbgWaitSetRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS, ApicRequest, ExpectedRequestSize); + + // + // Send the APIC request packets + // + if (!KdCommandPacketAndBufferToDebuggee( + DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGER_TO_DEBUGGEE_EXECUTE_ON_VMX_ROOT, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_ACTIONS_ON_APIC, + (CHAR *)ApicRequest, + sizeof(DEBUGGER_APIC_REQUEST) // only sending the request header + )) + { + return FALSE; + } + + // + // Wait until the result of actions to APIC is received + // + DbgWaitForKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS); + + return TRUE; +} + /** * @brief Sends a breakpoint set or 'bp' command packet to the debuggee * @param BpPacket diff --git a/hyperdbg/libhyperdbg/header/debugger.h b/hyperdbg/libhyperdbg/header/debugger.h index 7787088b..f34519e6 100644 --- a/hyperdbg/libhyperdbg/header/debugger.h +++ b/hyperdbg/libhyperdbg/header/debugger.h @@ -56,6 +56,7 @@ #define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_SHORT_CIRCUITING_EVENT_STATE 0x18 #define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_PAGE_IN_STATE 0x19 #define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_WRITE_REGISTER 0x1a +#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS 0x1b ////////////////////////////////////////////////// // Event Details // diff --git a/hyperdbg/libhyperdbg/header/kd.h b/hyperdbg/libhyperdbg/header/kd.h index 78cadcf9..cf3b0d05 100644 --- a/hyperdbg/libhyperdbg/header/kd.h +++ b/hyperdbg/libhyperdbg/header/kd.h @@ -198,6 +198,9 @@ KdSendBpPacketToDebuggee(PDEBUGGEE_BP_PACKET BpPacket); BOOLEAN KdSendVa2paAndPa2vaPacketToDebuggee(PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paAndPa2vaPacket); +BOOLEAN +KdSendApicActionPacketsToDebuggee(PDEBUGGER_APIC_REQUEST ApicRequest, UINT32 ExpectedRequestSize); + BOOLEAN KdSendPtePacketToDebuggee(PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PtePacket); diff --git a/hyperdbg/libhyperdbg/libhyperdbg.vcxproj b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj index a8e7d747..3dbc5824 100644 --- a/hyperdbg/libhyperdbg/libhyperdbg.vcxproj +++ b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj @@ -168,6 +168,7 @@ + diff --git a/hyperdbg/libhyperdbg/libhyperdbg.vcxproj.filters b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj.filters index 74492a7e..84538ae7 100644 --- a/hyperdbg/libhyperdbg/libhyperdbg.vcxproj.filters +++ b/hyperdbg/libhyperdbg/libhyperdbg.vcxproj.filters @@ -565,6 +565,9 @@ code\debugger\commands\hwdbg-commands + + code\debugger\commands\extension-commands + From 851375ec15bbd691e21d28a5bab82124c2dd4969 Mon Sep 17 00:00:00 2001 From: SinaKarvandi Date: Fri, 8 Nov 2024 21:00:21 +0100 Subject: [PATCH 4/7] add local apic command --- CHANGELOG.md | 8 ++ .../debugger/commands/ExtensionCommands.c | 41 ++++++++ .../hyperkd/code/debugger/kernel-level/Kd.c | 20 ++++ hyperdbg/hyperkd/code/driver/Ioctl.c | 42 ++++++++ .../debugger/commands/ExtensionCommands.h | 3 + hyperdbg/include/SDK/headers/Connection.h | 1 + hyperdbg/include/SDK/headers/Constants.h | 4 +- hyperdbg/include/SDK/headers/ErrorCodes.h | 6 ++ .../commands/extension-commands/apic.cpp | 22 +++-- .../code/debugger/core/debugger.cpp | 5 + .../code/debugger/core/interpreter.cpp | 99 ++++++++++--------- .../kernel-level/kernel-listening.cpp | 22 +++++ hyperdbg/libhyperdbg/header/commands.h | 5 + hyperdbg/libhyperdbg/header/help.h | 3 + 14 files changed, 224 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bba99790..71b3a84b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.11.0.0] - 2024-XX-XX +New release of the HyperDbg Debugger. + +### Added +- Added the local APIC command (xAPIC and x2APIC modes) ([link](https://docs.hyperdbg.org/commands/extension-commands/apic)) + +### Changed + ## [0.10.2.0] - 2024-10-11 New release of the HyperDbg Debugger. diff --git a/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c b/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c index 22e7b30b..376a8df4 100644 --- a/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c +++ b/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c @@ -12,6 +12,47 @@ */ #include "pch.h" +/** + * @brief Perform actions regarding APIC + * + * @param ApicRequest + * + * @return UINT32 Size to send to the debuggee + */ +UINT32 +ExtensionCommandPerformActionsForApicRequests(PDEBUGGER_APIC_REQUEST ApicRequest) +{ + PLAPIC_PAGE BufferToStoreLApic = (LAPIC_PAGE *)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)); + + if (ApicRequest->ApicType == DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC) + { + if (VmFuncApicStoreLocalApicFields(BufferToStoreLApic)) + { + // + // The status was okay + // + ApicRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + return sizeof(DEBUGGER_APIC_REQUEST) + sizeof(LAPIC_PAGE); + } + else + { + // + // There was an error performing the action + // + ApicRequest->KernelStatus = DEBUGGER_ERROR_APIC_ACTIONS_ERROR; + return sizeof(DEBUGGER_APIC_REQUEST); + } + } + else + { + // + // Invalid request + // + ApicRequest->KernelStatus = DEBUGGER_ERROR_APIC_ACTIONS_ERROR; + return sizeof(DEBUGGER_APIC_REQUEST); + } +} + /** * @brief routines for !va2pa and !pa2va commands * diff --git a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c index fa25a297..c8db966c 100644 --- a/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c +++ b/hyperdbg/hyperkd/code/debugger/kernel-level/Kd.c @@ -2308,6 +2308,7 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) PDEBUGGER_SEARCH_MEMORY SearchQueryPacket; PDEBUGGEE_BP_PACKET BpPacket; PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PtePacket; + PDEBUGGER_APIC_REQUEST ApicPacket; PDEBUGGER_PAGE_IN_REQUEST PageinPacket; PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS Va2paPa2vaPacket; PDEBUGGEE_BP_LIST_OR_MODIFY_PACKET BpListOrModifyPacket; @@ -2994,6 +2995,25 @@ KdDispatchAndPerformCommandsFromDebugger(PROCESSOR_DEBUGGING_STATE * DbgState) break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_ACTIONS_ON_APIC: + + ApicPacket = (DEBUGGER_APIC_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Call APIC handler (size to send is computed by this function) + // + SizeToSend = ExtensionCommandPerformActionsForApicRequests(ApicPacket); + + // + // Send the result of the APIC requests back to the debuggee + // + KdResponsePacketToDebugger(DEBUGGER_REMOTE_PACKET_TYPE_DEBUGGEE_TO_DEBUGGER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_APIC_REQUESTS, + (CHAR *)ApicPacket, + SizeToSend); + + break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_INJECT_PAGE_FAULT: PageinPacket = (DEBUGGER_PAGE_IN_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); diff --git a/hyperdbg/hyperkd/code/driver/Ioctl.c b/hyperdbg/hyperkd/code/driver/Ioctl.c index 23a27b17..86cc6b25 100644 --- a/hyperdbg/hyperkd/code/driver/Ioctl.c +++ b/hyperdbg/hyperkd/code/driver/Ioctl.c @@ -39,6 +39,7 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) PDEBUGGER_FLUSH_LOGGING_BUFFERS DebuggerFlushBuffersRequest; PDEBUGGER_PREALLOC_COMMAND DebuggerReservePreallocPoolRequest; PDEBUGGER_PREACTIVATE_COMMAND DebuggerPreactivationRequest; + PDEBUGGER_APIC_REQUEST DebuggerApicRequest; PDEBUGGER_UD_COMMAND_PACKET DebuggerUdCommandRequest; PUSERMODE_LOADED_MODULE_DETAILS DebuggerUsermodeModulesRequest; PDEBUGGER_QUERY_ACTIVE_PROCESSES_OR_THREADS DebuggerUsermodeProcessOrThreadQueryRequest; @@ -202,6 +203,7 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) break; case IOCTL_DEBUGGER_READ_OR_WRITE_MSR: + // // First validate the parameters. // @@ -1106,6 +1108,46 @@ DrvDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) break; + case IOCTL_PERFROM_ACTIONS_ON_APIC: + + // + // First validate the parameters. + // + if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_DEBUGGER_APIC_REQUEST || Irp->AssociatedIrp.SystemBuffer == NULL) + { + Status = STATUS_INVALID_PARAMETER; + LogError("Err, invalid parameter to IOCTL dispatcher"); + break; + } + + InBuffLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; + OutBuffLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; + + if (!InBuffLength || !OutBuffLength) + { + Status = STATUS_INVALID_PARAMETER; + break; + } + + // + // Both usermode and to send to usermode and the coming buffer are + // at the same place + // + DebuggerApicRequest = (PDEBUGGER_APIC_REQUEST)Irp->AssociatedIrp.SystemBuffer; + + // + // Perform the actions relating to the APIC request + // + Irp->IoStatus.Information = ExtensionCommandPerformActionsForApicRequests(DebuggerApicRequest); + Status = STATUS_SUCCESS; + + // + // Avoid zeroing it + // + DoNotChangeInformation = TRUE; + + break; + case IOCTL_SEND_USER_DEBUGGER_COMMANDS: // diff --git a/hyperdbg/hyperkd/header/debugger/commands/ExtensionCommands.h b/hyperdbg/hyperkd/header/debugger/commands/ExtensionCommands.h index c854408f..07972b7d 100644 --- a/hyperdbg/hyperkd/header/debugger/commands/ExtensionCommands.h +++ b/hyperdbg/hyperkd/header/debugger/commands/ExtensionCommands.h @@ -18,6 +18,9 @@ BOOLEAN ExtensionCommandPte(PDEBUGGER_READ_PAGE_TABLE_ENTRIES_DETAILS PteDetails, BOOLEAN IsOperatingInVmxRoot); +UINT32 +ExtensionCommandPerformActionsForApicRequests(PDEBUGGER_APIC_REQUEST ApicRequest); + VOID ExtensionCommandVa2paAndPa2va(PDEBUGGER_VA2PA_AND_PA2VA_COMMANDS AddressDetails, BOOLEAN OperateOnVmxRoot); diff --git a/hyperdbg/include/SDK/headers/Connection.h b/hyperdbg/include/SDK/headers/Connection.h index 36e8c299..9d13e190 100644 --- a/hyperdbg/include/SDK/headers/Connection.h +++ b/hyperdbg/include/SDK/headers/Connection.h @@ -130,6 +130,7 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_VA2PA_AND_PA2VA, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_BRINGING_PAGES_IN, DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_WRITE_REGISTER, + DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_APIC_REQUESTS, // // hardware debuggee to debugger diff --git a/hyperdbg/include/SDK/headers/Constants.h b/hyperdbg/include/SDK/headers/Constants.h index b6f52da7..9c0de0ae 100644 --- a/hyperdbg/include/SDK/headers/Constants.h +++ b/hyperdbg/include/SDK/headers/Constants.h @@ -17,8 +17,8 @@ ////////////////////////////////////////////////// #define VERSION_MAJOR 0 -#define VERSION_MINOR 10 -#define VERSION_PATCH 2 +#define VERSION_MINOR 11 +#define VERSION_PATCH 0 // // Example of __DATE__ string: "Jul 27 2012" diff --git a/hyperdbg/include/SDK/headers/ErrorCodes.h b/hyperdbg/include/SDK/headers/ErrorCodes.h index 76e411c2..7bc6f683 100644 --- a/hyperdbg/include/SDK/headers/ErrorCodes.h +++ b/hyperdbg/include/SDK/headers/ErrorCodes.h @@ -539,6 +539,12 @@ */ #define DEBUGGER_ERROR_INVALID_PHYSICAL_ADDRESS 0xc0000052 +/** + * @brief error, could not perform APIC actions + * + */ +#define DEBUGGER_ERROR_APIC_ACTIONS_ERROR 0xc0000053 + // // WHEN YOU ADD ANYTHING TO THIS LIST OF ERRORS, THEN // MAKE SURE TO ADD AN ERROR MESSAGE TO ShowErrorMessage(UINT32 Error) diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp index 398ca549..32de037c 100644 --- a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp @@ -42,7 +42,9 @@ CommandApicHelp() * @return VOID */ BOOLEAN -CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, PVOID ApicBuffer, UINT32 ExpectedRequestSize) +CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, + PVOID ApicBuffer, + UINT32 ExpectedRequestSize) { BOOL Status; ULONG ReturnedLength; @@ -77,7 +79,15 @@ CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, PVOID ApicBuffer, UI // // Send the request over serial kernel debugger // - return KdSendApicActionPacketsToDebuggee(ApicRequest, RequestSize); + if (!KdSendApicActionPacketsToDebuggee(ApicRequest, RequestSize)) + { + return FALSE; + } + else + { + RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize); + return TRUE; + } } else { @@ -89,9 +99,9 @@ CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, PVOID ApicBuffer, UI Status = DeviceIoControl( g_DeviceHandle, // Handle to device IOCTL_PERFROM_ACTIONS_ON_APIC, // IO Control Code (IOCTL) - &ApicRequest, // Input Buffer to driver. + ApicRequest, // Input Buffer to driver. SIZEOF_DEBUGGER_APIC_REQUEST, // Input buffer length - &ApicBuffer, // Output Buffer from driver. + ApicRequest, // Output Buffer from driver. RequestSize, // Length of output // buffer in bytes. &ReturnedLength, // Bytes placed in buffer. @@ -109,7 +119,7 @@ CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, PVOID ApicBuffer, UI // // Fill the request buffer // - RtlCopyMemory(ApicBuffer, ApicRequest, ExpectedRequestSize); + RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize); return TRUE; } else @@ -170,7 +180,7 @@ CommandApic(vector CommandTokens, string Command) // // Show different fields of the Local APIC // - ShowMessages("*** (xAPIC Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s')\n" + ShowMessages("*** PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s')\n" " -> TPR = 0x%08x, PPR = 0x%08x\n" " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" diff --git a/hyperdbg/libhyperdbg/code/debugger/core/debugger.cpp b/hyperdbg/libhyperdbg/code/debugger/core/debugger.cpp index cb0de455..f8238167 100644 --- a/hyperdbg/libhyperdbg/code/debugger/core/debugger.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/core/debugger.cpp @@ -532,6 +532,11 @@ ShowErrorMessage(UINT32 Error) Error); break; + case DEBUGGER_ERROR_APIC_ACTIONS_ERROR: + ShowMessages("err, could not perform APIC actions (%x)\n", + Error); + break; + default: ShowMessages("err, error not found (%x)\n", Error); diff --git a/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp b/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp index d756cae3..1145009f 100644 --- a/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/core/interpreter.cpp @@ -73,15 +73,14 @@ public: if (c2 == '/') // start to look for comments { - // // to solve cases like: //"}" // size_t StrLitEnd = 0; size_t StrLitBeg = input.find("\"", i); - if (StrLitBeg != std::string::npos ) + if (StrLitBeg != std::string::npos) { - if (i) + if (i) { if (input[i - 1] != '\\') // if not escaped { @@ -101,7 +100,7 @@ public: } } } - + // // assuming " }" as the end of a line comment aka //, if we are within {} // @@ -137,7 +136,7 @@ public: vector PosVec; PosVec.push_back(CloseBrktPos); PosVec.push_back(NewLineSrtPos); - PosVec.push_back(NewLineChrPos); + PosVec.push_back(NewLineChrPos); auto min = *(min_element(PosVec.begin(), PosVec.end())); // see which one occures first @@ -171,12 +170,12 @@ public: IsNewLineEsc = input[NewLineSrtPos - 1] == '\\'; } - //if (NewLineSrtPos != std::string::npos && !IsNewLineEsc) // is not escaped + // if (NewLineSrtPos != std::string::npos && !IsNewLineEsc) // is not escaped //{ - // // - // // here we could get the comment but for now we just skip - // // - // std::string comment(input.substr(i, NewLineSrtPos - i)); + // // + // // here we could get the comment but for now we just skip + // // + // std::string comment(input.substr(i, NewLineSrtPos - i)); // // // // append comments to be passed to script engine @@ -193,7 +192,7 @@ public: // continue; //} - //else if (NewLineChrPos != std::string::npos) + // else if (NewLineChrPos != std::string::npos) //{ // // // // here we could get the comment but for now we just skip @@ -215,41 +214,41 @@ public: // continue; // go past '\n' //} - //else + // else //{ - // - // no "\\n" nor '\n' found so we just mark the chars as comment till end of string - // - std::string comment(input.substr(i, input.size())); + // + // no "\\n" nor '\n' found so we just mark the chars as comment till end of string + // + std::string comment(input.substr(i, input.size())); - // fix the escaped newline - if (IsNewLineEsc) + // fix the escaped newline + if (IsNewLineEsc) + { + size_t start_pos = 0; + while ((start_pos = comment.find("\\\\n", start_pos)) != std::string::npos) { - size_t start_pos = 0; - while ((start_pos = comment.find("\\\\n", start_pos)) != std::string::npos) - { - comment.replace(start_pos, 3, "\\n"); - start_pos += 2; // Handles case where 'to' is a substring of 'from' - } - - IsNewLineEsc = false; + comment.replace(start_pos, 3, "\\n"); + start_pos += 2; // Handles case where 'to' is a substring of 'from' } - // - // append comments to be passed to script engine - // - if (IdxBracket) - { - current += comment; - } - - // - // forward the buffer - // - i = i + (input.size() - i); - - continue; + IsNewLineEsc = false; } + + // + // append comments to be passed to script engine + // + if (IdxBracket) + { + current += comment; + } + + // + // forward the buffer + // + i = i + (input.size() - i); + + continue; + } //} } else if (c2 == '*') @@ -288,7 +287,7 @@ public: if (InQuotes) { - if (c == '"' ) + if (c == '"') { if (input[i - 1] != '\\') { @@ -319,7 +318,6 @@ public: current.pop_back(); // remove last read \\ current += c; continue; - } } } @@ -353,8 +351,7 @@ public: } } - - if ( (c == ' ' || c == ' ') && !InQuotes && !IdxBracket) // finding seperator space char // Tab seperator added too + if ((c == ' ' || c == ' ') && !InQuotes && !IdxBracket) // finding seperator space char // Tab seperator added too { if (!current.empty() && current != " ") { @@ -393,7 +390,7 @@ public: } } } - else if (c == '{' && !InQuotes ) + else if (c == '{' && !InQuotes) { if (i) // check if this { is the first char to avoid out of range check { @@ -407,12 +404,12 @@ public: IdxBracket++; if (IdxBracket == 1) // first { - continue; // don't include '{' in string + continue; // don't include '{' in string } else { - input.erase(i - 1,1); - i--; //compensate for the removed char + input.erase(i - 1, 1); + i--; // compensate for the removed char current.pop_back(); // remove last read \\ } @@ -421,7 +418,7 @@ public: { IdxBracket++; if (IdxBracket == 1) // first { - continue; // don't include '{' in string + continue; // don't include '{' in string } } @@ -1448,6 +1445,10 @@ InitializeCommandsDictionary() g_CommandsList["~"] = {&CommandCore, &CommandCoreHelp, DEBUGGER_COMMAND_CORE_ATTRIBUTES}; g_CommandsList["core"] = {&CommandCore, &CommandCoreHelp, DEBUGGER_COMMAND_CORE_ATTRIBUTES}; + g_CommandsList["!apic"] = {&CommandApic, &CommandApicHelp, DEBUGGER_COMMAND_APIC_ATTRIBUTES}; + g_CommandsList["!lapic"] = {&CommandApic, &CommandApicHelp, DEBUGGER_COMMAND_APIC_ATTRIBUTES}; + g_CommandsList["!localapic"] = {&CommandApic, &CommandApicHelp, DEBUGGER_COMMAND_APIC_ATTRIBUTES}; + g_CommandsList["!monitor"] = {&CommandMonitor, &CommandMonitorHelp, DEBUGGER_COMMAND_MONITOR_ATTRIBUTES}; g_CommandsList["!vmcall"] = {&CommandVmcall, &CommandVmcallHelp, DEBUGGER_COMMAND_VMCALL_ATTRIBUTES}; diff --git a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp index 5df6cb20..a9e7c80a 100644 --- a/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/kernel-level/kernel-listening.cpp @@ -63,6 +63,7 @@ ListeningSerialPortInDebugger() PDEBUGGER_DEBUGGER_TEST_QUERY_BUFFER TestQueryPacket; PDEBUGGEE_REGISTER_READ_DESCRIPTION ReadRegisterPacket; PDEBUGGEE_REGISTER_WRITE_DESCRIPTION WriteRegisterPacket; + PDEBUGGER_APIC_REQUEST ApicRequestPacket; PDEBUGGER_READ_MEMORY ReadMemoryPacket; PDEBUGGER_EDIT_MEMORY EditMemoryPacket; PDEBUGGEE_BP_PACKET BpPacket; @@ -831,6 +832,27 @@ StartAgain: break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_APIC_REQUESTS: + + ApicRequestPacket = (DEBUGGER_APIC_REQUEST *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); + + // + // Get the address and size of the caller + // + DbgWaitGetRequestData(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS, &CallerAddress, &CallerSize); + + // + // Copy the memory buffer for the caller + // + memcpy(CallerAddress, ApicRequestPacket, CallerSize); + + // + // Signal the event relating to receiving result of performing actions into APIC + // + DbgReceivedKernelResponse(DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS); + + break; + case DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_READING_MEMORY: ReadMemoryPacket = (DEBUGGER_READ_MEMORY *)(((CHAR *)TheActualPacket) + sizeof(DEBUGGER_REMOTE_PACKET)); diff --git a/hyperdbg/libhyperdbg/header/commands.h b/hyperdbg/libhyperdbg/header/commands.h index e2299eda..c1680f43 100644 --- a/hyperdbg/libhyperdbg/header/commands.h +++ b/hyperdbg/libhyperdbg/header/commands.h @@ -322,6 +322,8 @@ typedef std::map CommandType; #define DEBUGGER_COMMAND_PTE_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE +#define DEBUGGER_COMMAND_APIC_ATTRIBUTES DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE + #define DEBUGGER_COMMAND_CORE_ATTRIBUTES \ DEBUGGER_COMMAND_ATTRIBUTE_LOCAL_COMMAND_IN_DEBUGGER_MODE @@ -697,6 +699,9 @@ CommandPe(vector CommandTokens, string Command); VOID CommandRev(vector CommandTokens, string Command); +VOID +CommandApic(vector CommandTokens, string Command); + VOID CommandTrack(vector CommandTokens, string Command); diff --git a/hyperdbg/libhyperdbg/header/help.h b/hyperdbg/libhyperdbg/header/help.h index ba803a16..f76b79ad 100644 --- a/hyperdbg/libhyperdbg/header/help.h +++ b/hyperdbg/libhyperdbg/header/help.h @@ -213,6 +213,9 @@ CommandPHelp(); VOID CommandCoreHelp(); +VOID +CommandApicHelp(); + VOID CommandProcessHelp(); From e3d8b6d980cf02f892e9aee69c137a7a7a28d1b9 Mon Sep 17 00:00:00 2001 From: SinaKarvandi Date: Sat, 9 Nov 2024 00:12:34 +0100 Subject: [PATCH 5/7] add SDK api for reading local apic --- .../include/SDK/imports/user/HyperDbgLibImports.h | 7 +++++++ .../debugger/commands/extension-commands/apic.cpp | 7 ++++--- hyperdbg/libhyperdbg/code/export/export.cpp | 15 +++++++++++++++ hyperdbg/libhyperdbg/header/debugger.h | 3 +++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h b/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h index d5206724..5865c280 100644 --- a/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h +++ b/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h @@ -232,6 +232,13 @@ hyperdbg_u_start_process(const WCHAR * path); IMPORT_EXPORT_LIBHYPERDBG BOOLEAN hyperdbg_u_start_process_with_args(const WCHAR * path, const WCHAR * arguments); +// +// APIC related command +// Exported functionality of the '!apic' command +// +IMPORT_EXPORT_LIBHYPERDBG BOOLEAN +hyperdbg_u_command_get_local_apic(PLAPIC_PAGE local_apic); + // // Assembler // Exported functionality of the 'a' command diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp index 32de037c..9a593483 100644 --- a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp @@ -134,12 +134,13 @@ CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, } /** - * @brief !apic command handler + * @brief Request to get Local APIC + * @param LocalApic * * @return BOOLEAN */ BOOLEAN -CommandGetLocalApic(PLAPIC_PAGE LocalApic) +HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic) { return CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC, LocalApic, sizeof(LAPIC_PAGE)); } @@ -172,7 +173,7 @@ CommandApic(vector CommandTokens, string Command) // // Get the local APIC results // - if (CommandGetLocalApic(&LocalApic) == FALSE) + if (HyperDbgGetLocalApic(&LocalApic) == FALSE) { return; } diff --git a/hyperdbg/libhyperdbg/code/export/export.cpp b/hyperdbg/libhyperdbg/code/export/export.cpp index 9c8590bb..f38e0b5e 100644 --- a/hyperdbg/libhyperdbg/code/export/export.cpp +++ b/hyperdbg/libhyperdbg/code/export/export.cpp @@ -684,6 +684,21 @@ hyperdbg_u_stepping_step_over_for_gu(BOOLEAN last_instruction) return SteppingStepOverForGu(last_instruction); } +/** + * @brief Get Local APIC + * @details The system automatically detects whether to read it + * in the xAPIC or x2APIC mode + * + * @param local_apic + * + * @return BOOLEAN + */ +BOOLEAN +hyperdbg_u_command_get_local_apic(PLAPIC_PAGE local_apic) +{ + return HyperDbgGetLocalApic(local_apic); +} + /** * @brief Run hwdbg script * diff --git a/hyperdbg/libhyperdbg/header/debugger.h b/hyperdbg/libhyperdbg/header/debugger.h index f34519e6..316c5481 100644 --- a/hyperdbg/libhyperdbg/header/debugger.h +++ b/hyperdbg/libhyperdbg/header/debugger.h @@ -278,3 +278,6 @@ HyperDbgDebugCurrentDeviceUsingComPort(const CHAR * PortName, DWORD Baudrate); BOOLEAN HyperDbgDebugCloseRemoteDebugger(); + +BOOLEAN +HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic); From a6c6c88d05c2b1687bd99c71d8b281a0eb6dfba8 Mon Sep 17 00:00:00 2001 From: SinaKarvandi Date: Sat, 9 Nov 2024 15:08:32 +0100 Subject: [PATCH 6/7] show different APIC modes (x2apic or xapic) --- hyperdbg/hyperhv/code/devices/Apic.c | 5 +++- hyperdbg/hyperhv/code/interface/Export.c | 5 ++-- hyperdbg/hyperhv/header/devices/Apic.h | 2 +- .../debugger/commands/ExtensionCommands.c | 7 ++++-- .../include/SDK/headers/RequestStructures.h | 1 + .../SDK/imports/kernel/HyperDbgVmmImports.h | 2 +- .../SDK/imports/user/HyperDbgLibImports.h | 2 +- .../commands/extension-commands/apic.cpp | 23 +++++++++++++++---- hyperdbg/libhyperdbg/code/export/export.cpp | 5 ++-- hyperdbg/libhyperdbg/header/debugger.h | 2 +- 10 files changed, 38 insertions(+), 16 deletions(-) diff --git a/hyperdbg/hyperhv/code/devices/Apic.c b/hyperdbg/hyperhv/code/devices/Apic.c index 8380a0c3..9b6d467b 100644 --- a/hyperdbg/hyperhv/code/devices/Apic.c +++ b/hyperdbg/hyperhv/code/devices/Apic.c @@ -184,18 +184,21 @@ ApicTriggerGenericNmi() /** * @brief Stire the details of APIC in xAPIC and x2APIC mode * @param LApicBuffer + * @param IsUsingX2APIC * * @return BOOLEAN */ BOOLEAN -ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer) +ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer, PBOOLEAN IsUsingX2APIC) { if (g_CompatibilityCheck.IsX2Apic) { + *IsUsingX2APIC = TRUE; return ApicStoreLocalApicInX2ApicMode(LApicBuffer); } else { + *IsUsingX2APIC = FALSE; return ApicStoretLocalApicInXApicMode(LApicBuffer); } } diff --git a/hyperdbg/hyperhv/code/interface/Export.c b/hyperdbg/hyperhv/code/interface/Export.c index 3ff107b0..bee44b89 100644 --- a/hyperdbg/hyperhv/code/interface/Export.c +++ b/hyperdbg/hyperhv/code/interface/Export.c @@ -817,11 +817,12 @@ VmFuncEnableAndCheckForPreviousExternalInterrupts(UINT32 CoreId) /** * @brief Store the details Local APIC in xapic or x2apic modes * @param LocalApicBuffer + * @param IsUsingX2APIC * * @return VOID */ BOOLEAN -VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer) +VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer, PBOOLEAN IsUsingX2APIC) { - return ApicStoreLocalApicFields(LocalApicBuffer); + return ApicStoreLocalApicFields(LocalApicBuffer, IsUsingX2APIC); } diff --git a/hyperdbg/hyperhv/header/devices/Apic.h b/hyperdbg/hyperhv/header/devices/Apic.h index 41cfbb76..8287a45b 100644 --- a/hyperdbg/hyperhv/header/devices/Apic.h +++ b/hyperdbg/hyperhv/header/devices/Apic.h @@ -154,7 +154,7 @@ VOID ApicUninitialize(); BOOLEAN -ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer); +ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer, PBOOLEAN IsUsingX2APIC); VOID ApicSelfIpi(UINT32 Vector); diff --git a/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c b/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c index 376a8df4..cdc1475c 100644 --- a/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c +++ b/hyperdbg/hyperkd/code/debugger/commands/ExtensionCommands.c @@ -22,16 +22,19 @@ UINT32 ExtensionCommandPerformActionsForApicRequests(PDEBUGGER_APIC_REQUEST ApicRequest) { + BOOLEAN IsUsingX2APIC = FALSE; PLAPIC_PAGE BufferToStoreLApic = (LAPIC_PAGE *)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)); if (ApicRequest->ApicType == DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC) { - if (VmFuncApicStoreLocalApicFields(BufferToStoreLApic)) + if (VmFuncApicStoreLocalApicFields(BufferToStoreLApic, &IsUsingX2APIC)) { // // The status was okay // - ApicRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + ApicRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL; + ApicRequest->IsUsingX2APIC = IsUsingX2APIC; + return sizeof(DEBUGGER_APIC_REQUEST) + sizeof(LAPIC_PAGE); } else diff --git a/hyperdbg/include/SDK/headers/RequestStructures.h b/hyperdbg/include/SDK/headers/RequestStructures.h index 1a72c7f5..4bb84c34 100644 --- a/hyperdbg/include/SDK/headers/RequestStructures.h +++ b/hyperdbg/include/SDK/headers/RequestStructures.h @@ -1041,6 +1041,7 @@ typedef enum _DEBUGGER_APIC_REQUEST_TYPE typedef struct _DEBUGGER_APIC_REQUEST { DEBUGGER_APIC_REQUEST_TYPE ApicType; + BOOLEAN IsUsingX2APIC; UINT32 KernelStatus; } DEBUGGER_APIC_REQUEST, *PDEBUGGER_APIC_REQUEST; diff --git a/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h index 9603fa32..195be25e 100644 --- a/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h +++ b/hyperdbg/include/SDK/imports/kernel/HyperDbgVmmImports.h @@ -216,7 +216,7 @@ IMPORT_EXPORT_VMM INT32 VmFuncVmxCompatibleMemcmp(const CHAR * Address1, const CHAR * Address2, size_t Count); IMPORT_EXPORT_VMM BOOLEAN -VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer); +VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer, PBOOLEAN IsUsingX2APIC); ////////////////////////////////////////////////// // Configuration Functions // diff --git a/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h b/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h index 5865c280..936e6885 100644 --- a/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h +++ b/hyperdbg/include/SDK/imports/user/HyperDbgLibImports.h @@ -237,7 +237,7 @@ hyperdbg_u_start_process_with_args(const WCHAR * path, const WCHAR * arguments); // Exported functionality of the '!apic' command // IMPORT_EXPORT_LIBHYPERDBG BOOLEAN -hyperdbg_u_command_get_local_apic(PLAPIC_PAGE local_apic); +hyperdbg_u_command_get_local_apic(PLAPIC_PAGE local_apic, BOOLEAN * is_using_x2apic); // // Assembler diff --git a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp index 9a593483..1418e20c 100644 --- a/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp +++ b/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/apic.cpp @@ -38,13 +38,15 @@ CommandApicHelp() * @param ApicType * @param ApicBuffer * @param ExpectedRequestSize + * @param IsUsingX2APIC * * @return VOID */ BOOLEAN CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, PVOID ApicBuffer, - UINT32 ExpectedRequestSize) + UINT32 ExpectedRequestSize, + PBOOLEAN IsUsingX2APIC) { BOOL Status; ULONG ReturnedLength; @@ -85,7 +87,9 @@ CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, } else { + *IsUsingX2APIC = ApicRequest->IsUsingX2APIC; RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize); + return TRUE; } } @@ -119,7 +123,9 @@ CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, // // Fill the request buffer // + *IsUsingX2APIC = ApicRequest->IsUsingX2APIC; RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize); + return TRUE; } else @@ -135,14 +141,19 @@ CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType, /** * @brief Request to get Local APIC + * * @param LocalApic + * @param IsUsingX2APIC * * @return BOOLEAN */ BOOLEAN -HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic) +HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic, PBOOLEAN IsUsingX2APIC) { - return CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC, LocalApic, sizeof(LAPIC_PAGE)); + return CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC, + LocalApic, + sizeof(LAPIC_PAGE), + IsUsingX2APIC); } /** @@ -156,6 +167,7 @@ HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic) VOID CommandApic(vector CommandTokens, string Command) { + BOOLEAN IsUsingX2APIC = FALSE; UINT8 i = 0, j = 0; UINT32 k = 0; UINT32 Reg = 0; @@ -173,7 +185,7 @@ CommandApic(vector CommandTokens, string Command) // // Get the local APIC results // - if (HyperDbgGetLocalApic(&LocalApic) == FALSE) + if (HyperDbgGetLocalApic(&LocalApic, &IsUsingX2APIC) == FALSE) { return; } @@ -181,7 +193,7 @@ CommandApic(vector CommandTokens, string Command) // // Show different fields of the Local APIC // - ShowMessages("*** PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s')\n" + ShowMessages("*** (%s Mode) PHYSICAL LAPIC ID = %u, Ver = 0x%x, MaxLvtEntry = %d, DirectedEOI = P%d/E%d, (SW: '%s')\n" " -> TPR = 0x%08x, PPR = 0x%08x\n" " -> LDR = 0x%08x, SVR = 0x%08x, Err = 0x%08x\n" " -> LVT_INT0 = 0x%08x, LVT_INT1 = 0x%08x\n" @@ -189,6 +201,7 @@ CommandApic(vector CommandTokens, string Command) " -> LVT_TMR = 0x%08x, LVT_TSR = 0x%08x\n" " -> LVT_ERR = 0x%08x\n" " -> InitialCount = 0x%08x, CurrentCount = 0x%08x, DivideConfig = 0x%08x\n", + IsUsingX2APIC ? "X2APIC" : "XAPIC", LocalApic.Id >> 24, LocalApic.Version, (LocalApic.Version & 0xFF0000) >> 16, diff --git a/hyperdbg/libhyperdbg/code/export/export.cpp b/hyperdbg/libhyperdbg/code/export/export.cpp index f38e0b5e..1e76792c 100644 --- a/hyperdbg/libhyperdbg/code/export/export.cpp +++ b/hyperdbg/libhyperdbg/code/export/export.cpp @@ -690,13 +690,14 @@ hyperdbg_u_stepping_step_over_for_gu(BOOLEAN last_instruction) * in the xAPIC or x2APIC mode * * @param local_apic + * @param is_using_x2apic * * @return BOOLEAN */ BOOLEAN -hyperdbg_u_command_get_local_apic(PLAPIC_PAGE local_apic) +hyperdbg_u_command_get_local_apic(PLAPIC_PAGE local_apic, BOOLEAN * is_using_x2apic) { - return HyperDbgGetLocalApic(local_apic); + return HyperDbgGetLocalApic(local_apic, is_using_x2apic); } /** diff --git a/hyperdbg/libhyperdbg/header/debugger.h b/hyperdbg/libhyperdbg/header/debugger.h index 316c5481..f8597746 100644 --- a/hyperdbg/libhyperdbg/header/debugger.h +++ b/hyperdbg/libhyperdbg/header/debugger.h @@ -280,4 +280,4 @@ BOOLEAN HyperDbgDebugCloseRemoteDebugger(); BOOLEAN -HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic); +HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic, PBOOLEAN IsUsingX2APIC); From 13d3efa3a442fd19fa766ca29798d205b8e66a55 Mon Sep 17 00:00:00 2001 From: SinaKarvandi Date: Sun, 10 Nov 2024 19:16:32 +0100 Subject: [PATCH 7/7] read and dump IO APIC entries --- hyperdbg/hyperhv/code/devices/Apic.c | 219 +++++++++++++++++- hyperdbg/hyperhv/header/devices/Apic.h | 58 +++++ .../hyperhv/header/globals/GlobalVariables.h | 8 +- 3 files changed, 283 insertions(+), 2 deletions(-) diff --git a/hyperdbg/hyperhv/code/devices/Apic.c b/hyperdbg/hyperhv/code/devices/Apic.c index 9b6d467b..9a2d4410 100644 --- a/hyperdbg/hyperhv/code/devices/Apic.c +++ b/hyperdbg/hyperhv/code/devices/Apic.c @@ -14,6 +14,183 @@ */ #include "pch.h" +/** + * @brief Perfom read I/O APIC + * + * @param IoApicBaseVa + * @param Reg + * + * @return UINT64 + */ +UINT64 +IoApicRead(volatile IO_APIC_ENT * IoApicBaseVa, UINT32 Reg) +{ + UINT32 High = 0, Low; + + IoApicBaseVa->Reg = Reg; + Low = IoApicBaseVa->Data; + + if (Reg >= IOAPIC_REDTBL(0) && Reg < IOAPIC_REDTBL(IOAPIC_REDTBL_MAX)) + { + // ASSERT(Reg % 2 == 0); + Reg++; + IoApicBaseVa->Reg = Reg; + High = IoApicBaseVa->Data; + return IOAPIC_APPEND_QWORD(High, Low); + } + else + { + return Low; + } +} + +/** + * @brief Perfom write to I/O APIC + * + * @param IoApicBaseVa + * @param Reg + * @param Data + * + * @return VOID + */ +VOID +IoApicWrite(volatile IO_APIC_ENT * IoApicBaseVa, UINT32 Reg, UINT64 Data) +{ + IoApicBaseVa->Reg = Reg; + IoApicBaseVa->Data = IOAPIC_LOW_DWORD(Data); + + if (Reg >= IOAPIC_REDTBL(0) && Reg < IOAPIC_REDTBL(IOAPIC_REDTBL_MAX)) + { + // ASSERT(Reg % 2 == 0); + Reg++; + IoApicBaseVa->Reg = Reg; + IoApicBaseVa->Data = IOAPIC_HIGH_DWORD(Data); + } +} + +/** + * @brief Dump redirections + * + * @param Desc + * @param CommandReg + * @param DestSelf + * @param Lh + * @param Ll + * + * @return ULONG + */ +ULONG +ApicDumpRedir(PUCHAR Desc, + BOOLEAN CommandReg, + BOOLEAN DestSelf, + ULONGLONG Lh, + ULONGLONG Ll) +{ + static PUCHAR DelMode[] = { + (PUCHAR) "FixedDel", + (PUCHAR) "LowestDl", + (PUCHAR) "res010 ", + (PUCHAR) "remoterd", + (PUCHAR) "NMI ", + (PUCHAR) "RESET ", + (PUCHAR) "res110 ", + (PUCHAR) "ExtINTA "}; + + static PUCHAR DesShDesc[] = {(PUCHAR) "", + (PUCHAR) " Dest=Self", + (PUCHAR) " Dest=ALL", + (PUCHAR) " Dest=Othrs"}; + + ULONG Del, Dest, Delstat, Rirr, Trig, Masked, Destsh; + + Del = (Ll >> 8) & 0x7; + Dest = (Ll >> 11) & 0x1; + Delstat = (Ll >> 12) & 0x1; + Rirr = (Ll >> 14) & 0x1; + Trig = (Ll >> 15) & 0x1; + Masked = (Ll >> 16) & 0x1; + Destsh = (Ll >> 18) & 0x3; + + if (CommandReg) + { + // + // command reg's don't have a mask + // + Masked = 0; + } + + Log("%s: %016llx Vec:%02X %s ", + Desc, + Ll, + Ll & 0xff, + DelMode[Del]); + + if (DestSelf) + { + Log("%s", DesShDesc[1]); + } + else if (CommandReg && Destsh) + { + Log("%s", DesShDesc[Destsh]); + } + else + { + if (Dest) + { + Log("Lg:%08x", Lh); + } + else + { + Log("PhysDest:%02X", (Lh >> 56) & 0xFF); + } + } + + Log("%s %s %s %s\n", + Delstat ? "-Pend" : " ", + Trig ? "level" : "edge ", + Rirr ? "rirr" : " ", + Masked ? "masked" : " "); + + return 0; +} + +/** + * @brief Dump I/O APIC + * + * @return VOID + */ +VOID +ApicDumpIoApic() +{ + UINT32 Index, Max; + UCHAR Desc[40]; + UINT64 ll, lh; + + UINT64 ApicBasePa = IO_APIC_DEFAULT_BASE_ADDR; + + ll = IoApicRead(g_IoApicBase, IO_VERS_REGISTER), + + Max = (ll >> 16) & 0xff; + + Log("IoApic @ %08x ID:%x (%x) Arb:%x\n", + ApicBasePa, + IoApicRead(g_IoApicBase, IO_ID_REGISTER) >> 24, + ll & 0xFF, + IoApicRead(g_IoApicBase, IO_ARB_ID_REGISTER)); + + // + // Dump inti table + // + Max *= 2; + for (Index = 0; Index <= Max; Index += 2) + { + ll = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 0); + lh = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 1); + sprintf((CHAR *)Desc, "Inti%02X.", Index / 2); + ApicDumpRedir(Desc, FALSE, FALSE, lh, ll); + } +} + /** * @brief Trigger NMI on XAPIC * @param Low @@ -121,6 +298,8 @@ ApicStoretLocalApicInXApicMode(PLAPIC_PAGE LApicBuffer) BOOLEAN ApicStoreLocalApicInX2ApicMode(PLAPIC_PAGE LApicBuffer) { + ApicDumpIoApic(); + // // Store fields // @@ -213,10 +392,36 @@ ApicInitialize() { UINT64 ApicBaseMSR; PHYSICAL_ADDRESS PaApicBase; + PHYSICAL_ADDRESS PaIoApicBase; ApicBaseMSR = __readmsr(IA32_APIC_BASE); + if (!(ApicBaseMSR & (1 << 11))) + { return FALSE; + } + + // + // Map I/O APIC default base address + // + // The exact APIC base address should be read from MADT table (ACPI) + // However, we don't have an ACPI parser right now, but the address + // is proved to stay at this (default) physical address since Intel + // recommends OS/BIOS to not relocate it, but it could be relocated + // however, this address is valid for almost all of the systems + // + PaIoApicBase.QuadPart = IO_APIC_DEFAULT_BASE_ADDR & 0xFFFFFF000; + g_IoApicBase = MmMapIoSpace(PaIoApicBase, 0x1000, MmNonCached); + + if (!g_IoApicBase) + { + // + // Not gonna fail the initialization since the IOAPIC might be relocated by + // either OS/BIOS + // + + // return FALSE; + } if (ApicBaseMSR & (1 << 10)) { @@ -230,7 +435,9 @@ ApicInitialize() g_ApicBase = MmMapIoSpace(PaApicBase, 0x1000, MmNonCached); if (!g_ApicBase) + { return FALSE; + } g_CompatibilityCheck.IsX2Apic = FALSE; } @@ -247,10 +454,20 @@ VOID ApicUninitialize() { // - // Unmap I/O Base + // Unmap Local APIC base // if (g_ApicBase) + { MmUnmapIoSpace(g_ApicBase, 0x1000); + } + + // + // Unmap I/O APIC base + // + if (g_IoApicBase) + { + MmUnmapIoSpace(g_IoApicBase, 0x1000); + } } /** diff --git a/hyperdbg/hyperhv/header/devices/Apic.h b/hyperdbg/hyperhv/header/devices/Apic.h index 8287a45b..4a69b51d 100644 --- a/hyperdbg/hyperhv/header/devices/Apic.h +++ b/hyperdbg/hyperhv/header/devices/Apic.h @@ -143,6 +143,64 @@ #define APIC_BASE_MSR 0x800 +////////////////////////////////////////////////// +// I/O APIC // +////////////////////////////////////////////////// + +typedef struct _IO_APIC_ENT +{ + UINT32 Reg; + UINT32 Pad[3]; + UINT32 Data; + +} IO_APIC_ENT, *PIO_APIC_ENT; + +#define IO_APIC_DEFAULT_BASE_ADDR 0xFEC00000 // Default physical address of IO APIC + +#define IOAPIC_APPEND_QWORD(hi, lo) (((UINT64)(hi) << 32) | (UINT64)(lo)) +#define IOAPIC_LOW_DWORD(x) ((UINT32)(x)) +#define IOAPIC_HIGH_DWORD(x) ((UINT32)((x) >> 32)) + +#define IOAPIC_REDTBL(x) (0x10 + (x) * 2) +#define IOAPIC_REDTBL_MAX (24) + +#define LU_SIZE 0x400 + +#define LU_ID_REGISTER 0x00000020 +#define LU_VERS_REGISTER 0x00000030 +#define LU_TPR 0x00000080 +#define LU_APR 0x00000090 +#define LU_PPR 0x000000A0 +#define LU_EOI 0x000000B0 +#define LU_REMOTE_REGISTER 0x000000C0 + +#define LU_DEST 0x000000D0 +#define LU_DEST_FORMAT 0x000000E0 + +#define LU_SPURIOUS_VECTOR 0x000000F0 +#define LU_FAULT_VECTOR 0x00000370 + +#define LU_ISR_0 0x00000100 +#define LU_TMR_0 0x00000180 +#define LU_IRR_0 0x00000200 +#define LU_ERROR_STATUS 0x00000280 +#define LU_INT_CMD_LOW 0x00000300 +#define LU_INT_CMD_HIGH 0x00000310 +#define LU_TIMER_VECTOR 0x00000320 +#define LU_INT_VECTOR_0 0x00000350 +#define LU_INT_VECTOR_1 0x00000360 +#define LU_INITIAL_COUNT 0x00000380 +#define LU_CURRENT_COUNT 0x00000390 +#define LU_DIVIDER_CONFIG 0x000003E0 + +#define IO_REGISTER_SELECT 0x00000000 +#define IO_REGISTER_WINDOW 0x00000010 + +#define IO_ID_REGISTER 0x00000000 +#define IO_VERS_REGISTER 0x00000001 +#define IO_ARB_ID_REGISTER 0x00000002 +#define IO_REDIR_BASE 0x00000010 + ////////////////////////////////////////////////// // Functions // ////////////////////////////////////////////////// diff --git a/hyperdbg/hyperhv/header/globals/GlobalVariables.h b/hyperdbg/hyperhv/header/globals/GlobalVariables.h index 85c720fd..8f525866 100644 --- a/hyperdbg/hyperhv/header/globals/GlobalVariables.h +++ b/hyperdbg/hyperhv/header/globals/GlobalVariables.h @@ -75,11 +75,17 @@ BOOLEAN g_IsEptHook2sDetourListInitialized; BOOLEAN g_TransparentMode; /** - * @brief APIC Base + * @brief Local APIC Base * */ VOID * g_ApicBase; +/** + * @brief I/O APIC Base + * + */ +VOID * g_IoApicBase; + /** * @brief check for broadcasting NMI mechanism support and its * initialization