├── Ring1.inf ├── Ring1.vcxproj ├── Ring1.vcxproj.filters ├── Ring1.vcxproj.user ├── core.hpp ├── entry.cpp ├── handler.cpp ├── rw.cpp └── tick.cpp /Ring1.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; Ring1.inf 3 | ; 4 | 5 | [Version] 6 | Signature="$WINDOWS NT$" 7 | Class=System ; TODO: specify appropriate Class 8 | ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318} ; TODO: specify appropriate ClassGuid 9 | Provider=%ManufacturerName% 10 | CatalogFile=Ring1.cat 11 | DriverVer= ; TODO: set DriverVer in stampinf property pages 12 | PnpLockdown=1 13 | 14 | [DestinationDirs] 15 | DefaultDestDir = 12 16 | Ring1_Device_CoInstaller_CopyFiles = 11 17 | 18 | [SourceDisksNames] 19 | 1 = %DiskName%,,,"" 20 | 21 | [SourceDisksFiles] 22 | Ring1.sys = 1,, 23 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames 24 | 25 | ;***************************************** 26 | ; Install Section 27 | ;***************************************** 28 | 29 | [Manufacturer] 30 | %ManufacturerName%=Standard,NT$ARCH$ 31 | 32 | [Standard.NT$ARCH$] 33 | %Ring1.DeviceDesc%=Ring1_Device, Root\Ring1 ; TODO: edit hw-id 34 | 35 | [Ring1_Device.NT] 36 | CopyFiles=Drivers_Dir 37 | 38 | [Drivers_Dir] 39 | Ring1.sys 40 | 41 | ;-------------- Service installation 42 | [Ring1_Device.NT.Services] 43 | AddService = Ring1,%SPSVCINST_ASSOCSERVICE%, Ring1_Service_Inst 44 | 45 | ; -------------- Ring1 driver install sections 46 | [Ring1_Service_Inst] 47 | DisplayName = %Ring1.SVCDESC% 48 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 49 | StartType = 3 ; SERVICE_DEMAND_START 50 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 51 | ServiceBinary = %12%\Ring1.sys 52 | 53 | ; 54 | ;--- Ring1_Device Coinstaller installation ------ 55 | ; 56 | 57 | [Ring1_Device.NT.CoInstallers] 58 | AddReg=Ring1_Device_CoInstaller_AddReg 59 | CopyFiles=Ring1_Device_CoInstaller_CopyFiles 60 | 61 | [Ring1_Device_CoInstaller_AddReg] 62 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" 63 | 64 | [Ring1_Device_CoInstaller_CopyFiles] 65 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll 66 | 67 | [Ring1_Device.NT.Wdf] 68 | KmdfService = Ring1, Ring1_wdfsect 69 | [Ring1_wdfsect] 70 | KmdfLibraryVersion = $KMDFVERSION$ 71 | 72 | [Strings] 73 | SPSVCINST_ASSOCSERVICE= 0x00000002 74 | ManufacturerName="" ;TODO: Replace with your manufacturer name 75 | DiskName = "Ring1 Installation Disk" 76 | Ring1.DeviceDesc = "Ring1 Device" 77 | Ring1.SVCDESC = "Ring1 Service" 78 | -------------------------------------------------------------------------------- /Ring1.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | Debug 14 | ARM64 15 | 16 | 17 | Release 18 | ARM64 19 | 20 | 21 | 22 | {A98BB9E0-E71D-439D-A027-2996F4419CA6} 23 | {1bc93793-694f-48fe-9372-81e2b05556fd} 24 | v4.5 25 | 12.0 26 | Debug 27 | x64 28 | Ring1 29 | $(LatestTargetPlatformVersion) 30 | 31 | 32 | 33 | Windows10 34 | true 35 | WindowsKernelModeDriver10.0 36 | Driver 37 | KMDF 38 | Universal 39 | 40 | 41 | Windows10 42 | false 43 | WindowsKernelModeDriver10.0 44 | Driver 45 | KMDF 46 | Universal 47 | Spectre 48 | 49 | 50 | Windows10 51 | true 52 | WindowsKernelModeDriver10.0 53 | Driver 54 | KMDF 55 | Universal 56 | 57 | 58 | Windows10 59 | false 60 | WindowsKernelModeDriver10.0 61 | Driver 62 | KMDF 63 | Universal 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | DbgengKernelDebugger 75 | 76 | 77 | DbgengKernelDebugger 78 | 79 | 80 | DbgengKernelDebugger 81 | 82 | 83 | DbgengKernelDebugger 84 | 85 | 86 | 87 | sha256 88 | 89 | 90 | 91 | 92 | sha256 93 | 94 | 95 | stdcpplatest 96 | false 97 | stdc17 98 | 99 | 100 | ReroutedEntry 101 | 102 | 103 | 104 | 105 | sha256 106 | 107 | 108 | 109 | 110 | sha256 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /Ring1.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Ring1.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Off 5 | 6 | -------------------------------------------------------------------------------- /core.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define cidOffset 0x478 5 | #define processOffset 0x220 6 | #define _DbgPrint DbgPrint 7 | inline std::uint64_t _SharedMemAddr; 8 | inline std::uint32_t _ClientPID; 9 | inline PEPROCESS _Client; 10 | inline PEPROCESS _Game; 11 | 12 | extern "C" 13 | { 14 | NTSTATUS NTAPI MmCopyVirtualMemory( PEPROCESS SourceProcess, PVOID SourceAddress, PEPROCESS TargetProcess, PVOID TargetAddress, SIZE_T BufferSize, KPROCESSOR_MODE PreviousMode, PSIZE_T ReturnSize ); 15 | NTKERNELAPI PVOID PsGetProcessSectionBaseAddress( PEPROCESS Process ); 16 | NTKERNELAPI PVOID NTAPI PsGetProcessWow64Process( IN PEPROCESS Process ); 17 | NTKERNELAPI PPEB NTAPI PsGetProcessPeb( IN PEPROCESS Process ); 18 | NTSTATUS NTAPI ZwQuerySystemInformation( ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); 19 | NTKERNELAPI PVOID NTAPI RtlFindExportedRoutineByName( PVOID ImageBase, PCCH RoutineNam ); 20 | NTSYSAPI NTSTATUS NTAPI ObReferenceObjectByName( PUNICODE_STRING ObjectName, ULONG Attributes, PACCESS_STATE AccessState, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PVOID ParseContext, PVOID* Object ); 21 | NTKERNELAPI PVOID __fastcall PsGetProcessImageFileName( PEPROCESS process ); 22 | NTKERNELAPI PVOID PsGetThreadWin32Thread( PKTHREAD thread ); 23 | NTKERNELAPI PVOID PsSetThreadWin32Thread( PKTHREAD thread, PVOID wantedValue, PVOID compareValue ); 24 | } 25 | 26 | namespace EtwEventRW 27 | { 28 | NTSTATUS PhysWrite( int pid, uint64_t Address, uint64_t AllocatedBuffer, SIZE_T size, SIZE_T* written ); 29 | NTSTATUS PhysRead( int pid, uint64_t Address, uint64_t AllocatedBuffer, SIZE_T size, SIZE_T* read ); 30 | } 31 | 32 | namespace pCore 33 | { 34 | 35 | bool 36 | SendPing 37 | ( 38 | 39 | ); 40 | 41 | 42 | bool 43 | SendSharedMemTick 44 | ( 45 | ); 46 | } 47 | 48 | enum EOperation 49 | { 50 | Complete, 51 | Read, 52 | Write, 53 | ImageBase, 54 | Ping 55 | }; 56 | 57 | struct c_PhysMem 58 | { 59 | std::uint32_t source_pid; 60 | std::uint64_t source_address; 61 | std::uint32_t target_pid; 62 | std::uint64_t target_address; 63 | std::uint64_t base_address; 64 | size_t size; 65 | }; 66 | 67 | struct c_SharedMem 68 | { 69 | std::uint32_t Operation; 70 | c_PhysMem PhysMem; 71 | }; 72 | 73 | inline c_SharedMem* SharedMem; -------------------------------------------------------------------------------- /entry.cpp: -------------------------------------------------------------------------------- 1 | #include "core.hpp" 2 | 3 | KAPC_STATE Apc; 4 | KAPC_STATE Apc2; 5 | PVOID currentWin32Thread = 0; 6 | PEPROCESS currentProcess = 0; 7 | PETHREAD currentThread = 0; 8 | CLIENT_ID currentCid = { 0 }; 9 | bool isWin32Thread = false; 10 | 11 | PETHREAD GetValidWin32Thread( PVOID* win32Thread ) 12 | { 13 | int currentThreadId = 1; 14 | NTSTATUS status = STATUS_SUCCESS; 15 | do 16 | { 17 | PETHREAD currentEthread = 0; 18 | status = PsLookupThreadByThreadId( ( HANDLE ) currentThreadId, ¤tEthread ); 19 | 20 | if ( !NT_SUCCESS( status ) || !currentEthread ) 21 | { 22 | currentThreadId++; 23 | continue; 24 | } 25 | 26 | if ( PsIsThreadTerminating( currentEthread ) ) 27 | { 28 | currentThreadId++; 29 | continue; 30 | } 31 | 32 | PVOID Win32Thread = PsGetThreadWin32Thread( currentEthread ); 33 | //memcpy(&Win32Thread, (PVOID)((UINT64)currentEthread + win32ThreadOffset), sizeof(PVOID)); 34 | 35 | if ( Win32Thread ) 36 | { 37 | PEPROCESS threadOwner = PsGetThreadProcess( currentEthread ); 38 | char procName[ 15 ]; 39 | memcpy( &procName, PsGetProcessImageFileName( threadOwner ), sizeof( procName ) ); 40 | if ( !strcmp( procName, "explorer.exe" ) ) 41 | { 42 | *win32Thread = Win32Thread; 43 | return currentEthread; 44 | } 45 | } 46 | currentThreadId++; 47 | } while ( 0x3000 > currentThreadId ); 48 | 49 | return 0; 50 | } 51 | 52 | inline void SpoofWin32Thread( PVOID newWin32Value, PEPROCESS newProcess, CLIENT_ID newClientId ) 53 | { 54 | PKTHREAD currentThread = KeGetCurrentThread( ); 55 | 56 | PsSetThreadWin32Thread( currentThread, newWin32Value, PsGetThreadWin32Thread( currentThread ) ); 57 | 58 | PVOID processPtr = ( PVOID ) ( ( char* ) currentThread + processOffset ); 59 | memcpy( processPtr, &newProcess, sizeof( PEPROCESS ) ); 60 | 61 | PVOID clientIdPtr = ( PVOID ) ( ( char* ) currentThread + cidOffset ); 62 | memcpy( clientIdPtr, &newClientId, sizeof( CLIENT_ID ) ); 63 | } 64 | 65 | 66 | bool SpoofWin32Thread( ) 67 | { 68 | if ( isWin32Thread ) 69 | { 70 | _DbgPrint( "already win32\n" ); 71 | return true; 72 | } 73 | 74 | PVOID targetWin32Thread = 0; 75 | PETHREAD targetThread = GetValidWin32Thread( &targetWin32Thread ); 76 | if ( !targetWin32Thread || !targetThread ) 77 | { 78 | _DbgPrint( "failed to find win32thread" ); 79 | return false; 80 | } 81 | PEPROCESS targetProcess = PsGetThreadProcess( targetThread ); 82 | 83 | CLIENT_ID targetCid = { 0 }; 84 | memcpy( &targetCid, ( PVOID ) ( ( char* ) targetThread + cidOffset ), sizeof( CLIENT_ID ) ); 85 | 86 | KeStackAttachProcess( targetProcess, &Apc ); 87 | SpoofWin32Thread( targetWin32Thread, targetProcess, targetCid ); 88 | 89 | isWin32Thread = true; 90 | } 91 | 92 | void UnspoofWin32Thread( ) 93 | { 94 | if ( !isWin32Thread ) 95 | return; 96 | 97 | SpoofWin32Thread( currentWin32Thread, currentProcess, currentCid ); 98 | KeUnstackDetachProcess( &Apc ); 99 | isWin32Thread = false; 100 | } 101 | 102 | VOID 103 | ThreadEntry 104 | ( 105 | PVOID Ctx 106 | ) 107 | { 108 | currentProcess = IoGetCurrentProcess( ); 109 | currentThread = KeGetCurrentThread( ); // __readgsqword(0x188u) 110 | //_ETHREAD->_CLIENT_ID Cid; 111 | memcpy( ¤tCid, ( PVOID ) ( ( char* ) currentThread + cidOffset ), sizeof( CLIENT_ID ) ); 112 | 113 | KeStackAttachProcess( 114 | (PRKPROCESS)_Client, 115 | &Apc2 116 | ); 117 | 118 | PHYSICAL_ADDRESS PhysShared = MmGetPhysicalAddress( 119 | reinterpret_cast< PVOID >( _SharedMemAddr ) 120 | ); 121 | 122 | if ( PhysShared.QuadPart ) 123 | { 124 | SharedMem = reinterpret_cast< c_SharedMem* >( 125 | MmMapIoSpace( 126 | PhysShared, 127 | sizeof( SharedMem ), 128 | MmNonCached 129 | ) 130 | ); 131 | } 132 | 133 | KeUnstackDetachProcess( 134 | &Apc2 135 | ); 136 | 137 | if ( SharedMem ) 138 | { 139 | while ( TRUE ) 140 | { 141 | if ( !SpoofWin32Thread( ) && !isWin32Thread ) 142 | { 143 | _DbgPrint( "Spoof thread failed\n" ); 144 | continue; 145 | } 146 | 147 | if ( !pCore::SendSharedMemTick( ) ) 148 | { 149 | _DbgPrint( "Sent tick failed\n" ); 150 | continue; 151 | } 152 | 153 | UnspoofWin32Thread( ); 154 | YieldProcessor( ); 155 | } 156 | } 157 | 158 | ObDereferenceObject( _Client ); 159 | } 160 | 161 | NTSTATUS 162 | ReroutedEntry( 163 | std::uint64_t SharedMemAddr, 164 | std::uint32_t ClientPID 165 | ) 166 | { 167 | _SharedMemAddr = SharedMemAddr; 168 | _ClientPID = ClientPID; 169 | 170 | _DbgPrint( "wowbigweaponssir -> Shared mem ptr -> 0x%llp\n", _SharedMemAddr ); 171 | _DbgPrint( "wowbigweaponssir -> Client proc ID-> 0x%llp\n", _ClientPID ); 172 | 173 | if ( !NT_SUCCESS( // [amap] driver entry returned [0xC0000001L] 174 | PsLookupProcessByProcessId( 175 | HANDLE( ClientPID ), 176 | &_Client 177 | ) 178 | ) 179 | ) 180 | { 181 | return STATUS_UNSUCCESSFUL; // [amap] driver entry returned [0xC0000001L] 182 | } 183 | 184 | HANDLE SystemThreadHdl; 185 | PsCreateSystemThread( 186 | &SystemThreadHdl, 187 | THREAD_ALL_ACCESS, 188 | NULL, 189 | NULL, 190 | NULL, 191 | ThreadEntry, 192 | NULL 193 | ); 194 | 195 | return ZwClose( 196 | SystemThreadHdl // [amap] driver entry returned [0x00000000L] 197 | ); 198 | } -------------------------------------------------------------------------------- /handler.cpp: -------------------------------------------------------------------------------- 1 | #include "core.hpp" 2 | 3 | bool 4 | pCore::SendPing 5 | ( 6 | 7 | ) 8 | { 9 | DbgPrint( 10 | "wowbigweaponssir -> Test request sent\n" 11 | ); 12 | 13 | return TRUE; 14 | } -------------------------------------------------------------------------------- /rw.cpp: -------------------------------------------------------------------------------- 1 | #include "core.hpp" 2 | #include 3 | 4 | #define WINDOWS_1803 17134 5 | #define WINDOWS_1809 17763 6 | #define WINDOWS_1903 18362 7 | #define WINDOWS_1909 18363 8 | #define WINDOWS_2004 19041 9 | #define WINDOWS_20H2 19569 10 | #define WINDOWS_21H1 20180 11 | #define WINDOWS_22H2 19045 12 | 13 | const DWORD GetUserDirectoryTableBaseOffset( ) 14 | { 15 | RTL_OSVERSIONINFOW ver = { 0 }; 16 | RtlGetVersion( &ver ); 17 | switch ( ver.dwBuildNumber ) 18 | { 19 | case WINDOWS_1803: 20 | return 0x0278; 21 | break; 22 | case WINDOWS_1809: 23 | return 0x0278; 24 | break; 25 | case WINDOWS_1903: 26 | return 0x0280; 27 | break; 28 | case WINDOWS_1909: 29 | return 0x0280; 30 | break; 31 | case WINDOWS_2004: 32 | return 0x0388; 33 | break; 34 | case WINDOWS_20H2: 35 | return 0x0388; 36 | break; 37 | case WINDOWS_21H1: 38 | return 0x0388; 39 | break; 40 | case WINDOWS_22H2: 41 | return 0x0388; 42 | break; 43 | default: 44 | return 0x0388; 45 | } 46 | } 47 | 48 | NTSTATUS ReadPhysicalAddress( PVOID TargetAddress, PVOID lpBuffer, SIZE_T Size, SIZE_T* BytesRead ) 49 | { 50 | if ( !MmIsAddressValid( TargetAddress ) ) 51 | { 52 | _DbgPrint( "wowbigweaponssir -> Non-valid physical memory addr!\n" ); 53 | return STATUS_ACCESS_VIOLATION; 54 | } 55 | 56 | if ( lpBuffer == NULL ) 57 | { 58 | _DbgPrint( "wowbigweaponssir -> Buffer is null!\n" ); 59 | return STATUS_INVALID_PARAMETER; 60 | } 61 | 62 | if ( Size == 0 ) 63 | { 64 | _DbgPrint( "wowbigweaponssir -> Size is null!\n" ); 65 | return STATUS_INVALID_PARAMETER; 66 | } 67 | 68 | if ( ( ULONG_PTR ) TargetAddress % MEMORY_ALLOCATION_ALIGNMENT != 0 ) 69 | { 70 | _DbgPrint( "wowbigweaponssir -> The physical memory addr is misaligned!\n" ); 71 | return STATUS_DATATYPE_MISALIGNMENT; 72 | } 73 | 74 | if ( ( ULONG_PTR ) lpBuffer % MEMORY_ALLOCATION_ALIGNMENT != 0 ) 75 | { 76 | _DbgPrint( "wowbigweaponssir -> The buffer memory addr is misaligned!\n" ); 77 | return STATUS_DATATYPE_MISALIGNMENT; 78 | } 79 | 80 | MM_COPY_ADDRESS AddrToRead = { 0 }; 81 | AddrToRead.PhysicalAddress.QuadPart = ( LONGLONG ) TargetAddress; 82 | return MmCopyMemory( lpBuffer, AddrToRead, Size, MM_COPY_MEMORY_PHYSICAL, BytesRead ); 83 | } 84 | 85 | NTSTATUS WritePhysicalAddress( PVOID TargetAddress, PVOID lpBuffer, SIZE_T Size, SIZE_T* BytesWritten ) 86 | { 87 | if ( !TargetAddress ) 88 | return STATUS_UNSUCCESSFUL; 89 | 90 | PHYSICAL_ADDRESS AddrToWrite = { 0 }; 91 | AddrToWrite.QuadPart = LONGLONG( TargetAddress ); 92 | 93 | PVOID pmapped_mem = MmMapIoSpaceEx( AddrToWrite, Size, PAGE_READWRITE ); 94 | 95 | if ( !pmapped_mem ) 96 | return STATUS_UNSUCCESSFUL; 97 | 98 | memcpy( pmapped_mem, lpBuffer, Size ); 99 | 100 | *BytesWritten = Size; 101 | MmUnmapIoSpace( pmapped_mem, Size ); 102 | return STATUS_SUCCESS; 103 | } 104 | 105 | const UINT64 GetProcessCr3( const PEPROCESS pProcess ) 106 | { 107 | PUCHAR process = ( PUCHAR ) pProcess; 108 | ULONG_PTR process_dirbase = *( PULONG_PTR ) ( process + 0x28 ); //dirbase x64, 32bit is 0x18 109 | if ( process_dirbase == 0 ) 110 | { 111 | DWORD UserDirOffset = GetUserDirectoryTableBaseOffset( ); 112 | 113 | ULONG_PTR process_userdirbase = *( PULONG_PTR ) ( process + UserDirOffset ); 114 | return process_userdirbase; 115 | } 116 | return process_dirbase; 117 | } 118 | 119 | 120 | const UINT64 GetKernelDirBase( ) 121 | { 122 | PUCHAR process = ( PUCHAR ) PsGetCurrentProcess( ); 123 | ULONG_PTR cr3 = *( PULONG_PTR ) ( process + 0x28 ); //dirbase x64, 32bit is 0x18 124 | return cr3; 125 | } 126 | 127 | 128 | #define PAGE_OFFSET_SIZE 12 129 | static const UINT64 PMASK = ( ~0xfull << 8 ) & 0xfffffffffull; 130 | 131 | const UINT64 TranslateLinearAddress( UINT64 directoryTableBase, UINT64 virtualAddress ) 132 | { 133 | directoryTableBase &= ~0xf; 134 | 135 | UINT64 pageOffset = virtualAddress & ~( ~0ul << PAGE_OFFSET_SIZE ); 136 | UINT64 pte = ( ( virtualAddress >> 12 ) & ( 0x1ffll ) ); 137 | UINT64 pt = ( ( virtualAddress >> 21 ) & ( 0x1ffll ) ); 138 | UINT64 pd = ( ( virtualAddress >> 30 ) & ( 0x1ffll ) ); 139 | UINT64 pdp = ( ( virtualAddress >> 39 ) & ( 0x1ffll ) ); 140 | 141 | SIZE_T readsize = 0; 142 | UINT64 pdpe = 0; 143 | ReadPhysicalAddress( PVOID( directoryTableBase + 8 * pdp ), &pdpe, sizeof( pdpe ), &readsize ); 144 | if ( ~pdpe & 1 ) 145 | return 0; 146 | 147 | UINT64 pde = 0; 148 | ReadPhysicalAddress( PVOID( ( pdpe & PMASK ) + 8 * pd ), &pde, sizeof( pde ), &readsize ); 149 | if ( ~pde & 1 ) 150 | return 0; 151 | 152 | /* 1GB large page, use pde's 12-34 bits */ 153 | if ( pde & 0x80 ) 154 | return ( pde & ( ~0ull << 42 >> 12 ) ) + ( virtualAddress & ~( ~0ull << 30 ) ); 155 | 156 | UINT64 pteAddr = 0; 157 | ReadPhysicalAddress( PVOID( ( pde & PMASK ) + 8 * pt ), &pteAddr, sizeof( pteAddr ), &readsize ); 158 | if ( ~pteAddr & 1 ) 159 | return 0; 160 | 161 | /* 2MB large page */ 162 | if ( pteAddr & 0x80 ) 163 | return ( pteAddr & PMASK ) + ( virtualAddress & ~( ~0ull << 21 ) ); 164 | 165 | virtualAddress = 0; 166 | ReadPhysicalAddress( PVOID( ( pteAddr & PMASK ) + 8 * pte ), &virtualAddress, sizeof( virtualAddress ), &readsize ); 167 | virtualAddress &= PMASK; 168 | 169 | if ( !virtualAddress ) 170 | return 0; 171 | 172 | return virtualAddress + pageOffset; 173 | } 174 | 175 | ULONG_PTR process_dirbase; 176 | namespace EtwEventRW 177 | { 178 | NTSTATUS PhysWrite( int pid, uint64_t Address, uint64_t AllocatedBuffer, SIZE_T size, SIZE_T* written ) 179 | { 180 | PEPROCESS pProcess = NULL; 181 | if ( pid == 0 ) return STATUS_UNSUCCESSFUL; 182 | 183 | NTSTATUS NtRet = PsLookupProcessByProcessId( ( HANDLE ) pid, &pProcess ); 184 | if ( NtRet != STATUS_SUCCESS ) return NtRet; 185 | 186 | ULONG_PTR process_dirbase = GetProcessCr3( pProcess ); 187 | ObDereferenceObject( pProcess ); 188 | SIZE_T CurOffset = 0; 189 | SIZE_T TotalSize = size; 190 | while ( TotalSize ) 191 | { 192 | uint64_t CurPhysAddr = TranslateLinearAddress( process_dirbase, ( ULONG64 ) Address + CurOffset ); 193 | if ( !CurPhysAddr ) return STATUS_UNSUCCESSFUL; 194 | 195 | ULONG64 WriteSize = min( PAGE_SIZE - ( CurPhysAddr & 0xFFF ), TotalSize ); 196 | SIZE_T BytesWritten = 0; 197 | NtRet = WritePhysicalAddress( ( PVOID ) CurPhysAddr, ( PVOID ) ( ( ULONG64 ) AllocatedBuffer + CurOffset ), WriteSize, &BytesWritten ); 198 | TotalSize -= BytesWritten; 199 | CurOffset += BytesWritten; 200 | if ( NtRet != STATUS_SUCCESS ) break; 201 | if ( BytesWritten == 0 ) break; 202 | } 203 | 204 | *written = CurOffset; 205 | return NtRet; 206 | } 207 | NTSTATUS PhysRead( int pid, uint64_t Address, uint64_t AllocatedBuffer, SIZE_T size, SIZE_T* read ) 208 | { 209 | LARGE_INTEGER delay; 210 | delay.QuadPart = -500 * 10000; // 500 milliseconds in 100-nanosecond intervals 211 | _DbgPrint( "wowbigweaponssir -> Passed data [%i, 0x%llp, 0x%llp, 0x%i]\n", pid, Address, AllocatedBuffer, size, read ); 212 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 213 | _DbgPrint( "wowbigweaponssir -> Getting peprocess\n" ); 214 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 215 | PEPROCESS pProcess = NULL; 216 | if ( pid == 0 ) return STATUS_UNSUCCESSFUL; 217 | 218 | NTSTATUS NtRet; 219 | _DbgPrint( "wowbigweaponssir -> Dirbase checks\n" ); 220 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 221 | if ( !process_dirbase ) 222 | { 223 | _DbgPrint( "wowbigweaponssir -> Invalid dirbase, attaching it..\n" ); 224 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 225 | NtRet = PsLookupProcessByProcessId( ( HANDLE ) pid, &pProcess ); 226 | if ( NtRet != STATUS_SUCCESS ) return NtRet; 227 | 228 | process_dirbase = GetProcessCr3( pProcess ); 229 | _DbgPrint( "wowbigweaponssir -> Proc CR3 = 0x%llp\n", process_dirbase ); 230 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 231 | } 232 | 233 | _DbgPrint( "wowbigweaponssir -> DirectoryTableBase = 0x%llp\n", process_dirbase ); 234 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 235 | ObDereferenceObject( pProcess ); 236 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 237 | 238 | SIZE_T CurOffset = 0; 239 | SIZE_T TotalSize = size; 240 | _DbgPrint( "wowbigweaponssir -> Entering tls loop\n" ); 241 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 242 | while ( TotalSize ) 243 | { 244 | 245 | _DbgPrint( "wowbigweaponssir -> Getting current phys addr\n" ); 246 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 247 | uint64_t CurPhysAddr = TranslateLinearAddress( process_dirbase, ( ULONG64 ) Address + CurOffset ); 248 | if ( !CurPhysAddr ) return STATUS_UNSUCCESSFUL; 249 | 250 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 251 | ULONG64 ReadSize = min( PAGE_SIZE - ( CurPhysAddr & 0xFFF ), TotalSize ); 252 | SIZE_T BytesRead = 0; 253 | _DbgPrint( "wowbigweaponssir -> Mapping physical memory to read!\n" ); 254 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 255 | NtRet = ReadPhysicalAddress( ( PVOID ) CurPhysAddr, ( PVOID ) ( ( ULONG64 ) AllocatedBuffer + CurOffset ), ReadSize, &BytesRead ); 256 | 257 | _DbgPrint( "wowbigweaponssir -> Phys mem has been read success!\n" ); 258 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 259 | 260 | _DbgPrint( "wowbigweaponssir -> Size1sett\n" ); 261 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 262 | 263 | TotalSize -= BytesRead; 264 | _DbgPrint( "wowbigweaponssir -> Size2sett\n" ); 265 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 266 | 267 | CurOffset += BytesRead; 268 | _DbgPrint( "wowbigweaponssir -> Size checks\n" ); 269 | KeDelayExecutionThread( KernelMode, FALSE, &delay ); 270 | 271 | if ( NtRet != STATUS_SUCCESS ) break; 272 | if ( BytesRead == 0 ) break; 273 | } 274 | 275 | *read = CurOffset; 276 | return NtRet; 277 | } 278 | } 279 | 280 | uint64_t VirtualAddressToPhysicalAddress( void* VirtualAddress ) 281 | { 282 | return MmGetPhysicalAddress( VirtualAddress ).QuadPart; 283 | } 284 | 285 | uint64_t PhysicalAddressToVirtualAddress( uint64_t PhysicalAddress ) 286 | { 287 | PHYSICAL_ADDRESS PhysicalAddr = { 0 }; 288 | PhysicalAddr.QuadPart = PhysicalAddress; 289 | 290 | return reinterpret_cast< uint64_t >( MmGetVirtualForPhysical( PhysicalAddr ) ); 291 | } -------------------------------------------------------------------------------- /tick.cpp: -------------------------------------------------------------------------------- 1 | #include "core.hpp" 2 | SIZE_T ForwardedETWBytes = NULL; 3 | bool pCore::SendSharedMemTick( ) 4 | { 5 | bool Return = FALSE; 6 | 7 | if ( SharedMem->Operation != EOperation::Complete ) 8 | { 9 | switch ( SharedMem->Operation ) 10 | { 11 | case EOperation::Ping: 12 | Return = SendPing( ); 13 | break; 14 | case EOperation::Read: 15 | // Shadow phys mem read through EtwEventTrace 16 | EtwEventRW::PhysRead( 17 | SharedMem->PhysMem.target_pid, 18 | SharedMem->PhysMem.source_address, 19 | SharedMem->PhysMem.target_address, 20 | SharedMem->PhysMem.size, 21 | &ForwardedETWBytes 22 | ); 23 | Return = TRUE; 24 | PsTerminateSystemThread( false ); 25 | case EOperation::Write: 26 | // Shadow phys mem write through EtwEventTrace 27 | EtwEventRW::PhysWrite( 28 | SharedMem->PhysMem.target_pid, 29 | SharedMem->PhysMem.source_address, 30 | SharedMem->PhysMem.target_address, 31 | SharedMem->PhysMem.size, 32 | &ForwardedETWBytes 33 | ); 34 | Return = TRUE; 35 | } 36 | 37 | SharedMem->Operation = EOperation::Complete; 38 | } 39 | else 40 | { 41 | Return = TRUE; 42 | } 43 | 44 | return Return; 45 | } 46 | --------------------------------------------------------------------------------