From 7ed5308bddeed89100d4bebf8b9691288715c5fb Mon Sep 17 00:00:00 2001 From: yardenshafir Date: Mon, 8 Apr 2024 07:58:25 -0400 Subject: [PATCH] Parse extension host callbacks on 24h2 and 25h2 --- Source/Shared/ntos/ntbuilds.h | 1 + Source/Shared/ntos/ntos.h | 47 ++++++++-- Source/WinObjEx64/extras/extrasCallbacks.c | 104 +++++++++++++++++---- 3 files changed, 130 insertions(+), 22 deletions(-) diff --git a/Source/Shared/ntos/ntbuilds.h b/Source/Shared/ntos/ntbuilds.h index 708dd3e..50e2f01 100644 --- a/Source/Shared/ntos/ntbuilds.h +++ b/Source/Shared/ntos/ntbuilds.h @@ -91,3 +91,4 @@ // Windows 11 Active Development Branch #define NT_WIN11_DEV 23615 //dev #define NT_WIN11_24H2 26020 //canary (24H2) +#define NT_WIN11_25H2 26080 //canary (25H2) diff --git a/Source/Shared/ntos/ntos.h b/Source/Shared/ntos/ntos.h index 340de02..c089d99 100644 --- a/Source/Shared/ntos/ntos.h +++ b/Source/Shared/ntos/ntos.h @@ -5238,21 +5238,37 @@ typedef VOID(NTAPI* PEX_HOST_NOTIFICATION) ( _In_ ULONG NotificationType, _In_opt_ PVOID Context); -typedef struct _EX_EXTENSION_INFORMATION { +typedef struct _EX_EXTENSION_INFORMATION_V1 { USHORT Id; USHORT Version; USHORT FunctionCount; -} EX_EXTENSION_INFORMATION, * PEX_EXTENSION_INFORMATION; +} EX_EXTENSION_INFORMATION_V1, * PEX_EXTENSION_INFORMATION_V1; + +typedef struct _EX_EXTENSION_VERSION { + USHORT MajorVersion; + USHORT MinorVersion; +} EX_EXTENSION_VERSION, * PEX_EXTENSION_VERSION; + +typedef struct _EX_EXTENSION_INFORMATION_V2 { + USHORT Id; + EX_EXTENSION_VERSION Version; + USHORT FunctionCount; +} EX_EXTENSION_INFORMATION_V2, * PEX_EXTENSION_INFORMATION_V2; + +typedef struct _EX_HOST_TABLE { + EX_EXTENSION_INFORMATION_V2 HostInformation; + PVOID FunctionTable; //calbacks +} EX_HOST_TABLE, * PEX_HOST_TABLE; typedef struct _EX_HOST_PARAMS { - EX_EXTENSION_INFORMATION HostInformation; + EX_EXTENSION_INFORMATION_V1 HostInformation; POOL_TYPE PoolType; PVOID HostTable; PVOID NotificationRoutine; PVOID NotificationContext; } EX_HOST_PARAMS, * PEX_HOST_PARAMS; -typedef struct _EX_HOST_ENTRY { +typedef struct _EX_HOST_ENTRY_V1 { LIST_ENTRY ListEntry; LONG RefCounter; EX_HOST_PARAMS HostParameters; @@ -5260,10 +5276,29 @@ typedef struct _EX_HOST_ENTRY { EX_PUSH_LOCK PushLock; PVOID FunctionTable; //callbacks ULONG Flags; -} EX_HOST_ENTRY, * PEX_HOST_ENTRY; +} EX_HOST_ENTRY_V1, * PEX_HOST_ENTRY_V1; + +typedef struct _EX_HOST_ENTRY_V2 { + LIST_ENTRY ListEntry; + EX_EXTENSION_INFORMATION_V2 HostInformation; + ULONG64 RefCounter; + EX_PUSH_LOCK PushLock; + PEX_HOST_TABLE HostTablesPtr; + USHORT HostTablesCount; + PEX_HOST_TABLE CurrentHostTableEntry; //only set when an extension registers + PVOID NotificationRoutine; + PVOID NotificationContext; + EX_EXTENSION_VERSION ExtensionVersion; + EX_RUNDOWN_REF RundownProtection; + PVOID FunctionTable; + USHORT ExtensionTableFunctionCount; + ULONG Pad; + ULONG Flags; + EX_HOST_TABLE HostTables[1]; +} EX_HOST_ENTRY_V2, * PEX_HOST_ENTRY_V2; typedef struct _EX_EXTENSION_REGISTRATION { - EX_EXTENSION_INFORMATION Information; + EX_EXTENSION_INFORMATION_V1 Information; PVOID FunctionTable; PVOID* HostTable; PDRIVER_OBJECT DriverObject; diff --git a/Source/WinObjEx64/extras/extrasCallbacks.c b/Source/WinObjEx64/extras/extrasCallbacks.c index f554bb5..be7ea7b 100644 --- a/Source/WinObjEx64/extras/extrasCallbacks.c +++ b/Source/WinObjEx64/extras/extrasCallbacks.c @@ -2527,11 +2527,21 @@ OBEX_FINDCALLBACK_ROUTINE(FindExHostCallbacks) ULONG_PTR kvarAddress = 0; PBYTE ptrCode; LONG Rel = 0; - ULONG Index, c; + ULONG Index, c, callIndex; hde64s hs; UNREFERENCED_PARAMETER(QueryFlags); + // another call was added in 24H2 to ExfAcquirePushLockSharedEx + if (g_NtBuildNumber > NT_WIN11_23H2) + { + callIndex = 2; + } + else + { + callIndex = 1; + } + if (kdIsSymAvailable((PSYMCONTEXT)g_kdctx.NtOsSymContext)) { kdGetAddressFromSymbol(&g_kdctx, @@ -2552,7 +2562,7 @@ OBEX_FINDCALLBACK_ROUTINE(FindExHostCallbacks) Index = 0; // - // Find ExpFindHost + // Find ExpFindHost / ExpFindCompatibleHost // do { @@ -2572,14 +2582,48 @@ OBEX_FINDCALLBACK_ROUTINE(FindExHostCallbacks) if (ptrCode[Index] == 0xE8) c++; - if (c > 1) { + if (c > callIndex) { Rel = *(PLONG)(ptrCode + Index + 1); break; } Index += hs.len; - } while (Index < 256); + } while (Index < 512); + + // + // If this is 25H2, the call is to ExpFindCompatibleHost + // Need to do another search to find the call to ExpFindHost + // + if (g_NtBuildNumber >= NT_WIN11_25H2) + { + ptrCode = ptrCode + Index + 5 + Rel; + Rel = 0; + Index = 0; + do { + + hde64_disasm(ptrCode + Index, &hs); + if (hs.flags & F_ERROR) + break; + + // + // Find call instruction. + // + if (hs.len != 5) { + Index += hs.len; + continue; + } + + if (ptrCode[Index] == 0xE8) + { + Rel = *(PLONG)(ptrCode + Index + 1); + break; + } + + Index += hs.len; + + } while (Index < 128); + } if (Rel == 0) return 0; @@ -4717,14 +4761,31 @@ OBEX_DISPLAYCALLBACK_ROUTINE(DumpExHostCallbacks) { LIST_ENTRY ListEntry; - EX_HOST_ENTRY HostEntry; + EX_HOST_ENTRY_V1 HostEntryV1; + EX_HOST_ENTRY_V2 HostEntryV2; + PVOID HostEntry; + ULONG HostEntrySize; ULONG_PTR ListHead = KernelVariableAddress; ULONG_PTR* HostTableDump; ULONG NumberOfCallbacks, i; + PVOID NotificationRoutine; + PVOID FunctionTable; HTREEITEM RootItem; + // Starting build 26080 (25H2) the structures were updated + if (g_NtBuildNumber < NT_WIN11_25H2) + { + HostEntrySize = sizeof(HostEntryV1); + HostEntry = &HostEntryV1; + } + else + { + HostEntrySize = sizeof(HostEntryV2); + HostEntry = &HostEntryV2; + } + // // Add callback root entry to the treelist. // @@ -4749,27 +4810,38 @@ OBEX_DISPLAYCALLBACK_ROUTINE(DumpExHostCallbacks) // Walk list entries. // while ((ULONG_PTR)ListEntry.Flink != ListHead) { - - RtlSecureZeroMemory(&HostEntry, sizeof(HostEntry)); + RtlSecureZeroMemory(HostEntry, HostEntrySize); if (!kdReadSystemMemory((ULONG_PTR)ListEntry.Flink, - &HostEntry, - sizeof(HostEntry))) + HostEntry, + HostEntrySize)) { break; } + // read extension function table + if (g_NtBuildNumber < NT_WIN11_25H2) + { + NumberOfCallbacks = HostEntryV1.HostParameters.HostInformation.FunctionCount; + NotificationRoutine = HostEntryV1.HostParameters.NotificationRoutine; + FunctionTable = HostEntryV1.FunctionTable; + } + else + { + NumberOfCallbacks = HostEntryV2.ExtensionTableFunctionCount; + NotificationRoutine = HostEntryV2.NotificationRoutine; + FunctionTable = HostEntryV2.FunctionTable; + } + // // Find not an empty host table. // - NumberOfCallbacks = HostEntry.HostParameters.HostInformation.FunctionCount; - if (NumberOfCallbacks) { - if (HostEntry.HostParameters.NotificationRoutine) { + if (NotificationRoutine) { AddEntryToList(TreeList, RootItem, - (ULONG_PTR)HostEntry.HostParameters.NotificationRoutine, + (ULONG_PTR)NotificationRoutine, L"NotificationRoutine", Modules); @@ -4778,12 +4850,12 @@ OBEX_DISPLAYCALLBACK_ROUTINE(DumpExHostCallbacks) // // Read function table. // - if (HostEntry.FunctionTable) { + if (FunctionTable) { HostTableDump = (ULONG_PTR*)supHeapAlloc(NumberOfCallbacks * sizeof(PVOID)); if (HostTableDump) { if (kdReadSystemMemory( - (ULONG_PTR)HostEntry.FunctionTable, + (ULONG_PTR)FunctionTable, HostTableDump, NumberOfCallbacks * sizeof(PVOID))) { @@ -4805,7 +4877,7 @@ OBEX_DISPLAYCALLBACK_ROUTINE(DumpExHostCallbacks) } } - ListEntry.Flink = HostEntry.ListEntry.Flink; + ListEntry.Flink = ((LIST_ENTRY*)(HostEntry))->Flink; } }