parent
4e4912c9c3
commit
62bf24fb47
@ -0,0 +1,87 @@
|
||||
;
|
||||
; NtWin32k.inf
|
||||
;
|
||||
|
||||
[Version]
|
||||
Signature="$WINDOWS NT$"
|
||||
Class=Sample ; TODO: edit Class
|
||||
ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid
|
||||
Provider=%ManufacturerName%
|
||||
CatalogFile=NtWin32k.cat
|
||||
DriverVer= ; TODO: set DriverVer in stampinf property pages
|
||||
PnpLockDown=1
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir = 12
|
||||
NtWin32k_Device_CoInstaller_CopyFiles = 11
|
||||
|
||||
; ================= Class section =====================
|
||||
|
||||
[ClassInstall32]
|
||||
Addreg=SampleClassReg
|
||||
|
||||
[SampleClassReg]
|
||||
HKR,,,0,%ClassName%
|
||||
HKR,,Icon,,-5
|
||||
|
||||
[SourceDisksNames]
|
||||
1 = %DiskName%,,,""
|
||||
|
||||
[SourceDisksFiles]
|
||||
NtWin32k.sys = 1,,
|
||||
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
|
||||
|
||||
;*****************************************
|
||||
; Install Section
|
||||
;*****************************************
|
||||
|
||||
[Manufacturer]
|
||||
%ManufacturerName%=Standard,NT$ARCH$
|
||||
|
||||
[Standard.NT$ARCH$]
|
||||
%NtWin32k.DeviceDesc%=NtWin32k_Device, Root\NtWin32k ; TODO: edit hw-id
|
||||
|
||||
[NtWin32k_Device.NT]
|
||||
CopyFiles=Drivers_Dir
|
||||
|
||||
[Drivers_Dir]
|
||||
NtWin32k.sys
|
||||
|
||||
;-------------- Service installation
|
||||
[NtWin32k_Device.NT.Services]
|
||||
AddService = NtWin32k,%SPSVCINST_ASSOCSERVICE%, NtWin32k_Service_Inst
|
||||
|
||||
; -------------- NtWin32k driver install sections
|
||||
[NtWin32k_Service_Inst]
|
||||
DisplayName = %NtWin32k.SVCDESC%
|
||||
ServiceType = 1 ; SERVICE_KERNEL_DRIVER
|
||||
StartType = 3 ; SERVICE_DEMAND_START
|
||||
ErrorControl = 1 ; SERVICE_ERROR_NORMAL
|
||||
ServiceBinary = %12%\NtWin32k.sys
|
||||
|
||||
;
|
||||
;--- NtWin32k_Device Coinstaller installation ------
|
||||
;
|
||||
|
||||
[NtWin32k_Device.NT.CoInstallers]
|
||||
AddReg=NtWin32k_Device_CoInstaller_AddReg
|
||||
CopyFiles=NtWin32k_Device_CoInstaller_CopyFiles
|
||||
|
||||
[NtWin32k_Device_CoInstaller_AddReg]
|
||||
HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
|
||||
|
||||
[NtWin32k_Device_CoInstaller_CopyFiles]
|
||||
WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
|
||||
|
||||
[NtWin32k_Device.NT.Wdf]
|
||||
KmdfService = NtWin32k, NtWin32k_wdfsect
|
||||
[NtWin32k_wdfsect]
|
||||
KmdfLibraryVersion = $KMDFVERSION$
|
||||
|
||||
[Strings]
|
||||
SPSVCINST_ASSOCSERVICE= 0x00000002
|
||||
ManufacturerName="<Your manufacturer name>" ;TODO: Replace with your manufacturer name
|
||||
ClassName="Samples" ; TODO: edit ClassName
|
||||
DiskName = "NtWin32k Installation Disk"
|
||||
NtWin32k.DeviceDesc = "NtWin32k Device"
|
||||
NtWin32k.SVCDESC = "NtWin32k Service"
|
@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Driver Files">
|
||||
<UniqueIdentifier>{8E41214B-6785-4CFE-B992-037D68949A14}</UniqueIdentifier>
|
||||
<Extensions>inf;inv;inx;mof;mc;</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Inf Include="NtWin32k.inf">
|
||||
<Filter>Driver Files</Filter>
|
||||
</Inf>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="kutils.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ntwin32k.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="driver_entry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<MASM Include="filter_handler.asm">
|
||||
<Filter>Source Files</Filter>
|
||||
</MASM>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,39 @@
|
||||
#include "ntwin32k.hpp"
|
||||
#define SYSCALL_KEY 0xDEADBEEF
|
||||
|
||||
extern "C" auto hook_handler(unsigned syscall_num, psyscall_args_t args) -> bool
|
||||
{
|
||||
if (args->rcx == SYSCALL_KEY)
|
||||
{
|
||||
DBG_PRINT("syscall number -> 0x%x\n", syscall_num);
|
||||
DBG_PRINT(" - rcx: 0x%p\n", args->rcx);
|
||||
DBG_PRINT(" - rdx: 0x%p\n", args->rdx);
|
||||
DBG_PRINT(" - r8: 0x%p\n", args->r8);
|
||||
DBG_PRINT(" - r9: 0x%p\n", args->r9);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// unhook win32k filter on unload...
|
||||
auto driver_unload(PDRIVER_OBJECT driver_object) -> void
|
||||
{
|
||||
nt::win32k::unhook_filter(original_function);
|
||||
}
|
||||
|
||||
auto driver_entry(
|
||||
PDRIVER_OBJECT driver_object,
|
||||
PUNICODE_STRING registry_path
|
||||
) -> NTSTATUS
|
||||
{
|
||||
RTL_OSVERSIONINFOW version;
|
||||
RtlGetVersion(&version);
|
||||
|
||||
if (version.dwBuildNumber >= 19041) // if 2004 and above...
|
||||
original_function = nt::win32k::hook_filter(&asm_hook_handler_2004);
|
||||
else
|
||||
original_function = nt::win32k::hook_filter(&asm_hook_handler);
|
||||
|
||||
driver_object->DriverUnload = &driver_unload;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
extern hook_handler : proc
|
||||
.code
|
||||
asm_hook_handler_2004 proc
|
||||
lea rdx, [rsp+58h] ; rcx is the syscall number...
|
||||
; rdx is a pointer to arguments...
|
||||
call hook_handler
|
||||
cmp rax, 1
|
||||
je sysreturn
|
||||
|
||||
xor rax, rax ; always return false...
|
||||
ret
|
||||
sysreturn:
|
||||
add rsp, 80h
|
||||
mov rax, 00C0FFEEh ; return back to usermode with 0xC0FFEE as result...
|
||||
ret
|
||||
asm_hook_handler_2004 endp
|
||||
|
||||
; stack distance to arguments is different on older versions of windows...
|
||||
asm_hook_handler proc
|
||||
lea rdx, [rsp + 28h]
|
||||
call hook_handler
|
||||
cmp rax, 1
|
||||
je sysreturn
|
||||
|
||||
xor rax, rax
|
||||
ret
|
||||
sysreturn:
|
||||
add rsp, 50h
|
||||
mov rax, 00C0FFEEh
|
||||
ret
|
||||
asm_hook_handler endp
|
||||
end
|
@ -0,0 +1,728 @@
|
||||
#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 NtQuerySystemInformation(
|
||||
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{};
|
||||
NtQuerySystemInformation(
|
||||
SystemModuleInformation,
|
||||
NULL, alloc_size, &alloc_size);
|
||||
|
||||
auto module_info =
|
||||
reinterpret_cast<PRTL_PROCESS_MODULES>(
|
||||
ExAllocatePool(NonPagedPool, alloc_size));
|
||||
|
||||
NtQuerySystemInformation(
|
||||
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{};
|
||||
NtQuerySystemInformation(
|
||||
SystemProcessInformation,
|
||||
nullptr, alloc_size, &alloc_size);
|
||||
|
||||
auto process_info =
|
||||
reinterpret_cast<PSYSTEM_PROCESS_INFORMATION>(
|
||||
ExAllocatePool(NonPagedPool, alloc_size));
|
||||
|
||||
const auto orig_ptr = process_info;
|
||||
NtQuerySystemInformation(
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,223 @@
|
||||
#pragma once
|
||||
#include "kutils.hpp"
|
||||
|
||||
#define WIN32K_SYSCALL_FILTER_MASK "xxxxxxxxxxxxxxxxxxxxxxx????xxx"
|
||||
#define WIN32K_SYSCALL_FILTER_SIG "\x48\x89\x4C\x24\x20\x48\x89\x54\x24\x28\x4C\x89\x44\x24\x30\x4C\x89\x4C\x24\x38\x48\xC7\xC1\x00\x00\x00\x00\x48\xFF\x15"
|
||||
static_assert(sizeof WIN32K_SYSCALL_FILTER_SIG == sizeof WIN32K_SYSCALL_FILTER_MASK, "signature and mask len invalid...");
|
||||
|
||||
typedef union _MISC_THREAD_VALUES
|
||||
{
|
||||
struct
|
||||
{
|
||||
ULONG ThreadFlagsSpare : 2; //0x78
|
||||
ULONG AutoAlignment : 1; //0x78
|
||||
ULONG DisableBoost : 1; //0x78
|
||||
ULONG AlertedByThreadId : 1; //0x78
|
||||
ULONG QuantumDonation : 1; //0x78
|
||||
ULONG EnableStackSwap : 1; //0x78
|
||||
ULONG GuiThread : 1; //0x78
|
||||
ULONG DisableQuantum : 1; //0x78
|
||||
ULONG ChargeOnlySchedulingGroup : 1; //0x78
|
||||
ULONG DeferPreemption : 1; //0x78
|
||||
ULONG QueueDeferPreemption : 1; //0x78
|
||||
ULONG ForceDeferSchedule : 1; //0x78
|
||||
ULONG SharedReadyQueueAffinity : 1; //0x78
|
||||
ULONG FreezeCount : 1; //0x78
|
||||
ULONG TerminationApcRequest : 1; //0x78
|
||||
ULONG AutoBoostEntriesExhausted : 1; //0x78
|
||||
ULONG KernelStackResident : 1; //0x78
|
||||
ULONG TerminateRequestReason : 2; //0x78
|
||||
ULONG ProcessStackCountDecremented : 1; //0x78
|
||||
ULONG RestrictedGuiThread : 1; //0x78
|
||||
ULONG VpBackingThread : 1; //0x78
|
||||
ULONG ThreadFlagsSpare2 : 1; //0x78
|
||||
ULONG EtwStackTraceApcInserted : 8; //0x78
|
||||
};
|
||||
volatile LONG ThreadFlags; //0x78
|
||||
} MISC_THREAD_VALUES, * PMISC_THREAD_VALUES;
|
||||
|
||||
typedef struct _syscall_args_t
|
||||
{
|
||||
u64 rcx, rdx, r8, r9;
|
||||
} syscall_args_t, *psyscall_args_t;
|
||||
|
||||
inline void* original_function = nullptr;
|
||||
|
||||
// handler is designed to get the arguments passed in registers...
|
||||
extern "C" void asm_hook_handler_2004(unsigned syscall_number);
|
||||
extern "C" void asm_hook_handler(unsigned syscall_number);
|
||||
|
||||
namespace nt
|
||||
{
|
||||
inline auto enable_filter(HANDLE tid) -> bool
|
||||
{
|
||||
PETHREAD thread;
|
||||
if (PsLookupThreadByThreadId(tid, &thread) == STATUS_SUCCESS)
|
||||
{
|
||||
const auto thread_misc_values =
|
||||
reinterpret_cast<PMISC_THREAD_VALUES>(
|
||||
reinterpret_cast<unsigned char*>(thread) + 0x78);
|
||||
|
||||
// make the thread gui and restricted...
|
||||
thread_misc_values->GuiThread = 1;
|
||||
thread_misc_values->RestrictedGuiThread = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline auto enable_filter(PETHREAD thread) -> void
|
||||
{
|
||||
const auto thread_misc_values =
|
||||
reinterpret_cast<PMISC_THREAD_VALUES>(
|
||||
reinterpret_cast<unsigned char*>(thread) + 0x78);
|
||||
|
||||
// make the thread gui and restricted...
|
||||
thread_misc_values->GuiThread = 1;
|
||||
thread_misc_values->RestrictedGuiThread = 1;
|
||||
}
|
||||
|
||||
namespace win32k
|
||||
{
|
||||
inline auto hook_filter(void* hook_func) -> void*
|
||||
{
|
||||
PEPROCESS peproc;
|
||||
KAPC_STATE apc_state;
|
||||
|
||||
RTL_OSVERSIONINFOW version;
|
||||
RtlGetVersion(&version);
|
||||
|
||||
const auto explorer_pid = kutils::process::get_pid(L"explorer.exe");
|
||||
PsLookupProcessByProcessId((HANDLE)explorer_pid, &peproc);
|
||||
|
||||
// attach to an address space that contains win32k.sys
|
||||
KeStackAttachProcess(peproc, &apc_state);
|
||||
{
|
||||
const auto win32k = kutils::driver::get_driver_base("win32k.sys");
|
||||
if (version.dwBuildNumber >= 19041) // if 2004 and above...
|
||||
{
|
||||
/*
|
||||
* .text:FFFFF97FFF0172E4 48 89 4C 24 20 mov [rsp+48h+var_28], rcx
|
||||
* .text:FFFFF97FFF0172E9 48 89 54 24 28 mov [rsp+48h+var_20], rdx
|
||||
* .text:FFFFF97FFF0172EE 4C 89 44 24 30 mov [rsp+48h+var_18], r8
|
||||
* .text:FFFFF97FFF0172F3 4C 89 4C 24 38 mov [rsp+48h+var_10], r9
|
||||
* .text:FFFFF97FFF0172F8 48 C7 C1 00 00 00 00 mov rcx, 0 ; _QWORD
|
||||
* .text:FFFFF97FFF0172FF 48 FF 15 [B2 A4 03 00] call cs:__imp_IsWin32KSyscallFiltered <==== 30 bytes to this RVA...
|
||||
*/
|
||||
|
||||
auto sig_result = reinterpret_cast<u64>(
|
||||
kutils::signature::scan(win32k,
|
||||
kutils::pe::get_nt_header(win32k)->OptionalHeader.SizeOfImage,
|
||||
WIN32K_SYSCALL_FILTER_SIG, WIN32K_SYSCALL_FILTER_MASK));
|
||||
|
||||
const auto sig_rva = *reinterpret_cast<int*>(sig_result + 30); // + 30 from above...
|
||||
sig_result = sig_result + sig_rva + 34; // 34 bytes to RIP...
|
||||
|
||||
if (sig_result)
|
||||
{
|
||||
/*
|
||||
* .rdata:FFFFF97FFF0517B8 ; __int64 (__fastcall *IsWin32KSyscallFiltered)(_QWORD)
|
||||
* .rdata:FFFFF97FFF0517B8 E4 05 01 FF 7F F9 FF FF __imp_IsWin32KSyscallFiltered dq offset IsWin32KSyscallFiltered <=== deference this....
|
||||
*/
|
||||
const auto win32k_filter_func =
|
||||
reinterpret_cast<u64>(
|
||||
*reinterpret_cast<void**>(sig_result));
|
||||
|
||||
/*
|
||||
* .text:FFFFF97FFF0105E4 IsWin32KSyscallFiltered proc near
|
||||
* .text:FFFFF97FFF0105E4 48 83 EC 28 sub rsp, 28h
|
||||
* .text:FFFFF97FFF0105E8 48 8B 05 [A1 67 05 00] mov rax, cs:qword_FFFFF97FFF066D90 <======= + 7 bytes to this RVA....
|
||||
* .text:FFFFF97FFF0105EF 48 85 C0 test rax, rax
|
||||
* .text:FFFFF97FFF0105F2 74 06 jz short loc_FFFFF97FFF0105FA
|
||||
* .text:FFFFF97FFF0105F4 FF 15 66 43 06 00 call cs:__guard_dispatch_icall_fptr
|
||||
*/
|
||||
const auto ptr_swap_rva = *reinterpret_cast<int*>(win32k_filter_func + 7); // + 7 from above^
|
||||
const auto win32k_syscall_filter_ptr = reinterpret_cast<void**>(ptr_swap_rva + win32k_filter_func + 11); // + 7 because 11 bytes in is the next instruction after the mov rax, cs....
|
||||
const auto result = *win32k_syscall_filter_ptr;
|
||||
*win32k_syscall_filter_ptr = hook_func;
|
||||
|
||||
KeUnstackDetachProcess(&apc_state);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else // else 1909 and below (IAT hook)...
|
||||
{
|
||||
auto result = kutils::driver::iat_hook(
|
||||
win32k, "IsWin32KSyscallFiltered", hook_func);
|
||||
|
||||
KeUnstackDetachProcess(&apc_state);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
KeUnstackDetachProcess(&apc_state);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline auto unhook_filter(void* original_function) -> void
|
||||
{
|
||||
PEPROCESS peproc;
|
||||
KAPC_STATE apc_state;
|
||||
|
||||
RTL_OSVERSIONINFOW version;
|
||||
RtlGetVersion(&version);
|
||||
|
||||
const auto explorer_pid = kutils::process::get_pid(L"explorer.exe");
|
||||
PsLookupProcessByProcessId((HANDLE)explorer_pid, &peproc);
|
||||
|
||||
// attach to an address space that contains win32k.sys
|
||||
KeStackAttachProcess(peproc, &apc_state);
|
||||
{
|
||||
const auto win32k = kutils::driver::get_driver_base("win32k.sys");
|
||||
if (version.dwBuildNumber >= 19041) // if 2004 and above...
|
||||
{
|
||||
/*
|
||||
* .text:FFFFF97FFF0172E4 48 89 4C 24 20 mov [rsp+48h+var_28], rcx
|
||||
* .text:FFFFF97FFF0172E9 48 89 54 24 28 mov [rsp+48h+var_20], rdx
|
||||
* .text:FFFFF97FFF0172EE 4C 89 44 24 30 mov [rsp+48h+var_18], r8
|
||||
* .text:FFFFF97FFF0172F3 4C 89 4C 24 38 mov [rsp+48h+var_10], r9
|
||||
* .text:FFFFF97FFF0172F8 48 C7 C1 00 00 00 00 mov rcx, 0 ; _QWORD
|
||||
* .text:FFFFF97FFF0172FF 48 FF 15 [B2 A4 03 00] call cs:__imp_IsWin32KSyscallFiltered <==== 30 bytes to this RVA...
|
||||
*/
|
||||
|
||||
auto sig_result = reinterpret_cast<u64>(
|
||||
kutils::signature::scan(win32k,
|
||||
kutils::pe::get_nt_header(win32k)->OptionalHeader.SizeOfImage,
|
||||
WIN32K_SYSCALL_FILTER_SIG, WIN32K_SYSCALL_FILTER_MASK));
|
||||
|
||||
const auto sig_rva = *reinterpret_cast<int*>(sig_result + 30); // + 30 from above...
|
||||
sig_result = sig_result + sig_rva + 34; // 34 bytes to RIP...
|
||||
|
||||
if (sig_result)
|
||||
{
|
||||
/*
|
||||
* .rdata:FFFFF97FFF0517B8 ; __int64 (__fastcall *IsWin32KSyscallFiltered)(_QWORD)
|
||||
* .rdata:FFFFF97FFF0517B8 E4 05 01 FF 7F F9 FF FF __imp_IsWin32KSyscallFiltered dq offset IsWin32KSyscallFiltered <=== deference this....
|
||||
*/
|
||||
const auto win32k_filter_func =
|
||||
reinterpret_cast<u64>(
|
||||
*reinterpret_cast<void**>(sig_result));
|
||||
|
||||
/*
|
||||
* .text:FFFFF97FFF0105E4 IsWin32KSyscallFiltered proc near
|
||||
* .text:FFFFF97FFF0105E4 48 83 EC 28 sub rsp, 28h
|
||||
* .text:FFFFF97FFF0105E8 48 8B 05 [A1 67 05 00] mov rax, cs:qword_FFFFF97FFF066D90 <======= + 7 bytes to this RVA....
|
||||
* .text:FFFFF97FFF0105EF 48 85 C0 test rax, rax
|
||||
* .text:FFFFF97FFF0105F2 74 06 jz short loc_FFFFF97FFF0105FA
|
||||
* .text:FFFFF97FFF0105F4 FF 15 66 43 06 00 call cs:__guard_dispatch_icall_fptr
|
||||
*/
|
||||
const auto ptr_swap_rva = *reinterpret_cast<int*>(win32k_filter_func + 7); // + 7 from above^
|
||||
const auto win32k_syscall_filter_ptr = reinterpret_cast<void**>(ptr_swap_rva + win32k_filter_func + 11); // + 7 because 11 bytes in is the next instruction after the mov rax, cs....
|
||||
*win32k_syscall_filter_ptr = original_function;
|
||||
}
|
||||
}
|
||||
else // else 1909 and below (IAT hook)...
|
||||
{
|
||||
// restore IAT...
|
||||
kutils::driver::iat_hook(win32k,
|
||||
"IsWin32KSyscallFiltered", original_function);
|
||||
}
|
||||
}
|
||||
KeUnstackDetachProcess(&apc_state);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{df92fe26-a275-403c-b242-35c82b881def}</ProjectGuid>
|
||||
<RootNamespace>NtWin32u</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ntwin32u.hpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ntwin32u.hpp">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
@ -0,0 +1,10 @@
|
||||
#include "ntwin32u.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::printf("syscall result -> 0x%p\n", nt::win32u::syscall());
|
||||
std::getchar();
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <winternl.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
namespace nt
|
||||
{
|
||||
namespace win32u
|
||||
{
|
||||
using syscall_table_t = std::vector<std::pair<std::string, std::uintptr_t>>;
|
||||
inline syscall_table_t syscall_table = ([&]()-> syscall_table_t
|
||||
{
|
||||
PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY syscall_policy{};
|
||||
syscall_policy.DisallowWin32kSystemCalls = true;
|
||||
|
||||
std::printf("disable win32ksyscall -> %d\n",
|
||||
SetProcessMitigationPolicy(ProcessSystemCallDisablePolicy,
|
||||
&syscall_policy, sizeof syscall_policy));
|
||||
|
||||
LoadLibraryA("user32.dll");
|
||||
syscall_table_t result;
|
||||
|
||||
const auto win32u =
|
||||
reinterpret_cast<PIMAGE_DOS_HEADER>(
|
||||
LoadLibraryA("win32u.dll"));
|
||||
|
||||
const auto nt_header =
|
||||
reinterpret_cast<PIMAGE_NT_HEADERS64>(
|
||||
reinterpret_cast<std::uintptr_t>(win32u) + win32u->e_lfanew);
|
||||
|
||||
const auto export_rvas =
|
||||
nt_header->OptionalHeader.DataDirectory[
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
|
||||
const auto exports =
|
||||
reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>(
|
||||
reinterpret_cast<std::uintptr_t>(win32u) + export_rvas);
|
||||
|
||||
const auto name_rva =
|
||||
reinterpret_cast<std::uint32_t*>(
|
||||
reinterpret_cast<std::uintptr_t>(win32u) + exports->AddressOfNames);
|
||||
|
||||
for (auto idx = 0u; idx < exports->NumberOfNames; ++idx)
|
||||
{
|
||||
const auto function_name =
|
||||
reinterpret_cast<const char*>(
|
||||
reinterpret_cast<std::uintptr_t>(win32u) + name_rva[idx]);
|
||||
|
||||
// add Nt functions...
|
||||
if (!strncmp(function_name, "Nt", 2))
|
||||
{
|
||||
const auto func_rva =
|
||||
reinterpret_cast<std::uint32_t*>(
|
||||
reinterpret_cast<std::uintptr_t>(win32u) + exports->AddressOfFunctions);
|
||||
|
||||
const auto ordinal_rva =
|
||||
reinterpret_cast<std::uint16_t*>(
|
||||
reinterpret_cast<std::uintptr_t>(win32u) + exports->AddressOfNameOrdinals);
|
||||
|
||||
const auto function_addr =
|
||||
reinterpret_cast<std::uintptr_t>(win32u) + func_rva[ordinal_rva[idx]];
|
||||
|
||||
result.push_back({ function_name, function_addr });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
|
||||
inline auto syscall() -> std::uintptr_t
|
||||
{
|
||||
static const auto random = [&](int min, int max) -> int
|
||||
{
|
||||
if (static std::atomic<bool> first = false; !first.exchange(true))
|
||||
srand(time(NULL));
|
||||
|
||||
return min + rand() % ((max + 1) - min);
|
||||
};
|
||||
|
||||
const auto [function_name, function_addr] =
|
||||
syscall_table[random(NULL, syscall_table.size())];
|
||||
|
||||
std::printf("%s -> 0x%p\n", function_name.c_str(), function_addr);
|
||||
std::getchar();
|
||||
|
||||
return reinterpret_cast<std::uintptr_t(*)(std::uintptr_t)>(function_addr)(0xC0FFEE);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue