mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-10 01:29:59 +00:00
Merge branch 'dev' into add-pcie-support
This commit is contained in:
commit
14a679a8dc
28 changed files with 1113 additions and 10 deletions
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
/**
|
||||
* @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)
|
||||
* @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,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
|
||||
|
|
@ -38,6 +218,130 @@ 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)
|
||||
{
|
||||
return __readmsr(X2_MSR_BASE + TO_X2(Offset));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store the local APIC in XAPIC mode
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
ApicStoretLocalApicInXApicMode(PLAPIC_PAGE LApicBuffer)
|
||||
{
|
||||
volatile LAPIC_PAGE * LocalApicVa = g_ApicBase;
|
||||
|
||||
//
|
||||
// Check if the base virtual address of local APIC is valid or not
|
||||
//
|
||||
if (!g_ApicBase)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Store fields
|
||||
//
|
||||
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;
|
||||
|
||||
//
|
||||
// Save the ISR, TMR and IRR
|
||||
//
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
LApicBuffer->ISR[i * 4] = LocalApicVa->ISR[i * 4];
|
||||
}
|
||||
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
LApicBuffer->TMR[i * 4] = LocalApicVa->TMR[i * 4];
|
||||
}
|
||||
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
LApicBuffer->IRR[i * 4] = LocalApicVa->IRR[i * 4];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store the local APIC in X2APIC mode
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
ApicStoreLocalApicInX2ApicMode(PLAPIC_PAGE LApicBuffer)
|
||||
{
|
||||
ApicDumpIoApic();
|
||||
|
||||
//
|
||||
// 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);
|
||||
|
||||
//
|
||||
// Save the ISR, TMR and IRR
|
||||
//
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
LApicBuffer->ISR[i * 4] = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i));
|
||||
}
|
||||
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
LApicBuffer->TMR[i * 4] = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i));
|
||||
}
|
||||
|
||||
for (UINT32 i = 0; i < 8; i++)
|
||||
{
|
||||
LApicBuffer->IRR[i * 4] = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trigger NMI on X2APIC or APIC based on Current system
|
||||
*
|
||||
|
|
@ -56,6 +360,28 @@ ApicTriggerGenericNmi()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stire the details of APIC in xAPIC and x2APIC mode
|
||||
* @param LApicBuffer
|
||||
* @param IsUsingX2APIC
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer, PBOOLEAN IsUsingX2APIC)
|
||||
{
|
||||
if (g_CompatibilityCheck.IsX2Apic)
|
||||
{
|
||||
*IsUsingX2APIC = TRUE;
|
||||
return ApicStoreLocalApicInX2ApicMode(LApicBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
*IsUsingX2APIC = FALSE;
|
||||
return ApicStoretLocalApicInXApicMode(LApicBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize APIC
|
||||
*
|
||||
|
|
@ -66,14 +392,41 @@ ApicInitialize()
|
|||
{
|
||||
UINT64 ApicBaseMSR;
|
||||
PHYSICAL_ADDRESS PaApicBase;
|
||||
PHYSICAL_ADDRESS PaIoApicBase;
|
||||
|
||||
ApicBaseMSR = __readmsr(IA32_APIC_BASE);
|
||||
|
||||
ApicBaseMSR = __readmsr(0x1B);
|
||||
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))
|
||||
{
|
||||
g_CompatibilityCheck.IsX2Apic = TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
|
|
@ -82,10 +435,13 @@ ApicInitialize()
|
|||
g_ApicBase = MmMapIoSpace(PaApicBase, 0x1000, MmNonCached);
|
||||
|
||||
if (!g_ApicBase)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_CompatibilityCheck.IsX2Apic = FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -98,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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -813,3 +813,16 @@ VmFuncEnableAndCheckForPreviousExternalInterrupts(UINT32 CoreId)
|
|||
{
|
||||
HvEnableAndCheckForPreviousExternalInterrupts(&g_GuestState[CoreId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store the details Local APIC in xapic or x2apic modes
|
||||
* @param LocalApicBuffer
|
||||
* @param IsUsingX2APIC
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
BOOLEAN
|
||||
VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer, PBOOLEAN IsUsingX2APIC)
|
||||
{
|
||||
return ApicStoreLocalApicFields(LocalApicBuffer, IsUsingX2APIC);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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 //
|
||||
//////////////////////////////////////////////////
|
||||
|
|
@ -153,6 +211,9 @@ ApicInitialize();
|
|||
VOID
|
||||
ApicUninitialize();
|
||||
|
||||
BOOLEAN
|
||||
ApicStoreLocalApicFields(PLAPIC_PAGE LApicBuffer, PBOOLEAN IsUsingX2APIC);
|
||||
|
||||
VOID
|
||||
ApicSelfIpi(UINT32 Vector);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -12,6 +12,50 @@
|
|||
*/
|
||||
#include "pch.h"
|
||||
|
||||
/**
|
||||
* @brief Perform actions regarding APIC
|
||||
*
|
||||
* @param ApicRequest
|
||||
*
|
||||
* @return UINT32 Size to send to the debuggee
|
||||
*/
|
||||
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, &IsUsingX2APIC))
|
||||
{
|
||||
//
|
||||
// The status was okay
|
||||
//
|
||||
ApicRequest->KernelStatus = DEBUGGER_OPERATION_WAS_SUCCESSFUL;
|
||||
ApicRequest->IsUsingX2APIC = IsUsingX2APIC;
|
||||
|
||||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -2995,6 +2996,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));
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION
|
|||
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_QUERY_PCITREE,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_ON_VMX_ROOT_PERFORM_ACTIONS_ON_APIC,
|
||||
|
||||
//
|
||||
// Debuggee to debugger
|
||||
|
|
@ -129,8 +130,9 @@ typedef enum _DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION
|
|||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PTE,
|
||||
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_WRITE_REGISTERz
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_PCITREE,
|
||||
DEBUGGER_REMOTE_PACKET_REQUESTED_ACTION_DEBUGGEE_RESULT_OF_APIC_REQUESTS,
|
||||
|
||||
//
|
||||
// hardware debuggee to debugger
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -294,4 +294,11 @@
|
|||
*
|
||||
*/
|
||||
#define IOCTL_PCIE_ENDPOINT_ENUM \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x821, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
/**
|
||||
* @brief ioctl, to perform actions related to APIC
|
||||
*
|
||||
*/
|
||||
#define IOCTL_PERFROM_ACTIONS_ON_APIC \
|
||||
CTL_CODE(FILE_DEVICE_UNKNOWN, 0x822, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
|
|
|||
|
|
@ -1023,6 +1023,139 @@ 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;
|
||||
BOOLEAN IsUsingX2APIC;
|
||||
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;
|
||||
|
||||
/* ==============================================================================================
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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 BOOLEAN
|
||||
VmFuncApicStoreLocalApicFields(PLAPIC_PAGE LocalApicBuffer, PBOOLEAN IsUsingX2APIC);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Configuration Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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, BOOLEAN * is_using_x2apic);
|
||||
|
||||
//
|
||||
// Assembler
|
||||
// Exported functionality of the 'a' command
|
||||
|
|
|
|||
|
|
@ -0,0 +1,282 @@
|
|||
/**
|
||||
* @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
|
||||
* @param IsUsingX2APIC
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
BOOLEAN
|
||||
CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE ApicType,
|
||||
PVOID ApicBuffer,
|
||||
UINT32 ExpectedRequestSize,
|
||||
PBOOLEAN IsUsingX2APIC)
|
||||
{
|
||||
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
|
||||
//
|
||||
if (!KdSendApicActionPacketsToDebuggee(ApicRequest, RequestSize))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*IsUsingX2APIC = ApicRequest->IsUsingX2APIC;
|
||||
RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
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
|
||||
ApicRequest, // 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
|
||||
//
|
||||
*IsUsingX2APIC = ApicRequest->IsUsingX2APIC;
|
||||
RtlCopyMemory(ApicBuffer, (PVOID)(((CHAR *)ApicRequest) + sizeof(DEBUGGER_APIC_REQUEST)), ExpectedRequestSize);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// An err occurred, no results
|
||||
//
|
||||
ShowErrorMessage(ApicRequest->KernelStatus);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request to get Local APIC
|
||||
*
|
||||
* @param LocalApic
|
||||
* @param IsUsingX2APIC
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic, PBOOLEAN IsUsingX2APIC)
|
||||
{
|
||||
return CommandApicSendRequest(DEBUGGER_APIC_REQUEST_TYPE_READ_LOCAL_APIC,
|
||||
LocalApic,
|
||||
sizeof(LAPIC_PAGE),
|
||||
IsUsingX2APIC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief !apic command handler
|
||||
*
|
||||
* @param CommandTokens
|
||||
* @param Command
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
CommandApic(vector<CommandToken> CommandTokens, string Command)
|
||||
{
|
||||
BOOLEAN IsUsingX2APIC = FALSE;
|
||||
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 (HyperDbgGetLocalApic(&LocalApic, &IsUsingX2APIC) == FALSE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Show different fields of the Local APIC
|
||||
//
|
||||
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"
|
||||
" -> 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",
|
||||
IsUsingX2APIC ? "X2APIC" : "XAPIC",
|
||||
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");
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1445,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};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -832,6 +833,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));
|
||||
|
|
|
|||
|
|
@ -684,6 +684,22 @@ 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
|
||||
* @param is_using_x2apic
|
||||
*
|
||||
* @return BOOLEAN
|
||||
*/
|
||||
BOOLEAN
|
||||
hyperdbg_u_command_get_local_apic(PLAPIC_PAGE local_apic, BOOLEAN * is_using_x2apic)
|
||||
{
|
||||
return HyperDbgGetLocalApic(local_apic, is_using_x2apic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Run hwdbg script
|
||||
*
|
||||
|
|
|
|||
|
|
@ -322,6 +322,8 @@ typedef std::map<std::string, COMMAND_DETAIL> 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
|
||||
|
||||
|
|
@ -700,6 +702,9 @@ CommandPe(vector<CommandToken> CommandTokens, string Command);
|
|||
VOID
|
||||
CommandRev(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
VOID
|
||||
CommandApic(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
VOID
|
||||
CommandTrack(vector<CommandToken> CommandTokens, string Command);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
#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_PCITREE_RESULT 0x1b
|
||||
#define DEBUGGER_SYNCRONIZATION_OBJECT_KERNEL_DEBUGGER_APIC_ACTIONS 0x1c
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Event Details //
|
||||
|
|
@ -278,3 +279,6 @@ HyperDbgDebugCurrentDeviceUsingComPort(const CHAR * PortName, DWORD Baudrate);
|
|||
|
||||
BOOLEAN
|
||||
HyperDbgDebugCloseRemoteDebugger();
|
||||
|
||||
BOOLEAN
|
||||
HyperDbgGetLocalApic(PLAPIC_PAGE LocalApic, PBOOLEAN IsUsingX2APIC);
|
||||
|
|
|
|||
|
|
@ -213,6 +213,9 @@ CommandPHelp();
|
|||
VOID
|
||||
CommandCoreHelp();
|
||||
|
||||
VOID
|
||||
CommandApicHelp();
|
||||
|
||||
VOID
|
||||
CommandProcessHelp();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@
|
|||
<ClCompile Include="code\debugger\commands\debugging-commands\k.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\preactivate.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\debugging-commands\prealloc.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\apic.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\crwrite.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\pcitree.cpp" />
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\rev.cpp" />
|
||||
|
|
|
|||
|
|
@ -566,6 +566,7 @@
|
|||
<Filter>code\debugger\commands\hwdbg-commands</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\pcitree.cpp">
|
||||
<ClCompile Include="code\debugger\commands\extension-commands\apic.cpp">
|
||||
<Filter>code\debugger\commands\extension-commands</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue