You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
866 lines
26 KiB
866 lines
26 KiB
3 years ago
|
/*
|
||
|
* 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
|