From 62bf24fb47e309f7ed7e346b1d53f1e75e43a089 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Tue, 5 Jan 2021 19:40:51 -0800 Subject: [PATCH] init commit --- NtWin32k.sln | 45 ++ NtWin32k/NtWin32k.inf | 87 ++++ NtWin32k/NtWin32k.vcxproj | 177 ++++++++ NtWin32k/NtWin32k.vcxproj.filters | 40 ++ NtWin32k/driver_entry.cpp | 39 ++ NtWin32k/filter_handler.asm | 32 ++ NtWin32k/kutils.hpp | 728 ++++++++++++++++++++++++++++++ NtWin32k/ntwin32k.hpp | 223 +++++++++ NtWin32u/NtWin32u.vcxproj | 151 +++++++ NtWin32u/NtWin32u.vcxproj.filters | 23 + NtWin32u/NtWin32u.vcxproj.user | 4 + NtWin32u/main.cpp | 10 + NtWin32u/ntwin32u.hpp | 93 ++++ 13 files changed, 1652 insertions(+) create mode 100644 NtWin32k.sln create mode 100644 NtWin32k/NtWin32k.inf create mode 100644 NtWin32k/NtWin32k.vcxproj create mode 100644 NtWin32k/NtWin32k.vcxproj.filters create mode 100644 NtWin32k/driver_entry.cpp create mode 100644 NtWin32k/filter_handler.asm create mode 100644 NtWin32k/kutils.hpp create mode 100644 NtWin32k/ntwin32k.hpp create mode 100644 NtWin32u/NtWin32u.vcxproj create mode 100644 NtWin32u/NtWin32u.vcxproj.filters create mode 100644 NtWin32u/NtWin32u.vcxproj.user create mode 100644 NtWin32u/main.cpp create mode 100644 NtWin32u/ntwin32u.hpp diff --git a/NtWin32k.sln b/NtWin32k.sln new file mode 100644 index 0000000..8b1d34c --- /dev/null +++ b/NtWin32k.sln @@ -0,0 +1,45 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30621.155 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NtWin32k", "NtWin32k\NtWin32k.vcxproj", "{CB140ADD-1805-4F91-9E5A-4844F98EAB52}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NtWin32u", "NtWin32u\NtWin32u.vcxproj", "{DF92FE26-A275-403C-B242-35C82B881DEF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Debug|x64.ActiveCfg = Debug|x64 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Debug|x64.Build.0 = Debug|x64 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Debug|x64.Deploy.0 = Debug|x64 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Debug|x86.ActiveCfg = Debug|Win32 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Debug|x86.Build.0 = Debug|Win32 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Debug|x86.Deploy.0 = Debug|Win32 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Release|x64.ActiveCfg = Release|x64 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Release|x64.Build.0 = Release|x64 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Release|x64.Deploy.0 = Release|x64 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Release|x86.ActiveCfg = Release|Win32 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Release|x86.Build.0 = Release|Win32 + {CB140ADD-1805-4F91-9E5A-4844F98EAB52}.Release|x86.Deploy.0 = Release|Win32 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Debug|x64.ActiveCfg = Debug|x64 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Debug|x64.Build.0 = Debug|x64 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Debug|x86.ActiveCfg = Debug|Win32 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Debug|x86.Build.0 = Debug|Win32 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Release|x64.ActiveCfg = Release|x64 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Release|x64.Build.0 = Release|x64 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Release|x86.ActiveCfg = Release|Win32 + {DF92FE26-A275-403C-B242-35C82B881DEF}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {115B9250-3D35-44AE-B94B-3F3BF017926A} + EndGlobalSection +EndGlobal diff --git a/NtWin32k/NtWin32k.inf b/NtWin32k/NtWin32k.inf new file mode 100644 index 0000000..62a485f --- /dev/null +++ b/NtWin32k/NtWin32k.inf @@ -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="" ;TODO: Replace with your manufacturer name +ClassName="Samples" ; TODO: edit ClassName +DiskName = "NtWin32k Installation Disk" +NtWin32k.DeviceDesc = "NtWin32k Device" +NtWin32k.SVCDESC = "NtWin32k Service" diff --git a/NtWin32k/NtWin32k.vcxproj b/NtWin32k/NtWin32k.vcxproj new file mode 100644 index 0000000..c11d737 --- /dev/null +++ b/NtWin32k/NtWin32k.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + + {CB140ADD-1805-4F91-9E5A-4844F98EAB52} + {1bc93793-694f-48fe-9372-81e2b05556fd} + v4.5 + 12.0 + Debug + Win32 + NtWin32k + $(LatestTargetPlatformVersion) + + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + false + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + + + Windows10 + true + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + + + Windows10 + false + WindowsKernelModeDriver10.0 + Driver + KMDF + Universal + + + + + + + + + + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + DbgengKernelDebugger + + + + stdcpp17 + false + false + false + + + driver_entry + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NtWin32k/NtWin32k.vcxproj.filters b/NtWin32k/NtWin32k.vcxproj.filters new file mode 100644 index 0000000..acfe9f1 --- /dev/null +++ b/NtWin32k/NtWin32k.vcxproj.filters @@ -0,0 +1,40 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {8E41214B-6785-4CFE-B992-037D68949A14} + inf;inv;inx;mof;mc; + + + + + Driver Files + + + + + Header Files + + + Header Files + + + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/NtWin32k/driver_entry.cpp b/NtWin32k/driver_entry.cpp new file mode 100644 index 0000000..3cecd6c --- /dev/null +++ b/NtWin32k/driver_entry.cpp @@ -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; +} \ No newline at end of file diff --git a/NtWin32k/filter_handler.asm b/NtWin32k/filter_handler.asm new file mode 100644 index 0000000..a531e4c --- /dev/null +++ b/NtWin32k/filter_handler.asm @@ -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 \ No newline at end of file diff --git a/NtWin32k/kutils.hpp b/NtWin32k/kutils.hpp new file mode 100644 index 0000000..8e8ffca --- /dev/null +++ b/NtWin32k/kutils.hpp @@ -0,0 +1,728 @@ +#pragma once +#include +#include + +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( + 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( + 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(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(base_addr); + + const auto nt_headers = + reinterpret_cast( + reinterpret_cast(base_addr) + dos_headers->e_lfanew); + + const auto import_dir = + nt_headers->OptionalHeader + .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; + + auto import_des = + reinterpret_cast( + 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(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(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( + 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( + reinterpret_cast(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( + PsGetProcessPeb(peproc)->LoaderData); + + auto current_entry = + ldr_data->InMemoryOrderModuleList.Flink; + + while (current_entry != &ldr_data->InMemoryOrderModuleList) + { + const auto current_entry_data = + reinterpret_cast( + reinterpret_cast(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(module_base); + + return reinterpret_cast( + reinterpret_cast(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; + } + } +} \ No newline at end of file diff --git a/NtWin32k/ntwin32k.hpp b/NtWin32k/ntwin32k.hpp new file mode 100644 index 0000000..f685122 --- /dev/null +++ b/NtWin32k/ntwin32k.hpp @@ -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( + reinterpret_cast(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( + reinterpret_cast(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( + 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(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( + *reinterpret_cast(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(win32k_filter_func + 7); // + 7 from above^ + const auto win32k_syscall_filter_ptr = reinterpret_cast(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( + 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(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( + *reinterpret_cast(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(win32k_filter_func + 7); // + 7 from above^ + const auto win32k_syscall_filter_ptr = reinterpret_cast(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); + } + } +} \ No newline at end of file diff --git a/NtWin32u/NtWin32u.vcxproj b/NtWin32u/NtWin32u.vcxproj new file mode 100644 index 0000000..d278ba7 --- /dev/null +++ b/NtWin32u/NtWin32u.vcxproj @@ -0,0 +1,151 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {df92fe26-a275-403c-b242-35c82b881def} + NtWin32u + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + stdcpp17 + + + Console + true + true + true + + + + + + + + + + + + \ No newline at end of file diff --git a/NtWin32u/NtWin32u.vcxproj.filters b/NtWin32u/NtWin32u.vcxproj.filters new file mode 100644 index 0000000..ea33b20 --- /dev/null +++ b/NtWin32u/NtWin32u.vcxproj.filters @@ -0,0 +1,23 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/NtWin32u/NtWin32u.vcxproj.user b/NtWin32u/NtWin32u.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/NtWin32u/NtWin32u.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/NtWin32u/main.cpp b/NtWin32u/main.cpp new file mode 100644 index 0000000..0e7a7c3 --- /dev/null +++ b/NtWin32u/main.cpp @@ -0,0 +1,10 @@ +#include "ntwin32u.hpp" + +int main() +{ + while (true) + { + std::printf("syscall result -> 0x%p\n", nt::win32u::syscall()); + std::getchar(); + } +} diff --git a/NtWin32u/ntwin32u.hpp b/NtWin32u/ntwin32u.hpp new file mode 100644 index 0000000..17da371 --- /dev/null +++ b/NtWin32u/ntwin32u.hpp @@ -0,0 +1,93 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +#include + +namespace nt +{ + namespace win32u + { + using syscall_table_t = std::vector>; + 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( + LoadLibraryA("win32u.dll")); + + const auto nt_header = + reinterpret_cast( + reinterpret_cast(win32u) + win32u->e_lfanew); + + const auto export_rvas = + nt_header->OptionalHeader.DataDirectory[ + IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + + const auto exports = + reinterpret_cast( + reinterpret_cast(win32u) + export_rvas); + + const auto name_rva = + reinterpret_cast( + reinterpret_cast(win32u) + exports->AddressOfNames); + + for (auto idx = 0u; idx < exports->NumberOfNames; ++idx) + { + const auto function_name = + reinterpret_cast( + reinterpret_cast(win32u) + name_rva[idx]); + + // add Nt functions... + if (!strncmp(function_name, "Nt", 2)) + { + const auto func_rva = + reinterpret_cast( + reinterpret_cast(win32u) + exports->AddressOfFunctions); + + const auto ordinal_rva = + reinterpret_cast( + reinterpret_cast(win32u) + exports->AddressOfNameOrdinals); + + const auto function_addr = + reinterpret_cast(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 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(function_addr)(0xC0FFEE); + } + } +} \ No newline at end of file