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.
728 lines
25 KiB
728 lines
25 KiB
#pragma once
|
|
#include <ntifs.h>
|
|
#include <intrin.h>
|
|
|
|
using u64 = unsigned long long;
|
|
using u32 = unsigned long;
|
|
using u16 = unsigned short;
|
|
using u8 = unsigned char;
|
|
|
|
#define DBG_PRINT(...) 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
|
|
|
|
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
|
|
USHORT e_magic; // Magic number
|
|
USHORT e_cblp; // Bytes on last page of file
|
|
USHORT e_cp; // Pages in file
|
|
USHORT e_crlc; // Relocations
|
|
USHORT e_cparhdr; // Size of header in paragraphs
|
|
USHORT e_minalloc; // Minimum extra paragraphs needed
|
|
USHORT e_maxalloc; // Maximum extra paragraphs needed
|
|
USHORT e_ss; // Initial (relative) SS value
|
|
USHORT e_sp; // Initial SP value
|
|
USHORT e_csum; // Checksum
|
|
USHORT e_ip; // Initial IP value
|
|
USHORT e_cs; // Initial (relative) CS value
|
|
USHORT e_lfarlc; // File address of relocation table
|
|
USHORT e_ovno; // Overlay number
|
|
USHORT e_res[4]; // Reserved words
|
|
USHORT e_oemid; // OEM identifier (for e_oeminfo)
|
|
USHORT e_oeminfo; // OEM information; e_oemid specific
|
|
USHORT e_res2[10]; // Reserved words
|
|
LONG e_lfanew; // File address of new exe header
|
|
} 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 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;
|
|
|
|
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;
|
|
|
|
extern "C" NTSTATUS ZwQuerySystemInformation (
|
|
SYSTEM_INFORMATION_CLASS SystemInformationClass,
|
|
PVOID SystemInformation,
|
|
ULONG SystemInformationLength,
|
|
PULONG ReturnLength
|
|
);
|
|
|
|
extern "C" PVOID RtlFindExportedRoutineByName(
|
|
_In_ PVOID ImageBase,
|
|
_In_ PCCH RoutineNam
|
|
);
|
|
|
|
extern "C" PVOID PsGetProcessSectionBaseAddress(
|
|
__in PEPROCESS Process
|
|
);
|
|
|
|
extern "C" PPEB PsGetProcessPeb(PEPROCESS Process);
|
|
|
|
namespace kutils
|
|
{
|
|
namespace driver
|
|
{
|
|
inline auto get_driver_base(const char* driver_name) -> void*
|
|
{
|
|
u32 alloc_size{};
|
|
ZwQuerySystemInformation (
|
|
SystemModuleInformation,
|
|
NULL, alloc_size, &alloc_size);
|
|
|
|
auto module_info =
|
|
reinterpret_cast<PRTL_PROCESS_MODULES>(
|
|
ExAllocatePool(NonPagedPool, alloc_size));
|
|
|
|
ZwQuerySystemInformation (
|
|
SystemModuleInformation,
|
|
module_info, alloc_size, &alloc_size);
|
|
|
|
for (auto idx = 0u; idx < module_info->NumberOfModules; ++idx)
|
|
{
|
|
auto module_name =
|
|
reinterpret_cast<const char*>(
|
|
module_info->Modules[idx].FullPathName +
|
|
module_info->Modules[idx].OffsetToFileName);
|
|
|
|
if (!strcmp(module_name, driver_name))
|
|
{
|
|
auto result = module_info->Modules[idx].ImageBase;
|
|
ExFreePool(module_info);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
ExFreePool(module_info);
|
|
return nullptr;
|
|
}
|
|
|
|
inline auto get_driver_export(const char* driver_name, const char* routine_name) -> void*
|
|
{
|
|
const auto driver_base =
|
|
get_driver_base(driver_name);
|
|
|
|
if (!driver_base)
|
|
return nullptr;
|
|
|
|
return RtlFindExportedRoutineByName(
|
|
reinterpret_cast<void*>(driver_base), routine_name);
|
|
}
|
|
|
|
inline auto get_driver_object(const wchar_t* driver_name) -> PDRIVER_OBJECT
|
|
{
|
|
HANDLE handle{};
|
|
OBJECT_ATTRIBUTES attributes{};
|
|
UNICODE_STRING directory_name{};
|
|
PVOID directory{};
|
|
BOOLEAN success = FALSE;
|
|
|
|
RtlInitUnicodeString(&directory_name, L"\\Driver");
|
|
InitializeObjectAttributes(
|
|
&attributes,
|
|
&directory_name,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
// open OBJECT_DIRECTORY for \\Driver
|
|
auto status = ZwOpenDirectoryObject(
|
|
&handle,
|
|
DIRECTORY_ALL_ACCESS,
|
|
&attributes
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
ZwClose(handle);
|
|
return NULL;
|
|
}
|
|
|
|
// Get OBJECT_DIRECTORY pointer from HANDLE
|
|
status = ObReferenceObjectByHandle(
|
|
handle,
|
|
DIRECTORY_ALL_ACCESS,
|
|
nullptr,
|
|
KernelMode,
|
|
&directory,
|
|
nullptr
|
|
);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
ZwClose(handle);
|
|
return NULL;
|
|
}
|
|
|
|
const auto directory_object = POBJECT_DIRECTORY(directory);
|
|
ExAcquirePushLockExclusiveEx(&directory_object->Lock, 0);
|
|
|
|
for (auto entry : directory_object->HashBuckets)
|
|
{
|
|
if (!entry)
|
|
continue;
|
|
|
|
while (entry && entry->Object)
|
|
{
|
|
auto driver = PDRIVER_OBJECT(entry->Object);
|
|
if (!driver)
|
|
continue;
|
|
|
|
if (wcscmp(driver->DriverExtension->ServiceKeyName.Buffer, driver_name) == 0)
|
|
return driver;
|
|
|
|
entry = entry->ChainLink;
|
|
}
|
|
}
|
|
|
|
ExReleasePushLockExclusiveEx(&directory_object->Lock, 0);
|
|
ObDereferenceObject(directory);
|
|
ZwClose(handle);
|
|
return nullptr;
|
|
}
|
|
|
|
inline auto iat_hook(void* base_addr, const char* routine_name, void* func_addr) -> void*
|
|
{
|
|
const auto dos_headers =
|
|
reinterpret_cast<PIMAGE_DOS_HEADER>(base_addr);
|
|
|
|
const auto nt_headers =
|
|
reinterpret_cast<PIMAGE_NT_HEADERS64>(
|
|
reinterpret_cast<DWORD_PTR>(base_addr) + dos_headers->e_lfanew);
|
|
|
|
const auto import_dir =
|
|
nt_headers->OptionalHeader
|
|
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
|
|
|
auto import_des =
|
|
reinterpret_cast<PIMAGE_IMPORT_DESCRIPTOR>(
|
|
import_dir.VirtualAddress + (DWORD_PTR)base_addr);
|
|
|
|
LPCSTR lib_name = NULL;
|
|
PVOID result = NULL;
|
|
PIMAGE_IMPORT_BY_NAME func_name = NULL;
|
|
|
|
while (import_des->Name != NULL)
|
|
{
|
|
lib_name = (LPCSTR)import_des->Name + (DWORD_PTR)base_addr;
|
|
|
|
if (driver::get_driver_base(lib_name))
|
|
{
|
|
PIMAGE_THUNK_DATA org_first_thunk = NULL, first_thunk = NULL;
|
|
org_first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)base_addr + import_des->OriginalFirstThunk);
|
|
first_thunk = (PIMAGE_THUNK_DATA)((DWORD_PTR)base_addr + import_des->FirstThunk);
|
|
while (org_first_thunk->u1.AddressOfData != NULL)
|
|
{
|
|
func_name = (PIMAGE_IMPORT_BY_NAME)((DWORD_PTR)base_addr + org_first_thunk->u1.AddressOfData);
|
|
if (strcmp(func_name->Name, routine_name) == 0)
|
|
{
|
|
// save old function pointer
|
|
result = reinterpret_cast<PVOID>(first_thunk->u1.Function);
|
|
|
|
//
|
|
// although disabling wp bit can cause crashes, im disabling it for nano seconds. only to write 8 bytes...
|
|
// in reality this is 1 mov instruction.
|
|
//
|
|
{
|
|
//
|
|
// disable write protection
|
|
//
|
|
_disable();
|
|
auto cr0 = __readcr0();
|
|
cr0 &= 0xfffffffffffeffff;
|
|
__writecr0(cr0);
|
|
}
|
|
|
|
// swap address
|
|
first_thunk->u1.Function = reinterpret_cast<ULONG64>(func_addr);
|
|
|
|
{
|
|
//
|
|
// enable write protection
|
|
//
|
|
auto cr0 = __readcr0();
|
|
cr0 |= 0x10000;
|
|
__writecr0(cr0);
|
|
_enable();
|
|
}
|
|
return result;
|
|
}
|
|
++org_first_thunk;
|
|
++first_thunk;
|
|
}
|
|
}
|
|
++import_des;
|
|
}
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
namespace process
|
|
{
|
|
inline auto get_pid(const wchar_t* process_name) -> u32
|
|
{
|
|
u32 alloc_size{};
|
|
ZwQuerySystemInformation (
|
|
SystemProcessInformation,
|
|
nullptr, alloc_size, &alloc_size);
|
|
|
|
auto process_info =
|
|
reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(
|
|
ExAllocatePool(NonPagedPool, alloc_size));
|
|
|
|
const auto orig_ptr = process_info;
|
|
ZwQuerySystemInformation (
|
|
SystemProcessInformation,
|
|
process_info, alloc_size, &alloc_size);
|
|
|
|
while (true)
|
|
{
|
|
if (process_info->ImageName.Buffer)
|
|
{
|
|
if (!_wcsicmp(process_info->ImageName.Buffer, process_name))
|
|
{
|
|
auto result = process_info->ProcessId;
|
|
ExFreePool(orig_ptr);
|
|
return (u32)result;
|
|
}
|
|
}
|
|
|
|
if (!process_info->NextEntryOffset)
|
|
break;
|
|
|
|
process_info = reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(
|
|
reinterpret_cast<u64>(process_info) + process_info->NextEntryOffset);
|
|
}
|
|
|
|
ExFreePool(orig_ptr);
|
|
return NULL;
|
|
}
|
|
|
|
inline auto get_process_base(u32 pid) -> void*
|
|
{
|
|
PEPROCESS peproc;
|
|
NTSTATUS result;
|
|
|
|
if ((result = PsLookupProcessByProcessId((HANDLE)pid, &peproc)) == STATUS_SUCCESS)
|
|
{
|
|
auto base_address =
|
|
PsGetProcessSectionBaseAddress(peproc);
|
|
|
|
ObDereferenceObject(peproc);
|
|
return base_address;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
inline auto get_module_base(u32 pid, const wchar_t* module_name) -> void*
|
|
{
|
|
PEPROCESS peproc;
|
|
NTSTATUS result;
|
|
KAPC_STATE apc_state;
|
|
|
|
if ((result = PsLookupProcessByProcessId((HANDLE)pid, &peproc)) == STATUS_SUCCESS)
|
|
{
|
|
KeStackAttachProcess(peproc, &apc_state);
|
|
{
|
|
const auto ldr_data =
|
|
reinterpret_cast<PPEB_LDR_DATA>(
|
|
PsGetProcessPeb(peproc)->LoaderData);
|
|
|
|
auto current_entry =
|
|
ldr_data->InMemoryOrderModuleList.Flink;
|
|
|
|
while (current_entry != &ldr_data->InMemoryOrderModuleList)
|
|
{
|
|
const auto current_entry_data =
|
|
reinterpret_cast<PLDR_DATA_TABLE_ENTRY>(
|
|
reinterpret_cast<u64>(current_entry) - sizeof LIST_ENTRY);
|
|
|
|
const auto entry_module_name =
|
|
current_entry_data->BaseDllName.Buffer;
|
|
|
|
if (!_wcsicmp(entry_module_name, module_name))
|
|
{
|
|
ObDereferenceObject(peproc);
|
|
auto module_base = current_entry_data->DllBase;
|
|
|
|
KeUnstackDetachProcess(&apc_state);
|
|
return module_base;
|
|
}
|
|
|
|
current_entry = current_entry->Flink;
|
|
}
|
|
}
|
|
KeUnstackDetachProcess(&apc_state);
|
|
ObDereferenceObject(peproc);
|
|
}
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
namespace pe
|
|
{
|
|
inline auto get_nt_header(void* module_base) -> PIMAGE_NT_HEADERS64
|
|
{
|
|
const auto dos_header =
|
|
reinterpret_cast<PIMAGE_DOS_HEADER>(module_base);
|
|
|
|
return reinterpret_cast<PIMAGE_NT_HEADERS64>(
|
|
reinterpret_cast<u64>(module_base) + dos_header->e_lfanew);
|
|
}
|
|
}
|
|
|
|
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;
|
|
};
|
|
|
|
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;
|
|
}
|
|
}
|
|
} |