├── EventSyncDrv ├── EventSyncDrv.inf ├── EventSyncDrv.sln ├── EventSyncDrv.vcxproj ├── EventSyncDrv.vcxproj.filters ├── EventSyncDrv.vcxproj.user ├── comms.cpp ├── comms.h ├── definitions.h ├── hooking.cpp ├── hooking.h ├── main.cpp ├── memory.cpp ├── memory.h ├── utilities.cpp └── utilities.h ├── README.md └── umctrlproc ├── includes.h ├── main.cpp ├── mem.cpp ├── mem.h ├── umctrlproc.sln ├── umctrlproc.vcxproj ├── umctrlproc.vcxproj.filters └── umctrlproc.vcxproj.user /EventSyncDrv/EventSyncDrv.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; HookDriver1.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=Sample ; TODO: edit Class 8 | ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid 9 | Provider=%ManufacturerName% 10 | CatalogFile=HookDriver1.cat 11 | DriverVer= ; TODO: set DriverVer in stampinf property pages 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | HookDriver1_Device_CoInstaller_CopyFiles = 11 16 | 17 | ; ================= Class section ===================== 18 | 19 | [ClassInstall32] 20 | Addreg=SampleClassReg 21 | 22 | [SampleClassReg] 23 | HKR,,,0,%ClassName% 24 | HKR,,Icon,,-5 25 | 26 | [SourceDisksNames] 27 | 1 = %DiskName%,,,"" 28 | 29 | [SourceDisksFiles] 30 | HookDriver1.sys = 1,, 31 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames 32 | 33 | ;***************************************** 34 | ; Install Section 35 | ;***************************************** 36 | 37 | [Manufacturer] 38 | %ManufacturerName%=Standard,NT$ARCH$ 39 | 40 | [Standard.NT$ARCH$] 41 | %HookDriver1.DeviceDesc%=HookDriver1_Device, Root\HookDriver1 ; TODO: edit hw-id 42 | 43 | [HookDriver1_Device.NT] 44 | CopyFiles=Drivers_Dir 45 | 46 | [Drivers_Dir] 47 | HookDriver1.sys 48 | 49 | ;-------------- Service installation 50 | [HookDriver1_Device.NT.Services] 51 | AddService = HookDriver1,%SPSVCINST_ASSOCSERVICE%, HookDriver1_Service_Inst 52 | 53 | ; -------------- HookDriver1 driver install sections 54 | [HookDriver1_Service_Inst] 55 | DisplayName = %HookDriver1.SVCDESC% 56 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 57 | StartType = 3 ; SERVICE_DEMAND_START 58 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 59 | ServiceBinary = %12%\HookDriver1.sys 60 | 61 | ; 62 | ;--- HookDriver1_Device Coinstaller installation ------ 63 | ; 64 | 65 | [HookDriver1_Device.NT.CoInstallers] 66 | AddReg=HookDriver1_Device_CoInstaller_AddReg 67 | CopyFiles=HookDriver1_Device_CoInstaller_CopyFiles 68 | 69 | [HookDriver1_Device_CoInstaller_AddReg] 70 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" 71 | 72 | [HookDriver1_Device_CoInstaller_CopyFiles] 73 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll 74 | 75 | [HookDriver1_Device.NT.Wdf] 76 | KmdfService = HookDriver1, HookDriver1_wdfsect 77 | [HookDriver1_wdfsect] 78 | KmdfLibraryVersion = $KMDFVERSION$ 79 | 80 | [Strings] 81 | SPSVCINST_ASSOCSERVICE= 0x00000002 82 | ManufacturerName="" ;TODO: Replace with your manufacturer name 83 | ClassName="Samples" ; TODO: edit ClassName 84 | DiskName = "HookDriver1 Installation Disk" 85 | HookDriver1.DeviceDesc = "HookDriver1 Device" 86 | HookDriver1.SVCDESC = "HookDriver1 Service" 87 | -------------------------------------------------------------------------------- /EventSyncDrv/EventSyncDrv.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30225.117 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EventSyncDrv", "EventSyncDrv.vcxproj", "{971A2FB2-FEDA-4EF3-A52C-637969CD7B14}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Debug|ARM64 = Debug|ARM64 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|ARM = Release|ARM 15 | Release|ARM64 = Release|ARM64 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|ARM.Build.0 = Debug|ARM 22 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|x64.ActiveCfg = Debug|x64 27 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|x64.Build.0 = Debug|x64 28 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|x64.Deploy.0 = Debug|x64 29 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|x86.ActiveCfg = Debug|Win32 30 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|x86.Build.0 = Debug|Win32 31 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Debug|x86.Deploy.0 = Debug|Win32 32 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|ARM.ActiveCfg = Release|ARM 33 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|ARM.Build.0 = Release|ARM 34 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|ARM.Deploy.0 = Release|ARM 35 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|ARM64.Build.0 = Release|ARM64 37 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|x64.ActiveCfg = Release|x64 39 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|x64.Build.0 = Release|x64 40 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|x64.Deploy.0 = Release|x64 41 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|x86.ActiveCfg = Release|Win32 42 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|x86.Build.0 = Release|Win32 43 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {3D9496D9-EEEE-41E0-9B5B-B18171698930} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /EventSyncDrv/EventSyncDrv.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | Debug 22 | ARM 23 | 24 | 25 | Release 26 | ARM 27 | 28 | 29 | Debug 30 | ARM64 31 | 32 | 33 | Release 34 | ARM64 35 | 36 | 37 | 38 | {971A2FB2-FEDA-4EF3-A52C-637969CD7B14} 39 | {1bc93793-694f-48fe-9372-81e2b05556fd} 40 | v4.5 41 | 12.0 42 | Debug 43 | Win32 44 | HookDriver1 45 | 46 | 47 | 48 | Windows10 49 | true 50 | WindowsKernelModeDriver10.0 51 | Driver 52 | KMDF 53 | Universal 54 | 55 | 56 | Windows10 57 | false 58 | WindowsKernelModeDriver10.0 59 | Driver 60 | KMDF 61 | Universal 62 | 63 | 64 | Windows10 65 | true 66 | WindowsKernelModeDriver10.0 67 | Driver 68 | WDM 69 | 70 | 71 | false 72 | 73 | 74 | Windows10 75 | false 76 | WindowsKernelModeDriver10.0 77 | Driver 78 | KMDF 79 | 80 | 81 | false 82 | NotSet 83 | 84 | 85 | Windows10 86 | true 87 | WindowsKernelModeDriver10.0 88 | Driver 89 | KMDF 90 | Universal 91 | 92 | 93 | Windows10 94 | false 95 | WindowsKernelModeDriver10.0 96 | Driver 97 | KMDF 98 | Universal 99 | 100 | 101 | Windows10 102 | true 103 | WindowsKernelModeDriver10.0 104 | Driver 105 | KMDF 106 | Universal 107 | 108 | 109 | Windows10 110 | false 111 | WindowsKernelModeDriver10.0 112 | Driver 113 | KMDF 114 | Universal 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | DbgengKernelDebugger 126 | 127 | 128 | DbgengKernelDebugger 129 | 130 | 131 | DbgengKernelDebugger 132 | 133 | 134 | DbgengKernelDebugger 135 | false 136 | 137 | 138 | DbgengKernelDebugger 139 | 140 | 141 | DbgengKernelDebugger 142 | 143 | 144 | DbgengKernelDebugger 145 | 146 | 147 | DbgengKernelDebugger 148 | 149 | 150 | 151 | MainEntry 152 | true 153 | false 154 | false 155 | 156 | 157 | false 158 | false 159 | Guard 160 | 161 | 162 | Disabled 163 | true 164 | Neither 165 | None 166 | 167 | 168 | 169 | 170 | false 171 | false 172 | Level3 173 | 174 | 175 | MainEntry 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | -------------------------------------------------------------------------------- /EventSyncDrv/EventSyncDrv.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | Source Files 46 | 47 | 48 | Source Files 49 | 50 | 51 | -------------------------------------------------------------------------------- /EventSyncDrv/EventSyncDrv.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Off 5 | 6 | -------------------------------------------------------------------------------- /EventSyncDrv/comms.cpp: -------------------------------------------------------------------------------- 1 | #include "comms.h" 2 | 3 | extern HANDLE um_pid; //reference handle to usermode control process 4 | HANDLE target_pid = NULL; //reference handle to usermode target process 5 | extern ULONG64 um_base64; 6 | extern PKEVENT sync_event; 7 | extern PKEVENT sync_event2; 8 | 9 | extern DWORD64 g_buffer_addr; 10 | enum Commcode { 11 | COMMAND_RPM = 1, 12 | COMMAND_WPM, 13 | COMMAND_GET_UM_PROC_BASE, 14 | COMMAND_QUIT 15 | }; 16 | 17 | // for get um proc base, put ptr to string of proc name into structure, base is returned in addr 18 | 19 | // read write buffer for communication between drv and usermode proc 20 | struct RWbuf { 21 | int command; 22 | int struct_size = 0; 23 | DWORD64 offset; 24 | DWORD64 structure; 25 | //int done = 1; 26 | }; 27 | 28 | 29 | BYTE temp_buffer[0x2FF0] = { 0 }; //temporary buffer in kernel 30 | bool comms::read_shared_buf(){ 31 | 32 | if (target_pid == NULL) { 33 | log("target pid is null!"); 34 | } 35 | 36 | 37 | 38 | 39 | RWbuf KM_buf; //set up temp buff for holding shared mem buff in KM 40 | 41 | 42 | 43 | 44 | log("waiting for UM to set event 1"); 45 | KeWaitForSingleObject(sync_event, Executive, KernelMode, TRUE, nullptr); //wait for UM to unlock buffer 46 | //log("WAIT PASSED THROUGH"); 47 | //entering critical section start 48 | k_RPM(um_pid, g_buffer_addr, &KM_buf, sizeof(RWbuf)); //copy shared mem buff into KM buff 49 | KeClearEvent(sync_event); //lock buffer 50 | log("command: %i", KM_buf.command); 51 | 52 | 53 | 54 | 55 | 56 | log("cmd: %i",KM_buf.command); 57 | log("size: %i",KM_buf.struct_size); 58 | log("offset: %llx",KM_buf.offset); 59 | log("structure: %llx",KM_buf.structure); 60 | 61 | 62 | //perform actions according to command given from usermode proc 63 | 64 | if (KM_buf.command == COMMAND_RPM) { 65 | 66 | //read memory from target um proc, read memory structure is placed in temp_buffer, then fowarded(written) to buffer in um control proc 67 | RtlSecureZeroMemory(&temp_buffer, sizeof(temp_buffer)); 68 | if (!k_RPM(target_pid, (uintptr_t)KM_buf.offset, &temp_buffer, KM_buf.struct_size)) { 69 | //read from game_proc to kernel buff 70 | //log("step 1 fail"); 71 | } 72 | if (!k_WPM(um_pid, KM_buf.structure, &temp_buffer, KM_buf.struct_size)) { 73 | //write from kernel buff to UM proc 74 | //log("step 2 fail"); 75 | } 76 | //log("rpm done"); 77 | } 78 | else if (KM_buf.command == COMMAND_WPM) { 79 | 80 | //write memory to target um proc, structure given by um control proc is placed in temp_buffer, then written to target um proc 81 | RtlSecureZeroMemory(&temp_buffer, sizeof(temp_buffer)); 82 | k_RPM(um_pid, (uintptr_t)KM_buf.structure, &temp_buffer, KM_buf.struct_size); //read from UM proc to kernel buff 83 | k_WPM(target_pid, KM_buf.offset, &temp_buffer, KM_buf.struct_size); //write from kernel buff to game_proc 84 | //log("wpm done"); 85 | } 86 | else if (KM_buf.command == COMMAND_GET_UM_PROC_BASE) { 87 | 88 | //retreive target um proc base address, temporarily store in game_name buffer, then write into structure inside um control proc 89 | BYTE game_name[64] = {0}; 90 | k_RPM(um_pid, KM_buf.structure, &game_name, KM_buf.struct_size); 91 | 92 | UNICODE_STRING u_game_name; 93 | RtlInitUnicodeString(&u_game_name, (PCWSTR)game_name); 94 | log("um target name requested is : %ws", u_game_name.Buffer); 95 | 96 | target_pid = get_module_pid((PCWSTR)game_name); 97 | while (target_pid == NULL) { 98 | log("Get module pid failed, retrying..."); 99 | Sleep(2000); 100 | target_pid = get_module_pid((PCWSTR)game_name); 101 | } 102 | 103 | DWORD64 game_base = 0; 104 | PEPROCESS game_process; 105 | if (PsLookupProcessByProcessId(target_pid, &game_process) != STATUS_SUCCESS) { 106 | return false; 107 | } 108 | 109 | log("ok here"); 110 | 111 | game_base = get_module_base_x64(game_process, u_game_name); 112 | while (game_base == 0) { 113 | Sleep(2000); 114 | game_base = get_module_base_x64(game_process, u_game_name); 115 | } 116 | k_WPM(um_pid, KM_buf.offset, &game_base, sizeof(DWORD64)); 117 | 118 | log("ok here 2"); 119 | 120 | } 121 | else if (KM_buf.command == COMMAND_QUIT) { 122 | //Quit using driver 123 | KeSetEvent(sync_event2,HIGH_PRIORITY,FALSE); 124 | return false; 125 | } 126 | 127 | 128 | //set event2 to allow um to work on buffer 129 | log("setting event2 to allow um to work on buffer"); 130 | KeSetEvent(sync_event2,HIGH_PRIORITY,FALSE); 131 | 132 | 133 | 134 | return true; 135 | 136 | 137 | } 138 | 139 | -------------------------------------------------------------------------------- /EventSyncDrv/comms.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "memory.h" 3 | #include "utilities.h" 4 | 5 | namespace comms 6 | { 7 | bool read_shared_buf(); 8 | 9 | 10 | } 11 | -------------------------------------------------------------------------------- /EventSyncDrv/definitions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #pragma comment(lib, "ntoskrnl.lib") 10 | #define log(format, ...) DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, format, __VA_ARGS__) 11 | 12 | 13 | typedef struct _PEB_LDR_DATA { 14 | ULONG Length; 15 | BOOLEAN Initialized; 16 | PVOID SsHandle; 17 | LIST_ENTRY ModuleListLoadOrder; 18 | LIST_ENTRY ModuleListMemoryOrder; 19 | LIST_ENTRY ModuleListInitOrder; 20 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 21 | 22 | typedef struct _LDR_DATA_TABLE_ENTRY 23 | { 24 | LIST_ENTRY InLoadOrderModuleList; 25 | LIST_ENTRY InMemoryOrderModuleList; 26 | LIST_ENTRY InInitializationOrderModuleList; 27 | PVOID DllBase; 28 | PVOID EntryPoint; 29 | ULONG SizeOfImage; //in bytes 30 | UNICODE_STRING FullDllName; 31 | UNICODE_STRING BaseDllName; 32 | ULONG Flags; 33 | USHORT LoadCount; 34 | USHORT TlsIndex; 35 | LIST_ENTRY HashLinks; 36 | PVOID SectionPointer; 37 | ULONG CheckSum; 38 | ULONG TimeDateStamp; 39 | 40 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 41 | 42 | typedef struct _RTL_USER_PROCESS_PARAMETERS { 43 | BYTE Reserved1[16]; 44 | PVOID Reserved2[10]; 45 | UNICODE_STRING ImagePathName; 46 | UNICODE_STRING CommandLine; 47 | } RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; 48 | 49 | typedef void(__stdcall* PPS_POST_PROCESS_INIT_ROUTINE)(void); // not supported 50 | 51 | typedef struct _PEB { 52 | BYTE Reserved1[2]; 53 | BYTE BeingDebugged; 54 | BYTE Reserved2[1]; 55 | PVOID Reserved3[2]; 56 | PPEB_LDR_DATA Ldr; 57 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 58 | PVOID Reserved4[3]; 59 | PVOID AtlThunkSListPtr; 60 | PVOID Reserved5; 61 | ULONG Reserved6; 62 | PVOID Reserved7; 63 | ULONG Reserved8; 64 | ULONG AtlThunkSListPtr32; 65 | PVOID Reserved9[45]; 66 | BYTE Reserved10[96]; 67 | PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; 68 | BYTE Reserved11[128]; 69 | PVOID Reserved12[1]; 70 | ULONG SessionId; 71 | } PEB, * PPEB; 72 | 73 | 74 | typedef struct _SYSTEM_PROCESS_INFORMATION { 75 | ULONG NextEntryOffset; 76 | ULONG NumberOfThreads; 77 | LARGE_INTEGER SpareLi1; 78 | LARGE_INTEGER SpareLi2; 79 | LARGE_INTEGER SpareLi3; 80 | LARGE_INTEGER CreateTime; 81 | LARGE_INTEGER UserTime; 82 | LARGE_INTEGER KernelTime; 83 | UNICODE_STRING ImageName; 84 | KPRIORITY BasePriority; 85 | HANDLE UniqueProcessId; 86 | HANDLE InheritedFromUniqueProcessId; 87 | ULONG HandleCount; 88 | ULONG SessionId; 89 | ULONG_PTR PageDirectoryBase; 90 | SIZE_T PeakVirtualSize; 91 | SIZE_T VirtualSize; 92 | ULONG PageFaultCount; 93 | SIZE_T PeakWorkingSetSize; 94 | SIZE_T WorkingSetSize; 95 | SIZE_T QuotaPeakPagedPoolUsage; 96 | SIZE_T QuotaPagedPoolUsage; 97 | SIZE_T QuotaPeakNonPagedPoolUsage; 98 | SIZE_T QuotaNonPagedPoolUsage; 99 | SIZE_T PagefileUsage; 100 | SIZE_T PeakPagefileUsage; 101 | SIZE_T PrivatePageCount; 102 | LARGE_INTEGER ReadOperationCount; 103 | LARGE_INTEGER WriteOperationCount; 104 | LARGE_INTEGER OtherOperationCount; 105 | LARGE_INTEGER ReadTransferCount; 106 | LARGE_INTEGER WriteTransferCount; 107 | LARGE_INTEGER OtherTransferCount; 108 | } SYSTEM_PROCESS_INFORMATION , 109 | *PSYSTEM_PROCESS_INFORMATION; 110 | 111 | 112 | typedef enum _SYSTEM_INFORMATION_CLASS 113 | { 114 | SystemBasicInformation, 115 | SystemProcessorInformation, 116 | SystemPerformanceInformation, 117 | SystemTimeOfDayInformation, 118 | SystemPathInformation, 119 | SystemProcessInformation, 120 | SystemCallCountInformation, 121 | SystemDeviceInformation, 122 | SystemProcessorPerformanceInformation, 123 | SystemFlagsInformation, 124 | SystemCallTimeInformation, 125 | SystemModuleInformation = 0x0B 126 | } SYSTEM_INFORMATION_CLASS, 127 | * PSYSTEM_INFORMATION_CLASS; 128 | 129 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 130 | { 131 | HANDLE Section; 132 | PVOID MappedBase; 133 | PVOID ImageBase; 134 | ULONG ImageSize; 135 | ULONG Flags; 136 | USHORT LoadOrderIndex; 137 | USHORT InitOrderIndex; 138 | USHORT LoadCount; 139 | USHORT OffsetToFileName; 140 | UCHAR FullPathName[256]; 141 | 142 | } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; 143 | 144 | typedef struct _RTL_PROCESS_MODULES 145 | { 146 | ULONG NumberOfModules; 147 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 148 | 149 | }RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 150 | 151 | 152 | 153 | extern "C" __declspec(dllimport) 154 | NTSTATUS NTAPI ZwProtectVirtualMemory( 155 | HANDLE ProcessHandle, 156 | PVOID * BaseAddress, 157 | PULONG ProtectSize, 158 | ULONG NewProtect, 159 | PULONG OldProtect 160 | ); 161 | 162 | 163 | 164 | extern "C" NTKERNELAPI 165 | PVOID 166 | NTAPI 167 | RtlFindExportedRoutineByName( 168 | _In_ PVOID ImageBase, 169 | _In_ PCCH RoutineNam 170 | ); 171 | 172 | extern "C" NTSTATUS ZwQuerySystemInformation(ULONG InforClass, PVOID Buffer, ULONG Length, PULONG ReturnLength); 173 | 174 | extern "C" NTKERNELAPI 175 | PPEB 176 | PsGetProcessPeb( 177 | IN PEPROCESS Process 178 | ); 179 | 180 | extern "C" NTSTATUS NTAPI MmCopyVirtualMemory 181 | ( 182 | PEPROCESS SourceProcess, 183 | PVOID SourceAddress, 184 | PEPROCESS TargetProcess, 185 | PVOID TargetAddress, 186 | SIZE_T BufferSize, 187 | KPROCESSOR_MODE PreviousMode, 188 | PSIZE_T ReturnSize 189 | ); 190 | 191 | EXTERN_C NTSYSAPI 192 | PIMAGE_NT_HEADERS 193 | NTAPI 194 | RtlImageNtHeader( 195 | IN PVOID ModuleAddress); 196 | 197 | struct PiDDBCacheEntry 198 | { 199 | LIST_ENTRY List; 200 | UNICODE_STRING DriverName; 201 | ULONG TimeDateStamp; 202 | NTSTATUS LoadStatus; 203 | char _0x0028[16]; // data from the shim engine, or uninitialized memory for custom drivers 204 | }; -------------------------------------------------------------------------------- /EventSyncDrv/hooking.cpp: -------------------------------------------------------------------------------- 1 | #include "hooking.h" 2 | #include "utilities.h" 3 | #include "comms.h" 4 | BYTE original[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //global byte array to store original syscall that will be hooked, so that it can be restored 5 | 6 | #define UM_EXENAME L"umctrlproc.exe" //Usermode control process name to connect with this driver to enable arbitrary r/w on another um process 7 | //Note: this is NOT the target process! 8 | 9 | 10 | HANDLE um_pid = NULL; //um process pid 11 | ULONG64 um_base64 = NULL; 12 | PVOID* gafAsyncKeyState = NULL; 13 | 14 | //========================global event variables 15 | PKEVENT sync_event; 16 | HANDLE event_handle; 17 | PKEVENT sync_event2; 18 | HANDLE event_handle2; 19 | //======================== 20 | DWORD64 g_buffer_addr = NULL; 21 | 22 | bool basichook::call_kernel_function(void* kernel_func_addr) 23 | { 24 | if (!kernel_func_addr) { //exit if kernel func's addr is null 25 | return false; 26 | } 27 | 28 | log("hookhandler addr : %p", kernel_func_addr); 29 | 30 | PVOID* function = reinterpret_cast(get_system_module_export("\\SystemRoot\\System32\\drivers\\dxgkrnl.sys", "NtQueryCompositionSurfaceStatistics")); 31 | 32 | if (!function) { 33 | return false; 34 | } 35 | 36 | BYTE dummy[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 37 | 38 | 39 | BYTE shell_code[] = {0x48, 0xB8}; //mov rax, xxx (xxx is the base addr of our own func) 40 | BYTE shell_code_end[] = { 0xFF, 0xE0 }; //jmp rax 41 | 42 | 43 | //setup shellcode 44 | RtlSecureZeroMemory(&dummy, sizeof(dummy)); //zeros out dummy ptr's memory 45 | RtlSecureZeroMemory(&original, sizeof(original)); //zeros out original ptr's memory 46 | 47 | memcpy((PVOID)((ULONG_PTR)original), function, sizeof(original)); //copy original bytes into buffer 48 | 49 | memcpy((PVOID)((ULONG_PTR)dummy), &shell_code, sizeof(shell_code)); //copy front 2 bytes of shell code to dummy 50 | uintptr_t hook_addr = reinterpret_cast(kernel_func_addr); //get mapped driver handler base addr 51 | log("hookhandler addr after putting in dummy : %p", hook_addr); 52 | memcpy((PVOID)((ULONG_PTR)dummy + sizeof(shell_code)), &hook_addr, sizeof(void*)); //put mapped driver handler func addr into dummy 53 | memcpy((PVOID)((ULONG_PTR)dummy + sizeof(shell_code) + sizeof(void*)), &shell_code_end, sizeof(shell_code_end)); //put last 2 bytes of shell code into dummy 54 | 55 | 56 | 57 | for (int i = 0; i < sizeof(original)/sizeof(BYTE); i++) 58 | { 59 | log("%02X", original[i]); //for checking if original bytes are correct 60 | } 61 | 62 | 63 | //actually writing hook to overwrite original kernel func 64 | 65 | write_to_read_only_memory(function, &dummy, sizeof(dummy)); //write dummy into kernel func's (NtQueryXXXX) base addr 66 | 67 | //from this point on calling NtQueryCompositionSurfaceStatistics will direct to our own mapped driver handler instead 68 | return true; 69 | 70 | 71 | 72 | 73 | 74 | } 75 | 76 | bool basichook::unhook_kernel_function() { 77 | 78 | PVOID* function = reinterpret_cast(get_system_module_export("\\SystemRoot\\System32\\drivers\\dxgkrnl.sys", "NtQueryCompositionSurfaceStatistics")); 79 | if (!function) { 80 | return false; 81 | } 82 | write_to_read_only_memory(function, &original, sizeof(original)); //write back original bytes into kernel func's (NtQueryXXXX) base addr 83 | 84 | return true; 85 | } 86 | 87 | 88 | 89 | 90 | // main driver start 91 | VOID basichook::hook_handler(PVOID called_param1) 92 | { 93 | //um control process rw buffer is stored in called_param1 94 | g_buffer_addr = *(DWORD64*)called_param1; 95 | 96 | 97 | 98 | 99 | log("buf addr: %llx", g_buffer_addr); 100 | 101 | 102 | 103 | 104 | 105 | basichook::unhook_kernel_function(); 106 | log("unhooked!"); 107 | 108 | ////////////////////////////////////////////////unhoooked ntoskrnl.exe from here================================= 109 | //Create notification events for synchronization 110 | 111 | UNICODE_STRING event_name; 112 | UNICODE_STRING event_name2; 113 | RtlInitUnicodeString(&event_name, L"\\BaseNamedObjects\\Evnt1"); 114 | RtlInitUnicodeString(&event_name2, L"\\BaseNamedObjects\\Evnt2"); 115 | sync_event = IoCreateNotificationEvent(&event_name, &event_handle); 116 | sync_event2 = IoCreateNotificationEvent(&event_name2, &event_handle2); 117 | KeClearEvent(sync_event); 118 | KeClearEvent(sync_event2); 119 | 120 | 121 | 122 | //obtain um proc info 123 | um_pid = get_module_pid(UM_EXENAME); 124 | if (um_pid == NULL) { 125 | log("cant find pid of um control process! exiting km thread."); 126 | return; 127 | } 128 | 129 | //get process struct 130 | PEPROCESS um_process; 131 | if (PsLookupProcessByProcessId(um_pid, &um_process) != STATUS_SUCCESS) { 132 | return; 133 | } 134 | 135 | UNICODE_STRING um_name; 136 | RtlInitUnicodeString(&um_name, UM_EXENAME); 137 | um_base64 = get_module_base_x64(um_process, um_name); 138 | log("um control base addr: %llx", um_base64); 139 | 140 | //continuously wait for job from UM control proc 141 | while (comms::read_shared_buf()) { 142 | 143 | } 144 | return; 145 | 146 | ZwClose(um_pid); 147 | ZwClose(event_handle); 148 | ZwClose(event_handle2); 149 | 150 | 151 | 152 | } -------------------------------------------------------------------------------- /EventSyncDrv/hooking.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "memory.h" 3 | 4 | 5 | namespace basichook 6 | { 7 | bool call_kernel_function(void* kernel_function_address); 8 | VOID hook_handler(PVOID called_param1); 9 | bool unhook_kernel_function(); 10 | } -------------------------------------------------------------------------------- /EventSyncDrv/main.cpp: -------------------------------------------------------------------------------- 1 | #include "hooking.h" 2 | #include "utilities.h" 3 | 4 | //NOTE: This driver is intended to be manual mapped with kdmapper (or other vulnerable driver manual mappers) 5 | // kdmapper sources: 6 | // - https://github.com/TheCruZ/kdmapper-1803-20H2 7 | // - https://github.com/z175/kdmapper 8 | 9 | 10 | extern "C" NTSTATUS MainEntry(PDRIVER_OBJECT, PUNICODE_STRING) { 11 | 12 | 13 | //since we are using kdmapper and manual mapping, no use for driver object 14 | 15 | 16 | Sleep(2000); 17 | 18 | basichook::call_kernel_function(&basichook::hook_handler); //passing the addr of the func that is to be executed (i.e. the main loop of driver) 19 | //hooks the kernel syscall in ntoskrnl.exe 20 | log("hook loaded!"); 21 | 22 | return STATUS_SUCCESS; 23 | } -------------------------------------------------------------------------------- /EventSyncDrv/memory.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | 3 | PVOID get_system_module_base(const char* module_name) 4 | { 5 | ULONG bytes = 0; 6 | NTSTATUS status = ZwQuerySystemInformation(SystemModuleInformation, NULL, bytes, &bytes); //ZwQuerySystemInformation params: infoclass, buffer, length, returnlength 7 | 8 | if (!bytes) { 9 | UNICODE_STRING string0 = RTL_CONSTANT_STRING(L"preliminary ZwQuerySysInfo failed!\n"); 10 | DbgPrint("%zW", &string0); 11 | //RtlFreeUnicodeString(&string0); 12 | return NULL; 13 | } 14 | 15 | PRTL_PROCESS_MODULES modules = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(NonPagedPool, bytes, 0x4e554c4c); //Tag is NULL, allocates non-paged mem pool pointed to by pointer "modules" 16 | 17 | status = ZwQuerySystemInformation(SystemModuleInformation, modules, bytes, &bytes); //actually load modules info into status ptr 18 | 19 | if (!NT_SUCCESS(status)) { 20 | UNICODE_STRING string1 = RTL_CONSTANT_STRING(L"ExAllocatePoolWithTag failed, or ZwQuerySysInfo status is NULL!\n"); 21 | DbgPrint("%zW", &string1); 22 | //RtlFreeUnicodeString(&string1); 23 | 24 | return NULL; 25 | } 26 | 27 | PRTL_PROCESS_MODULE_INFORMATION module = modules->Modules; 28 | PVOID module_base = 0, module_size = 0; 29 | 30 | for (ULONG i = 0; i < modules->NumberOfModules; ++i) { 31 | 32 | if (strcmp((char*)module[i].FullPathName, module_name) == 0) { //if path matches module 33 | module_base = module[i].ImageBase; //image base for addr calculation 34 | module_size = (PVOID)module[i].ImageSize; 35 | //log("found module base! %s %p", module_name, module_base); 36 | break; 37 | 38 | } 39 | } 40 | 41 | if (modules) { 42 | ExFreePoolWithTag(modules, NULL); 43 | } 44 | if (module_base <= NULL) { 45 | return NULL; 46 | } 47 | 48 | return module_base; 49 | 50 | } 51 | 52 | 53 | HANDLE get_module_pid(PCWSTR module_name) 54 | { 55 | 56 | UNICODE_STRING WantedImageName; 57 | HANDLE found_pid = NULL; 58 | 59 | RtlInitUnicodeString(&WantedImageName, (PCWSTR)module_name); 60 | ULONG bytes = 0; 61 | PVOID buffer; 62 | NTSTATUS status = ZwQuerySystemInformation(SystemProcessInformation, NULL, bytes, &bytes); //ZwQuerySystemInformation params: infoclass, buffer, length, returnlength 63 | 64 | if (!bytes) { 65 | log("ZwQuerySysInfo for PID failed!\n"); 66 | return NULL; 67 | } 68 | //buffer saves original addr of mem pool for deletion 69 | buffer = (PSYSTEM_PROCESS_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, bytes, 0x4e554c4c); //Tag is NULL, allocates non-paged mem pool pointed to by pointer "modules" 70 | 71 | PSYSTEM_PROCESS_INFORMATION processes = (PSYSTEM_PROCESS_INFORMATION)buffer; 72 | 73 | status = ZwQuerySystemInformation(SystemProcessInformation, processes, bytes, &bytes); //actually load modules info into status ptr 74 | 75 | if (!NT_SUCCESS(status)) { 76 | log("ExAllocatePoolWithTag failed, or ZwQuerySysInfo status is NULL when finding PID!\n"); 77 | return NULL; 78 | } 79 | 80 | for (;;) { 81 | //log("\nProcess name: %ws | Process ID: %d\n", processes->ImageName.Buffer, processes->UniqueProcessId); // Display process information. 82 | if (RtlEqualUnicodeString(&processes->ImageName, &WantedImageName, TRUE)) { 83 | log("%ws has been found!\n", processes->ImageName.Buffer); 84 | found_pid = processes->UniqueProcessId; 85 | break; 86 | } 87 | else if (processes->NextEntryOffset) { 88 | processes = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)processes + processes->NextEntryOffset); 89 | } 90 | else { 91 | 92 | break; 93 | } 94 | } 95 | 96 | 97 | 98 | ExFreePoolWithTag(buffer, NULL); 99 | 100 | 101 | return found_pid; 102 | 103 | 104 | } 105 | 106 | //this is for obtaining csrss 2 107 | HANDLE get_module_pid2(PCWSTR module_name) 108 | { 109 | 110 | UNICODE_STRING WantedImageName; 111 | HANDLE found_pid = NULL; 112 | 113 | RtlInitUnicodeString(&WantedImageName, (PCWSTR)module_name); 114 | ULONG bytes = 0; 115 | PVOID buffer; 116 | NTSTATUS status = ZwQuerySystemInformation(SystemProcessInformation, NULL, bytes, &bytes); //ZwQuerySystemInformation params: infoclass, buffer, length, returnlength 117 | int cnt = 0; 118 | 119 | if (!bytes) { 120 | UNICODE_STRING string0 = RTL_CONSTANT_STRING(L"ZwQuerySysInfo for PID failed!\n"); 121 | DbgPrint("%zW", &string0); 122 | return NULL; 123 | } 124 | //buffer saves original addr of mem pool for deletion 125 | buffer = (PSYSTEM_PROCESS_INFORMATION)ExAllocatePoolWithTag(NonPagedPool, bytes, 0x4e554c4c); //Tag is NULL, allocates non-paged mem pool pointed to by pointer "modules" 126 | 127 | PSYSTEM_PROCESS_INFORMATION processes = (PSYSTEM_PROCESS_INFORMATION)buffer; 128 | 129 | status = ZwQuerySystemInformation(SystemProcessInformation, processes, bytes, &bytes); //actually load modules info into status ptr 130 | 131 | if (!NT_SUCCESS(status)) { 132 | UNICODE_STRING string1 = RTL_CONSTANT_STRING(L"ExAllocatePoolWithTag failed, or ZwQuerySysInfo status is NULL when finding PID!\n"); 133 | DbgPrint("%zW", &string1); 134 | 135 | return NULL; 136 | } 137 | 138 | for (;;) { 139 | //log("\nProcess name: %ws | Process ID: %d\n", processes->ImageName.Buffer, processes->UniqueProcessId); // Display process information. 140 | if (RtlEqualUnicodeString(&processes->ImageName, &WantedImageName, TRUE)) { 141 | if (cnt == 0) { 142 | ++cnt; 143 | if (processes->NextEntryOffset) { 144 | processes = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)processes + processes->NextEntryOffset); 145 | } 146 | else { 147 | break; 148 | } 149 | } 150 | else { 151 | log("%ws second has been found!\n", processes->ImageName.Buffer); 152 | found_pid = processes->UniqueProcessId; 153 | break; 154 | } 155 | 156 | } 157 | else if (processes->NextEntryOffset) 158 | processes = (PSYSTEM_PROCESS_INFORMATION)((PUCHAR)processes + processes->NextEntryOffset); 159 | else 160 | break; 161 | } 162 | 163 | 164 | 165 | ExFreePoolWithTag(buffer, NULL); 166 | 167 | 168 | return found_pid; 169 | 170 | 171 | } 172 | 173 | 174 | PVOID get_system_module_export(const char* module_name, LPCSTR routine_name) { 175 | 176 | PVOID lpModule = get_system_module_base(module_name); 177 | 178 | if (!lpModule) { 179 | return NULL; 180 | } 181 | 182 | return RtlFindExportedRoutineByName(lpModule, routine_name); 183 | } 184 | 185 | bool write_memory(void* address, void* buffer, size_t size) { 186 | 187 | if (!RtlCopyMemory(address, buffer, size)) { 188 | return false; 189 | } 190 | else { 191 | return true; 192 | } 193 | } 194 | 195 | bool write_to_read_only_memory(void* address, void* buffer, size_t size) { 196 | 197 | PMDL Mdl = IoAllocateMdl(address, size, FALSE, FALSE, NULL); 198 | 199 | if (!Mdl) { 200 | return false; 201 | } 202 | 203 | MmProbeAndLockPages(Mdl, KernelMode, IoReadAccess); 204 | PVOID Mapping = MmMapLockedPagesSpecifyCache(Mdl, KernelMode, MmNonCached, NULL, FALSE, NormalPagePriority); 205 | MmProtectMdlSystemAddress(Mdl, PAGE_READWRITE); 206 | 207 | write_memory(Mapping, buffer, size); 208 | 209 | MmUnmapLockedPages(Mapping, Mdl); 210 | MmUnlockPages(Mdl); 211 | IoFreeMdl(Mdl); 212 | 213 | return true; 214 | 215 | } 216 | 217 | ULONG64 get_module_base_x64(PEPROCESS proc, UNICODE_STRING module_name) { 218 | PPEB pPeb = PsGetProcessPeb(proc); 219 | 220 | if (!pPeb) { 221 | log("process module x64 peb not found"); 222 | return NULL; 223 | 224 | } 225 | KAPC_STATE state; 226 | KeStackAttachProcess(proc, &state); 227 | PPEB_LDR_DATA pLdr = (PPEB_LDR_DATA)pPeb->Ldr; 228 | 229 | if (!pLdr) { 230 | KeUnstackDetachProcess(&state); 231 | return NULL; 232 | } 233 | 234 | for (PLIST_ENTRY list = (PLIST_ENTRY)pLdr->ModuleListLoadOrder.Flink; list != &pLdr->ModuleListLoadOrder; list = (PLIST_ENTRY)list->Flink) { 235 | 236 | //looping through linked list 237 | PLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD(list, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList); 238 | 239 | if (RtlCompareUnicodeString(&pEntry->BaseDllName, &module_name, TRUE) == NULL) { 240 | 241 | ULONG64 baseAddr = (ULONG64)pEntry->DllBase; 242 | log("%ws process found, returning..", module_name.Buffer); 243 | KeUnstackDetachProcess(&state); 244 | return baseAddr; 245 | } 246 | 247 | } 248 | 249 | log("%ws process NOT found, exiting.", module_name.Buffer); 250 | KeUnstackDetachProcess(&state); 251 | return NULL; 252 | 253 | } 254 | 255 | bool k_RPM(HANDLE pid, uintptr_t address, void* buffer, SIZE_T size) { 256 | 257 | if (!address || !buffer || !size) { 258 | log("rpm invalid params"); 259 | return false; 260 | } 261 | 262 | SIZE_T bytes = 0; 263 | NTSTATUS status = STATUS_SUCCESS; 264 | PEPROCESS process; 265 | KAPC_STATE state; 266 | 267 | if (PsLookupProcessByProcessId((HANDLE)pid, &process) != STATUS_SUCCESS) { 268 | log("pslookupprocess in rpm failed"); 269 | return false; 270 | } 271 | 272 | 273 | status = MmCopyVirtualMemory(process, (void*)address, (PEPROCESS)PsGetCurrentProcess(), (void*)buffer, size, KernelMode, &bytes); 274 | 275 | if (!NT_SUCCESS(status)) { 276 | return false; 277 | } 278 | 279 | return true; 280 | 281 | 282 | 283 | 284 | 285 | } 286 | 287 | bool k_WPM(HANDLE pid, uintptr_t address, void* buffer, SIZE_T size) { 288 | 289 | if (!address || !buffer || !size) { 290 | return false; 291 | } 292 | 293 | NTSTATUS status = STATUS_SUCCESS; 294 | PEPROCESS process; 295 | if (PsLookupProcessByProcessId((HANDLE)pid, &process) != STATUS_SUCCESS) { 296 | return false; 297 | } 298 | 299 | KAPC_STATE state; 300 | KeStackAttachProcess((PEPROCESS)process, &state); 301 | 302 | MEMORY_BASIC_INFORMATION info; 303 | status = ZwQueryVirtualMemory(ZwCurrentProcess(), (PVOID)address, MemoryBasicInformation, &info, sizeof(info), NULL); 304 | if (!NT_SUCCESS(status)) { 305 | KeUnstackDetachProcess(&state); 306 | return false; 307 | } 308 | 309 | if (((uintptr_t)info.BaseAddress + info.RegionSize) < (address + size)) 310 | { 311 | KeUnstackDetachProcess(&state); 312 | return false; 313 | } 314 | 315 | if (!(info.State & MEM_COMMIT) || 316 | (info.Protect & (PAGE_GUARD | PAGE_NOACCESS))) 317 | { 318 | KeUnstackDetachProcess(&state); 319 | return false; 320 | } 321 | 322 | 323 | //if flags indicate can write to the memory 324 | if ((info.Protect & PAGE_EXECUTE_READWRITE) || 325 | (info.Protect & PAGE_EXECUTE_WRITECOPY) || 326 | (info.Protect & PAGE_READWRITE) || 327 | (info.Protect & PAGE_WRITECOPY)) 328 | { 329 | RtlCopyMemory((void*)address, buffer, size); 330 | } 331 | KeUnstackDetachProcess(&state); 332 | return true; 333 | 334 | } -------------------------------------------------------------------------------- /EventSyncDrv/memory.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "definitions.h" 3 | 4 | PVOID get_system_module_base(const char* module_name); 5 | PVOID get_system_module_export(const char* module_name, LPCSTR routine_name); 6 | bool write_memory(void* address, void* buffer, size_t size); 7 | bool write_to_read_only_memory(void* address, void* buffer, size_t size); 8 | HANDLE get_module_pid(PCWSTR module_name); 9 | 10 | HANDLE get_module_pid2(PCWSTR module_name); 11 | ULONG64 get_module_base_x64(PEPROCESS proc, UNICODE_STRING module_name); 12 | bool k_RPM(HANDLE pid, uintptr_t address, void* buffer, SIZE_T size); 13 | bool k_WPM(HANDLE pid, uintptr_t address, void* buffer, SIZE_T size); 14 | -------------------------------------------------------------------------------- /EventSyncDrv/utilities.cpp: -------------------------------------------------------------------------------- 1 | #include "utilities.h" 2 | #include "memory.h" 3 | 4 | 5 | 6 | void Sleep(int ms) { 7 | LARGE_INTEGER timeout; 8 | timeout.QuadPart = ms * -10000; 9 | KeDelayExecutionThread(KernelMode, FALSE, &timeout); 10 | } 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /EventSyncDrv/utilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "definitions.h" 3 | 4 | 5 | void Sleep(int ms); 6 | bool is_key_down(UINT8 const vk); 7 | bool was_key_pressed(UINT8 const vk); 8 | void update_key_state_bitmap(PEPROCESS csrss_proc, PVOID* gafAsyncKeyState); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ===EventSyncDriver=== 2 | 3 | A Windows kernel driver meant to be manually mapped into kernel memory to allow arbitrary read/write access to any usermode process, 4 | via hooking a kernel routine in ntoskrnl.exe and trapping a usermode thread inside a syscall, and unhooking immediately. 5 | 6 | This is mainly meant for bypassing kernel anti-cheats which scan for rogue system threads (the ones launched from an address not in a valid base image in memory), 7 | since the usermode thread trapped is technically launched from ntoskrnl, which is backed by a valid image. 8 | 9 | 10 | Note that this driver is meant to be launched with a manual mapper (e.g. kdmapper), but can be modified into a regular driver to be used for bypasses if you have a valid cert for signing Windows drivers. 11 | kdmapper sources: 12 | - https://github.com/TheCruZ/kdmapper-1803-20H2 13 | - https://github.com/z175/kdmapper 14 | 15 | This project must be used in conjunction with a usermode control process (umctrlproc in this repo) which calls a custom API, to issue commands to the driver to do any r/w operations on a target usermode process, 16 | example usage of the usermode control API is given in the umctrlproc main.cpp file. 17 | 18 | Usermode control process and driver thread are synchronized using windows event objects. 19 | 20 | 21 | Please compile both projects (EventSyncDrv and umctrlproc => EventSyncDrv.sys and umctrlproc.exe respectively) as x64 Release. 22 | 23 | Steps to launch this PoC: 24 | 1. launch cmd as admin 25 | 2. place kdmapper executable, EventSyncDrv.sys and umctrlproc.exe in the current working directory 26 | 3. run "kdmapper.exe EventSyncDrv.sys" 27 | 4. run "umctrlproc.exe" 28 | 5. run the process meant to be targeted by the usermode control process 29 | 6. for the example code provided, console should output base address of targeted um process, and then exit after 3 seconds. 30 | 31 | ATTENTION: This PoC by itself is not capable of bypassing most kernel anticheats without further modification yourself and cleaning traces leftover by manual driver mapping! 32 | 33 | -------------------------------------------------------------------------------- /umctrlproc/includes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | -------------------------------------------------------------------------------- /umctrlproc/main.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "mem.h" 3 | 4 | //event handles for synchronization 5 | HANDLE event_handle = NULL; 6 | HANDLE event_handle2 = NULL; 7 | //Read/Write Buffer struct 8 | RWbuf buffer; 9 | 10 | 11 | template 12 | void call_hook_test(const A ... arguments) 13 | { 14 | void* control_function = GetProcAddress(LoadLibrary("win32u.dll"), "NtQueryCompositionSurfaceStatistics"); 15 | 16 | if (!control_function) { 17 | std::cout << "cannot find hooked func addr"; 18 | return; 19 | } 20 | printf("%p address of NtQueryXXX in usermode dll\n", control_function); 21 | auto func = static_cast(control_function); 22 | //std::cout << func << "\n"; 23 | 24 | //call the um func which calls the hooked kernel func 25 | func(arguments ...); 26 | 27 | } 28 | 29 | 30 | 31 | DWORD WINAPI km_thread(LPVOID lpParameter) { 32 | 33 | DWORD64 adr = (DWORD64)&buffer; 34 | //call hook in kernel with address of buffer in um control process as input parameter 35 | call_hook_test(&adr); 36 | return 0; 37 | 38 | } 39 | 40 | int main() { 41 | //a loadlibrary is required so that calling NtQueryXXX directly doesnt result in a BSOD 42 | LoadLibrary("user32.dll"); 43 | 44 | 45 | 46 | DWORD64 target_proc_base; 47 | //um target proc name, e.g. notepad.exe 48 | BYTE target_proc_name[64] = { 0 }; 49 | 50 | target_proc_name[0] = L'n'; 51 | target_proc_name[2] = L'o'; 52 | target_proc_name[4] = L't'; 53 | target_proc_name[6] = L'e'; 54 | target_proc_name[8] = L'p'; 55 | target_proc_name[10] = L'a'; 56 | target_proc_name[12] = L'd'; 57 | target_proc_name[14] = L'.'; 58 | target_proc_name[16] = L'e'; 59 | target_proc_name[18] = L'x'; 60 | target_proc_name[20] = L'e'; 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | std::cout << "launching KM hook...\n"; 69 | //then launch kernel thread 70 | 71 | HANDLE hThreadKM = CreateThread( 72 | NULL, // Thread attributes 73 | 0, // Stack size (0 = use default) 74 | km_thread, // Thread start address 75 | NULL, // Parameter to pass to the thread 76 | 0, // Creation flags 77 | NULL); // Thread id 78 | if (hThreadKM == NULL) 79 | { 80 | // Thread creation failed. 81 | printf("%s", "KM thread creation failed\n"); 82 | // More details can be retrieved by calling GetLastError() 83 | return 1; 84 | } 85 | std::cout << "KM hook launched and unhooked (probably, check DbgView if you wanna be sure)\n"; 86 | //at this point KM thread is stuck in kernel mode until given COMMAND_QUIT, um process cannot exit until this thread returns! 87 | Sleep(2000); 88 | 89 | //register event handles (must do this AFTER KM thread launch, or else event havent been created lol) 90 | event_handle = OpenEventW(EVENT_MODIFY_STATE, FALSE, L"Global\\Evnt1"); 91 | if (event_handle == NULL) { 92 | printf("event1 handle open error: %u\n", GetLastError()); 93 | } 94 | event_handle2 = OpenEventW(EVENT_ALL_ACCESS, FALSE, L"Global\\Evnt2"); 95 | if (event_handle2 == NULL) { 96 | printf("event2 handle open error: %u\n", GetLastError()); 97 | } 98 | 99 | 100 | 101 | printf("target proc name buffer addr: %llx\n", &target_proc_name); 102 | printf("rwbuffer addr: %llx\n", &buffer); 103 | 104 | //example usage 105 | //getting base address of target usermode process with its name 106 | printf("grabbing target usermode process (notepad.exe as example) base address\n"); 107 | issue_comm(COMMAND_GET_UM_PROC_BASE, (DWORD64)&target_proc_base, &target_proc_name, sizeof(target_proc_name)); 108 | printf("target proc base is %llx\n", target_proc_base); 109 | 110 | 111 | 112 | 113 | 114 | //read a float from target usermode process at address baseaddress+0xBEEF 115 | /* 116 | float dummyflt; 117 | issue_comm(COMMAND_RPM, target_proc_base + 0xBEEF , &dummyflt, sizeof(float)); 118 | printf("Float read = %f", dummyfloat); 119 | 120 | */ 121 | 122 | //write an integer from usermode control process (this process) to target usermode address baseaddress+0xBEEF 123 | /* 124 | int dummyint; 125 | issue_comm(COMMAND_WPM, target_proc_base + 0xBEEF , &dummyint, sizeof(int)); 126 | 127 | */ 128 | //exit km thread and then exit um control process 129 | printf("issuing quit command in 3 seconds...\n"); 130 | Sleep(3000); 131 | issue_comm(COMMAND_QUIT, NULL, (void*)NULL, sizeof(int)); 132 | 133 | printf("END\n"); 134 | 135 | 136 | 137 | } -------------------------------------------------------------------------------- /umctrlproc/mem.cpp: -------------------------------------------------------------------------------- 1 | #include "mem.h" 2 | 3 | 4 | 5 | extern RWbuf buffer; 6 | extern HANDLE event_handle; 7 | extern HANDLE event_handle2; 8 | 9 | 10 | bool issue_comm(Commcode cmd, DWORD64 addr, void* structure, int size) { 11 | buffer.command = cmd; 12 | buffer.struct_size = size; 13 | buffer.offset = addr; 14 | buffer.structure = (DWORD64)structure; 15 | //buffer.done = 0; 16 | 17 | SetEvent(event_handle); 18 | //printf("%s", "command issued!\n"); 19 | if (WaitForSingleObject(event_handle2, INFINITE) == WAIT_FAILED) { 20 | printf("Failed to lock and wait for event2\n"); 21 | } 22 | 23 | //command now finished by kernel 24 | ResetEvent(event_handle2); 25 | printf("issuecomm completed\n"); 26 | return true; 27 | } -------------------------------------------------------------------------------- /umctrlproc/mem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "includes.h" 3 | 4 | 5 | //Command codes for issuing commands to driver to do job 6 | enum Commcode { 7 | COMMAND_RPM = 1, 8 | COMMAND_WPM, 9 | COMMAND_GET_UM_PROC_BASE, 10 | COMMAND_QUIT 11 | }; 12 | 13 | // for get um proc base, put ptr to string of proc name into structure, base is returned in addr 14 | 15 | 16 | // read write buffer for comms 17 | struct RWbuf { 18 | int command; 19 | int struct_size = 0; 20 | DWORD64 offset = 0; 21 | DWORD64 structure = 0; 22 | //int done = 1; 23 | }; 24 | 25 | bool issue_comm(Commcode cmd, DWORD64 addr, void* structure, int size); 26 | -------------------------------------------------------------------------------- /umctrlproc/umctrlproc.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30225.117 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "umctrlproc", "umctrlproc.vcxproj", "{E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Debug|x64.ActiveCfg = Debug|x64 17 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Debug|x64.Build.0 = Debug|x64 18 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Debug|x86.ActiveCfg = Debug|Win32 19 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Debug|x86.Build.0 = Debug|Win32 20 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Release|x64.ActiveCfg = Release|x64 21 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Release|x64.Build.0 = Release|x64 22 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Release|x86.ActiveCfg = Release|Win32 23 | {E0A42A17-EC4F-42D9-BBC4-86A9B71A716D}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {4EBA9F9A-3146-4057-8D34-53AD61F116D6} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /umctrlproc/umctrlproc.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {e0a42a17-ec4f-42d9-bbc4-86a9b71a716d} 25 | umctrlproc 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | MultiByte 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | stdcpp17 134 | 135 | 136 | Console 137 | true 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | -------------------------------------------------------------------------------- /umctrlproc/umctrlproc.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /umctrlproc/umctrlproc.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | --------------------------------------------------------------------------------