├── README.md ├── km ├── cache.h ├── cleaning.h ├── crt.h ├── definitions.h ├── encrypt.h ├── entry.cpp ├── ia32.h ├── imports.h ├── interface.h ├── km.vcxproj ├── km.vcxproj.filters ├── km.vcxproj.user └── utils.h ├── um ├── entry.cpp ├── kinterface.h ├── mmap.h ├── um.vcxproj ├── um.vcxproj.filters ├── um.vcxproj.user └── utils.h └── vmt.sln /README.md: -------------------------------------------------------------------------------- 1 | Hello, since i found a better way to inject my internal cheat, i decided to release this one after some indian guy i gave to him leaked it. 2 | 3 | - 3 .data pointers chained in .data section of win32k.sys. 4 | - PFN Clearing (nulling). 5 | - Allocating kernel memory then exposing it to the game by modifying PFN. 6 | - Present Pointer Swapping, calling DllMain by swapping the present pointer to the Dll Entry. 7 | - Driver unloading (unhook) after injection. 8 | - Discord & Medal present pointers (offset & signatures). 9 | - Shadow Imports. 10 | 11 | # PresentInjector 12 | A simple present scene, kernel allocation injector. 13 | -------------------------------------------------------------------------------- /km/cache.h: -------------------------------------------------------------------------------- 1 | namespace cache 2 | { 3 | __int64( __fastcall *o_qword_address )( void * ) = nullptr; 4 | __int64( __fastcall *o_function_qword_1 )( void * ) = nullptr; 5 | __int64( __fastcall *o_function_qword_2 )( void * ) = nullptr; 6 | 7 | uintptr_t qword_address = 0; 8 | uintptr_t function_qword_1 = 0; 9 | uintptr_t function_qword_2 = 0; 10 | } -------------------------------------------------------------------------------- /km/cleaning.h: -------------------------------------------------------------------------------- 1 | namespace clean 2 | { 3 | bool null_pfn( PMDL mdl ) 4 | { 5 | PPFN_NUMBER mdl_pages = MmGetMdlPfnArray( mdl ); 6 | if ( !mdl_pages ) { return false; } 7 | 8 | ULONG mdl_page_count = ADDRESS_AND_SIZE_TO_SPAN_PAGES( MmGetMdlVirtualAddress( mdl ), MmGetMdlByteCount( mdl ) ); 9 | 10 | ULONG null_pfn = 0x0; 11 | 12 | MM_COPY_ADDRESS source_address = { 0 }; 13 | source_address.VirtualAddress = &null_pfn; 14 | 15 | for ( ULONG i = 0; i < mdl_page_count; i++ ) 16 | { 17 | size_t bytes = 0; 18 | MmCopyMemory( &mdl_pages[i], source_address, sizeof( ULONG ), MM_COPY_MEMORY_VIRTUAL, &bytes ); 19 | } 20 | 21 | return true; 22 | } 23 | } -------------------------------------------------------------------------------- /km/crt.h: -------------------------------------------------------------------------------- 1 | namespace crt 2 | { 3 | template 4 | __forceinline int strlen( t str ) { 5 | if ( !str ) 6 | { 7 | return 0; 8 | } 9 | 10 | t buffer = str; 11 | 12 | while ( *buffer ) 13 | { 14 | *buffer++; 15 | } 16 | 17 | return ( int )( buffer - str ); 18 | } 19 | 20 | bool strcmp( const char *src, const char *dst ) 21 | { 22 | if ( !src || !dst ) 23 | { 24 | return true; 25 | } 26 | 27 | const auto src_sz = crt::strlen( src ); 28 | const auto dst_sz = crt::strlen( dst ); 29 | 30 | if ( src_sz != dst_sz ) 31 | { 32 | return true; 33 | } 34 | 35 | for ( int i = 0; i < src_sz; i++ ) 36 | { 37 | if ( src[i] != dst[i] ) 38 | { 39 | return true; 40 | } 41 | } 42 | 43 | return false; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /km/definitions.h: -------------------------------------------------------------------------------- 1 | #define PFN_TO_PAGE(pfn) ( pfn << 12 ) 2 | #define dereference(ptr) (const uintptr_t)(ptr + *( int * )( ( BYTE * )ptr + 3 ) + 7) 3 | #define in_range(x,a,b) (x >= a && x <= b) 4 | #define get_bits( x ) (in_range((x&(~0x20)),'A','F') ? ((x&(~0x20)) - 'A' + 0xA) : (in_range(x,'0','9') ? x - '0' : 0)) 5 | #define get_byte( x ) (get_bits(x[0]) << 4 | get_bits(x[1])) 6 | #define size_align(Size) ((Size + 0xFFF) & 0xFFFFFFFFFFFFF000) 7 | #define to_lower_i(Char) ((Char >= 'A' && Char <= 'Z') ? (Char + 32) : Char) 8 | #define to_lower_c(Char) ((Char >= (char*)'A' && Char <= (char*)'Z') ? (Char + 32) : Char) 9 | 10 | typedef unsigned int uint32_t; 11 | 12 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 13 | { 14 | HANDLE Section; 15 | PVOID MappedBase; 16 | PVOID ImageBase; 17 | ULONG ImageSize; 18 | ULONG Flags; 19 | USHORT LoadOrderIndex; 20 | USHORT InitOrderIndex; 21 | USHORT LoadCount; 22 | USHORT OffsetToFileName; 23 | UCHAR FullPathName[256]; 24 | } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; 25 | 26 | typedef struct _RTL_PROCESS_MODULES 27 | { 28 | ULONG NumberOfModules; 29 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 30 | } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; 31 | 32 | typedef struct _LDR_DATA_TABLE_ENTRY 33 | { 34 | LIST_ENTRY InLoadOrderLinks; 35 | LIST_ENTRY InMemoryOrderLinks; 36 | LIST_ENTRY InInitializationOrderLinks; 37 | PVOID DllBase; 38 | PVOID EntryPoint; 39 | ULONG SizeOfImage; 40 | UNICODE_STRING FullDllName; 41 | UNICODE_STRING BaseDllName; 42 | ULONG Flags; 43 | WORD LoadCount; 44 | WORD TlsIndex; 45 | union 46 | { 47 | LIST_ENTRY HashLinks; 48 | struct 49 | { 50 | PVOID SectionPointer; 51 | ULONG CheckSum; 52 | }; 53 | }; 54 | union 55 | { 56 | ULONG TimeDateStamp; 57 | PVOID LoadedImports; 58 | }; 59 | VOID *EntryPointActivationContext; 60 | PVOID PatchInformation; 61 | LIST_ENTRY ForwarderLinks; 62 | LIST_ENTRY ServiceTagLinks; 63 | LIST_ENTRY StaticLinks; 64 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 65 | 66 | typedef struct _RTL_CRITICAL_SECTION 67 | { 68 | VOID *DebugInfo; 69 | LONG LockCount; 70 | LONG RecursionCount; 71 | PVOID OwningThread; 72 | PVOID LockSemaphore; 73 | ULONG SpinCount; 74 | } RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION; 75 | 76 | typedef struct _PEB_LDR_DATA 77 | { 78 | ULONG Length; 79 | UCHAR Initialized; 80 | PVOID SsHandle; 81 | LIST_ENTRY InLoadOrderModuleList; 82 | LIST_ENTRY InMemoryOrderModuleList; 83 | LIST_ENTRY InInitializationOrderModuleList; 84 | PVOID EntryInProgress; 85 | } PEB_LDR_DATA, *PPEB_LDR_DATA; 86 | 87 | typedef struct _PEB 88 | { 89 | UCHAR InheritedAddressSpace; 90 | UCHAR ReadImageFileExecOptions; 91 | UCHAR BeingDebugged; 92 | UCHAR BitField; 93 | ULONG ImageUsesLargePages : 1; 94 | ULONG IsProtectedProcess : 1; 95 | ULONG IsLegacyProcess : 1; 96 | ULONG IsImageDynamicallyRelocated : 1; 97 | ULONG SpareBits : 4; 98 | PVOID Mutant; 99 | PVOID ImageBaseAddress; 100 | PPEB_LDR_DATA Ldr; 101 | VOID *ProcessParameters; 102 | PVOID SubSystemData; 103 | PVOID ProcessHeap; 104 | PRTL_CRITICAL_SECTION FastPebLock; 105 | PVOID AtlThunkSListPtr; 106 | PVOID IFEOKey; 107 | ULONG CrossProcessFlags; 108 | ULONG ProcessInJob : 1; 109 | ULONG ProcessInitializing : 1; 110 | ULONG ReservedBits0 : 30; 111 | union 112 | { 113 | PVOID KernelCallbackTable; 114 | PVOID UserSharedInfoPtr; 115 | }; 116 | ULONG SystemReserved[1]; 117 | ULONG SpareUlong; 118 | VOID *FreeList; 119 | ULONG TlsExpansionCounter; 120 | PVOID TlsBitmap; 121 | ULONG TlsBitmapBits[2]; 122 | PVOID ReadOnlySharedMemoryBase; 123 | PVOID HotpatchInformation; 124 | VOID **ReadOnlyStaticServerData; 125 | PVOID AnsiCodePageData; 126 | PVOID OemCodePageData; 127 | PVOID UnicodeCaseTableData; 128 | ULONG NumberOfProcessors; 129 | ULONG NtGlobalFlag; 130 | LARGE_INTEGER CriticalSectionTimeout; 131 | ULONG HeapSegmentReserve; 132 | ULONG HeapSegmentCommit; 133 | ULONG HeapDeCommitTotalFreeThreshold; 134 | ULONG HeapDeCommitFreeBlockThreshold; 135 | ULONG NumberOfHeaps; 136 | ULONG MaximumNumberOfHeaps; 137 | VOID **ProcessHeaps; 138 | PVOID GdiSharedHandleTable; 139 | PVOID ProcessStarterHelper; 140 | ULONG GdiDCAttributeList; 141 | PRTL_CRITICAL_SECTION LoaderLock; 142 | ULONG OSMajorVersion; 143 | ULONG OSMinorVersion; 144 | WORD OSBuildNumber; 145 | WORD OSCSDVersion; 146 | ULONG OSPlatformId; 147 | ULONG ImageSubsystem; 148 | ULONG ImageSubsystemMajorVersion; 149 | ULONG ImageSubsystemMinorVersion; 150 | ULONG ImageProcessAffinityMask; 151 | ULONG GdiHandleBuffer[34]; 152 | PVOID PostProcessInitRoutine; 153 | PVOID TlsExpansionBitmap; 154 | ULONG TlsExpansionBitmapBits[32]; 155 | ULONG SessionId; 156 | ULARGE_INTEGER AppCompatFlags; 157 | ULARGE_INTEGER AppCompatFlagsUser; 158 | PVOID pShimData; 159 | PVOID AppCompatInfo; 160 | UNICODE_STRING CSDVersion; 161 | VOID *ActivationContextData; 162 | VOID *ProcessAssemblyStorageMap; 163 | VOID *SystemDefaultActivationContextData; 164 | VOID *SystemAssemblyStorageMap; 165 | ULONG MinimumStackCommit; 166 | VOID *FlsCallback; 167 | LIST_ENTRY FlsListHead; 168 | PVOID FlsBitmap; 169 | ULONG FlsBitmapBits[4]; 170 | ULONG FlsHighIndex; 171 | PVOID WerRegistrationData; 172 | PVOID WerShipAssertPtr; 173 | } PEB, *PPEB; 174 | 175 | typedef enum _SYSTEM_INFORMATION_CLASS 176 | { 177 | SystemBasicInformation, 178 | SystemProcessorInformation, 179 | SystemPerformanceInformation, 180 | SystemTimeOfDayInformation, 181 | SystemPathInformation, 182 | SystemProcessInformation, 183 | SystemCallCountInformation, 184 | SystemDeviceInformation, 185 | SystemProcessorPerformanceInformation, 186 | SystemFlagsInformation, 187 | SystemCallTimeInformation, 188 | SystemModuleInformation, 189 | SystemLocksInformation, 190 | SystemStackTraceInformation, 191 | SystemPagedPoolInformation, 192 | SystemNonPagedPoolInformation, 193 | SystemHandleInformation, 194 | SystemObjectInformation, 195 | SystemPageFileInformation, 196 | SystemVdmInstemulInformation, 197 | SystemVdmBopInformation, 198 | SystemFileCacheInformation, 199 | SystemPoolTagInformation, 200 | SystemInterruptInformation, 201 | SystemDpcBehaviorInformation, 202 | SystemFullMemoryInformation, 203 | SystemLoadGdiDriverInformation, 204 | SystemUnloadGdiDriverInformation, 205 | SystemTimeAdjustmentInformation, 206 | SystemSummaryMemoryInformation, 207 | SystemNextEventIdInformation, 208 | SystemEventIdsInformation, 209 | SystemCrashDumpInformation, 210 | SystemExceptionInformation, 211 | SystemCrashDumpStateInformation, 212 | SystemKernelDebuggerInformation, 213 | SystemContextSwitchInformation, 214 | SystemRegistryQuotaInformation, 215 | SystemExtendServiceTableInformation, 216 | SystemPrioritySeperation, 217 | SystemPlugPlayBusInformation, 218 | SystemDockInformation, 219 | SystemProcessorSpeedInformation, 220 | SystemCurrentTimeZoneInformation, 221 | SystemLookasideInformation 222 | } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; 223 | 224 | typedef struct _PAGE_INFORMATION 225 | { 226 | PML4E_64 *PML4E; 227 | PDPTE_64 *PDPTE; 228 | PDE_64 *PDE; 229 | PTE_64 *PTE; 230 | }PAGE_INFORMATION, *PPAGE_INFORMATION; 231 | 232 | typedef struct _MDL_INFORMATION 233 | { 234 | MDL *mdl; 235 | uintptr_t va; 236 | }MDL_INFORMATION, *PMDL_INFORMATION; 237 | 238 | typedef union _VIRTUAL_ADDRESS 239 | { 240 | PVOID value; 241 | struct 242 | { 243 | ULONG64 offset : 12; 244 | ULONG64 pt_index : 9; 245 | ULONG64 pd_index : 9; 246 | ULONG64 pdpt_index : 9; 247 | ULONG64 pml4_index : 9; 248 | ULONG64 reserved : 16; 249 | }; 250 | } VIRTUAL_ADDRESS, *PVIRTUAL_ADDRESS; 251 | 252 | extern "C" 253 | { 254 | NTKERNELAPI NTSTATUS NTAPI ZwQuerySystemInformation( 255 | _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, 256 | _Inout_ PVOID SystemInformation, 257 | _In_ ULONG SystemInformationLength, 258 | _Out_opt_ PULONG ReturnLength 259 | ); 260 | 261 | NTSTATUS NTAPI MmCopyVirtualMemory( 262 | PEPROCESS SourceProcess, 263 | PVOID SourceAddress, 264 | PEPROCESS TargetProcess, 265 | PVOID TargetAddress, 266 | SIZE_T BufferSize, 267 | KPROCESSOR_MODE PreviousMode, 268 | PSIZE_T ReturnSize 269 | ); 270 | 271 | NTSTATUS ZwAllocateVirtualMemory( 272 | _In_ HANDLE ProcessHandle, 273 | _Inout_ PVOID *BaseAddress, 274 | _In_ ULONG_PTR ZeroBits, 275 | _Inout_ PSIZE_T RegionSize, 276 | _In_ ULONG AllocationType, 277 | _In_ ULONG Protect 278 | ); 279 | 280 | NTKERNELAPI 281 | PPEB 282 | PsGetProcessPeb( 283 | IN PEPROCESS Process 284 | ); 285 | 286 | NTKERNELAPI 287 | PVOID NTAPI RtlFindExportedRoutineByName( 288 | _In_ PVOID ImageBase, 289 | _In_ PCCH RoutineName 290 | ); 291 | } -------------------------------------------------------------------------------- /km/encrypt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /*____________________________________________________________________________________________________________ 4 | Original Author: skadro 5 | Github: https://github.com/skadro-official 6 | License: See end of file 7 | skCrypter 8 | Compile-time, Usermode + Kernelmode, safe and lightweight string crypter library for C++11+ 9 | *Not removing this part is appreciated* 10 | ____________________________________________________________________________________________________________*/ 11 | 12 | #ifdef _KERNEL_MODE 13 | namespace std 14 | { 15 | // STRUCT TEMPLATE remove_reference 16 | template 17 | struct remove_reference { 18 | using type = _Ty; 19 | }; 20 | 21 | template 22 | struct remove_reference<_Ty &> { 23 | using type = _Ty; 24 | }; 25 | 26 | template 27 | struct remove_reference<_Ty &&> { 28 | using type = _Ty; 29 | }; 30 | 31 | template 32 | using remove_reference_t = typename remove_reference<_Ty>::type; 33 | 34 | // STRUCT TEMPLATE remove_const 35 | template 36 | struct remove_const { // remove top-level const qualifier 37 | using type = _Ty; 38 | }; 39 | 40 | template 41 | struct remove_const { 42 | using type = _Ty; 43 | }; 44 | 45 | template 46 | using remove_const_t = typename remove_const<_Ty>::type; 47 | } 48 | #else 49 | #include 50 | #endif 51 | 52 | namespace skc 53 | { 54 | template 55 | using clean_type = typename std::remove_const_t>; 56 | 57 | template 58 | class skCrypter 59 | { 60 | public: 61 | __forceinline constexpr skCrypter( T *data ) 62 | { 63 | crypt( data ); 64 | } 65 | 66 | __forceinline T *get( ) 67 | { 68 | return _storage; 69 | } 70 | 71 | __forceinline int size( ) // (w)char count 72 | { 73 | return _size; 74 | } 75 | 76 | __forceinline char key( ) 77 | { 78 | return _key1; 79 | } 80 | 81 | __forceinline T *encrypt( ) 82 | { 83 | if ( !isEncrypted( ) ) 84 | crypt( _storage ); 85 | 86 | return _storage; 87 | } 88 | 89 | __forceinline T *decrypt( ) 90 | { 91 | if ( isEncrypted( ) ) 92 | crypt( _storage ); 93 | 94 | return _storage; 95 | } 96 | 97 | __forceinline bool isEncrypted( ) 98 | { 99 | return _storage[_size - 1] != 0; 100 | } 101 | 102 | __forceinline void clear( ) // set full storage to 0 103 | { 104 | for ( int i = 0; i < _size; i++ ) 105 | { 106 | _storage[i] = 0; 107 | } 108 | } 109 | 110 | __forceinline operator T *( ) 111 | { 112 | decrypt( ); 113 | 114 | return _storage; 115 | } 116 | 117 | private: 118 | __forceinline constexpr void crypt( T *data ) 119 | { 120 | for ( int i = 0; i < _size; i++ ) 121 | { 122 | _storage[i] = data[i] ^ ( _key1 + i % ( 1 + _key2 ) ); 123 | } 124 | } 125 | 126 | T _storage[_size] {}; 127 | }; 128 | } 129 | 130 | #define e(str) skCrypt_key(str, __TIME__[4], __TIME__[7]) 131 | #define skCrypt_key(str, key1, key2) []() { \ 132 | constexpr static auto crypted = skc::skCrypter \ 133 | >((skc::clean_type*)str); \ 134 | return crypted; }() 135 | -------------------------------------------------------------------------------- /km/entry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "imports.h" 10 | #include "ia32.h" 11 | #include "definitions.h" 12 | #include "encrypt.h" 13 | #include "crt.h" 14 | #include "utils.h" 15 | #include "interface.h" 16 | #include "cache.h" 17 | #include "cleaning.h" 18 | 19 | __int64 __fastcall communication_handler( void *a1 ) 20 | { 21 | if ( !a1 || ExGetPreviousMode( ) != UserMode || reinterpret_cast< request_data * >( a1 )->unique != request_unique ) 22 | { 23 | return cache::o_function_qword_2( a1 ); 24 | } 25 | 26 | const auto request = reinterpret_cast< request_data * >( a1 ); 27 | 28 | switch ( request->code ) 29 | { 30 | case request_base: 31 | { 32 | base_request data { 0 }; 33 | 34 | if ( !utils::safe_copy( &data, request->data, sizeof( base_request ) ) ) 35 | { 36 | return 0; 37 | } 38 | 39 | if ( !data.name || !data.pid ) 40 | { 41 | return 0; 42 | } 43 | 44 | const auto base = utils::get_module_handle( data.pid, data.name ); 45 | 46 | if ( !base ) 47 | { 48 | return 0; 49 | } 50 | 51 | reinterpret_cast< base_request * > ( request->data )->handle = base; 52 | 53 | return request_success; 54 | } 55 | case request_write: 56 | { 57 | write_request data { 0 }; 58 | 59 | if ( !utils::safe_copy( &data, request->data, sizeof( write_request ) ) ) 60 | { 61 | return 0; 62 | } 63 | 64 | if ( !data.address || !data.pid || !data.buffer || !data.size ) 65 | { 66 | return 0; 67 | } 68 | 69 | PEPROCESS process; 70 | if ( PsLookupProcessByProcessId( ( HANDLE )data.pid, &process ) == STATUS_SUCCESS ) 71 | { 72 | size_t bytes = 0; 73 | if ( MmCopyVirtualMemory( IoGetCurrentProcess( ), ( void * )reinterpret_cast< write_request * > ( request->data )->buffer, process, ( void * )data.address, data.size, KernelMode, &bytes ) != STATUS_SUCCESS || bytes != data.size ) 74 | { 75 | ObDereferenceObject( process ); 76 | return 0; 77 | } 78 | 79 | ObDereferenceObject( process ); 80 | } 81 | else 82 | { 83 | return 0; 84 | } 85 | 86 | return request_success; 87 | } 88 | case request_read: 89 | { 90 | read_request data { 0 }; 91 | 92 | if ( !utils::safe_copy( &data, request->data, sizeof( read_request ) ) ) 93 | { 94 | return 0; 95 | } 96 | 97 | if ( !data.address || !data.pid || !data.buffer || !data.size ) 98 | { 99 | return 0; 100 | } 101 | 102 | PEPROCESS process; 103 | if ( PsLookupProcessByProcessId( ( HANDLE )data.pid, &process ) == STATUS_SUCCESS ) 104 | { 105 | size_t bytes = 0; 106 | if ( MmCopyVirtualMemory( process, ( void * )data.address, IoGetCurrentProcess( ), reinterpret_cast< write_request * > ( request->data )->buffer, data.size, KernelMode, &bytes ) != STATUS_SUCCESS || bytes != data.size ) 107 | { 108 | ObDereferenceObject( process ); 109 | return 0; 110 | } 111 | 112 | ObDereferenceObject( process ); 113 | } 114 | else 115 | { 116 | return 0; 117 | } 118 | 119 | return request_success; 120 | } 121 | case request_pattern: 122 | { 123 | pattern_request data { 0 }; 124 | 125 | if ( !utils::safe_copy( &data, request->data, sizeof( pattern_request ) ) ) 126 | { 127 | return 0; 128 | } 129 | 130 | PEPROCESS process; 131 | if ( PsLookupProcessByProcessId( ( HANDLE )data.pid, &process ) == STATUS_SUCCESS ) 132 | { 133 | const auto o_process = utils::swap_process( ( uintptr_t )process ); 134 | 135 | if ( !o_process ) 136 | { 137 | utils::swap_process( ( uintptr_t )o_process ); 138 | 139 | ObDereferenceObject( process ); 140 | 141 | return 0; 142 | } 143 | 144 | const auto address = utils::find_pattern( data.base, data.signature ); 145 | 146 | utils::swap_process( o_process ); 147 | 148 | ObDereferenceObject( process ); 149 | 150 | if ( !address ) 151 | { 152 | return 0; 153 | } 154 | 155 | reinterpret_cast< pattern_request * > ( request->data )->address = address; 156 | } 157 | else 158 | { 159 | return 0; 160 | } 161 | 162 | return request_success; 163 | } 164 | case request_swap: 165 | { 166 | swap_request data { 0 }; 167 | 168 | if ( !utils::safe_copy( &data, request->data, sizeof( allocate_request ) ) ) 169 | { 170 | return 0; 171 | } 172 | 173 | if ( !data.src || !data.dst || !data.pid ) 174 | { 175 | return 0; 176 | } 177 | 178 | PEPROCESS process; 179 | if ( PsLookupProcessByProcessId( ( HANDLE )data.pid, &process ) == STATUS_SUCCESS ) 180 | { 181 | const auto o_process = utils::swap_process( ( uintptr_t )process ); 182 | 183 | if ( !o_process ) 184 | { 185 | utils::swap_process( ( uintptr_t )o_process ); 186 | 187 | ObDereferenceObject( process ); 188 | 189 | return 0; 190 | } 191 | 192 | uintptr_t old = 0; 193 | 194 | *( void ** )&old = InterlockedExchangePointer( ( void ** )data.src, ( void * )data.dst ); 195 | 196 | utils::swap_process( ( uintptr_t )o_process ); 197 | 198 | ObDereferenceObject( process ); 199 | 200 | if ( !old ) 201 | { 202 | return 0; 203 | } 204 | 205 | reinterpret_cast< swap_request * > ( request->data )->old = old; 206 | 207 | return request_success; 208 | } 209 | 210 | return 0; 211 | } 212 | case request_allocate: 213 | { 214 | allocate_request data { 0 }; 215 | 216 | if ( !utils::safe_copy( &data, request->data, sizeof( allocate_request ) ) ) 217 | { 218 | return 0; 219 | } 220 | 221 | uintptr_t mdl = 0; 222 | const auto address = utils::allocate_kernel_memory( data.size, &mdl ); 223 | 224 | if ( !address ) 225 | { 226 | return 0; 227 | } 228 | 229 | if ( !mdl || !address ) 230 | { 231 | return 0; 232 | } 233 | 234 | reinterpret_cast< allocate_request * >( request->data )->mdl = mdl; 235 | reinterpret_cast< allocate_request * >( request->data )->address = address; 236 | 237 | return request_success; 238 | } 239 | case request_free: 240 | { 241 | free_request data { 0 }; 242 | 243 | if ( !utils::safe_copy( &data, request->data, sizeof( free_request ) ) ) 244 | { 245 | return 0; 246 | } 247 | 248 | if ( !data.mdl || !data.address ) 249 | { 250 | return 0; 251 | } 252 | 253 | MDL_INFORMATION mdl = { ( MDL * )data.mdl, ( uintptr_t )data.address }; 254 | 255 | utils::free_mdl_memory( mdl ); 256 | 257 | return request_success; 258 | } 259 | case request_expose: 260 | { 261 | expose_request data { 0 }; 262 | 263 | if ( !utils::safe_copy( &data, request->data, sizeof( expose_request ) ) ) 264 | { 265 | return 0; 266 | } 267 | 268 | if ( !data.pid || !data.address || !data.size ) 269 | { 270 | return 0; 271 | } 272 | 273 | if ( !utils::expose_kernel_memory( data.pid, (uintptr_t)data.address, data.size ) ) 274 | { 275 | return 0; 276 | } 277 | 278 | return request_success; 279 | } 280 | case request_unload: 281 | { 282 | *reinterpret_cast< unload_request * > ( request->data )->buffer = true; 283 | 284 | InterlockedExchangePointer( ( void ** )dereference( cache::qword_address ), ( void * )cache::o_qword_address ); 285 | InterlockedExchangePointer( ( void ** )dereference( cache::function_qword_1 ), ( void * )cache::o_function_qword_1 ); 286 | InterlockedExchangePointer( ( void ** )dereference( cache::function_qword_2 ), ( void * )cache::o_function_qword_2 ); 287 | 288 | return request_success; 289 | } 290 | } 291 | 292 | return 0; 293 | } 294 | 295 | NTSTATUS DriverEntry( ) 296 | { 297 | const auto win32k = utils::get_kernel_module( e( "win32k.sys" ) ); 298 | 299 | cache::qword_address = utils::find_pattern( win32k, e( "\x48\x8B\x05\x95\xCD\x05\x00" ), e( "xxxxxxx" ) ); 300 | 301 | cache::function_qword_1 = utils::find_pattern( win32k, e( "\x48\x8B\x05\x11\xD7\x05\x00" ), e( "xxxxxxx" ) ); 302 | 303 | cache::function_qword_2 = utils::find_pattern( win32k, e( "\x48\x8B\x05\xA1\xD6\x05\x00" ), e( "xxxxxxx" ) ); 304 | 305 | *( void ** )&cache::o_qword_address = InterlockedExchangePointer( ( void ** )dereference( cache::qword_address ), ( void * )utils::find_pattern( win32k, e( "\x48\x83\xEC\x28\x48\x8B\x05\x11\xD7" ), e( "xxxxxxxxx" ) ) ); 306 | 307 | *( void ** )&cache::o_function_qword_1 = InterlockedExchangePointer( ( void ** )dereference( cache::function_qword_1 ), ( void * )utils::find_pattern( win32k, e( "\x48\x83\xEC\x28\x48\x8B\x05\xA1\xD6" ), e( "xxxxxxxxx" ) ) ); 308 | 309 | *( void ** )&cache::o_function_qword_2 = InterlockedExchangePointer( ( void ** )dereference( cache::function_qword_2 ), ( void * )communication_handler ); 310 | 311 | return STATUS_SUCCESS; 312 | } -------------------------------------------------------------------------------- /km/imports.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nou4r/PresentInjector/ce1a20515fb73223c4f41140732f1ee1bdd82e26/km/imports.h -------------------------------------------------------------------------------- /km/interface.h: -------------------------------------------------------------------------------- 1 | typedef enum _request_codes 2 | { 3 | request_free = 0x109, 4 | request_base = 0x119, 5 | request_read = 0x129, 6 | request_write = 0x139, 7 | request_allocate = 0x149, 8 | request_expose = 0x159, 9 | request_swap = 0x169, 10 | request_pattern = 0x179, 11 | request_success = 0x91a, 12 | request_unique = 0x92b, 13 | request_unload = 0x93c, 14 | }request_codes, *prequest_codes; 15 | 16 | typedef struct _unload_request 17 | { 18 | bool *buffer; 19 | }unload_request, *punload_request; 20 | 21 | typedef struct _read_request { 22 | uint32_t pid; 23 | uintptr_t address; 24 | void *buffer; 25 | size_t size; 26 | } read_request, *pread_request; 27 | 28 | typedef struct _write_request { 29 | uint32_t pid; 30 | uintptr_t address; 31 | void *buffer; 32 | size_t size; 33 | } write_request, *pwrite_request; 34 | 35 | typedef struct _base_request { 36 | uint32_t pid; 37 | uintptr_t handle; 38 | WCHAR name[260]; 39 | } base_request, *pbase_request; 40 | 41 | typedef struct _swap_request 42 | { 43 | uint32_t pid; 44 | uintptr_t dst; 45 | uintptr_t src; 46 | uintptr_t old; 47 | }swap_request, *pswap_request; 48 | 49 | typedef struct _free_request 50 | { 51 | void *address; 52 | uintptr_t mdl; 53 | }free_request, *pfree_request; 54 | 55 | typedef struct _allocate_request 56 | { 57 | void *address; 58 | uintptr_t mdl; 59 | size_t size; 60 | }allocate_request, *pallocate_request; 61 | 62 | typedef struct _expose_request 63 | { 64 | void *address; 65 | size_t size; 66 | uint32_t pid; 67 | }expose_request, *pexpose_request; 68 | 69 | typedef struct _pattern_request 70 | { 71 | int pid; 72 | uintptr_t base; 73 | char signature[260]; 74 | uintptr_t address; 75 | }pattern_request, *ppattern_request; 76 | 77 | typedef struct _request_data 78 | { 79 | uint32_t unique; 80 | request_codes code; 81 | void *data; 82 | }request_data, *prequest_data; -------------------------------------------------------------------------------- /km/km.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 | {4c4c54e5-c199-4146-b5d7-fddc9fe74066} 25 | km 26 | 10.0.22000.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 | Driver 50 | false 51 | WindowsKernelModeDriver10.0 52 | true 53 | NotSet 54 | Windows10 55 | Universal 56 | KMDF 57 | 1 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | true 85 | 86 | 87 | false 88 | $(SolutionDir)bin\ 89 | $(SolutionDir)bin\intermediates\ 90 | $(ProjectName)_x64 91 | false 92 | 93 | 94 | 95 | Level3 96 | true 97 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 98 | true 99 | 100 | 101 | Console 102 | true 103 | 104 | 105 | 106 | 107 | Level3 108 | true 109 | true 110 | true 111 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 112 | true 113 | 114 | 115 | Console 116 | true 117 | true 118 | true 119 | 120 | 121 | 122 | 123 | Level3 124 | true 125 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | true 127 | 128 | 129 | Console 130 | true 131 | 132 | 133 | 134 | 135 | TurnOffAllWarnings 136 | false 137 | true 138 | false 139 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 140 | false 141 | stdcpp20 142 | stdc17 143 | MaxSpeed 144 | AnySuitable 145 | true 146 | true 147 | Size 148 | true 149 | None 150 | true 151 | false 152 | false 153 | true 154 | 155 | 156 | Native 157 | true 158 | true 159 | false 160 | false 161 | $(SUBSYSTEM_NATVER) 162 | Driver 163 | DriverEntry 164 | 165 | 166 | true 167 | %(AdditionalDependencies) 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | -------------------------------------------------------------------------------- /km/km.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /km/km.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Off 5 | 6 | -------------------------------------------------------------------------------- /km/utils.h: -------------------------------------------------------------------------------- 1 | namespace utils 2 | { 3 | uintptr_t swap_process( uintptr_t new_process ) 4 | { 5 | auto current_thread = ( uintptr_t )KeGetCurrentThread( ); 6 | 7 | auto apc_state = *( uintptr_t * )( current_thread + 0x98 ); 8 | auto old_process = *( uintptr_t * )( apc_state + 0x20 ); 9 | *( uintptr_t * )( apc_state + 0x20 ) = new_process; 10 | 11 | auto dir_table_base = *( uintptr_t * )( new_process + 0x28 ); 12 | __writecr3( dir_table_base ); 13 | 14 | return old_process; 15 | } 16 | 17 | uintptr_t resolve_relative_address( uintptr_t instruction, ULONG offset_offset, ULONG instruction_size ) 18 | { 19 | auto instr = instruction; 20 | 21 | const auto rip_offset = *( PLONG )( instr + offset_offset ); 22 | 23 | const auto resolved_addr = instr + instruction_size + rip_offset; 24 | 25 | return resolved_addr; 26 | } 27 | 28 | void *get_system_information( SYSTEM_INFORMATION_CLASS information_class ) 29 | { 30 | unsigned long size = 32; 31 | char buffer[32]; 32 | 33 | ZwQuerySystemInformation( information_class, buffer, size, &size ); 34 | 35 | void *info = ExAllocatePoolZero( NonPagedPool, size, 7265746172 ); 36 | 37 | if ( !info ) 38 | return nullptr; 39 | 40 | if ( !NT_SUCCESS( ZwQuerySystemInformation( information_class, info, size, &size ) ) ) 41 | { 42 | ExFreePool( info ); 43 | return nullptr; 44 | } 45 | 46 | return info; 47 | } 48 | 49 | uintptr_t get_kernel_module( const char *name ) 50 | { 51 | const auto to_lower = []( char *string ) -> const char * 52 | { 53 | for ( char *pointer = string; *pointer != '\0'; ++pointer ) 54 | { 55 | *pointer = ( char )( short )tolower( *pointer ); 56 | } 57 | 58 | return string; 59 | }; 60 | 61 | const PRTL_PROCESS_MODULES info = ( PRTL_PROCESS_MODULES )get_system_information( SystemModuleInformation ); 62 | 63 | if ( !info ) 64 | return NULL; 65 | 66 | for ( size_t i = 0; i < info->NumberOfModules; ++i ) 67 | { 68 | const auto &mod = info->Modules[i]; 69 | 70 | if ( crt::strcmp( to_lower_c( ( char * )mod.FullPathName + mod.OffsetToFileName ), name ) == 0 ) 71 | { 72 | const void *address = mod.ImageBase; 73 | ExFreePool( info ); 74 | return ( uintptr_t )address; 75 | } 76 | } 77 | 78 | ExFreePool( info ); 79 | return NULL; 80 | } 81 | 82 | auto get_kernel_export( const char *module_name, LPCSTR export_name ) -> uintptr_t 83 | { 84 | return reinterpret_cast< uintptr_t > ( RtlFindExportedRoutineByName( reinterpret_cast< void * > ( utils::get_kernel_module( module_name ) ), export_name ) ); 85 | } 86 | 87 | void sleep( int ms ) 88 | { 89 | LARGE_INTEGER time; 90 | time.QuadPart = -( ms ) * 10 * 1000; 91 | KeDelayExecutionThread( KernelMode, TRUE, &time ); 92 | } 93 | 94 | uintptr_t find_pattern( uintptr_t base, size_t range, const char *pattern, const char *mask ) 95 | { 96 | const auto check_mask = []( const char *base, const char *pattern, const char *mask ) -> bool 97 | { 98 | for ( ; *mask; ++base, ++pattern, ++mask ) 99 | { 100 | if ( *mask == 'x' && *base != *pattern ) 101 | { 102 | return false; 103 | } 104 | } 105 | 106 | return true; 107 | }; 108 | 109 | range = range - crt::strlen( mask ); 110 | 111 | for ( size_t i = 0; i < range; ++i ) 112 | { 113 | if ( check_mask( ( const char * )base + i, pattern, mask ) ) 114 | { 115 | return base + i; 116 | } 117 | } 118 | 119 | return NULL; 120 | } 121 | 122 | uintptr_t find_pattern( uintptr_t base, const char *pattern, const char *mask ) 123 | { 124 | const PIMAGE_NT_HEADERS headers = ( PIMAGE_NT_HEADERS )( base + ( ( PIMAGE_DOS_HEADER )base )->e_lfanew ); 125 | const PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION( headers ); 126 | 127 | for ( size_t i = 0; i < headers->FileHeader.NumberOfSections; i++ ) 128 | { 129 | const PIMAGE_SECTION_HEADER section = §ions[i]; 130 | 131 | if ( section->Characteristics & IMAGE_SCN_MEM_EXECUTE ) 132 | { 133 | const auto match = find_pattern( base + section->VirtualAddress, section->Misc.VirtualSize, pattern, mask ); 134 | 135 | if ( match ) 136 | { 137 | return match; 138 | } 139 | } 140 | } 141 | 142 | return 0; 143 | } 144 | 145 | uintptr_t find_pattern( uintptr_t module_base, const char* pattern ) 146 | { 147 | auto pattern_ = pattern; 148 | uintptr_t first_match = 0; 149 | 150 | if ( !module_base ) 151 | { 152 | return 0; 153 | } 154 | 155 | const auto nt = reinterpret_cast< IMAGE_NT_HEADERS * >( module_base + reinterpret_cast< IMAGE_DOS_HEADER * >( module_base )->e_lfanew ); 156 | 157 | for ( uintptr_t current = module_base; current < module_base + nt->OptionalHeader.SizeOfImage; current++ ) 158 | { 159 | if ( !*pattern_ ) 160 | { 161 | return first_match; 162 | } 163 | 164 | if ( *( BYTE * )pattern_ == '\?' || *( BYTE * )current == get_byte( pattern_ ) ) 165 | { 166 | if ( !first_match ) 167 | first_match = current; 168 | 169 | if ( !pattern_[2] ) 170 | return first_match; 171 | 172 | if ( *( WORD * )pattern_ == '\?\?' || *( BYTE * )pattern_ != '\?' ) 173 | pattern_ += 3; 174 | 175 | else 176 | pattern_ += 2; 177 | } 178 | else 179 | { 180 | pattern_ = pattern; 181 | first_match = 0; 182 | } 183 | } 184 | 185 | return 0; 186 | } 187 | 188 | uintptr_t get_module_handle( uintptr_t pid, LPCWSTR module_name ) 189 | { 190 | PEPROCESS target_proc; 191 | uintptr_t base = 0; 192 | if ( !NT_SUCCESS( PsLookupProcessByProcessId( ( HANDLE )pid, &target_proc ) ) ) 193 | return 0; 194 | 195 | const auto o_process = swap_process( ( uintptr_t )target_proc ); 196 | 197 | PPEB peb = PsGetProcessPeb( target_proc ); 198 | if ( !peb ) 199 | goto end; 200 | 201 | if ( !peb->Ldr || !peb->Ldr->Initialized ) 202 | goto end; 203 | 204 | 205 | UNICODE_STRING module_name_unicode; 206 | RtlInitUnicodeString( &module_name_unicode, module_name ); 207 | for ( PLIST_ENTRY list = peb->Ldr->InLoadOrderModuleList.Flink; 208 | list != &peb->Ldr->InLoadOrderModuleList; 209 | list = list->Flink ) { 210 | PLDR_DATA_TABLE_ENTRY entry = CONTAINING_RECORD( list, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); 211 | if ( RtlCompareUnicodeString( &entry->BaseDllName, &module_name_unicode, TRUE ) == 0 ) { 212 | base = ( uintptr_t )entry->DllBase; 213 | goto end; 214 | } 215 | } 216 | 217 | end: 218 | 219 | swap_process( ( uintptr_t )o_process ); 220 | 221 | ObDereferenceObject( target_proc ); 222 | 223 | return base; 224 | } 225 | 226 | bool safe_copy( void* dst, void *src, size_t size ) 227 | { 228 | SIZE_T bytes = 0; 229 | 230 | if ( MmCopyVirtualMemory( IoGetCurrentProcess( ), src, IoGetCurrentProcess( ), dst, size, KernelMode, &bytes ) == STATUS_SUCCESS && bytes == size ) 231 | { 232 | return true; 233 | } 234 | 235 | return false; 236 | } 237 | 238 | MEMORY_BASIC_INFORMATION query_virtual_memory( void* address ) 239 | { 240 | MEMORY_BASIC_INFORMATION mbi; 241 | ZwQueryVirtualMemory( ( HANDLE )-1, address, MemoryBasicInformation, &mbi, sizeof( MEMORY_BASIC_INFORMATION ), 0 ); 242 | return mbi; 243 | } 244 | 245 | PAGE_INFORMATION get_page_information( void *va, CR3 cr3 ) 246 | { 247 | ADDRESS_TRANSLATION_HELPER helper; 248 | UINT32 level; 249 | PML4E_64 *pml4, *pml4e; 250 | PDPTE_64 *pdpt, *pdpte; 251 | PDE_64 *pd, *pde; 252 | PTE_64 *pt, *pte; 253 | 254 | PAGE_INFORMATION info; 255 | 256 | helper.AsUInt64 = ( uintptr_t )va; 257 | 258 | PHYSICAL_ADDRESS pa; 259 | 260 | pa.QuadPart = cr3.AddressOfPageDirectory << PAGE_SHIFT; 261 | 262 | pml4 = ( PML4E_64 * )MmGetVirtualForPhysical( pa ); 263 | 264 | pml4e = &pml4[helper.AsIndex.Pml4]; 265 | 266 | info.PML4E = pml4e; 267 | 268 | if ( pml4e->Present == FALSE ) 269 | { 270 | info.PTE = nullptr; 271 | info.PDE = nullptr; 272 | info.PDPTE = nullptr; 273 | 274 | goto end; 275 | } 276 | 277 | pa.QuadPart = pml4e->PageFrameNumber << PAGE_SHIFT; 278 | 279 | pdpt = ( PDPTE_64 * )MmGetVirtualForPhysical( pa ); 280 | 281 | pdpte = &pdpt[helper.AsIndex.Pdpt]; 282 | 283 | info.PDPTE = pdpte; 284 | 285 | if ( ( pdpte->Present == FALSE ) || ( pdpte->LargePage != FALSE ) ) 286 | { 287 | info.PTE = nullptr; 288 | info.PDE = nullptr; 289 | 290 | goto end; 291 | } 292 | 293 | pa.QuadPart = pdpte->PageFrameNumber << PAGE_SHIFT; 294 | 295 | pd = ( PDE_64 * )MmGetVirtualForPhysical( pa ); 296 | 297 | pde = &pd[helper.AsIndex.Pd]; 298 | 299 | info.PDE = pde; 300 | 301 | if ( ( pde->Present == FALSE ) || ( pde->LargePage != FALSE ) ) 302 | { 303 | info.PTE = nullptr; 304 | 305 | goto end; 306 | } 307 | 308 | pa.QuadPart = pde->PageFrameNumber << PAGE_SHIFT; 309 | 310 | pt = ( PTE_64 * )MmGetVirtualForPhysical( pa ); 311 | 312 | pte = &pt[helper.AsIndex.Pt]; 313 | 314 | info.PTE = pte; 315 | 316 | return info; 317 | 318 | end: 319 | return info; 320 | } 321 | 322 | MDL_INFORMATION allocate_mdl_memory( size_t size ) 323 | { 324 | MDL_INFORMATION memory; 325 | 326 | PHYSICAL_ADDRESS lower, higher; 327 | lower.QuadPart = 0; 328 | higher.QuadPart = 0xffff'ffff'ffff'ffffULL; 329 | 330 | const auto pages = ( size / PAGE_SIZE ) + 1; 331 | 332 | const auto mdl = MmAllocatePagesForMdl( lower, higher, lower, pages * ( uintptr_t )0x1000 ); 333 | 334 | if ( !mdl ) 335 | { 336 | return { 0, 0 }; 337 | } 338 | 339 | const auto mapping_start_address = MmMapLockedPagesSpecifyCache( mdl, KernelMode, MmCached, NULL, FALSE, NormalPagePriority ); 340 | 341 | if ( !mapping_start_address ) 342 | { 343 | return { 0, 0 }; 344 | } 345 | 346 | if ( !NT_SUCCESS( MmProtectMdlSystemAddress( mdl, PAGE_EXECUTE_READWRITE ) ) ) 347 | { 348 | return { 0, 0 }; 349 | } 350 | 351 | memory.mdl = mdl; 352 | memory.va = reinterpret_cast ( mapping_start_address ); 353 | 354 | return memory; 355 | } 356 | 357 | void free_mdl_memory( MDL_INFORMATION &memory ) 358 | { 359 | MmUnmapLockedPages( reinterpret_cast< void * >( memory.va ), memory.mdl ); 360 | MmFreePagesFromMdl( memory.mdl ); 361 | ExFreePool( memory.mdl ); 362 | } 363 | 364 | void* allocate_kernel_memory( const size_t _size, uintptr_t* mdl ) 365 | { 366 | const auto size = size_align( _size ); 367 | 368 | auto memory = allocate_mdl_memory( size ); 369 | 370 | while ( memory.va % 0x10000 != 0 ) 371 | { 372 | free_mdl_memory( memory ); 373 | memory = allocate_mdl_memory( size ); 374 | } 375 | 376 | *mdl = (uintptr_t)memory.mdl; 377 | return (void*)memory.va; 378 | } 379 | 380 | bool expose_kernel_memory( const int pid, const uintptr_t kernel_address, const size_t size ) 381 | { 382 | PEPROCESS process; 383 | if ( PsLookupProcessByProcessId( ( HANDLE )pid, &process ) == STATUS_SUCCESS ) 384 | { 385 | const auto o_process = utils::swap_process( ( uintptr_t )process ); 386 | 387 | CR3 cr3 { }; 388 | cr3.Flags = __readcr3( ); 389 | 390 | for ( uintptr_t address = kernel_address; address <= kernel_address + size; address += 0x1000 ) 391 | { 392 | const auto page_information = utils::get_page_information( ( void * )address, cr3 ); 393 | 394 | page_information.PDE->Supervisor = 1; 395 | page_information.PDPTE->Supervisor = 1; 396 | page_information.PML4E->Supervisor = 1; 397 | 398 | if ( !page_information.PDE || ( page_information.PTE && !page_information.PTE->Present ) ) 399 | { 400 | 401 | } 402 | else 403 | { 404 | page_information.PTE->Supervisor = 1; 405 | } 406 | } 407 | 408 | utils::swap_process( ( uintptr_t )o_process ); 409 | } 410 | else 411 | { 412 | return false; 413 | } 414 | 415 | return true; 416 | } 417 | } -------------------------------------------------------------------------------- /um/entry.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "kinterface.h" 9 | #include "utils.h" 10 | #include "mmap.h" 11 | 12 | void main( ) 13 | { 14 | const auto pid = utils::get_process_id( "RustClient.exe" ); 15 | 16 | if ( pid ) 17 | { 18 | printf( "game found %i\n", pid ); 19 | 20 | kinterface->initialize( ); 21 | 22 | printf( "kinterface intialized.\n" ); 23 | 24 | mmap->map( pid, utils::read_file( "default.dll" ).data( ) ); 25 | } 26 | else 27 | { 28 | printf( "game not found\n" ); 29 | } 30 | 31 | kinterface->unload( ); 32 | printf( "kinterface unloaded.\n" ); 33 | 34 | std::cin.get( ); 35 | } 36 | -------------------------------------------------------------------------------- /um/kinterface.h: -------------------------------------------------------------------------------- 1 | class kinterface_t 2 | { 3 | private: 4 | __int64( __fastcall *function_address )( void * ) = nullptr; 5 | 6 | typedef enum _request_codes 7 | { 8 | request_free = 0x109, 9 | request_base = 0x119, 10 | request_read = 0x129, 11 | request_write = 0x139, 12 | request_allocate = 0x149, 13 | request_expose = 0x159, 14 | request_swap = 0x169, 15 | request_pattern = 0x179, 16 | request_success = 0x91a, 17 | request_unique = 0x92b, 18 | request_unload = 0x93c, 19 | }request_codes, *prequest_codes; 20 | 21 | typedef struct _unload_request 22 | { 23 | bool *buffer; 24 | }unload_request, *punload_request; 25 | 26 | typedef struct _read_request { 27 | uint32_t pid; 28 | uintptr_t address; 29 | void *buffer; 30 | size_t size; 31 | } read_request, *pread_request; 32 | 33 | typedef struct _write_request { 34 | uint32_t pid; 35 | uintptr_t address; 36 | void *buffer; 37 | size_t size; 38 | } write_request, *pwrite_request; 39 | 40 | typedef struct _base_request { 41 | uint32_t pid; 42 | uintptr_t handle; 43 | WCHAR name[260]; 44 | } base_request, *pbase_request; 45 | 46 | typedef struct _swap_request 47 | { 48 | uint32_t pid; 49 | uintptr_t dst; 50 | uintptr_t src; 51 | uintptr_t old; 52 | }swap_request, *pswap_request; 53 | 54 | typedef struct _free_request 55 | { 56 | void *address; 57 | uintptr_t mdl; 58 | }free_request, *pfree_request; 59 | 60 | typedef struct _allocate_request 61 | { 62 | void *address; 63 | uintptr_t mdl; 64 | size_t size; 65 | }allocate_request, *pallocate_request; 66 | 67 | typedef struct _expose_request 68 | { 69 | void *address; 70 | size_t size; 71 | uint32_t pid; 72 | }expose_request, *pexpose_request; 73 | 74 | typedef struct _pattern_request 75 | { 76 | int pid; 77 | uintptr_t base; 78 | char signature[260]; 79 | uintptr_t address; 80 | }pattern_request, *ppattern_request; 81 | 82 | typedef struct _request_data 83 | { 84 | uint32_t unique; 85 | request_codes code; 86 | void *data; 87 | }request_data, *prequest_data; 88 | 89 | public: 90 | 91 | inline auto initialize( ) -> bool 92 | { 93 | LoadLibrary( "user32.dll" ); 94 | 95 | const auto win32k = LoadLibrary( "win32u.dll" ); 96 | 97 | if ( !win32k ) 98 | { 99 | return false; 100 | } 101 | 102 | *( void ** )&function_address = GetProcAddress( win32k, "NtUserUpdateWindowTrackingInfo" ); 103 | 104 | if ( !function_address ) 105 | { 106 | return false; 107 | } 108 | 109 | return true; 110 | } 111 | 112 | inline auto send_cmd( void *data, request_codes code ) -> bool 113 | { 114 | if ( !data || !code ) 115 | { 116 | return false; 117 | } 118 | 119 | request_data request { 0 }; 120 | 121 | request.unique = request_unique; 122 | request.data = data; 123 | request.code = code; 124 | 125 | const auto result = function_address( &request ); 126 | 127 | if ( result != request_success ) 128 | { 129 | return false; 130 | } 131 | 132 | return true; 133 | } 134 | 135 | inline auto get_module_base( const int pid, const std::string module_name ) -> const std::uintptr_t 136 | { 137 | base_request data { 0 }; 138 | 139 | data.pid = pid; 140 | data.handle = 0; 141 | 142 | std::wstring wstr { std::wstring( module_name.begin( ), module_name.end( ) ) }; 143 | 144 | memset( data.name, 0, sizeof( WCHAR ) * 260 ); 145 | wcscpy( data.name, wstr.c_str( ) ); 146 | 147 | send_cmd( &data, request_base ); 148 | 149 | return data.handle; 150 | } 151 | 152 | inline auto free_virtual_memory( void *address, uintptr_t mdl ) -> bool 153 | { 154 | free_request data { 0 }; 155 | 156 | data.mdl = mdl; 157 | data.address = address; 158 | 159 | return send_cmd( &data, request_free ); 160 | } 161 | 162 | inline auto find_signature( const int pid, const std::uintptr_t base, const std::string signature ) -> std::uintptr_t 163 | { 164 | pattern_request data { 0 }; 165 | 166 | data.pid = pid; 167 | data.base = base; 168 | data.address = 0; 169 | 170 | memset( data.signature, 0, sizeof( char ) * 260 ); 171 | strcpy( data.signature, signature.c_str( ) ); 172 | 173 | send_cmd( &data, request_pattern ); 174 | 175 | return data.address; 176 | } 177 | 178 | inline auto swap_virtual_pointer( const int pid, std::uintptr_t src, std::uintptr_t dst ) -> std::uintptr_t 179 | { 180 | swap_request data { 0 }; 181 | 182 | data.pid = pid; 183 | data.src = src; 184 | data.dst = dst; 185 | data.old = 0; 186 | 187 | send_cmd( &data, request_swap ); 188 | 189 | return data.old; 190 | } 191 | 192 | inline auto read_virtual_memory( const int pid, const std::uintptr_t address, void *buffer, const std::size_t size ) -> bool 193 | { 194 | read_request data { 0 }; 195 | 196 | data.pid = pid; 197 | data.address = address; 198 | data.buffer = buffer; 199 | data.size = size; 200 | 201 | return send_cmd( &data, request_read ); 202 | } 203 | 204 | template 205 | inline auto read_virtual_memory( const int pid, const std::uintptr_t address ) -> t 206 | { 207 | t response { }; 208 | read_virtual_memory( pid, address, &response, sizeof( t ) ); 209 | return response; 210 | } 211 | 212 | inline auto write_virtual_memory( const int pid, const std::uintptr_t address, void *buffer, const std::size_t size ) -> bool 213 | { 214 | write_request data { 0 }; 215 | 216 | data.pid = pid; 217 | data.address = address; 218 | data.buffer = buffer; 219 | data.size = size; 220 | 221 | return send_cmd( &data, request_write ); 222 | } 223 | 224 | template 225 | inline auto write_virtual_memory( const int pid, const std::uintptr_t address, t value ) -> bool 226 | { 227 | return write_virtual_memory( pid, address, &value, sizeof( t ) ); 228 | } 229 | 230 | inline auto allocate_kernel_memory( const std::size_t size, std::uintptr_t* mdl ) -> void* 231 | { 232 | allocate_request data { 0 }; 233 | 234 | data.size = size; 235 | data.address = 0; 236 | data.mdl = 0; 237 | 238 | send_cmd( &data, request_allocate ); 239 | 240 | *mdl = data.mdl; 241 | 242 | return data.address; 243 | } 244 | 245 | inline auto expose_kernel_memory( const int pid, void *kernel_address, const std::size_t size ) -> bool 246 | { 247 | expose_request data { 0 }; 248 | 249 | data.pid = pid; 250 | data.address = kernel_address; 251 | data.size = size; 252 | 253 | return send_cmd( &data, request_expose ); 254 | } 255 | 256 | inline auto unload( ) -> bool 257 | { 258 | unload_request data { 0 }; 259 | 260 | bool buffer = false; 261 | 262 | data.buffer = &buffer; 263 | 264 | const auto result = send_cmd( &data, request_unload ); 265 | 266 | if ( !result || !buffer ) 267 | { 268 | return false; 269 | } 270 | 271 | return true; 272 | } 273 | }; 274 | 275 | static kinterface_t *kinterface = new kinterface_t( ); -------------------------------------------------------------------------------- /um/mmap.h: -------------------------------------------------------------------------------- 1 | class mmap_t 2 | { 3 | private: 4 | 5 | unsigned char remote_call_dll_main[103] = { 6 | 0x48, 0x83, 0xEC, 0x38, 7 | 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | 0x48, 0x39, 0xFF, 0x90, 0x39, 0xC0, 9 | 0x90, 10 | 0x48, 0x89, 0x44, 0x24, 0x20, 11 | 0x48, 0x8B, 0x44, 0x24, 12 | 0x20, 0x83, 0x38, 0x00, 0x75, 0x39, 13 | 0x48, 0x8B, 0x44, 0x24, 0x20, 0xC7, 0x00, 0x01, 0x00, 0x00, 0x00, 14 | 0x48, 0x8B, 0x44, 0x24, 0x20, 15 | 0x48, 0x8B, 0x40, 0x08, 0x48, 0x89, 0x44, 0x24, 0x28, 0x45, 0x33, 0xC0, 0xBA, 0x01, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x44, 0x24, 0x20, 16 | 0x48, 0x8B, 17 | 0x48, 0x10, 0xFF, 0x54, 0x24, 0x28, 0x48, 0x8B, 0x44, 0x24, 0x20, 0xC7, 0x00, 0x81, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x38, 0xC3, 0x48, 18 | 0x39, 0xC0, 0x90, 0xCC 19 | }; 20 | 21 | typedef struct _remote_dll { 22 | INT status; 23 | uintptr_t dll_main_address; 24 | HINSTANCE dll_base; 25 | } remote_dll, *premote_dll; 26 | 27 | auto get_nt_headers( const std::uintptr_t image_base ) -> IMAGE_NT_HEADERS * 28 | { 29 | const auto dos_header = reinterpret_cast< IMAGE_DOS_HEADER * > ( image_base ); 30 | 31 | return reinterpret_cast< IMAGE_NT_HEADERS * > ( image_base + dos_header->e_lfanew ); 32 | } 33 | 34 | auto rva_va( const std::uintptr_t rva, IMAGE_NT_HEADERS *nt_header, void *local_image ) -> void * 35 | { 36 | const auto first_section = IMAGE_FIRST_SECTION( nt_header ); 37 | 38 | for ( auto section = first_section; section < first_section + nt_header->FileHeader.NumberOfSections; section++ ) 39 | { 40 | if ( rva >= section->VirtualAddress && rva < section->VirtualAddress + section->Misc.VirtualSize ) 41 | { 42 | return ( unsigned char * )local_image + section->PointerToRawData + ( rva - section->VirtualAddress ); 43 | } 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | auto relocate_image( void *remote_image, void *local_image, IMAGE_NT_HEADERS *nt_header ) -> bool 50 | { 51 | typedef struct _RELOC_ENTRY 52 | { 53 | ULONG ToRVA; 54 | ULONG Size; 55 | struct 56 | { 57 | WORD Offset : 12; 58 | WORD Type : 4; 59 | } Item[1]; 60 | } RELOC_ENTRY, *PRELOC_ENTRY; 61 | 62 | const auto delta_offset = ( std::uintptr_t )remote_image - nt_header->OptionalHeader.ImageBase; 63 | 64 | if ( !delta_offset ) 65 | { 66 | return true; 67 | } 68 | 69 | else if ( !( nt_header->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE ) ) 70 | { 71 | return false; 72 | } 73 | 74 | auto relocation_entry = ( RELOC_ENTRY * )rva_va( nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress, nt_header, local_image ); 75 | const auto relocation_end = ( std::uintptr_t )relocation_entry + nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; 76 | 77 | if ( relocation_entry == nullptr ) 78 | { 79 | return true; 80 | } 81 | 82 | while ( ( std::uintptr_t )relocation_entry < relocation_end && relocation_entry->Size ) 83 | { 84 | auto records_count = ( relocation_entry->Size - 8 ) >> 1; 85 | 86 | for ( auto i = 0ul; i < records_count; i++ ) 87 | { 88 | WORD fixed_type = ( relocation_entry->Item[i].Type ); 89 | WORD shift_delta = ( relocation_entry->Item[i].Offset ) % 4096; 90 | 91 | if ( fixed_type == IMAGE_REL_BASED_ABSOLUTE ) 92 | { 93 | continue; 94 | } 95 | 96 | if ( fixed_type == IMAGE_REL_BASED_HIGHLOW || fixed_type == IMAGE_REL_BASED_DIR64 ) 97 | { 98 | auto fixed_va = ( std::uintptr_t )rva_va( relocation_entry->ToRVA, nt_header, local_image ); 99 | 100 | if ( !fixed_va ) 101 | { 102 | fixed_va = ( std::uintptr_t )local_image; 103 | } 104 | 105 | *( std::uintptr_t * )( fixed_va + shift_delta ) += delta_offset; 106 | } 107 | } 108 | 109 | relocation_entry = ( PRELOC_ENTRY )( ( LPBYTE )relocation_entry + relocation_entry->Size ); 110 | } 111 | 112 | return true; 113 | } 114 | 115 | auto resolve_function_address( LPCSTR module_name, LPCSTR function_name ) -> std::uintptr_t 116 | { 117 | const auto handle = LoadLibraryExA( module_name, nullptr, DONT_RESOLVE_DLL_REFERENCES ); 118 | 119 | const auto offset = ( std::uintptr_t )GetProcAddress( handle, function_name ) - ( std::uintptr_t )handle; 120 | 121 | FreeLibrary( handle ); 122 | 123 | return offset; 124 | } 125 | 126 | auto write_sections( int pid, void *module_base, void *local_image, IMAGE_NT_HEADERS *nt_header ) -> void 127 | { 128 | auto section = IMAGE_FIRST_SECTION( nt_header ); 129 | 130 | for ( WORD count = 0; count < nt_header->FileHeader.NumberOfSections; count++, section++ ) 131 | { 132 | kinterface->write_virtual_memory( pid, ( std::uintptr_t )( ( std::uintptr_t )module_base + section->VirtualAddress ), ( void * )( ( std::uintptr_t )local_image + section->PointerToRawData ), section->SizeOfRawData ); 133 | } 134 | } 135 | 136 | auto resolve_import( void *local_image, IMAGE_NT_HEADERS *nt_header ) -> bool 137 | { 138 | IMAGE_IMPORT_DESCRIPTOR *import_description = ( IMAGE_IMPORT_DESCRIPTOR * )rva_va( nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress, nt_header, local_image ); 139 | 140 | if ( !nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress || !nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size ) 141 | { 142 | return true; 143 | } 144 | 145 | LPSTR module_name = NULL; 146 | 147 | while ( ( module_name = ( LPSTR )rva_va( import_description->Name, nt_header, local_image ) ) ) 148 | { 149 | const auto base_image = ( std::uintptr_t )LoadLibraryA( module_name ); 150 | 151 | if ( !base_image ) 152 | { 153 | return false; 154 | } 155 | 156 | auto import_header_data = ( IMAGE_THUNK_DATA * )rva_va( import_description->FirstThunk, nt_header, local_image ); 157 | 158 | while ( import_header_data->u1.AddressOfData ) 159 | { 160 | if ( import_header_data->u1.Ordinal & IMAGE_ORDINAL_FLAG ) 161 | { 162 | import_header_data->u1.Function = base_image + resolve_function_address( module_name, ( LPCSTR )( import_header_data->u1.Ordinal & 0xFFFF ) ); 163 | } 164 | else 165 | { 166 | IMAGE_IMPORT_BY_NAME *ibn = ( IMAGE_IMPORT_BY_NAME * )rva_va( import_header_data->u1.AddressOfData, nt_header, local_image ); 167 | import_header_data->u1.Function = base_image + resolve_function_address( module_name, ( LPCSTR )ibn->Name ); 168 | } 169 | import_header_data++; 170 | } 171 | import_description++; 172 | } 173 | 174 | return true; 175 | } 176 | 177 | auto erase_discardable_section( int pid, void *module_base, IMAGE_NT_HEADERS *nt_header ) -> void 178 | { 179 | auto section = IMAGE_FIRST_SECTION( nt_header ); 180 | 181 | for ( WORD count = 0; count < nt_header->FileHeader.NumberOfSections; count++, section++ ) 182 | { 183 | if ( section->SizeOfRawData == 0 ) 184 | { 185 | continue; 186 | } 187 | 188 | if ( section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE ) 189 | { 190 | auto zero_memory = VirtualAlloc( 0, section->SizeOfRawData, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); 191 | 192 | kinterface->write_virtual_memory( pid, ( std::uintptr_t )( ( std::uintptr_t )module_base + section->VirtualAddress ), zero_memory, section->SizeOfRawData ); 193 | 194 | VirtualFree( zero_memory, 0, MEM_RELEASE ); 195 | } 196 | } 197 | } 198 | 199 | auto vmt_hook( const int pid, void *base, IMAGE_NT_HEADERS *nt_header ) -> bool 200 | { 201 | const auto shellcode_size = sizeof( remote_call_dll_main ) + sizeof( remote_dll ); 202 | 203 | std::uintptr_t mdl = 0; 204 | const auto shellcode_allocation = kinterface->allocate_kernel_memory( nt_header->OptionalHeader.SizeOfImage, &mdl ); 205 | 206 | if ( !kinterface->expose_kernel_memory( GetCurrentProcessId( ), shellcode_allocation, nt_header->OptionalHeader.SizeOfImage ) ) 207 | { 208 | return false; 209 | } 210 | 211 | if ( !kinterface->expose_kernel_memory( pid, shellcode_allocation, nt_header->OptionalHeader.SizeOfImage ) ) 212 | { 213 | return false; 214 | } 215 | 216 | printf( "exposed kernel memory [shellcode_allocation]: 0x%llx\n", shellcode_allocation ); 217 | 218 | const auto local_allocation = VirtualAlloc( 0, shellcode_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE ); 219 | 220 | memcpy( local_allocation, &remote_call_dll_main, sizeof( remote_call_dll_main ) ); 221 | 222 | const auto shellcode_data = ( std::uintptr_t )shellcode_allocation + sizeof( remote_call_dll_main ); 223 | 224 | memcpy( ( void * )( ( std::uintptr_t )local_allocation + 0x6 ), &shellcode_data, sizeof( std::uintptr_t ) ); 225 | 226 | auto remote = ( remote_dll * )( ( std::uintptr_t )local_allocation + sizeof( remote_call_dll_main ) ); 227 | 228 | remote->dll_base = ( HINSTANCE )base; 229 | 230 | remote->dll_main_address = ( ( std::uintptr_t )base + nt_header->OptionalHeader.AddressOfEntryPoint ); 231 | 232 | if ( !kinterface->write_virtual_memory( pid, ( std::uintptr_t )shellcode_allocation, local_allocation, shellcode_size ) ) 233 | { 234 | return false; 235 | } 236 | 237 | const auto renderer = kinterface->get_module_base( pid, "DiscordHook64.dll" ); 238 | 239 | /* MEDAL.TV 240 | 241 | if ( !renderer ) 242 | { 243 | printf( "renderer not found\n" ); 244 | return false; 245 | } 246 | 247 | auto present_ptr = kinterface->find_signature( pid, renderer, "FF 15 ?? ?? ?? ?? 48 8B 03 48 8B CB FF 50 ?? 8B C6" ); 248 | 249 | if ( !present_ptr ) 250 | { 251 | printf( "present ptr not found\n" ); 252 | return false; 253 | } 254 | 255 | printf( "present_ptr: 0x%llx\n", present_ptr ); 256 | 257 | const auto present_address = present_ptr + kinterface->read_virtual_memory ( pid, present_ptr + 2 ) + 6; 258 | 259 | printf( "present_address: 0x%llx\n", present_address ); 260 | 261 | */ 262 | 263 | const auto present_address = renderer + 0x1B3080; 264 | 265 | const auto old_ptr = kinterface->swap_virtual_pointer( pid, present_address, ( std::uintptr_t )shellcode_allocation ); 266 | 267 | if ( !old_ptr ) 268 | { 269 | return false; 270 | } 271 | 272 | while ( remote->status != 0x81 ) 273 | { 274 | kinterface->read_virtual_memory( pid, ( std::uintptr_t )shellcode_data, remote, sizeof( remote_dll ) ); 275 | } 276 | 277 | if ( !kinterface->swap_virtual_pointer( pid, present_address, old_ptr ) ) 278 | { 279 | return false; 280 | } 281 | 282 | printf( "successfully executed\n" ); 283 | 284 | BYTE null_shellcode[shellcode_size] = { 0 }; 285 | 286 | if ( !kinterface->write_virtual_memory( pid, ( std::uintptr_t )shellcode_allocation, null_shellcode, shellcode_size ) ) 287 | { 288 | return false; 289 | } 290 | 291 | if ( !kinterface->free_virtual_memory( shellcode_allocation, mdl ) ) 292 | { 293 | return false; 294 | } 295 | 296 | VirtualFree( local_allocation, 0, MEM_RELEASE ); 297 | 298 | return true; 299 | } 300 | 301 | public: 302 | 303 | auto map( const int pid, void *buffer ) -> bool 304 | { 305 | const auto nt_header = get_nt_headers( reinterpret_cast< std::uintptr_t > ( buffer ) ); 306 | printf( "nt_headers: 0x%llx\n", nt_header ); 307 | 308 | std::uintptr_t mdl = 0; 309 | const auto base = kinterface->allocate_kernel_memory( nt_header->OptionalHeader.SizeOfImage, &mdl ); 310 | 311 | if ( !base ) 312 | { 313 | printf( "invalid base.\n" ); 314 | return false; 315 | } 316 | 317 | if ( !kinterface->expose_kernel_memory( GetCurrentProcessId( ), base, nt_header->OptionalHeader.SizeOfImage )) 318 | { 319 | printf( "invalid expose 0.\n" ); 320 | return false; 321 | } 322 | 323 | if ( !kinterface->expose_kernel_memory( pid, base, nt_header->OptionalHeader.SizeOfImage ) ) 324 | { 325 | printf( "invalid expose 1.\n" ); 326 | return false; 327 | } 328 | 329 | printf( "exposed kernel memory [base]: 0x%llx\n", base ); 330 | 331 | if ( !relocate_image( base, buffer, nt_header ) ) 332 | { 333 | return false; 334 | } 335 | printf( "relocated image\n" ); 336 | 337 | if ( !resolve_import( buffer, nt_header ) ) 338 | { 339 | return false; 340 | } 341 | printf( "resolved imports\n" ); 342 | 343 | write_sections( pid, base, buffer, nt_header ); 344 | printf( "wrote sections\n" ); 345 | 346 | if ( !vmt_hook( pid, base, nt_header ) ) 347 | { 348 | return false; 349 | } 350 | 351 | printf( "shellcode called\n" ); 352 | 353 | erase_discardable_section( pid, base, nt_header ); 354 | printf( "erased discardable section\n" ); 355 | 356 | VirtualFree( buffer, 0, MEM_RELEASE ); 357 | printf( "cleaning up\n" ); 358 | 359 | return true; 360 | } 361 | }; 362 | 363 | static mmap_t *mmap = new mmap_t( ); -------------------------------------------------------------------------------- /um/um.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 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 16.0 32 | Win32Proj 33 | {c39d3318-ea1d-4d09-bd0f-6ff09cdffda0} 34 | um 35 | 10.0 36 | 37 | 38 | 39 | Application 40 | true 41 | v142 42 | Unicode 43 | 44 | 45 | Application 46 | false 47 | v142 48 | true 49 | Unicode 50 | 51 | 52 | Application 53 | true 54 | v142 55 | MultiByte 56 | 57 | 58 | Application 59 | false 60 | v142 61 | true 62 | MultiByte 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | true 84 | 85 | 86 | false 87 | 88 | 89 | true 90 | $(SolutionDir)bin\ 91 | $(SolutionDir)bin\intermediates\ 92 | $(ProjectName)_x64 93 | 94 | 95 | false 96 | $(SolutionDir)bin\ 97 | $(SolutionDir)bin\intermediates\ 98 | $(ProjectName)_x64 99 | 100 | 101 | 102 | Level3 103 | true 104 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | 107 | 108 | Console 109 | true 110 | 111 | 112 | 113 | 114 | Level3 115 | true 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | true 120 | 121 | 122 | Console 123 | true 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | _DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 133 | true 134 | stdcpp20 135 | stdc17 136 | 137 | 138 | Console 139 | true 140 | RequireAdministrator 141 | 142 | 143 | 144 | 145 | Level3 146 | true 147 | true 148 | true 149 | NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) 150 | true 151 | stdcpp20 152 | stdc17 153 | 154 | 155 | Console 156 | true 157 | true 158 | false 159 | AsInvoker 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /um/um.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /um/um.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /um/utils.h: -------------------------------------------------------------------------------- 1 | namespace utils 2 | { 3 | auto get_process_id( std::string name ) -> int 4 | { 5 | const auto snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); 6 | 7 | PROCESSENTRY32 entry { }; 8 | entry.dwSize = sizeof( PROCESSENTRY32 ); 9 | 10 | Process32First( snapshot, &entry ); 11 | do 12 | { 13 | if ( !name.compare ( entry.szExeFile ) ) 14 | { 15 | return entry.th32ProcessID; 16 | } 17 | 18 | } while ( Process32Next( snapshot, &entry ) ); 19 | } 20 | 21 | auto read_file( const std::string filename ) -> std::vector 22 | { 23 | std::ifstream stream( filename, std::ios::binary ); 24 | 25 | std::vector buffer { }; 26 | 27 | buffer.assign( ( std::istreambuf_iterator( stream ) ), std::istreambuf_iterator( ) ); 28 | 29 | stream.close( ); 30 | 31 | return buffer; 32 | } 33 | } -------------------------------------------------------------------------------- /vmt.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.32413.511 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "um", "um\um.vcxproj", "{C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "km", "km\km.vcxproj", "{4C4C54E5-C199-4146-B5D7-FDDC9FE74066}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Debug|x64.ActiveCfg = Debug|x64 19 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Debug|x64.Build.0 = Debug|x64 20 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Debug|x86.ActiveCfg = Debug|Win32 21 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Debug|x86.Build.0 = Debug|Win32 22 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Release|x64.ActiveCfg = Release|x64 23 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Release|x64.Build.0 = Release|x64 24 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Release|x86.ActiveCfg = Release|Win32 25 | {C39D3318-EA1D-4D09-BD0F-6FF09CDFFDA0}.Release|x86.Build.0 = Release|Win32 26 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Debug|x64.ActiveCfg = Debug|x64 27 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Debug|x64.Build.0 = Debug|x64 28 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Debug|x86.ActiveCfg = Debug|Win32 29 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Debug|x86.Build.0 = Debug|Win32 30 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Release|x64.ActiveCfg = Release|x64 31 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Release|x64.Build.0 = Release|x64 32 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Release|x64.Deploy.0 = Release|x64 33 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Release|x86.ActiveCfg = Release|Win32 34 | {4C4C54E5-C199-4146-B5D7-FDDC9FE74066}.Release|x86.Build.0 = Release|Win32 35 | EndGlobalSection 36 | GlobalSection(SolutionProperties) = preSolution 37 | HideSolutionNode = FALSE 38 | EndGlobalSection 39 | GlobalSection(ExtensibilityGlobals) = postSolution 40 | SolutionGuid = {90F2CE61-7D32-4CDF-9E37-281424E443B7} 41 | EndGlobalSection 42 | EndGlobal 43 | --------------------------------------------------------------------------------