mirror of
https://github.com/HyperDbg/HyperDbg.git
synced 2026-07-09 17:19:26 +00:00
fix IPT kernel structure based on the new model
This commit is contained in:
parent
72a8aa325f
commit
5bccbff58b
9 changed files with 86 additions and 95 deletions
|
|
@ -155,23 +155,23 @@ PtFilter(UINT32 ProcessId, UINT64 Start, UINT64 End)
|
|||
HYPERTRACE_PT_OPERATION_PACKETS Op = {};
|
||||
|
||||
Op.PtOperationType = HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FILTER;
|
||||
Op.TraceUser = 1;
|
||||
Op.TargetProcessId = ProcessId;
|
||||
Op.FilterOptions.TraceUser = 1;
|
||||
Op.EnableOptions.Pid = ProcessId;
|
||||
|
||||
if (End > Start)
|
||||
{
|
||||
Op.NumAddrRanges = 1;
|
||||
Op.AddrRanges[0].Start = Start;
|
||||
Op.AddrRanges[0].End = End;
|
||||
Op.FilterOptions.NumAddrRanges = 1;
|
||||
Op.FilterOptions.AddrRanges[0].Start = Start;
|
||||
Op.FilterOptions.AddrRanges[0].End = End;
|
||||
}
|
||||
|
||||
if (!hyperdbg_u_pt_operation(&Op))
|
||||
return FALSE;
|
||||
|
||||
printf("[+] PT filter: cr3=0x%llx traceuser=%u ranges=%u buffer=0x%llx\n",
|
||||
(unsigned long long)Op.TargetCr3,
|
||||
Op.TraceUser,
|
||||
Op.NumAddrRanges,
|
||||
(unsigned long long)Op.EnableOptions.Cr3,
|
||||
Op.FilterOptions.TraceUser,
|
||||
Op.FilterOptions.NumAddrRanges,
|
||||
(unsigned long long)Op.BufferSize);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1670,13 +1670,13 @@ DrvDispatchHyperTraceIoControl(PIRP Irp, PIO_STACK_LOCATION IrpStack, BOOLEAN *
|
|||
// kernel/user CR3 is chosen based on the requested trace mode so
|
||||
// it works whether or not KVA shadowing (KPTI) is enabled.
|
||||
//
|
||||
if (HyperTracePtOperationRequest->TargetProcessId != 0 &&
|
||||
HyperTracePtOperationRequest->TargetCr3 == 0)
|
||||
if (HyperTracePtOperationRequest->EnableOptions.Pid != 0 &&
|
||||
HyperTracePtOperationRequest->EnableOptions.Cr3 == 0)
|
||||
{
|
||||
HyperTracePtOperationRequest->TargetCr3 =
|
||||
DrvResolvePtTargetCr3(HyperTracePtOperationRequest->TargetProcessId,
|
||||
(BOOLEAN)(HyperTracePtOperationRequest->TraceUser != 0),
|
||||
(BOOLEAN)(HyperTracePtOperationRequest->TraceKernel != 0));
|
||||
HyperTracePtOperationRequest->EnableOptions.Cr3 =
|
||||
DrvResolvePtTargetCr3(HyperTracePtOperationRequest->EnableOptions.Pid,
|
||||
(BOOLEAN)(HyperTracePtOperationRequest->FilterOptions.TraceUser != 0),
|
||||
(BOOLEAN)(HyperTracePtOperationRequest->FilterOptions.TraceKernel != 0));
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -36,26 +36,26 @@ HyperTracePtBuildConfig(const HYPERTRACE_PT_OPERATION_PACKETS * Req,
|
|||
// If the request specifies neither user nor kernel, default to both
|
||||
// (matches LBR behaviour when filter is empty).
|
||||
//
|
||||
if (Req->TraceUser || Req->TraceKernel)
|
||||
if (Req->FilterOptions.TraceUser || Req->FilterOptions.TraceKernel)
|
||||
{
|
||||
OutCfg->TraceUser = (Req->TraceUser != 0) ? TRUE : FALSE;
|
||||
OutCfg->TraceKernel = (Req->TraceKernel != 0) ? TRUE : FALSE;
|
||||
OutCfg->TraceUser = (Req->FilterOptions.TraceUser != 0) ? TRUE : FALSE;
|
||||
OutCfg->TraceKernel = (Req->FilterOptions.TraceKernel != 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
OutCfg->TargetCr3 = Req->TargetCr3;
|
||||
OutCfg->TargetCr3 = Req->EnableOptions.Cr3;
|
||||
|
||||
if (Req->BufferSize != 0)
|
||||
{
|
||||
OutCfg->BufferSize = Req->BufferSize;
|
||||
}
|
||||
|
||||
OutCfg->NumAddrRanges = Req->NumAddrRanges;
|
||||
OutCfg->NumAddrRanges = Req->FilterOptions.NumAddrRanges;
|
||||
if (OutCfg->NumAddrRanges > PT_MAX_ADDR_RANGES)
|
||||
OutCfg->NumAddrRanges = PT_MAX_ADDR_RANGES;
|
||||
|
||||
for (Copy = 0; Copy < OutCfg->NumAddrRanges; Copy++)
|
||||
{
|
||||
OutCfg->AddrRanges[Copy] = Req->AddrRanges[Copy];
|
||||
OutCfg->AddrRanges[Copy] = Req->FilterOptions.AddrRanges[Copy];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -284,6 +284,7 @@ HyperTracePtSize(HYPERTRACE_PT_OPERATION_PACKETS * HyperTraceOperationRequest)
|
|||
return FALSE;
|
||||
|
||||
ProcessorsCount = KeQueryActiveProcessorCount(0);
|
||||
|
||||
if (ProcessorsCount > PT_MAX_CPUS_FOR_MMAP)
|
||||
ProcessorsCount = PT_MAX_CPUS_FOR_MMAP;
|
||||
|
||||
|
|
@ -405,37 +406,37 @@ HyperTracePtFlush(HYPERTRACE_PT_OPERATION_PACKETS * HyperTraceOperationRequest)
|
|||
BOOLEAN
|
||||
HyperTracePtFilter(HYPERTRACE_PT_OPERATION_PACKETS * Req)
|
||||
{
|
||||
PT_FILTER_OPTIONS FilterOptions = {0};
|
||||
BOOLEAN WasEnabled = g_ProcessorTraceEnabled;
|
||||
BOOLEAN BufferChanged = FALSE;
|
||||
UINT64 ExistingSize = 0;
|
||||
UINT32 Copy;
|
||||
PT_APPLY_CORE_FILTER_REQUEST ApplyCoreFilterReq = {0};
|
||||
BOOLEAN WasEnabled = g_ProcessorTraceEnabled;
|
||||
BOOLEAN BufferChanged = FALSE;
|
||||
UINT64 ExistingSize = 0;
|
||||
|
||||
//
|
||||
// Translate the user-mode packet into PT_FILTER_OPTIONS — the narrow
|
||||
// Copy the user-mode request into a kernel-mode PT_APPLY_CORE_FILTER_REQUEST
|
||||
//
|
||||
memcpy(&ApplyCoreFilterReq.FilterOptions, &Req->FilterOptions, sizeof(PT_FILTER_OPTIONS));
|
||||
memcpy(&ApplyCoreFilterReq.EnableOptions, &Req->EnableOptions, sizeof(PT_ENABLE_OPTIONS));
|
||||
ApplyCoreFilterReq.BufferSize = Req->BufferSize;
|
||||
|
||||
//
|
||||
// Translate the user-mode packet into PT_FILTER_OPTIONS - the narrow
|
||||
// surface PtFilter operates on. Default to user+kernel when the
|
||||
// caller specified neither (matches LBR's empty-filter behaviour).
|
||||
//
|
||||
if (Req->TraceUser || Req->TraceKernel)
|
||||
if (Req->FilterOptions.TraceUser || Req->FilterOptions.TraceKernel)
|
||||
{
|
||||
FilterOptions.TraceUser = (Req->TraceUser != 0) ? TRUE : FALSE;
|
||||
FilterOptions.TraceKernel = (Req->TraceKernel != 0) ? TRUE : FALSE;
|
||||
ApplyCoreFilterReq.FilterOptions.TraceUser = (Req->FilterOptions.TraceUser != 0) ? TRUE : FALSE;
|
||||
ApplyCoreFilterReq.FilterOptions.TraceKernel = (Req->FilterOptions.TraceKernel != 0) ? TRUE : FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
FilterOptions.TraceUser = TRUE;
|
||||
FilterOptions.TraceKernel = TRUE;
|
||||
}
|
||||
FilterOptions.TargetCr3 = Req->TargetCr3;
|
||||
FilterOptions.BufferSize = Req->BufferSize;
|
||||
FilterOptions.NumAddrRanges = Req->NumAddrRanges;
|
||||
if (FilterOptions.NumAddrRanges > PT_MAX_ADDR_RANGES)
|
||||
FilterOptions.NumAddrRanges = PT_MAX_ADDR_RANGES;
|
||||
for (Copy = 0; Copy < FilterOptions.NumAddrRanges; Copy++)
|
||||
{
|
||||
FilterOptions.AddrRanges[Copy] = Req->AddrRanges[Copy];
|
||||
ApplyCoreFilterReq.FilterOptions.TraceUser = TRUE;
|
||||
ApplyCoreFilterReq.FilterOptions.TraceKernel = TRUE;
|
||||
}
|
||||
|
||||
if (Req->FilterOptions.NumAddrRanges > PT_MAX_ADDR_RANGES)
|
||||
ApplyCoreFilterReq.FilterOptions.NumAddrRanges = PT_MAX_ADDR_RANGES;
|
||||
|
||||
//
|
||||
// Decide between fast (filter-only) and slow (buffer-resize) paths.
|
||||
//
|
||||
|
|
@ -443,7 +444,8 @@ HyperTracePtFilter(HYPERTRACE_PT_OPERATION_PACKETS * Req)
|
|||
{
|
||||
ExistingSize = g_PtStateList[0].Config.BufferSize;
|
||||
}
|
||||
if (FilterOptions.BufferSize != 0 && FilterOptions.BufferSize != ExistingSize)
|
||||
|
||||
if (ApplyCoreFilterReq.BufferSize != 0 && ApplyCoreFilterReq.BufferSize != ExistingSize)
|
||||
{
|
||||
BufferChanged = TRUE;
|
||||
}
|
||||
|
|
@ -495,8 +497,8 @@ HyperTracePtFilter(HYPERTRACE_PT_OPERATION_PACKETS * Req)
|
|||
// unchanged. Force FilterOptions.BufferSize=0 so PtFilter on each core
|
||||
// keeps the buffer that's already allocated, then broadcast.
|
||||
//
|
||||
FilterOptions.BufferSize = 0;
|
||||
BroadcastFilterPtOnAllCores(&FilterOptions);
|
||||
ApplyCoreFilterReq.BufferSize = 0;
|
||||
BroadcastFilterPtOnAllCores(&ApplyCoreFilterReq);
|
||||
}
|
||||
|
||||
if (Req != NULL)
|
||||
|
|
|
|||
|
|
@ -153,10 +153,12 @@ BroadcastFlushPtOnAllCores()
|
|||
* pointer is passed to every per-core DPC; KeGenericCallDpc is
|
||||
* synchronous so the caller's storage is valid throughout.
|
||||
*
|
||||
* @param FilterRequest Pointer to a PT_APPLY_CORE_FILTER_REQUEST structure containing the filter options to apply on all cores
|
||||
*
|
||||
* @return VOID
|
||||
*/
|
||||
VOID
|
||||
BroadcastFilterPtOnAllCores(PT_FILTER_OPTIONS * FilterOptions)
|
||||
BroadcastFilterPtOnAllCores(PT_APPLY_CORE_FILTER_REQUEST * FilterRequest)
|
||||
{
|
||||
KeGenericCallDpc(DpcRoutineFilterPt, (PVOID)FilterOptions);
|
||||
KeGenericCallDpc(DpcRoutineFilterPt, (PVOID)FilterRequest);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ DpcRoutineFlushPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOI
|
|||
/**
|
||||
* @brief Broadcast applying a PT filter to all cores.
|
||||
*
|
||||
* DeferredContext carries the PT_FILTER_OPTIONS * supplied by the
|
||||
* DeferredContext carries the PT_APPLY_CORE_FILTER_REQUEST * supplied by the
|
||||
* broadcaster; PtFilter writes the user-tunable fields into the
|
||||
* current CPU's per-CPU PT_TRACE_CONFIG and reprograms PT MSRs.
|
||||
*/
|
||||
|
|
@ -339,7 +339,7 @@ DpcRoutineFilterPt(KDPC * Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
|
|||
{
|
||||
UNREFERENCED_PARAMETER(Dpc);
|
||||
|
||||
PtFilter((const PT_FILTER_OPTIONS *)DeferredContext);
|
||||
PtFilter((const PT_APPLY_CORE_FILTER_REQUEST *)DeferredContext);
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Synchronize the end of this routine with the caller
|
||||
|
|
|
|||
|
|
@ -1399,14 +1399,14 @@ PtDump()
|
|||
* handles that case before broadcasting.
|
||||
*/
|
||||
VOID
|
||||
PtFilter(const PT_FILTER_OPTIONS * FilterOptions)
|
||||
PtFilter(const PT_APPLY_CORE_FILTER_REQUEST * FilterRequest)
|
||||
{
|
||||
UINT32 CurrentCore;
|
||||
PT_PER_CPU * Cpu;
|
||||
UINT32 i;
|
||||
PT_CAPABILITIES Caps = {0};
|
||||
|
||||
if (g_PtStateList == NULL || FilterOptions == NULL)
|
||||
if (g_PtStateList == NULL || FilterRequest == NULL)
|
||||
return;
|
||||
|
||||
if (PtEngineQueryCapabilities(&Caps) != 0)
|
||||
|
|
@ -1429,42 +1429,42 @@ PtFilter(const PT_FILTER_OPTIONS * FilterOptions)
|
|||
//
|
||||
// Apply only the user-tunable fields to this CPU's per-CPU config.
|
||||
//
|
||||
Cpu->Config.TraceUser = FilterOptions->TraceUser;
|
||||
Cpu->Config.TraceKernel = FilterOptions->TraceKernel;
|
||||
Cpu->Config.TraceUser = (BOOLEAN)FilterRequest->FilterOptions.TraceUser;
|
||||
Cpu->Config.TraceKernel = (BOOLEAN)FilterRequest->FilterOptions.TraceKernel;
|
||||
|
||||
if (FilterOptions->TargetCr3 != 0 && !Caps.Cr3Filtering)
|
||||
if (FilterRequest->EnableOptions.Cr3 != 0 && !Caps.Cr3Filtering)
|
||||
{
|
||||
LogInfo("PT: CR3 filtering requested but not supported by CPU\n");
|
||||
Cpu->Config.TargetCr3 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Cpu->Config.TargetCr3 = FilterOptions->TargetCr3;
|
||||
Cpu->Config.TargetCr3 = FilterRequest->EnableOptions.Cr3;
|
||||
}
|
||||
|
||||
if (FilterOptions->NumAddrRanges > Caps.NumAddrRanges)
|
||||
if (FilterRequest->FilterOptions.NumAddrRanges > Caps.NumAddrRanges)
|
||||
{
|
||||
LogInfo("PT: requested %u IP filter ranges, but CPU only supports %u\n", FilterOptions->NumAddrRanges, Caps.NumAddrRanges);
|
||||
LogInfo("PT: requested %u IP filter ranges, but CPU only supports %u\n", FilterRequest->FilterOptions.NumAddrRanges, Caps.NumAddrRanges);
|
||||
Cpu->Config.NumAddrRanges = Caps.NumAddrRanges;
|
||||
}
|
||||
else if (FilterOptions->NumAddrRanges > 0 && !Caps.IpFiltering)
|
||||
else if (FilterRequest->FilterOptions.NumAddrRanges > 0 && !Caps.IpFiltering)
|
||||
{
|
||||
LogInfo("PT: IP filtering requested but not supported by CPU\n");
|
||||
Cpu->Config.NumAddrRanges = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Cpu->Config.NumAddrRanges = FilterOptions->NumAddrRanges;
|
||||
Cpu->Config.NumAddrRanges = FilterRequest->FilterOptions.NumAddrRanges;
|
||||
}
|
||||
|
||||
if (FilterOptions->BufferSize != 0)
|
||||
if (FilterRequest->BufferSize != 0)
|
||||
{
|
||||
Cpu->Config.BufferSize = FilterOptions->BufferSize;
|
||||
Cpu->Config.BufferSize = FilterRequest->BufferSize;
|
||||
}
|
||||
|
||||
for (i = 0; i < PT_MAX_ADDR_RANGES; i++)
|
||||
{
|
||||
Cpu->Config.AddrRanges[i] = FilterOptions->AddrRanges[i];
|
||||
Cpu->Config.AddrRanges[i] = FilterRequest->FilterOptions.AddrRanges[i];
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -50,4 +50,4 @@ VOID
|
|||
BroadcastFlushPtOnAllCores();
|
||||
|
||||
VOID
|
||||
BroadcastFilterPtOnAllCores(PT_FILTER_OPTIONS * FilterOptions);
|
||||
BroadcastFilterPtOnAllCores(PT_APPLY_CORE_FILTER_REQUEST * FilterRequest);
|
||||
|
|
|
|||
|
|
@ -12,42 +12,10 @@
|
|||
*/
|
||||
#pragma once
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Constants //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
//
|
||||
// Pool tag for PT contiguous allocations (ASCII "PtHd")
|
||||
//
|
||||
#define POOL_TAG_PT 'dHtP'
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Structures //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @brief Narrow input descriptor for PtFilter.
|
||||
*
|
||||
* These are the only fields a caller is allowed to set per-CPU
|
||||
* when reconfiguring an active PT trace. Engine-internal options
|
||||
* (BranchEn, TscEn, MtcEn, CycEn, RetCompression, *Freq, etc.)
|
||||
* stay under the engine's control and are NOT exposed here.
|
||||
*
|
||||
* BufferSize == 0 means "keep whatever the per-CPU slot already
|
||||
* has" — pure filter changes don't touch the ToPA / output /
|
||||
* overflow buffers and can run from a DPC.
|
||||
*/
|
||||
typedef struct _PT_FILTER_OPTIONS
|
||||
{
|
||||
BOOLEAN TraceUser;
|
||||
BOOLEAN TraceKernel;
|
||||
UINT64 TargetCr3;
|
||||
UINT64 BufferSize;
|
||||
UINT32 NumAddrRanges;
|
||||
PT_ADDR_RANGE AddrRanges[PT_MAX_ADDR_RANGES];
|
||||
|
||||
} PT_FILTER_OPTIONS, *PPT_FILTER_OPTIONS;
|
||||
|
||||
/**
|
||||
* @brief Per-CPU bookkeeping for the user-mode mmap surface.
|
||||
*
|
||||
|
|
@ -63,6 +31,17 @@ typedef struct _PT_USER_MAPPING
|
|||
|
||||
} PT_USER_MAPPING, *PPT_USER_MAPPING;
|
||||
|
||||
/**
|
||||
* @brief PT apply core filter requests.
|
||||
*/
|
||||
typedef struct _PT_APPLY_CORE_FILTER_REQUEST
|
||||
{
|
||||
PT_FILTER_OPTIONS FilterOptions;
|
||||
PT_ENABLE_OPTIONS EnableOptions;
|
||||
UINT64 BufferSize; /* Output buffer size (0 = default / PT_DEFAULT_BUFFER_SIZE) */
|
||||
|
||||
} PT_APPLY_CORE_FILTER_REQUEST, *PPT_APPLY_CORE_FILTER_REQUEST;
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// Functions //
|
||||
//////////////////////////////////////////////////
|
||||
|
|
@ -97,14 +76,14 @@ PtFlush();
|
|||
|
||||
//
|
||||
// LBR-style filter wrapper, one CPU at a time. Mirrors LbrFilter in shape:
|
||||
// caller passes a PT_FILTER_OPTIONS describing only the user-tunable bits
|
||||
// caller passes a PT_APPLY_CORE_FILTER_REQUEST describing only the user-tunable bits
|
||||
// (TraceUser, TraceKernel, TargetCr3, BufferSize, NumAddrRanges, AddrRanges),
|
||||
// and PtFilter handles the stop / config-update / start sequence on the
|
||||
// CURRENT CPU. Engine-internal config (BranchEn, TscEn, etc.) is left
|
||||
// untouched in the per-CPU PT_TRACE_CONFIG.
|
||||
//
|
||||
VOID
|
||||
PtFilter(const PT_FILTER_OPTIONS * FilterOptions);
|
||||
PtFilter(const PT_APPLY_CORE_FILTER_REQUEST * FilterRequest);
|
||||
|
||||
//
|
||||
// PASSIVE_LEVEL helpers — call before / after the per-core DPC broadcasts.
|
||||
|
|
|
|||
|
|
@ -1355,6 +1355,7 @@ typedef enum _HYPERTRACE_PT_OPERATION_REQUEST_TYPE
|
|||
HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DISABLE,
|
||||
HYPERTRACE_PT_OPERATION_REQUEST_TYPE_PAUSE,
|
||||
HYPERTRACE_PT_OPERATION_REQUEST_TYPE_RESUME,
|
||||
HYPERTRACE_PT_OPERATION_REQUEST_TYPE_SIZE,
|
||||
HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FLUSH,
|
||||
HYPERTRACE_PT_OPERATION_REQUEST_TYPE_DUMP,
|
||||
HYPERTRACE_PT_OPERATION_REQUEST_TYPE_FILTER,
|
||||
|
|
@ -1395,6 +1396,7 @@ typedef struct _PT_FILTER_OPTIONS
|
|||
UINT32 TraceUser : 1; // Trace user mode
|
||||
UINT32 TraceKernel : 1; // Trace kernel mode
|
||||
|
||||
UINT8 NumAddrRanges; /* Number of valid AddrRanges entries */
|
||||
PT_ADDR_RANGE AddrRanges[PT_MAX_ADDR_RANGES]; // Address ranges to filter by
|
||||
|
||||
} PT_FILTER_OPTIONS, *PPT_FILTER_OPTIONS;
|
||||
|
|
@ -1442,6 +1444,12 @@ typedef struct _HYPERTRACE_PT_OPERATION_PACKETS
|
|||
//
|
||||
PT_PACKET_OPTIONS PacketOptions; /* Options for PT packets */
|
||||
|
||||
//
|
||||
// Size
|
||||
//
|
||||
UINT32 NumCpus; /* CPUs populated in BytesPerCpu */
|
||||
UINT64 BytesPerCpu[PT_MAX_CPUS_FOR_MMAP];
|
||||
|
||||
} HYPERTRACE_PT_OPERATION_PACKETS, *PHYPERTRACE_PT_OPERATION_PACKETS;
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue