parent
f356110d85
commit
9dcdd10f73
@ -0,0 +1,865 @@
|
||||
/*
|
||||
* HEADER ONLY KERNEL UTIL LIBRARY - NO IMPORTS - NO STRINGS
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <intrin.h>
|
||||
#include <ntifs.h>
|
||||
|
||||
using u64 = unsigned long long;
|
||||
using u32 = unsigned long;
|
||||
using u16 = unsigned short;
|
||||
using u8 = unsigned char;
|
||||
|
||||
namespace hashstr {
|
||||
template <unsigned... pack>
|
||||
struct idx_list_t {};
|
||||
template <typename idx_list_t, unsigned right>
|
||||
struct append_t;
|
||||
template <unsigned... left, unsigned right>
|
||||
struct append_t<idx_list_t<left...>, right> {
|
||||
typedef idx_list_t<left..., right> result_t;
|
||||
};
|
||||
|
||||
template <unsigned N>
|
||||
struct constr_idx_list {
|
||||
typedef typename append_t<typename constr_idx_list<N - 1>::result_t,
|
||||
N - 1>::result_t result_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct constr_idx_list<0> {
|
||||
typedef idx_list_t<> result_t;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
consteval T add(T first) {
|
||||
return first;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
consteval T add(T first, Args... args) {
|
||||
return first + add(args...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
consteval T mul(T first) {
|
||||
return first;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
consteval T mul(T first, Args... args) {
|
||||
return first * mul(args...);
|
||||
}
|
||||
|
||||
template <typename idx_list_t>
|
||||
class hashstr_t;
|
||||
template <int... idx>
|
||||
struct hashstr_t<idx_list_t<idx...> > {
|
||||
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<hashstr::constr_idx_list<sizeof(str) - 1>::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_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 {
|
||||
FORCEINLINE PVOID GetDriverExportByHash(_In_ PVOID lpDriverBase,
|
||||
_In_ ULONG nStrHash) {
|
||||
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)lpDriverBase;
|
||||
PIMAGE_NT_HEADERS64 lpNtHeader =
|
||||
(PIMAGE_NT_HEADERS64)(lpDosHeader->e_lfanew + (ULONG64)lpDriverBase);
|
||||
|
||||
PIMAGE_EXPORT_DIRECTORY lpExportDir =
|
||||
(PIMAGE_EXPORT_DIRECTORY)((ULONG64)lpDriverBase +
|
||||
lpNtHeader->OptionalHeader
|
||||
.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]
|
||||
.VirtualAddress);
|
||||
|
||||
ULONG32* lpNameArr =
|
||||
(ULONG32*)(lpExportDir->AddressOfNames + (ULONG64)lpDriverBase);
|
||||
|
||||
ULONG32* lpFuncs =
|
||||
(ULONG32*)(lpExportDir->AddressOfFunctions + (ULONG64)lpDriverBase);
|
||||
|
||||
USHORT* lpOrdinals =
|
||||
(USHORT*)(lpExportDir->AddressOfNameOrdinals + (ULONG64)lpDriverBase);
|
||||
|
||||
for (auto nIdx = 0u; nIdx < lpExportDir->NumberOfFunctions; ++nIdx) {
|
||||
if (!lpNameArr[nIdx] || !lpOrdinals[nIdx])
|
||||
continue;
|
||||
|
||||
if (hashstr::hash((PCHAR)((ULONG64)lpDriverBase + lpNameArr[nIdx])) ==
|
||||
nStrHash)
|
||||
return (PVOID)((ULONG64)lpDriverBase + lpFuncs[lpOrdinals[nIdx]]);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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...
|
||||
/// </summary>
|
||||
/// <returns>returns the kernel base address...</returns>
|
||||
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 (lpNtHeaders->OptionalHeader.SizeOfImage < 0x1000000)
|
||||
continue;
|
||||
|
||||
return (PVOID)nPage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets driver base address by the hash of the file name of the driver...
|
||||
/// </summary>
|
||||
/// <param name="dwHash">hash of the drivers file name...</param>
|
||||
/// <returns></returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get driver base given the module name of the driver... This function calls
|
||||
/// GetDriverBaseByHash internally...
|
||||
/// </summary>
|
||||
/// <param name="pszDriverName">file name of the driver, this is not case
|
||||
/// dependant...</param> <returns>returns a void pointer to the drivers
|
||||
/// base...</returns>
|
||||
FORCEINLINE PVOID GetDriverBase(_In_ CONST CHAR* pszDriverName) {
|
||||
return GetDriverBaseByHash(hashstr::hash(pszDriverName));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetDriverExport via driver name and export routine name... this function
|
||||
/// calls GetDriverExportByHash internally...
|
||||
/// </summary>
|
||||
/// <param name="pszDriverName">null terminated c-string given the module name
|
||||
/// of the driver... example: "win32k.sys"</param> <param
|
||||
/// name="pszRoutineName">the c-string name of the export...</param>
|
||||
/// <returns>returns a linear virtual address to the export...</returns>
|
||||
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 PWCHAR 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<PSYSTEM_PROCESS_INFORMATION>(
|
||||
reinterpret_cast<u64>(procInfo) + procInfo->NextEntryOffset);
|
||||
}
|
||||
|
||||
DYN_NT_SYM(ExFreePool)(origPtr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FORCEINLINE PVOID GetProcessBase(_In_ HANDLE pid) {
|
||||
PEPROCESS lpProc;
|
||||
if (NT_SUCCESS(DYN_NT_SYM(PsLookupProcessByProcessId)(pid, &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 callback) {
|
||||
u32 allocSize{};
|
||||
DYN_NT_SYM(ZwQuerySystemInformation)
|
||||
(SystemProcessInformation, NULL, allocSize, &allocSize);
|
||||
|
||||
auto procInfo = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(
|
||||
DYN_NT_SYM(ExAllocatePool)(NonPagedPool, allocSize));
|
||||
|
||||
const auto origPtr = procInfo;
|
||||
DYN_NT_SYM(ZwQuerySystemInformation)
|
||||
(SystemProcessInformation, procInfo, allocSize, &allocSize);
|
||||
|
||||
while (true) {
|
||||
for (auto idx = 0u; idx < procInfo->NumberOfThreads; ++idx)
|
||||
callback(*procInfo);
|
||||
|
||||
if (!procInfo->NextEntryOffset)
|
||||
break;
|
||||
|
||||
procInfo = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(
|
||||
reinterpret_cast<u64>(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 (UINT 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 PWCHAR lpwszModuleName) {
|
||||
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<PPEB_LDR_DATA>(
|
||||
DYN_NT_SYM(PsGetProcessPeb)(lpProc)->LoaderData);
|
||||
|
||||
auto currentEntry = ldrData->InMemoryOrderModuleList.Flink;
|
||||
while (currentEntry != &ldrData->InMemoryOrderModuleList) {
|
||||
const auto currentEntryData = reinterpret_cast<PLDR_DATA_TABLE_ENTRY>(
|
||||
reinterpret_cast<u64>(currentEntry) - sizeof LIST_ENTRY);
|
||||
|
||||
const auto entryModuleName = currentEntryData->BaseDllName.Buffer;
|
||||
if (!DYN_NT_SYM(_wcsicmp)(entryModuleName, lpwszModuleName)) {
|
||||
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
|
Loading…
Reference in new issue