From 5bccbff58b0a43a070743e9ce900484bc5805dd1 Mon Sep 17 00:00:00 2001 From: sina Date: Wed, 1 Jul 2026 19:44:15 +0200 Subject: [PATCH] fix IPT kernel structure based on the new model --- .../user/hyperdbg_app/code/hyperdbg-ipt.cpp | 16 ++--- hyperdbg/hyperkd/code/driver/Ioctl.c | 12 ++-- hyperdbg/hypertrace/code/api/PtApi.c | 60 ++++++++++--------- .../hypertrace/code/broadcast/Broadcast.c | 6 +- .../hypertrace/code/broadcast/DpcRoutines.c | 4 +- hyperdbg/hypertrace/code/pt/Pt.c | 26 ++++---- .../hypertrace/header/broadcast/Broadcast.h | 2 +- hyperdbg/hypertrace/header/pt/Pt.h | 47 ++++----------- .../include/SDK/headers/RequestStructures.h | 8 +++ 9 files changed, 86 insertions(+), 95 deletions(-) diff --git a/examples/user/hyperdbg_app/code/hyperdbg-ipt.cpp b/examples/user/hyperdbg_app/code/hyperdbg-ipt.cpp index 280fde5e..aacd776f 100644 --- a/examples/user/hyperdbg_app/code/hyperdbg-ipt.cpp +++ b/examples/user/hyperdbg_app/code/hyperdbg-ipt.cpp @@ -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; } diff --git a/hyperdbg/hyperkd/code/driver/Ioctl.c b/hyperdbg/hyperkd/code/driver/Ioctl.c index b7bb7d16..ddd88593 100644 --- a/hyperdbg/hyperkd/code/driver/Ioctl.c +++ b/hyperdbg/hyperkd/code/driver/Ioctl.c @@ -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)); } // diff --git a/hyperdbg/hypertrace/code/api/PtApi.c b/hyperdbg/hypertrace/code/api/PtApi.c index 7945fbfd..408848c3 100644 --- a/hyperdbg/hypertrace/code/api/PtApi.c +++ b/hyperdbg/hypertrace/code/api/PtApi.c @@ -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) diff --git a/hyperdbg/hypertrace/code/broadcast/Broadcast.c b/hyperdbg/hypertrace/code/broadcast/Broadcast.c index 7dc5fce7..0fd14565 100644 --- a/hyperdbg/hypertrace/code/broadcast/Broadcast.c +++ b/hyperdbg/hypertrace/code/broadcast/Broadcast.c @@ -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); } diff --git a/hyperdbg/hypertrace/code/broadcast/DpcRoutines.c b/hyperdbg/hypertrace/code/broadcast/DpcRoutines.c index 0bd904a2..b17accdd 100644 --- a/hyperdbg/hypertrace/code/broadcast/DpcRoutines.c +++ b/hyperdbg/hypertrace/code/broadcast/DpcRoutines.c @@ -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 diff --git a/hyperdbg/hypertrace/code/pt/Pt.c b/hyperdbg/hypertrace/code/pt/Pt.c index cd8d6d7f..de2e6a01 100644 --- a/hyperdbg/hypertrace/code/pt/Pt.c +++ b/hyperdbg/hypertrace/code/pt/Pt.c @@ -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]; } // diff --git a/hyperdbg/hypertrace/header/broadcast/Broadcast.h b/hyperdbg/hypertrace/header/broadcast/Broadcast.h index 878cd3cd..eb857072 100644 --- a/hyperdbg/hypertrace/header/broadcast/Broadcast.h +++ b/hyperdbg/hypertrace/header/broadcast/Broadcast.h @@ -50,4 +50,4 @@ VOID BroadcastFlushPtOnAllCores(); VOID -BroadcastFilterPtOnAllCores(PT_FILTER_OPTIONS * FilterOptions); +BroadcastFilterPtOnAllCores(PT_APPLY_CORE_FILTER_REQUEST * FilterRequest); diff --git a/hyperdbg/hypertrace/header/pt/Pt.h b/hyperdbg/hypertrace/header/pt/Pt.h index 07a10506..f7801bbb 100644 --- a/hyperdbg/hypertrace/header/pt/Pt.h +++ b/hyperdbg/hypertrace/header/pt/Pt.h @@ -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. diff --git a/hyperdbg/include/SDK/headers/RequestStructures.h b/hyperdbg/include/SDK/headers/RequestStructures.h index fbd6510c..fdf53450 100644 --- a/hyperdbg/include/SDK/headers/RequestStructures.h +++ b/hyperdbg/include/SDK/headers/RequestStructures.h @@ -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; /**