/* * HEADER ONLY KERNEL UTIL LIBRARY - NO IMPORTS - NO STRINGS */ #pragma once #include #include using u64 = unsigned long long; using u32 = unsigned long; using u16 = unsigned short; using u8 = unsigned char; namespace hashstr { template struct idx_list_t {}; template struct append_t; template struct append_t, right> { typedef idx_list_t result_t; }; template struct constr_idx_list { typedef typename append_t::result_t, N - 1>::result_t result_t; }; template <> struct constr_idx_list<0> { typedef idx_list_t<> result_t; }; template consteval T add(T first) { return first; } template consteval T add(T first, Args... args) { return first + add(args...); } template consteval T mul(T first) { return first; } template consteval T mul(T first, Args... args) { return first * mul(args...); } template class hashstr_t; template struct hashstr_t > { consteval hashstr_t(const char (&str)[sizeof...(idx) + 1]) : _hash((mul(hashchar(str[idx], idx)...) + add(hashchar(str[idx], idx)...)) ^ 0xCBF29CE484222325) {} unsigned _hash; consteval unsigned hashchar(const char c, unsigned idx) { return (c + 1) * 0x100000001B3 * (idx + 1 + c); } unsigned hash() { return _hash; } }; // runtime equivelent of the compile time hash... inline unsigned hash(const char* str) { unsigned add_res = 0u, mul_res = 1u; for (auto idx = 0u; str[idx]; ++idx) { add_res += (str[idx] + 1) * 0x100000001B3 * (idx + 1 + str[idx]); mul_res *= (str[idx] + 1) * 0x100000001B3 * (idx + 1 + str[idx]); } return (add_res + mul_res) ^ 0xCBF29CE484222325; } } // namespace hashstr #define HSTRING(str) \ (hashstr::hashstr_t::result_t>( \ str) \ .hash()) #define DYN_MOD(x) KUtils::Driver::GetDriverBaseByHash(HSTRING(#x)) #define DYN_NT_SYM(x) \ ((decltype(&x))KUtils::Driver::GetDriverExportByHash( \ KUtils::Driver::GetKernelBase(), HSTRING(#x))) #define DYN_MOD_SYM(mod, exp) \ ((decltype(&y))KUtils::Driver::GetDriverExportByHash(HSTRING(#mod), \ HSTRING(#exp))) #define DBG_PRINT(...) \ DYN_NT_SYM(DbgPrintEx) \ (DPFLTR_SYSTEM_ID, DPFLTR_ERROR_LEVEL, "[KUTILS]" __VA_ARGS__); // Export Directory #define IMAGE_DIRECTORY_ENTRY_EXPORT 0 // Import Directory #define IMAGE_DIRECTORY_ENTRY_IMPORT 1 // Resource Directory #define IMAGE_DIRECTORY_ENTRY_RESOURCE 2 // Exception Directory #define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 // Security Directory #define IMAGE_DIRECTORY_ENTRY_SECURITY 4 // Base Relocation Table #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 // Debug Directory #define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Description String #define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 // Machine Value (MIPS GP) #define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 // TLS Directory #define IMAGE_DIRECTORY_ENTRY_TLS 9 // Load Configuration Directory #define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 #define DOS_HEADER_MAGIC 0x5A4D #define PE_HEADER_MAGIC 0x4550 namespace KUtils { typedef struct _IMAGE_DOS_HEADER { USHORT e_magic; USHORT e_cblp; USHORT e_cp; USHORT e_crlc; USHORT e_cparhdr; USHORT e_minalloc; USHORT e_maxalloc; USHORT e_ss; USHORT e_sp; USHORT e_csum; USHORT e_ip; USHORT e_cs; USHORT e_lfarlc; USHORT e_ovno; USHORT e_res[4]; USHORT e_oemid; USHORT e_oeminfo; USHORT e_res2[10]; LONG e_lfanew; } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; typedef struct _IMAGE_FILE_HEADER { short Machine; short NumberOfSections; unsigned TimeDateStamp; unsigned PointerToSymbolTable; unsigned NumberOfSymbols; short SizeOfOptionalHeader; short Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER; typedef struct _IMAGE_DATA_DIRECTORY { unsigned VirtualAddress; unsigned Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; typedef struct _IMAGE_SECTION_HEADER { unsigned char Name[8]; union { unsigned PhysicalAddress; unsigned VirtualSize; } Misc; unsigned VirtualAddress; unsigned SizeOfRawData; unsigned PointerToRawData; unsigned PointerToRelocations; unsigned PointerToLinenumbers; unsigned short NumberOfRelocations; unsigned short NumberOfLinenumbers; unsigned Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; typedef struct _IMAGE_OPTIONAL_HEADER64 { short Magic; unsigned char MajorLinkerVersion; unsigned char MinorLinkerVersion; unsigned SizeOfCode; unsigned SizeOfInitializedData; unsigned SizeOfUninitializedData; unsigned AddressOfEntryPoint; unsigned BaseOfCode; ULONGLONG ImageBase; unsigned SectionAlignment; unsigned FileAlignment; short MajorOperatingSystemVersion; short MinorOperatingSystemVersion; short MajorImageVersion; short MinorImageVersion; short MajorSubsystemVersion; short MinorSubsystemVersion; unsigned Win32VersionValue; unsigned SizeOfImage; unsigned SizeOfHeaders; unsigned CheckSum; short Subsystem; short DllCharacteristics; ULONGLONG SizeOfStackReserve; ULONGLONG SizeOfStackCommit; ULONGLONG SizeOfHeapReserve; ULONGLONG SizeOfHeapCommit; unsigned LoaderFlags; unsigned NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[16]; } IMAGE_OPTIONAL_HEADER64, *PIMAGE_OPTIONAL_HEADER64; typedef struct _IMAGE_NT_HEADERS64 { unsigned Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER64 OptionalHeader; } IMAGE_NT_HEADERS64, *PIMAGE_NT_HEADERS64; typedef struct _IMAGE_IMPORT_DESCRIPTOR { union { unsigned long Characteristics; // 0 for terminating null import descriptor unsigned long OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA) } DUMMYUNIONNAME; unsigned long TimeDateStamp; // 0 if not bound, // -1 if bound, and real date\time stamp // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND) // O.W. date/time stamp of DLL bound to (Old BIND) unsigned long ForwarderChain; // -1 if no forwarders unsigned long Name; unsigned long FirstThunk; // RVA to IAT (if bound this IAT has actual addresses) } IMAGE_IMPORT_DESCRIPTOR; typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED* PIMAGE_IMPORT_DESCRIPTOR; typedef struct _IMAGE_IMPORT_BY_NAME { unsigned long Hint; CHAR Name[1]; } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME; typedef struct _IMAGE_THUNK_DATA64 { union { ULONGLONG ForwarderString; // PBYTE ULONGLONG Function; // PDWORD ULONGLONG Ordinal; ULONGLONG AddressOfData; // PIMAGE_IMPORT_BY_NAME } u1; } IMAGE_THUNK_DATA64, *PIMAGE_THUNK_DATA64; typedef PIMAGE_THUNK_DATA64 PIMAGE_THUNK_DATA; typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; unsigned short LoadCount; unsigned short TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { ULONG TimeDateStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; LIST_ENTRY ForwarderLinks; LIST_ENTRY ServiceTagLinks; LIST_ENTRY StaticLinks; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; typedef struct _PEB_LDR_DATA { ULONG Length; UCHAR Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID EntryInProgress; } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _PEB { BOOLEAN InheritedAddressSpace; BOOLEAN ReadImageFileExecOptions; BOOLEAN BeingDebugged; BOOLEAN Spare; HANDLE Mutant; PVOID ImageBaseAddress; PPEB_LDR_DATA LoaderData; PVOID ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; PVOID FastPebLock; PVOID FastPebLockRoutine; PVOID FastPebUnlockRoutine; ULONG EnvironmentUpdateCount; PVOID KernelCallbackTable; PVOID EventLogSection; PVOID EventLog; PVOID FreeList; ULONG TlsExpansionCounter; PVOID TlsBitmap; ULONG TlsBitmapBits[0x2]; PVOID ReadOnlySharedMemoryBase; PVOID ReadOnlySharedMemoryHeap; PVOID* ReadOnlyStaticServerData; PVOID AnsiCodePageData; PVOID OemCodePageData; PVOID UnicodeCaseTableData; ULONG NumberOfProcessors; ULONG NtGlobalFlag; unsigned char Spare2[0x4]; LARGE_INTEGER CriticalSectionTimeout; ULONG HeapSegmentReserve; ULONG HeapSegmentCommit; ULONG HeapDeCommitTotalFreeThreshold; ULONG HeapDeCommitFreeBlockThreshold; ULONG NumberOfHeaps; ULONG MaximumNumberOfHeaps; PVOID** ProcessHeaps; PVOID GdiSharedHandleTable; PVOID ProcessStarterHelper; PVOID GdiDCAttributeList; PVOID LoaderLock; ULONG OSMajorVersion; ULONG OSMinorVersion; ULONG OSBuildNumber; ULONG OSPlatformId; ULONG ImageSubSystem; ULONG ImageSubSystemMajorVersion; ULONG ImageSubSystemMinorVersion; ULONG GdiHandleBuffer[0x22]; ULONG PostProcessInitRoutine; ULONG TlsExpansionBitmap; unsigned char TlsExpansionBitmapBits[0x80]; ULONG SessionId; } PEB, *PPEB; typedef struct _SYSTEM_THREAD { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientId; KPRIORITY Priority; LONG BasePriority; ULONG ContextSwitchCount; ULONG State; KWAIT_REASON WaitReason; } SYSTEM_THREAD, *PSYSTEM_THREAD; typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; ULONG NumberOfThreads; LARGE_INTEGER Reserved[3]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ImageName; KPRIORITY BasePriority; HANDLE ProcessId; HANDLE InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; ULONG PrivatePageCount; VM_COUNTERS VirtualMemoryCounters; IO_COUNTERS IoCounters; SYSTEM_THREAD Threads[0]; } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; typedef struct _RTL_PROCESS_MODULE_INFORMATION { HANDLE Section; PVOID MappedBase; PVOID ImageBase; ULONG ImageSize; ULONG Flags; USHORT LoadOrderIndex; USHORT InitOrderIndex; USHORT LoadCount; USHORT OffsetToFileName; UCHAR FullPathName[256]; } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; typedef struct _RTL_PROCESS_MODULES { ULONG NumberOfModules; RTL_PROCESS_MODULE_INFORMATION Modules[1]; } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; typedef struct _OBJECT_DIRECTORY_ENTRY { struct _OBJECT_DIRECTORY_ENTRY* ChainLink; PVOID Object; ULONG HashValue; } OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY; typedef struct _OBJECT_DIRECTORY { POBJECT_DIRECTORY_ENTRY HashBuckets[37]; EX_PUSH_LOCK Lock; struct _DEVICE_MAP* DeviceMap; ULONG SessionId; PVOID NamespaceEntry; ULONG Flags; } OBJECT_DIRECTORY, *POBJECT_DIRECTORY; typedef struct _DEVICE_MAP { POBJECT_DIRECTORY DosDevicesDirectory; POBJECT_DIRECTORY GlobalDosDevicesDirectory; ULONG ReferenceCount; ULONG DriveMap; UCHAR DriveType[32]; } DEVICE_MAP, *PDEVICE_MAP; typedef struct _IMAGE_EXPORT_DIRECTORY { ULONG Characteristics; ULONG TimeDateStamp; USHORT MajorVersion; USHORT MinorVersion; ULONG Name; ULONG Base; ULONG NumberOfFunctions; ULONG NumberOfNames; ULONG AddressOfFunctions; ULONG AddressOfNames; ULONG AddressOfNameOrdinals; } IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY; #pragma pack(push, 1) typedef struct _IDTR { USHORT Size; ULONG64 Address; } IDTR, PIDTR; #pragma pack(pop) typedef union _KIDTENTRY64 { union { struct { /* 0x0000 */ unsigned short OffsetLow; /* 0x0002 */ unsigned short Selector; struct /* bitfield */ { /* 0x0004 */ unsigned short IstIndex : 3; /* bit position: 0 */ /* 0x0004 */ unsigned short Reserved0 : 5; /* bit position: 3 */ /* 0x0004 */ unsigned short Type : 5; /* bit position: 8 */ /* 0x0004 */ unsigned short Dpl : 2; /* bit position: 13 */ /* 0x0004 */ unsigned short Present : 1; /* bit position: 15 */ }; /* bitfield */ /* 0x0006 */ unsigned short OffsetMiddle; /* 0x0008 */ unsigned long OffsetHigh; /* 0x000c */ unsigned long Reserved1; }; /* size: 0x0010 */ /* 0x0000 */ unsigned __int64 Alignment; }; /* size: 0x0010 */ } KIDTENTRY64, *PKIDTENTRY64; /* size: 0x0010 */ typedef union _IDT_ADDR_T { ULONG64 Addr; struct { ULONG64 OffsetLow : 16; ULONG64 OffsetMiddle : 16; ULONG64 OffsetHigh : 32; }; } IDT_ADDR_T, PIDT_ADDR_T; typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, SystemProcessorInformation, SystemPerformanceInformation, SystemTimeOfDayInformation, SystemPathInformation, SystemProcessInformation, SystemCallCountInformation, SystemDeviceInformation, SystemProcessorPerformanceInformation, SystemFlagsInformation, SystemCallTimeInformation, SystemModuleInformation, SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, SystemNonPagedPoolInformation, SystemHandleInformation, SystemObjectInformation, SystemPageFileInformation, SystemVdmInstemulInformation, SystemVdmBopInformation, SystemFileCacheInformation, SystemPoolTagInformation, SystemInterruptInformation, SystemDpcBehaviorInformation, SystemFullMemoryInformation, SystemLoadGdiDriverInformation, SystemUnloadGdiDriverInformation, SystemTimeAdjustmentInformation, SystemSummaryMemoryInformation, SystemNextEventIdInformation, SystemEventIdsInformation, SystemCrashDumpInformation, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemExtendServiceTableInformation, SystemPrioritySeperation, SystemPlugPlayBusInformation, SystemDockInformation } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; extern "C" PVOID PsGetProcessSectionBaseAddress(__in PEPROCESS Process); extern "C" PPEB PsGetProcessPeb(PEPROCESS Process); extern "C" NTSTATUS ZwQuerySystemInformation( SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength); namespace Driver { /// /// walk export directory of a module given its base and the hash of the export /// string. /// /// /// /// FORCEINLINE PVOID GetDriverExportByHash(_In_ PVOID ModuleBase, _In_ ULONG nStrHash) { PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)ModuleBase; PIMAGE_NT_HEADERS64 lpNtHeader = (PIMAGE_NT_HEADERS64)(lpDosHeader->e_lfanew + (ULONG64)ModuleBase); PIMAGE_EXPORT_DIRECTORY lpExportDir = (PIMAGE_EXPORT_DIRECTORY)((ULONG64)ModuleBase + lpNtHeader->OptionalHeader .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] .VirtualAddress); ULONG32* lpNameArr = (ULONG32*)(lpExportDir->AddressOfNames + (ULONG64)ModuleBase); ULONG32* lpFuncs = (ULONG32*)(lpExportDir->AddressOfFunctions + (ULONG64)ModuleBase); USHORT* lpOrdinals = (USHORT*)(lpExportDir->AddressOfNameOrdinals + (ULONG64)ModuleBase); for (auto nIdx = 0u; nIdx < lpExportDir->NumberOfFunctions; ++nIdx) { if (!lpNameArr[nIdx] || !lpOrdinals[nIdx]) continue; if (hashstr::hash((PCHAR)((ULONG64)ModuleBase + lpNameArr[nIdx])) == nStrHash) return (PVOID)((ULONG64)ModuleBase + lpFuncs[lpOrdinals[nIdx]]); } return NULL; } /// /// Gets ntoskrnl.exe module base address by reading the interrupt descriptor /// table. It reads the first IDT entry which is just div 0 handler. it then /// loops backwards page by page looking for valid DOS/NT headers and ensures /// that the size of the image is legit... /// /// returns the kernel base address... FORCEINLINE PVOID GetKernelBase() { IDTR stIdtr; __sidt(&stIdtr); PKIDTENTRY64 lpDivZero = (PKIDTENTRY64)stIdtr.Address; IDT_ADDR_T stHndlrAddr; stHndlrAddr.OffsetLow = lpDivZero->OffsetLow; stHndlrAddr.OffsetMiddle = lpDivZero->OffsetMiddle; stHndlrAddr.OffsetHigh = lpDivZero->OffsetHigh; // loop backwards until we find the kernels base address... ULONG64 nStartPage = (ULONG64)PAGE_ALIGN(stHndlrAddr.Addr); for (ULONG64 nPage = nStartPage;; nPage -= PAGE_SIZE) { if (*(USHORT*)nPage == DOS_HEADER_MAGIC) { PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)nPage; PIMAGE_NT_HEADERS64 lpNtHeaders = (PIMAGE_NT_HEADERS64)(lpDosHeader->e_lfanew + nPage); if (lpNtHeaders->Signature != PE_HEADER_MAGIC) continue; if (!GetDriverExportByHash((PVOID)nPage, HSTRING("ExAllocatePoolWithTag"))) continue; return (PVOID)nPage; } } } /// /// Gets driver base address by the hash of the file name of the driver... /// /// hash of the drivers file name... /// FORCEINLINE PVOID GetDriverBaseByHash(_In_ CONST ULONG dwHash) { ULONG dwAllocSize{}; DYN_NT_SYM(ZwQuerySystemInformation) (SystemModuleInformation, NULL, dwAllocSize, &dwAllocSize); PRTL_PROCESS_MODULES moduleInfo = (PRTL_PROCESS_MODULES)DYN_NT_SYM( ExAllocatePool)(NonPagedPool, dwAllocSize); DYN_NT_SYM(ZwQuerySystemInformation) (SystemModuleInformation, moduleInfo, dwAllocSize, &dwAllocSize); for (INT nIdx = 0u; nIdx < moduleInfo->NumberOfModules; ++nIdx) { PCHAR pszModuleName = (PCHAR)moduleInfo->Modules[nIdx].FullPathName + moduleInfo->Modules[nIdx].OffsetToFileName; if (hashstr::hash(pszModuleName) == dwHash) { PVOID lpModuleBase = moduleInfo->Modules[nIdx].ImageBase; DYN_NT_SYM(ExFreePool)(moduleInfo); return lpModuleBase; } } DYN_NT_SYM(ExFreePool)(moduleInfo); return NULL; } /// /// Get driver base given the module name of the driver... This function calls /// GetDriverBaseByHash internally... /// /// file name of the driver, this is not case /// dependant... returns a void pointer to the drivers /// base... FORCEINLINE PVOID GetDriverBase(_In_ CONST CHAR* pszDriverName) { return GetDriverBaseByHash(hashstr::hash(pszDriverName)); } /// /// GetDriverExport via driver name and export routine name... this function /// calls GetDriverExportByHash internally... /// /// null terminated c-string given the module name /// of the driver... example: "win32k.sys" the c-string name of the export... /// returns a linear virtual address to the export... FORCEINLINE PVOID GetDriverExport(_In_ CONST CHAR* pszDriverName, _In_ CONST CHAR* pszRoutineName) { PVOID lpDriverBase = GetDriverBase(pszDriverName); return lpDriverBase ? GetDriverExportByHash(lpDriverBase, hashstr::hash(pszRoutineName)) : NULL; } FORCEINLINE PDRIVER_OBJECT GetDriverObject(_In_ CONST WCHAR* pwszDriverName) { HANDLE handle{}; OBJECT_ATTRIBUTES attr{}; UNICODE_STRING dirName{}; PVOID dir{}; BOOLEAN success = FALSE; DYN_NT_SYM(RtlInitUnicodeString)(&dirName, L"\\Driver"); InitializeObjectAttributes(&attr, &dirName, OBJ_CASE_INSENSITIVE, NULL, NULL); // open OBJECT_DIRECTORY for \\Driver NTSTATUS status = DYN_NT_SYM(ZwOpenDirectoryObject)(&handle, DIRECTORY_ALL_ACCESS, &attr); if (!NT_SUCCESS(status)) { DYN_NT_SYM(ZwClose)(handle); return NULL; } // Get OBJECT_DIRECTORY pointer from HANDLE status = DYN_NT_SYM(ObReferenceObjectByHandle)( handle, DIRECTORY_ALL_ACCESS, nullptr, KernelMode, &dir, nullptr); if (!NT_SUCCESS(status)) { DYN_NT_SYM(ZwClose)(handle); return NULL; } const auto directory_object = POBJECT_DIRECTORY(dir); DYN_NT_SYM(ExAcquirePushLockExclusiveEx)(&directory_object->Lock, 0); for (auto entry : directory_object->HashBuckets) { if (!entry) continue; while (entry && entry->Object) { PDRIVER_OBJECT driver = (PDRIVER_OBJECT)entry->Object; if (!driver) continue; if (!DYN_NT_SYM(wcscmp)(driver->DriverExtension->ServiceKeyName.Buffer, pwszDriverName)) { DYN_NT_SYM(ExReleasePushLockExclusiveEx)(&directory_object->Lock, 0); DYN_NT_SYM(ObfDereferenceObject)(dir); DYN_NT_SYM(ZwClose)(handle); return driver; } entry = entry->ChainLink; } } DYN_NT_SYM(ExReleasePushLockExclusiveEx)(&directory_object->Lock, 0); DYN_NT_SYM(ObfDereferenceObject)(dir); DYN_NT_SYM(ZwClose)(handle); return NULL; } } // namespace Driver namespace Process { FORCEINLINE HANDLE GetPid(_In_ CONST WCHAR* pwszProcessName) { u32 allocSize{}; DYN_NT_SYM(ZwQuerySystemInformation) (SystemProcessInformation, NULL, allocSize, &allocSize); PSYSTEM_PROCESS_INFORMATION procInfo = (PSYSTEM_PROCESS_INFORMATION)DYN_NT_SYM(ExAllocatePool)(NonPagedPool, allocSize); const auto origPtr = procInfo; DYN_NT_SYM(ZwQuerySystemInformation) (SystemProcessInformation, procInfo, allocSize, &allocSize); while (true) { if (procInfo->ImageName.Buffer) { if (!DYN_NT_SYM(_wcsicmp)(procInfo->ImageName.Buffer, pwszProcessName)) { auto result = procInfo->ProcessId; DYN_NT_SYM(ExFreePool)(origPtr); return result; } } if (!procInfo->NextEntryOffset) break; procInfo = reinterpret_cast( reinterpret_cast(procInfo) + procInfo->NextEntryOffset); } DYN_NT_SYM(ExFreePool)(origPtr); return NULL; } FORCEINLINE PVOID GetProcessBase(_In_ HANDLE hPid) { PEPROCESS lpProc; if (NT_SUCCESS(DYN_NT_SYM(PsLookupProcessByProcessId)(hPid, &lpProc))) { PVOID lpBaseAddr = DYN_NT_SYM(PsGetProcessSectionBaseAddress)(lpProc); DYN_NT_SYM(ObfDereferenceObject)(lpProc); return lpBaseAddr; } return NULL; } VOID TdCallbackExample(CONST SYSTEM_THREAD& ThreadInfo); VOID PsCallbackExample(CONST SYSTEM_PROCESS_INFORMATION& PsInfo); using TdCallbackPtr = decltype(&TdCallbackExample); using PsCallbackPtr = decltype(&PsCallbackExample); FORCEINLINE VOID ForEachProcess(_In_ PsCallbackPtr lpCallback) { ULONG nAllocSize{}; DYN_NT_SYM(ZwQuerySystemInformation) (SystemProcessInformation, NULL, nAllocSize, &nAllocSize); auto procInfo = reinterpret_cast( DYN_NT_SYM(ExAllocatePool)(NonPagedPool, nAllocSize)); const auto origPtr = procInfo; DYN_NT_SYM(ZwQuerySystemInformation) (SystemProcessInformation, procInfo, nAllocSize, &nAllocSize); while (true) { for (auto idx = 0u; idx < procInfo->NumberOfThreads; ++idx) lpCallback(*procInfo); if (!procInfo->NextEntryOffset) break; procInfo = reinterpret_cast( reinterpret_cast(procInfo) + procInfo->NextEntryOffset); } DYN_NT_SYM(ExFreePool)(origPtr); } FORCEINLINE VOID ForEachThread(_In_ HANDLE hPid, _In_ TdCallbackPtr lpCallback) { ULONG nAllocSize{}; DYN_NT_SYM(ZwQuerySystemInformation) (SystemProcessInformation, NULL, nAllocSize, &nAllocSize); PSYSTEM_PROCESS_INFORMATION lpstProcInfo = (PSYSTEM_PROCESS_INFORMATION)DYN_NT_SYM(ExAllocatePool)(NonPagedPool, nAllocSize); CONST PSYSTEM_PROCESS_INFORMATION lpstOrigPtr = lpstProcInfo; DYN_NT_SYM(ZwQuerySystemInformation) (SystemProcessInformation, lpstProcInfo, nAllocSize, &nAllocSize); while (true) { if (lpstProcInfo->ProcessId == hPid) for (INT idx = 0u; idx < lpstProcInfo->NumberOfThreads; ++idx) lpCallback(lpstProcInfo->Threads[idx]); if (!lpstProcInfo->NextEntryOffset) break; lpstProcInfo = (PSYSTEM_PROCESS_INFORMATION)((ULONG64)lpstProcInfo + lpstProcInfo->NextEntryOffset); } DYN_NT_SYM(ExFreePool)(lpstOrigPtr); } FORCEINLINE PVOID GetModuleBase(_In_ HANDLE hPid, _In_ CONST WCHAR* pwszModuleName) { PEPROCESS lpProc; KAPC_STATE stApcState; if (NT_SUCCESS(DYN_NT_SYM(PsLookupProcessByProcessId)(hPid, &lpProc))) { DYN_NT_SYM(KeStackAttachProcess)(lpProc, &stApcState); { const auto ldrData = reinterpret_cast( DYN_NT_SYM(PsGetProcessPeb)(lpProc)->LoaderData); auto currentEntry = ldrData->InMemoryOrderModuleList.Flink; while (currentEntry != &ldrData->InMemoryOrderModuleList) { const auto currentEntryData = reinterpret_cast( reinterpret_cast(currentEntry) - sizeof LIST_ENTRY); const auto entryModuleName = currentEntryData->BaseDllName.Buffer; if (!DYN_NT_SYM(_wcsicmp)(entryModuleName, pwszModuleName)) { DYN_NT_SYM(ObfDereferenceObject)(lpProc); auto moduleBase = currentEntryData->DllBase; DYN_NT_SYM(KeUnstackDetachProcess)(&stApcState); return moduleBase; } currentEntry = currentEntry->Flink; } } DYN_NT_SYM(KeUnstackDetachProcess)(&stApcState); DYN_NT_SYM(ObfDereferenceObject)(lpProc); } return NULL; } } // namespace Process namespace Signature { inline auto Scan(void* base, u32 size, const char* pattern, const char* mask) -> void* { static const auto check_mask = [&](const char* base, const char* pattern, const char* mask) -> bool { for (; *mask; ++base, ++pattern, ++mask) if (*mask == 'x' && *base != *pattern) return false; return true; }; static const auto _strlen = [&](const char* str) -> unsigned { const char* s; for (s = str; *s; ++s) ; return (s - str); }; size -= _strlen(mask); for (auto i = 0; i <= size; ++i) { void* addr = (void*)&(((char*)base)[i]); if (check_mask((char*)addr, pattern, mask)) return addr; } return nullptr; } } // namespace Signature } // namespace KUtils