├── README.md ├── commandsOffsets.h ├── RealExtern.vcxproj.user ├── RealExtern.vcxproj.filters ├── RealExtern.inf ├── RealExtern.sln ├── kdmapperTraces.h ├── RealExtern.vcxproj ├── Driver.cpp ├── Undocumented.h └── KernelUtils.h /README.md: -------------------------------------------------------------------------------- 1 | # What this is for: 2 | 3 | This is a simple kernel driver for reading / writing process memory, it uses IOCTL communication, in case someone claims IOCTL communication is detected: byte patch a part of the ioctl function with a jmp I described that better in the source itself. 4 | 5 | # Note: 6 | This driver won't work on every Winver, until you update the memory addresses for it in the source code itself. Offsets that need to be changed are located in disk.sys, “ULONG64 hook Location = (ULONG64)diskSysBase + 0x32A2;” and “ ULONG64 returnPlaceOfIOCTL = (ULONG64)diskSysBase + 0x16AF; “. This is intended to be manually mapped. 7 | -------------------------------------------------------------------------------- /commandsOffsets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Undocumented.h" 4 | 5 | 6 | 7 | 8 | struct communicationStruct 9 | { 10 | DWORD64 address; 11 | DWORD commandID; 12 | DWORD64 processID; 13 | DWORD size; 14 | const UCHAR buffer[25]; 15 | char section[10]; 16 | char wildCard; 17 | BOOLEAN dataOnly; 18 | wchar_t targetmoduleName[20]; 19 | wchar_t currentmoduleName[20]; 20 | }; 21 | 22 | 23 | 24 | /* super important info!!!! 1137!!! */ 25 | ULONG64 interceptedIRP = (ULONG64)0x5555; 26 | communicationStruct* SystemBuffer; 27 | PEPROCESS TargetProcess; 28 | DWORD64 ClientBaseAddress = 0; 29 | DWORD64 GameBaseAddress = 0; 30 | static DWORD64 readOutputAddress; // for sending data to usermode 31 | PEPROCESS clientProcess; 32 | 33 | const int sigScanCommand = 120; 34 | const int CleanTraces = 3121; 35 | const int ReadMemoryCommand = 244; 36 | const int WriteMemorycommand = 384; 37 | const int initProcessInfoCommand = 943; 38 | const int exitProcess = 666; 39 | const int resolveAddressCommand = 23; 40 | const int testCommand = 304; -------------------------------------------------------------------------------- /RealExtern.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Off 5 | New Computer 6 | 7 | 8 | New Computer 9 | 10 | 11 | New Computer 12 | 13 | 14 | New Computer 15 | 16 | 17 | New Computer 18 | 19 | 20 | New Computer 21 | 22 | 23 | New Computer 24 | 25 | 26 | New Computer 27 | 28 | -------------------------------------------------------------------------------- /RealExtern.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 | {8E41214B-6785-4CFE-B992-037D68949A14} 18 | inf;inv;inx;mof;mc; 19 | 20 | 21 | 22 | 23 | Driver Files 24 | 25 | 26 | 27 | 28 | Source Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | Source Files 43 | 44 | 45 | -------------------------------------------------------------------------------- /RealExtern.inf: -------------------------------------------------------------------------------- 1 | ; 2 | ; RealExtern.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=RealExtern.cat 11 | DriverVer= ; TODO: set DriverVer in stampinf property pages 12 | 13 | [DestinationDirs] 14 | DefaultDestDir = 12 15 | RealExtern_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 | RealExtern.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 | %RealExtern.DeviceDesc%=RealExtern_Device, Root\RealExtern ; TODO: edit hw-id 42 | 43 | [RealExtern_Device.NT] 44 | CopyFiles=Drivers_Dir 45 | 46 | [Drivers_Dir] 47 | RealExtern.sys 48 | 49 | ;-------------- Service installation 50 | [RealExtern_Device.NT.Services] 51 | AddService = RealExtern,%SPSVCINST_ASSOCSERVICE%, RealExtern_Service_Inst 52 | 53 | ; -------------- RealExtern driver install sections 54 | [RealExtern_Service_Inst] 55 | DisplayName = %RealExtern.SVCDESC% 56 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER 57 | StartType = 3 ; SERVICE_DEMAND_START 58 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL 59 | ServiceBinary = %12%\RealExtern.sys 60 | 61 | ; 62 | ;--- RealExtern_Device Coinstaller installation ------ 63 | ; 64 | 65 | [RealExtern_Device.NT.CoInstallers] 66 | AddReg=RealExtern_Device_CoInstaller_AddReg 67 | CopyFiles=RealExtern_Device_CoInstaller_CopyFiles 68 | 69 | [RealExtern_Device_CoInstaller_AddReg] 70 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller" 71 | 72 | [RealExtern_Device_CoInstaller_CopyFiles] 73 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll 74 | 75 | [RealExtern_Device.NT.Wdf] 76 | KmdfService = RealExtern, RealExtern_wdfsect 77 | [RealExtern_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 = "RealExtern Installation Disk" 85 | RealExtern.DeviceDesc = "RealExtern Device" 86 | RealExtern.SVCDESC = "RealExtern Service" 87 | -------------------------------------------------------------------------------- /RealExtern.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30128.74 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RealExtern", "RealExtern.vcxproj", "{3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}" 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 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|ARM.ActiveCfg = Debug|ARM 21 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|ARM.Build.0 = Debug|ARM 22 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|ARM.Deploy.0 = Debug|ARM 23 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|ARM64.ActiveCfg = Debug|ARM64 24 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|ARM64.Build.0 = Debug|ARM64 25 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|ARM64.Deploy.0 = Debug|ARM64 26 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|x64.ActiveCfg = Debug|x64 27 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|x64.Build.0 = Debug|x64 28 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|x64.Deploy.0 = Debug|x64 29 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|x86.ActiveCfg = Debug|Win32 30 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|x86.Build.0 = Debug|Win32 31 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Debug|x86.Deploy.0 = Debug|Win32 32 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|ARM.ActiveCfg = Release|ARM 33 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|ARM.Build.0 = Release|ARM 34 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|ARM.Deploy.0 = Release|ARM 35 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|ARM64.ActiveCfg = Release|ARM64 36 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|ARM64.Build.0 = Release|ARM64 37 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|ARM64.Deploy.0 = Release|ARM64 38 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|x64.ActiveCfg = Release|x64 39 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|x64.Build.0 = Release|x64 40 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|x64.Deploy.0 = Release|x64 41 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|x86.ActiveCfg = Release|Win32 42 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|x86.Build.0 = Release|Win32 43 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9}.Release|x86.Deploy.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {9B6ECC2A-4B26-4079-AAB7-A48D63CC538F} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /kdmapperTraces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "KernelUtils.h" 4 | 5 | BOOLEAN IsUnloadedDriverEntryEmpty( 6 | _In_ PMM_UNLOADED_DRIVER Entry 7 | ) 8 | { 9 | if (Entry->Name.MaximumLength == 0 || 10 | Entry->Name.Length == 0 || 11 | Entry->Name.Buffer == NULL) 12 | { 13 | return TRUE; 14 | } 15 | 16 | return FALSE; 17 | } 18 | 19 | UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"iqvw64e.sys"); 20 | UNICODE_STRING NewDriverName = RTL_CONSTANT_STRING(L"ddlpqgz.sys"); 21 | 22 | 23 | PMM_UNLOADED_DRIVER MmUnloadedDrivers; 24 | PULONG MmLastUnloadedDriver; 25 | UCHAR MmUnloadedDriverSig[] = "\x4C\x8B\x00\x00\x00\x00\x00\x4C\x8B\xC9\x4D\x85\x00\x74"; 26 | 27 | NTSTATUS findMMunloadedDrivers() 28 | { 29 | PVOID MmUnloadedDriversPtr = NULL; 30 | 31 | NTSTATUS status = BBScanSection("PAGE", MmUnloadedDriverSig, 0x00, sizeof(MmUnloadedDriverSig) - 1, (PVOID*)(&MmUnloadedDriversPtr)); 32 | if (!NT_SUCCESS(status)) { 33 | DbgPrint("Unable to find MmUnloadedDriver sig %p\n", MmUnloadedDriversPtr); 34 | return FALSE; 35 | } 36 | DbgPrint("MmUnloadedDriversPtr address found: %p \n", MmUnloadedDriversPtr); 37 | 38 | 39 | MmUnloadedDrivers = *(PMM_UNLOADED_DRIVER*)ResolveRelativeAddress(MmUnloadedDriversPtr, 3, 7); 40 | //REAL REAL mmunloadeddrivers 41 | DbgPrint("MmUnloadedDrivers real location is: %p\n", &MmUnloadedDrivers); 42 | 43 | return status; 44 | } 45 | 46 | 47 | 48 | 49 | 50 | 51 | UCHAR PiDDBLockPtr_sig[] = "\x48\x8D\x0D\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x4C\x8B\x8C"; 52 | UCHAR PiDDBCacheTablePtr_sig[] = "\x66\x03\xD2\x48\x8D\x0D"; 53 | 54 | bool LocatePiDDB(PERESOURCE* lock, PRTL_AVL_TABLE* table) 55 | { 56 | PVOID PiDDBLockPtr = nullptr, PiDDBCacheTablePtr = nullptr; 57 | if (!NT_SUCCESS(BBScanSection("PAGE", PiDDBLockPtr_sig, 0, sizeof(PiDDBLockPtr_sig) - 1, reinterpret_cast(&PiDDBLockPtr)))) { 58 | DbgPrint("Unable to find PiDDBLockPtr sig. Piddblockptr is: %p.\n", PiDDBLockPtr); 59 | return false; 60 | } 61 | DbgPrint("found PiDDBLockPtr sig. Piddblockptr is: %p\n", PiDDBLockPtr); 62 | 63 | if (!NT_SUCCESS(BBScanSection("PAGE", PiDDBCacheTablePtr_sig, 0, sizeof(PiDDBCacheTablePtr_sig) - 1, reinterpret_cast(&PiDDBCacheTablePtr)))) { 64 | DbgPrint("Unable to find PiDDBCacheTablePtr sig. PiDDBCacheTablePtr is: %p\n", PiDDBCacheTablePtr); 65 | return false; 66 | } 67 | DbgPrint("found PiDDBCacheTablePtr sig. PiDDBCacheTablePtr is: %p\n", PiDDBCacheTablePtr); 68 | 69 | 70 | PiDDBCacheTablePtr = PVOID((uintptr_t)PiDDBCacheTablePtr + 3); 71 | 72 | *lock = (PERESOURCE)(ResolveRelativeAddress(PiDDBLockPtr, 3, 7)); 73 | *table = (PRTL_AVL_TABLE)(ResolveRelativeAddress(PiDDBCacheTablePtr, 3, 7)); 74 | 75 | return true; 76 | } 77 | 78 | 79 | 80 | 81 | 82 | BOOLEAN ClearPiddbCacheTable() 83 | { 84 | PERESOURCE PiDDBLock = NULL; 85 | PRTL_AVL_TABLE PiDDBCacheTable = NULL; 86 | NTSTATUS Status = LocatePiDDB(&PiDDBLock, &PiDDBCacheTable); 87 | if (PiDDBCacheTable == NULL || PiDDBLock == NULL) 88 | { 89 | DbgPrint("LocatePIDDB lock and/or cachetable not found\n"); 90 | return Status; 91 | } 92 | else 93 | { 94 | DbgPrint("Successfully found PiddbCachetable and lock!!!1111\n"); 95 | DbgPrint("PiddbLock: %p\n", PiDDBLock); 96 | DbgPrint("PiddbCacheTable: %p\n", PiDDBCacheTable); 97 | 98 | PIDCacheobj Entry; 99 | UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"iqvw64e.sys"); 100 | Entry.DriverName = DriverName; 101 | Entry.TimeDateStamp = 0x5284EAC3; 102 | ExAcquireResourceExclusiveLite(PiDDBLock, TRUE); 103 | PIDCacheobj* pFoundEntry = (PIDCacheobj*)RtlLookupElementGenericTableAvl(PiDDBCacheTable, &Entry); 104 | 105 | if (pFoundEntry == NULL) 106 | { 107 | DbgPrint("pFoundEntry not found !!!\n"); 108 | // release ddb resource lock 109 | ExReleaseResourceLite(PiDDBLock); 110 | return FALSE; 111 | } 112 | else 113 | { 114 | DbgPrint("Found iqvw64e.sys in PiDDBCachetable!!\n"); 115 | //unlink from list 116 | RemoveEntryList(&pFoundEntry->List); 117 | RtlDeleteElementGenericTableAvl(PiDDBCacheTable, pFoundEntry); 118 | // release the ddb resource lock 119 | ExReleaseResourceLite(PiDDBLock); 120 | DbgPrint("Clear success and finish !!!\n"); 121 | return TRUE; 122 | } 123 | 124 | } 125 | } 126 | 127 | 128 | 129 | BOOLEAN isMmUnloadedDriversFilled() 130 | { 131 | PMM_UNLOADED_DRIVER entry; 132 | for (ULONG Index = 0; Index < MM_UNLOADED_DRIVERS_SIZE; ++Index) 133 | { 134 | entry = &MmUnloadedDrivers[Index]; 135 | if (entry->Name.Buffer == NULL || entry->Name.Length == 0 || entry->Name.MaximumLength == 0) 136 | { 137 | return FALSE; 138 | } 139 | 140 | } 141 | return TRUE; 142 | } 143 | 144 | 145 | 146 | 147 | BOOLEAN cleanUnloadedDriverString() 148 | { 149 | findMMunloadedDrivers(); 150 | BOOLEAN cleared = FALSE; 151 | BOOLEAN Filled = isMmUnloadedDriversFilled(); 152 | 153 | DbgPrint("about to clear mmunload\n"); 154 | 155 | for (ULONG Index = 0; Index < MM_UNLOADED_DRIVERS_SIZE; ++Index) 156 | { 157 | 158 | 159 | PMM_UNLOADED_DRIVER Entry = &MmUnloadedDrivers[Index]; 160 | 161 | if (RtlCompareUnicodeString(&DriverName, &Entry->Name, TRUE)) 162 | { 163 | if (Index == 0) 164 | { 165 | RtlZeroMemory(Entry, sizeof(MM_UNLOADED_DRIVER)); 166 | } 167 | else 168 | { 169 | //random 7 letter name 170 | RtlCopyUnicodeString(&Entry->Name, &NewDriverName); 171 | Entry->UnloadTime = MmUnloadedDrivers[Index - 1].UnloadTime - 50; 172 | 173 | DbgPrint("DONE randomizing name inside CleanUnloadedDriverString\n"); 174 | } 175 | return TRUE; 176 | } 177 | } 178 | DbgPrint("cannot find iqvw64e.sys!!!!111 cleanunloadeddriverstring fail!!1111\n"); 179 | 180 | return FALSE; 181 | } 182 | 183 | 184 | BOOLEAN clearKdmapperTraces() 185 | { 186 | BOOLEAN status; 187 | status = cleanUnloadedDriverString(); 188 | if (status == FALSE) 189 | { 190 | DbgPrint("problem with mmunloadeddrivers\n"); 191 | } 192 | status = ClearPiddbCacheTable(); 193 | if (status == FALSE) 194 | { 195 | DbgPrint("problem with PiddbCacheTable\n"); 196 | } 197 | return status; 198 | } -------------------------------------------------------------------------------- /RealExtern.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 | {3C45CB8A-8CD5-4DF9-89EE-D347F34D3DE9} 39 | {1bc93793-694f-48fe-9372-81e2b05556fd} 40 | v4.5 41 | 12.0 42 | Debug 43 | Win32 44 | RealExtern 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 | KMDF 69 | Universal 70 | 71 | 72 | Windows10 73 | false 74 | WindowsKernelModeDriver10.0 75 | Driver 76 | KMDF 77 | Universal 78 | 79 | 80 | Windows10 81 | true 82 | WindowsKernelModeDriver10.0 83 | Driver 84 | KMDF 85 | Universal 86 | 87 | 88 | Windows10 89 | false 90 | WindowsKernelModeDriver10.0 91 | Driver 92 | KMDF 93 | Universal 94 | 95 | 96 | Windows10 97 | true 98 | WindowsKernelModeDriver10.0 99 | Driver 100 | KMDF 101 | Universal 102 | 103 | 104 | Windows10 105 | false 106 | WindowsKernelModeDriver10.0 107 | Driver 108 | KMDF 109 | Universal 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | DbgengKernelDebugger 121 | 122 | 123 | DbgengKernelDebugger 124 | 125 | 126 | DbgengKernelDebugger 127 | 128 | 129 | DbgengKernelDebugger 130 | 131 | 132 | DbgengKernelDebugger 133 | 134 | 135 | DbgengKernelDebugger 136 | 137 | 138 | DbgengKernelDebugger 139 | 140 | 141 | DbgengKernelDebugger 142 | 143 | 144 | 145 | false 146 | false 147 | TurnOffAllWarnings 148 | false 149 | 150 | 151 | DriverA 152 | 153 | 154 | 155 | 156 | false 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /Driver.cpp: -------------------------------------------------------------------------------- 1 | #include "KernelUtils.h" 2 | #include "kdmapperTraces.h" 3 | #include "commandsOffsets.h" 4 | 5 | 6 | 7 | 8 | DWORD64 initProcess(HANDLE processID, HANDLE clientProcessID, communicationStruct* systemBuffer) /* setup required info (and sig scan), find read output buffer */ 9 | { 10 | PsLookupProcessByProcessId(processID, &TargetProcess); 11 | PsLookupProcessByProcessId(clientProcessID, &clientProcess); 12 | 13 | 14 | // get address of output buffer 15 | BOOLEAN isWow64 = (PsGetProcessWow64Process(TargetProcess) != NULL) ? TRUE : FALSE; 16 | UNICODE_STRING clientprocessName; 17 | RtlInitUnicodeString(&clientprocessName, systemBuffer->currentmoduleName); 18 | 19 | DWORD64 gameBaseAddress = 0; 20 | BOOLEAN isclientWow64 = (PsGetProcessWow64Process(clientProcess) != NULL) ? TRUE : FALSE; 21 | UNICODE_STRING processName; 22 | 23 | RtlInitUnicodeString(&processName, systemBuffer->targetmoduleName); 24 | 25 | 26 | KAPC_STATE apc; 27 | KeStackAttachProcess(TargetProcess, &apc); 28 | 29 | 30 | gameBaseAddress = (ULONG64)GetUserModule(TargetProcess, &processName, isWow64); 31 | GameBaseAddress = gameBaseAddress; 32 | 33 | 34 | KeUnstackDetachProcess(&apc); 35 | 36 | if (gameBaseAddress == 0) 37 | { 38 | gameBaseAddress = 0x400000; 39 | } 40 | 41 | KeStackAttachProcess(clientProcess, &apc); 42 | 43 | 44 | DWORD64 clientBaseAddress = (ULONG64)GetUserModule(clientProcess, &clientprocessName, isclientWow64); //BSOD (sometimes) 45 | 46 | ClientBaseAddress = clientBaseAddress; 47 | 48 | UCHAR pattern[] = { 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4, 0x4 }; 49 | UINT64 realPattern = 0xFFFF8F08F280E084; 50 | RtlCopyMemory(pattern, (PVOID64)&realPattern, sizeof(UINT64)); 51 | BBScanSection(".data", pattern, 0xCC, sizeof(UINT64), reinterpret_cast(&readOutputAddress), (PVOID64)ClientBaseAddress, TRUE); 52 | 53 | readOutputAddress += 8; 54 | 55 | RtlCopyMemory(&readOutputAddress, (PVOID64)readOutputAddress, sizeof(DWORD64)); 56 | 57 | DbgPrint("initProcess(): Buffer Address is: %p \n", readOutputAddress); 58 | 59 | RtlCopyMemory((PVOID64)readOutputAddress, &GameBaseAddress, sizeof(GameBaseAddress)); 60 | 61 | 62 | KeUnstackDetachProcess(&apc); 63 | 64 | ClientBaseAddress = clientBaseAddress; 65 | 66 | DbgPrint("reached 1 \n"); 67 | 68 | return gameBaseAddress; 69 | } 70 | 71 | void exitProcessFunction() 72 | { 73 | if (clientProcess) 74 | { 75 | ObDereferenceObject(clientProcess); 76 | } 77 | if (TargetProcess) 78 | { 79 | ObDereferenceObject(TargetProcess); 80 | } 81 | } 82 | 83 | 84 | void EVERYTHINGhandler(communicationStruct* SystemBuffer) 85 | { 86 | SystemBuffer = (communicationStruct*)(((PIRP)interceptedIRP)->AssociatedIrp.SystemBuffer); 87 | 88 | DWORD64 result; 89 | KFLOATING_SAVE saveData; 90 | KAPC_STATE apcState; 91 | KeSaveFloatingPointState(&saveData); 92 | switch (SystemBuffer->commandID) 93 | { 94 | case CleanTraces: 95 | clearKdmapperTraces(); /* clear traces */ 96 | break; 97 | case ReadMemoryCommand: 98 | ReadMemory(SystemBuffer->address, (PVOID)&SystemBuffer->buffer, SystemBuffer->size, TargetProcess, clientProcess, (PVOID)readOutputAddress); /* Read memory */ 99 | break; 100 | case WriteMemorycommand: 101 | WriteMemory(SystemBuffer->address, (PVOID)&SystemBuffer->buffer, SystemBuffer->size, TargetProcess); /* Write memory */ 102 | break; 103 | case initProcessInfoCommand: 104 | GameBaseAddress = initProcess((HANDLE)SystemBuffer->processID, (HANDLE)SystemBuffer->address, SystemBuffer); 105 | break; /* setup required info (and sig scan) */ 106 | case sigScanCommand: 107 | 108 | KeStackAttachProcess(TargetProcess, &apcState); 109 | BBScanSection(SystemBuffer->section, SystemBuffer->buffer, SystemBuffer->wildCard, SystemBuffer->size, 110 | (PVOID64*)&SystemBuffer->address, (PVOID64)GameBaseAddress, SystemBuffer->dataOnly); 111 | KeUnstackDetachProcess(&apcState); 112 | 113 | WriteMemory(readOutputAddress, &SystemBuffer->address, sizeof(DWORD64), clientProcess); 114 | break; 115 | case resolveAddressCommand: 116 | KeStackAttachProcess(TargetProcess, &apcState); 117 | result = (DWORD64)ResolveRelativeAddress((PVOID)SystemBuffer->address, *(int*)(SystemBuffer->buffer), SystemBuffer->size); 118 | KeUnstackDetachProcess(&apcState); 119 | WriteMemory(readOutputAddress, &result, sizeof(DWORD64), clientProcess); 120 | break; 121 | case testCommand: 122 | DbgPrint("test command called\n"); 123 | break; 124 | case exitProcess: 125 | exitProcessFunction(); 126 | break; 127 | default: 128 | break; 129 | } 130 | 131 | KeRestoreFloatingPointState(&saveData); 132 | return; 133 | } 134 | 135 | 136 | #pragma optimize("", off) 137 | // handles EVERY COMMAND 138 | void EVERYTHING() 139 | { 140 | 141 | // here we get command from IRP system buffer (RSI) 142 | int a1 = 5; 143 | int a2 = 5; 144 | int a3 = 5; // 32 free bytes 145 | int a4 = 5; 146 | 147 | EVERYTHINGhandler(SystemBuffer); 148 | 149 | // hook my own function like a nigga because microsoft wont let me use inline asm 150 | // padding for the shellcode 151 | int a5 = 5; 152 | int a6 = 5; // 32 free bytes 153 | int a7 = 5; 154 | int a8 = 5; 155 | DbgPrint("EVERYTHING failed to return\n"); 156 | } 157 | #pragma optimize("", on) 158 | 159 | 160 | 161 | 162 | 163 | 164 | // hook my own function like a nigga because microsoft wont let me use inline asm 165 | BOOLEAN PlaceEverythingHook() 166 | { 167 | ULONG diskSysSize; 168 | PVOID diskSysBase = getDiskSysBase(&diskSysSize); 169 | 170 | ULONG64 returnPlaceOfIOCTL = (ULONG64)diskSysBase + 0x112E; 171 | 172 | //grab values from rsi and r14 (device object and pirp) 173 | 174 | ULONG64 handlerPointer = (ULONG64)(PVOID64)EVERYTHING; 175 | handlerPointer += 48; //skip past dbgprint 176 | 177 | UCHAR shellCode[] = "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xE0"; 178 | 179 | ULONG64 jumpAddress = (ULONG64)(PVOID64)returnPlaceOfIOCTL; 180 | 181 | memcpy(shellCode + 2, &jumpAddress, 8); // copy address into shellcode 182 | 183 | 184 | 185 | 186 | 187 | 188 | /* 189 | get value from r14 and pop into interceptedIRP variable 190 | 14 bytes required 191 | 192 | 41 56 push r14 193 | 48 b8 00 00 00 00 00 00 00 00 mov rax, &interceptedIRP 194 | 8f 00 pop[rax] 195 | */ 196 | 197 | 198 | UCHAR shellCodeForR14[] = "\x56\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x00\x8f\x00\x90\x90"; 199 | PVOID64 iinterceptedIRP = &interceptedIRP; 200 | memcpy(shellCodeForR14 + 3, (PVOID64)(&iinterceptedIRP), 8); //has to be 3 if its push rsi 201 | 202 | DbgPrint("address of intercepted IRP pointer is: %p \n", (ULONG64)&interceptedIRP); 203 | 204 | if (MmIsAddressValid((PVOID)handlerPointer) && MmIsAddressValid((PVOID)(handlerPointer + sizeof(shellCode) - 1))) 205 | { 206 | KIRQL tempirql = KeRaiseIrqlToDpcLevel(); 207 | 208 | ULONG64 cr0 = __readcr0(); 209 | 210 | cr0 &= 0xfffffffffffeffff; 211 | 212 | __writecr0(cr0); 213 | 214 | _disable(); 215 | 216 | RtlCopyMemory((PVOID)handlerPointer, shellCode, 12); 217 | 218 | handlerPointer = (ULONG64)(PVOID64)EVERYTHING; 219 | 220 | handlerPointer += 21; // should be 20 if it is push r14, 21 if its push rsi 221 | 222 | RtlCopyMemory((PVOID)handlerPointer, shellCodeForR14, sizeof(shellCodeForR14) - 1); 223 | cr0 = __readcr0(); 224 | 225 | cr0 |= 0x10000; 226 | 227 | _enable(); 228 | 229 | __writecr0(cr0); 230 | 231 | KeLowerIrql(tempirql); 232 | } 233 | return TRUE; 234 | 235 | 236 | } 237 | 238 | 239 | 240 | BOOLEAN PlaceDiskHook() 241 | { 242 | // Setup all the require info 243 | 244 | ULONG diskSysSize; 245 | PVOID diskSysBase = getDiskSysBase(&diskSysSize); 246 | 247 | 248 | 249 | //DiskIoctlVerify 250 | ULONG64 hookLocation = (ULONG64)diskSysBase + 0x2D90; 251 | 252 | 253 | // "\x48\xB8" EVERYTHING address "\xFF\xE0"; 254 | //mov rax, EVERYTHING 255 | //jmp rax 256 | 257 | 258 | BYTE shellCode[] = { 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0 }; 259 | 260 | ULONG64 jumpAddress = (ULONG64)(PVOID64)EVERYTHING; 261 | jumpAddress += 21; // skip sub rsp and padding (should be 20 if you push r14 instead) 262 | 263 | memcpy(shellCode + 2, &jumpAddress, 8); 264 | 265 | 266 | 267 | //for now we will write without using write function because we don't want to attach to any process 268 | 269 | if (MmIsAddressValid((PVOID)hookLocation) && MmIsAddressValid((PVOID)(hookLocation + sizeof(shellCode) - 1))) 270 | { 271 | KIRQL tempirql = KeRaiseIrqlToDpcLevel(); 272 | 273 | ULONG64 cr0 = __readcr0(); 274 | 275 | cr0 &= 0xfffffffffffeffff; 276 | 277 | __writecr0(cr0); 278 | 279 | _disable(); 280 | 281 | RtlCopyMemory((PVOID64)hookLocation, shellCode, 12); 282 | 283 | cr0 = __readcr0(); 284 | 285 | cr0 |= 0x10000; 286 | 287 | _enable(); 288 | 289 | __writecr0(cr0); 290 | 291 | KeLowerIrql(tempirql); 292 | } 293 | return TRUE; 294 | 295 | } 296 | 297 | 298 | 299 | /* 300 | loc_2D90: 301 | 48 8B D6 mov rdx, rsi 302 | 49 8B CE mov rcx, r14 ; DeviceObject 303 | E8 C9 15 00 00 call DiskIoctlVerify 304 | 90 nop 305 | E9 8D E3 FF FF jmp loc_112E 306 | */ 307 | 308 | extern "C" 309 | NTSTATUS DriverEntry(_In_ _DRIVER_OBJECT * DriverObject, _In_ PUNICODE_STRING RegistryPath) 310 | { 311 | NTSTATUS Status = STATUS_SUCCESS; 312 | UNREFERENCED_PARAMETER(DriverObject); 313 | UNREFERENCED_PARAMETER(RegistryPath); 314 | ULONG sizeOfModule; 315 | PlaceDiskHook(); 316 | PlaceEverythingHook(); 317 | return Status; 318 | } 319 | 320 | 321 | 322 | NTSTATUS DriverA(_In_ _DRIVER_OBJECT* DriverObject, _In_ PUNICODE_STRING RegistryPath) 323 | { 324 | DbgPrint("driver start \n"); 325 | NTSTATUS Status = STATUS_SUCCESS; 326 | BOOLEAN ClearStatus; 327 | 328 | 329 | UNREFERENCED_PARAMETER(DriverObject); 330 | UNREFERENCED_PARAMETER(RegistryPath); 331 | DriverEntry(NULL, NULL); 332 | return Status; 333 | } 334 | -------------------------------------------------------------------------------- /Undocumented.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | 10 | #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 11 | 12 | #define FLT_MAX 3.402823466e+38F /* max value */ 13 | extern "C" int _fltused = 0; 14 | 15 | 16 | 17 | extern "C" __declspec(dllimport) 18 | NTSTATUS NTAPI MmCopyVirtualMemory 19 | ( 20 | PEPROCESS SourceProcess, 21 | PVOID SourceAddress, 22 | PEPROCESS TargetProcess, 23 | PVOID TargetAddress, 24 | SIZE_T BufferSize, 25 | KPROCESSOR_MODE PreviousMode, 26 | PSIZE_T ReturnSize 27 | ); 28 | 29 | typedef struct _IMAGE_DATA_DIRECTORY 30 | { 31 | ULONG VirtualAddress; 32 | ULONG Size; 33 | } IMAGE_DATA_DIRECTORY, * PIMAGE_DATA_DIRECTORY; 34 | 35 | 36 | 37 | typedef enum _SYSTEM_INFORMATION_CLASS 38 | { 39 | SystemBasicInformation = 0, 40 | SystemProcessorInformation = 1, // obsolete...delete 41 | SystemPerformanceInformation = 2, 42 | SystemTimeOfDayInformation = 3, 43 | SystemPathInformation = 4, 44 | SystemProcessInformation = 5, 45 | SystemCallCountInformation = 6, 46 | SystemDeviceInformation = 7, 47 | SystemProcessorPerformanceInformation = 8, 48 | SystemFlagsInformation = 9, 49 | SystemCallTimeInformation = 10, 50 | SystemModuleInformation = 11, 51 | SystemLocksInformation = 12, 52 | SystemStackTraceInformation = 13, 53 | SystemPagedPoolInformation = 14, 54 | SystemNonPagedPoolInformation = 15, 55 | SystemHandleInformation = 16, 56 | SystemObjectInformation = 17, 57 | SystemPageFileInformation = 18, 58 | SystemVdmInstemulInformation = 19, 59 | SystemVdmBopInformation = 20, 60 | SystemFileCacheInformation = 21, 61 | SystemPoolTagInformation = 22, 62 | SystemInterruptInformation = 23, 63 | SystemDpcBehaviorInformation = 24, 64 | SystemFullMemoryInformation = 25, 65 | SystemLoadGdiDriverInformation = 26, 66 | SystemUnloadGdiDriverInformation = 27, 67 | SystemTimeAdjustmentInformation = 28, 68 | SystemSummaryMemoryInformation = 29, 69 | SystemMirrorMemoryInformation = 30, 70 | SystemPerformanceTraceInformation = 31, 71 | SystemObsolete0 = 32, 72 | SystemExceptionInformation = 33, 73 | SystemCrashDumpStateInformation = 34, 74 | SystemKernelDebuggerInformation = 35, 75 | SystemContextSwitchInformation = 36, 76 | SystemRegistryQuotaInformation = 37, 77 | SystemExtendServiceTableInformation = 38, 78 | SystemPrioritySeperation = 39, 79 | SystemVerifierAddDriverInformation = 40, 80 | SystemVerifierRemoveDriverInformation = 41, 81 | SystemProcessorIdleInformation = 42, 82 | SystemLegacyDriverInformation = 43, 83 | SystemCurrentTimeZoneInformation = 44, 84 | SystemLookasideInformation = 45, 85 | SystemTimeSlipNotification = 46, 86 | SystemSessionCreate = 47, 87 | SystemSessionDetach = 48, 88 | SystemSessionInformation = 49, 89 | SystemRangeStartInformation = 50, 90 | SystemVerifierInformation = 51, 91 | SystemVerifierThunkExtend = 52, 92 | SystemSessionProcessInformation = 53, 93 | SystemLoadGdiDriverInSystemSpace = 54, 94 | SystemNumaProcessorMap = 55, 95 | SystemPrefetcherInformation = 56, 96 | SystemExtendedProcessInformation = 57, 97 | SystemRecommendedSharedDataAlignment = 58, 98 | SystemComPlusPackage = 59, 99 | SystemNumaAvailableMemory = 60, 100 | SystemProcessorPowerInformation = 61, 101 | SystemEmulationBasicInformation = 62, 102 | SystemEmulationProcessorInformation = 63, 103 | SystemExtendedHandleInformation = 64, 104 | SystemLostDelayedWriteInformation = 65, 105 | SystemBigPoolInformation = 66, 106 | SystemSessionPoolTagInformation = 67, 107 | SystemSessionMappedViewInformation = 68, 108 | SystemHotpatchInformation = 69, 109 | SystemObjectSecurityMode = 70, 110 | SystemWatchdogTimerHandler = 71, 111 | SystemWatchdogTimerInformation = 72, 112 | SystemLogicalProcessorInformation = 73, 113 | SystemWow64SharedInformation = 74, 114 | SystemRegisterFirmwareTableInformationHandler = 75, 115 | SystemFirmwareTableInformation = 76, 116 | SystemModuleInformationEx = 77, 117 | SystemVerifierTriageInformation = 78, 118 | SystemSuperfetchInformation = 79, 119 | SystemMemoryListInformation = 80, 120 | SystemFileCacheInformationEx = 81, 121 | MaxSystemInfoClass = 82 // MaxSystemInfoClass should always be the last enum 122 | 123 | } SYSTEM_INFORMATION_CLASS; 124 | 125 | 126 | typedef struct _SYSTEM_THREADS 127 | { 128 | LARGE_INTEGER KernelTime; 129 | LARGE_INTEGER UserTime; 130 | LARGE_INTEGER CreateTime; 131 | ULONG WaitTime; 132 | PVOID StartAddress; 133 | CLIENT_ID ClientID; 134 | KPRIORITY Priority; 135 | KPRIORITY BasePriority; 136 | ULONG ContextSwitchCount; 137 | ULONG ThreadState; 138 | KWAIT_REASON WaitReason; 139 | ULONG Reserved; //Add 140 | }SYSTEM_THREADS, * PSYSTEM_THREADS; 141 | 142 | 143 | typedef struct _SYSTEM_PROCESS_INFORMATION { 144 | ULONG NextEntryOffset; 145 | ULONG NumberOfThreads; 146 | LARGE_INTEGER Reserved[3]; 147 | LARGE_INTEGER CreateTime; 148 | LARGE_INTEGER UserTime; 149 | LARGE_INTEGER KernelTime; 150 | UNICODE_STRING ImageName; 151 | KPRIORITY BasePriority; 152 | HANDLE ProcessId; 153 | HANDLE InheritedFromProcessId; 154 | ULONG HandleCount; 155 | ULONG Reserved2[2]; 156 | ULONG PrivatePageCount; 157 | VM_COUNTERS VirtualMemoryCounters; 158 | IO_COUNTERS IoCounters; 159 | SYSTEM_THREADS Threads[1]; 160 | } SYSTEM_PROCESS_INFORMATION, * PSYSTEM_PROCESS_INFORMATION; 161 | 162 | 163 | typedef struct _PEB32 164 | { 165 | UCHAR InheritedAddressSpace; 166 | UCHAR ReadImageFileExecOptions; 167 | UCHAR BeingDebugged; 168 | UCHAR BitField; 169 | ULONG Mutant; 170 | ULONG ImageBaseAddress; 171 | ULONG Ldr; 172 | ULONG ProcessParameters; 173 | ULONG SubSystemData; 174 | ULONG ProcessHeap; 175 | ULONG FastPebLock; 176 | ULONG AtlThunkSListPtr; 177 | ULONG IFEOKey; 178 | ULONG CrossProcessFlags; 179 | ULONG UserSharedInfoPtr; 180 | ULONG SystemReserved; 181 | ULONG AtlThunkSListPtr32; 182 | ULONG ApiSetMap; 183 | } PEB32, * PPEB32; 184 | 185 | 186 | typedef struct _PEB_LDR_DATA32 187 | { 188 | ULONG Length; 189 | UCHAR Initialized; 190 | ULONG SsHandle; 191 | LIST_ENTRY32 InLoadOrderModuleList; 192 | LIST_ENTRY32 InMemoryOrderModuleList; 193 | LIST_ENTRY32 InInitializationOrderModuleList; 194 | } PEB_LDR_DATA32, * PPEB_LDR_DATA32; 195 | 196 | 197 | typedef struct _LDR_DATA_TABLE_ENTRY 198 | { 199 | LIST_ENTRY InLoadOrderLinks; 200 | LIST_ENTRY InMemoryOrderLinks; 201 | LIST_ENTRY InInitializationOrderLinks; 202 | PVOID DllBase; 203 | PVOID EntryPoint; 204 | ULONG SizeOfImage; 205 | UNICODE_STRING FullDllName; 206 | UNICODE_STRING BaseDllName; 207 | ULONG Flags; 208 | USHORT LoadCount; 209 | USHORT TlsIndex; 210 | LIST_ENTRY HashLinks; 211 | ULONG TimeDateStamp; 212 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; 213 | typedef struct _LDR_DATA_TABLE_ENTRY32 214 | { 215 | LIST_ENTRY32 InLoadOrderLinks; 216 | LIST_ENTRY32 InMemoryOrderLinks; 217 | LIST_ENTRY32 InInitializationOrderLinks; 218 | ULONG DllBase; 219 | ULONG EntryPoint; 220 | ULONG SizeOfImage; 221 | UNICODE_STRING32 FullDllName; 222 | UNICODE_STRING32 BaseDllName; 223 | ULONG Flags; 224 | USHORT LoadCount; 225 | USHORT TlsIndex; 226 | LIST_ENTRY32 HashLinks; 227 | ULONG TimeDateStamp; 228 | } LDR_DATA_TABLE_ENTRY32, * PLDR_DATA_TABLE_ENTRY32; 229 | 230 | typedef struct _PEB_LDR_DATA 231 | { 232 | ULONG Length; 233 | UCHAR Initialized; 234 | PVOID SsHandle; 235 | LIST_ENTRY InLoadOrderModuleList; 236 | LIST_ENTRY InMemoryOrderModuleList; 237 | LIST_ENTRY InInitializationOrderModuleList; 238 | } PEB_LDR_DATA, * PPEB_LDR_DATA; 239 | 240 | typedef struct _PEB 241 | { 242 | UCHAR InheritedAddressSpace; 243 | UCHAR ReadImageFileExecOptions; 244 | UCHAR BeingDebugged; 245 | UCHAR BitField; 246 | PVOID Mutant; 247 | PVOID ImageBaseAddress; 248 | PPEB_LDR_DATA Ldr; 249 | PVOID ProcessParameters; 250 | PVOID SubSystemData; 251 | PVOID ProcessHeap; 252 | PVOID FastPebLock; 253 | PVOID AtlThunkSListPtr; 254 | PVOID IFEOKey; 255 | PVOID CrossProcessFlags; 256 | PVOID KernelCallbackTable; 257 | ULONG SystemReserved; 258 | ULONG AtlThunkSListPtr32; 259 | PVOID ApiSetMap; 260 | } PEB, * PPEB; 261 | 262 | typedef struct PiDDBCacheEntry 263 | { 264 | LIST_ENTRY List; 265 | UNICODE_STRING DriverName; 266 | ULONG TimeDateStamp; 267 | NTSTATUS LoadStatus; 268 | char _0x0028[16]; // data from the shim engine, or uninitialized memory for custom drivers 269 | }PIDCacheobj; 270 | 271 | typedef struct _RTL_PROCESS_MODULE_INFORMATION 272 | { 273 | HANDLE Section; // Not filled in 274 | PVOID MappedBase; 275 | PVOID ImageBase; 276 | ULONG ImageSize; 277 | ULONG Flags; 278 | USHORT LoadOrderIndex; 279 | USHORT InitOrderIndex; 280 | USHORT LoadCount; 281 | USHORT OffsetToFileName; 282 | UCHAR FullPathName[MAXIMUM_FILENAME_LENGTH]; 283 | } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; 284 | 285 | 286 | typedef struct _RTL_PROCESS_MODULES 287 | { 288 | ULONG NumberOfModules; 289 | RTL_PROCESS_MODULE_INFORMATION Modules[1]; 290 | } RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; 291 | 292 | typedef struct _IMAGE_SECTION_HEADER { 293 | BYTE Name[8]; 294 | union { 295 | DWORD PhysicalAddress; 296 | DWORD VirtualSize; 297 | } Misc; 298 | DWORD VirtualAddress; 299 | DWORD SizeOfRawData; 300 | DWORD PointerToRawData; 301 | DWORD PointerToRelocations; 302 | DWORD PointerToLinenumbers; 303 | WORD NumberOfRelocations; 304 | WORD NumberOfLinenumbers; 305 | DWORD Characteristics; 306 | } IMAGE_SECTION_HEADER, * PIMAGE_SECTION_HEADER; 307 | 308 | 309 | typedef struct _IMAGE_FILE_HEADER // Size=20 310 | { 311 | USHORT Machine; 312 | USHORT NumberOfSections; 313 | ULONG TimeDateStamp; 314 | ULONG PointerToSymbolTable; 315 | ULONG NumberOfSymbols; 316 | USHORT SizeOfOptionalHeader; 317 | USHORT Characteristics; 318 | } IMAGE_FILE_HEADER, * PIMAGE_FILE_HEADER; 319 | 320 | typedef struct _IMAGE_OPTIONAL_HEADER64 321 | { 322 | USHORT Magic; 323 | UCHAR MajorLinkerVersion; 324 | UCHAR MinorLinkerVersion; 325 | ULONG SizeOfCode; 326 | ULONG SizeOfInitializedData; 327 | ULONG SizeOfUninitializedData; 328 | ULONG AddressOfEntryPoint; 329 | ULONG BaseOfCode; 330 | ULONGLONG ImageBase; 331 | ULONG SectionAlignment; 332 | ULONG FileAlignment; 333 | USHORT MajorOperatingSystemVersion; 334 | USHORT MinorOperatingSystemVersion; 335 | USHORT MajorImageVersion; 336 | USHORT MinorImageVersion; 337 | USHORT MajorSubsystemVersion; 338 | USHORT MinorSubsystemVersion; 339 | ULONG Win32VersionValue; 340 | ULONG SizeOfImage; 341 | ULONG SizeOfHeaders; 342 | ULONG CheckSum; 343 | USHORT Subsystem; 344 | USHORT DllCharacteristics; 345 | ULONGLONG SizeOfStackReserve; 346 | ULONGLONG SizeOfStackCommit; 347 | ULONGLONG SizeOfHeapReserve; 348 | ULONGLONG SizeOfHeapCommit; 349 | ULONG LoaderFlags; 350 | ULONG NumberOfRvaAndSizes; 351 | struct _IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; 352 | } IMAGE_OPTIONAL_HEADER64, * PIMAGE_OPTIONAL_HEADER64; 353 | 354 | 355 | 356 | typedef struct _MM_UNLOADED_DRIVER 357 | { 358 | UNICODE_STRING Name; 359 | PVOID ModuleStart; 360 | PVOID ModuleEnd; 361 | ULONG64 UnloadTime; 362 | } MM_UNLOADED_DRIVER, * PMM_UNLOADED_DRIVER; 363 | 364 | 365 | 366 | 367 | typedef struct _IMAGE_NT_HEADERS64 { 368 | DWORD Signature; 369 | IMAGE_FILE_HEADER FileHeader; 370 | IMAGE_OPTIONAL_HEADER64 OptionalHeader; 371 | } IMAGE_NT_HEADERS64, * PIMAGE_NT_HEADERS64; 372 | 373 | 374 | EXTERN_C NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( 375 | IN SYSTEM_INFORMATION_CLASS SystemInformationClass, 376 | OUT PVOID SystemInformation, 377 | IN ULONG SystemInformationLength, 378 | OUT PULONG ReturnLength OPTIONAL 379 | ); 380 | 381 | EXTERN_C NTKERNELAPI PVOID NTAPI PsGetProcessWow64Process( 382 | _In_ PEPROCESS Process 383 | ); 384 | 385 | EXTERN_C NTKERNELAPI PPEB NTAPI PsGetProcessPeb(IN PEPROCESS Process); 386 | 387 | EXTERN_C 388 | NTSYSAPI 389 | PIMAGE_NT_HEADERS 390 | NTAPI 391 | RtlImageNtHeader( 392 | IN PVOID ModuleAddress); -------------------------------------------------------------------------------- /KernelUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #pragma once 5 | #include "Undocumented.h" 6 | #include 7 | 8 | 9 | 10 | 11 | #define MM_UNLOADED_DRIVERS_SIZE 50 12 | #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 13 | #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 14 | #define IMAGE_SCN_CNT_CODE 0x00000020 15 | #define IMAGE_SCN_MEM_EXECUTE 0x20000000 16 | #define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 17 | #define IMAGE_NT_SIGNATURE 0x00004550 18 | #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ 19 | #define STANDARD_RIGHTS_ALL 0x001F0000L 20 | 21 | 22 | 23 | 24 | 25 | ULONG KernelSize; 26 | PVOID KernelBase; 27 | PVOID getKernelBase(OUT PULONG pSize) 28 | { 29 | NTSTATUS Status = STATUS_SUCCESS; 30 | ULONG Bytes = 0; 31 | PRTL_PROCESS_MODULES arrayOfModules; 32 | PVOID routinePtr = NULL; /*RoutinePtr points to a 33 | routine and checks if it is in Ntoskrnl*/ 34 | 35 | UNICODE_STRING routineName; 36 | 37 | if (KernelBase != NULL) 38 | { 39 | if (pSize) 40 | *pSize = KernelSize; 41 | return KernelBase; 42 | } 43 | 44 | RtlUnicodeStringInit(&routineName, L"NtOpenFile"); 45 | routinePtr = MmGetSystemRoutineAddress(&routineName); //get address of NtOpenFile 46 | 47 | 48 | if (routinePtr == NULL) 49 | { 50 | return NULL; 51 | } 52 | else 53 | { 54 | 55 | DbgPrint("MmGetSystemRoutineAddress inside getkernelbase succeed\n"); 56 | } 57 | 58 | 59 | //get size of system module information 60 | Status = ZwQuerySystemInformation(SystemModuleInformation, 0, Bytes, &Bytes); 61 | if (Bytes == 0) 62 | { 63 | DbgPrint("%s: Invalid SystemModuleInformation size\n"); 64 | return NULL; 65 | } 66 | 67 | 68 | arrayOfModules = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(NonPagedPool, Bytes, 0x454E4F45); //array of loaded kernel modules 69 | RtlZeroMemory(arrayOfModules, Bytes); //clean memory 70 | 71 | 72 | Status = ZwQuerySystemInformation(SystemModuleInformation, arrayOfModules, Bytes, &Bytes); 73 | if (NT_SUCCESS(Status)) 74 | { 75 | DbgPrint("ZwQuerySystemInformation inside getkernelbase succeed\n"); 76 | PRTL_PROCESS_MODULE_INFORMATION pMod = arrayOfModules->Modules; 77 | for (int i = 0; i < arrayOfModules->NumberOfModules; ++i) 78 | { 79 | 80 | if (routinePtr >= pMod[i].ImageBase && routinePtr < (PVOID)((PUCHAR)pMod[i].ImageBase + pMod[i].ImageSize)) 81 | { 82 | 83 | KernelBase = pMod[i].ImageBase; 84 | KernelSize = pMod[i].ImageSize; 85 | 86 | if (pSize) 87 | *pSize = KernelSize; 88 | break; 89 | } 90 | } 91 | } 92 | if (arrayOfModules) 93 | ExFreePoolWithTag(arrayOfModules, 0x454E4F45); // 'ENON' 94 | 95 | DbgPrint("KernelSize : %i\n", KernelSize); 96 | DbgPrint("g_KernelBase : %p\n", KernelBase); 97 | return (PVOID)KernelBase; 98 | } 99 | 100 | 101 | 102 | 103 | PVOID getDiskSysBase(OUT PULONG pSize) 104 | { 105 | NTSTATUS Status = STATUS_SUCCESS; 106 | ULONG Bytes = 0; 107 | PRTL_PROCESS_MODULES arrayOfModules; 108 | 109 | 110 | 111 | PVOID diskSysBase = 0; 112 | ULONG64 DiskSysSize = 0; 113 | 114 | 115 | 116 | //get size of system module information 117 | Status = ZwQuerySystemInformation(SystemModuleInformation, 0, Bytes, &Bytes); 118 | if (Bytes == 0) 119 | { 120 | DbgPrint("%s: Invalid SystemModuleInformation size\n"); 121 | return NULL; 122 | } 123 | 124 | 125 | arrayOfModules = (PRTL_PROCESS_MODULES)ExAllocatePoolWithTag(NonPagedPool, Bytes, 0x45454545); //array of loaded kernel modules 126 | RtlZeroMemory(arrayOfModules, Bytes); //clean memory 127 | 128 | 129 | Status = ZwQuerySystemInformation(SystemModuleInformation, arrayOfModules, Bytes, &Bytes); 130 | 131 | if (NT_SUCCESS(Status)) 132 | { 133 | DbgPrint("ZwQuerySystemInformation inside getkernelbase succeed\n"); 134 | PRTL_PROCESS_MODULE_INFORMATION pMod = arrayOfModules->Modules; 135 | for (int i = 0; i < arrayOfModules->NumberOfModules; ++i) 136 | { 137 | //list the module names: 138 | 139 | DbgPrint("Image name: %s\n", pMod[i].FullPathName + pMod[i].OffsetToFileName); 140 | // path name plus some amount of characters will lead to the name itself 141 | const char* DriverName = (const char*)pMod[i].FullPathName + pMod[i].OffsetToFileName; 142 | 143 | if (strcmp(DriverName, "disk.sys") == 0) 144 | { 145 | DbgPrint("found disk.sys\n"); 146 | 147 | 148 | diskSysBase = pMod[i].ImageBase; 149 | DiskSysSize = pMod[i].ImageSize; 150 | 151 | DbgPrint("Disk.sys Size : %i\n", DiskSysSize); 152 | DbgPrint("Disk.sys Base : %p\n", diskSysBase); 153 | 154 | 155 | if (arrayOfModules) 156 | ExFreePoolWithTag(arrayOfModules, 0x45454545); // 'ENON' 157 | 158 | 159 | 160 | 161 | *pSize = DiskSysSize; 162 | return diskSysBase; 163 | } 164 | } 165 | } 166 | if (arrayOfModules) 167 | ExFreePoolWithTag(arrayOfModules, 0x45454545); // 'ENON' 168 | 169 | 170 | 171 | *pSize = DiskSysSize; 172 | return (PVOID)diskSysBase; 173 | } 174 | 175 | 176 | 177 | 178 | 179 | NTSTATUS BBSearchPattern(IN PCUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, IN const VOID* base, IN ULONG_PTR size, OUT PVOID* ppFound) 180 | { 181 | ASSERT(ppFound != NULL && pattern != NULL && base != NULL); 182 | if (ppFound == NULL || pattern == NULL || base == NULL) 183 | return STATUS_INVALID_PARAMETER; 184 | 185 | for (ULONG_PTR i = 0; i < size - len; i++) 186 | { 187 | BOOLEAN found = TRUE; 188 | for (ULONG_PTR j = 0; j < len; j++) 189 | { 190 | if (pattern[j] != wildcard && pattern[j] != ((PCUCHAR)base)[i + j]) 191 | { 192 | found = FALSE; 193 | break; 194 | } 195 | } 196 | 197 | if (found != FALSE) 198 | { 199 | *ppFound = (PUCHAR)base + i; 200 | return STATUS_SUCCESS; 201 | } 202 | } 203 | 204 | return STATUS_NOT_FOUND; 205 | } 206 | 207 | 208 | 209 | NTSTATUS BBScanSection(IN PCCHAR section, IN PCUCHAR pattern, IN UCHAR wildcard, IN ULONG_PTR len, OUT PVOID* ppFound, PVOID base = nullptr, BOOLEAN dataOnly = FALSE) 210 | { 211 | 212 | //ASSERT(ppFound != NULL); 213 | if (ppFound == NULL) 214 | return STATUS_ACCESS_DENIED; //STATUS_INVALID_PARAMETER 215 | 216 | if (nullptr == base) 217 | base = getKernelBase(NULL); 218 | if (base == nullptr) 219 | return STATUS_ACCESS_DENIED; //STATUS_NOT_FOUND; 220 | 221 | PIMAGE_NT_HEADERS64 pHdr = (PIMAGE_NT_HEADERS64)RtlImageNtHeader(base); 222 | if (!pHdr) 223 | return STATUS_ACCESS_DENIED; // STATUS_INVALID_IMAGE_FORMAT; 224 | 225 | //PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)(pHdr + 1); 226 | PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)((uintptr_t)&pHdr->FileHeader + pHdr->FileHeader.SizeOfOptionalHeader + sizeof(IMAGE_FILE_HEADER)); 227 | 228 | PVOID ptr = NULL; 229 | 230 | for (PIMAGE_SECTION_HEADER pSection = pFirstSection; pSection < pFirstSection + pHdr->FileHeader.NumberOfSections; pSection++) 231 | { 232 | 233 | ANSI_STRING s1, s2; 234 | RtlInitAnsiString(&s1, section); 235 | RtlInitAnsiString(&s2, (PCCHAR)pSection->Name); 236 | if ((dataOnly == FALSE) && ((RtlCompareString(&s1, &s2, TRUE) == 0) || (pSection->Characteristics & IMAGE_SCN_CNT_CODE) || (pSection->Characteristics & IMAGE_SCN_MEM_EXECUTE))) 237 | { 238 | 239 | NTSTATUS status = BBSearchPattern(pattern, wildcard, len, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize, &ptr); 240 | if (NT_SUCCESS(status)) { 241 | *(PULONG64)ppFound = (ULONG_PTR)(ptr); //- (PUCHAR)base 242 | DbgPrint("found\r\n"); 243 | return status; 244 | } 245 | //we continue scanning because there can be multiple sections with the same name. 246 | } 247 | else if ((dataOnly == TRUE) && (RtlCompareString(&s1, &s2, TRUE) == 0)) 248 | { 249 | DbgPrint("valid section\r\n"); 250 | ptr = NULL; 251 | NTSTATUS status = BBSearchPattern(pattern, wildcard, len, (PUCHAR)base + pSection->VirtualAddress, pSection->Misc.VirtualSize, &ptr); 252 | if (NT_SUCCESS(status)) { 253 | *(PULONG64)ppFound = (ULONG_PTR)(ptr); //- (PUCHAR)base 254 | DbgPrint("BBscansection(): found at address: %p ", *(PULONG64)ppFound); 255 | return status; 256 | } 257 | return status; 258 | //we continue scanning because there can be multiple sections with the same name. 259 | } 260 | } 261 | 262 | return STATUS_ACCESS_DENIED; //STATUS_NOT_FOUND; 263 | } 264 | 265 | PVOID ResolveRelativeAddress( 266 | _In_ PVOID Instruction, 267 | _In_ ULONG OffsetOffset, 268 | _In_ ULONG InstructionSize 269 | ) 270 | { 271 | ULONG_PTR Instr = (ULONG_PTR)Instruction; 272 | LONG RipOffset = *(PLONG)(Instr + OffsetOffset); 273 | PVOID ResolvedAddr = (PVOID)(Instr + InstructionSize + RipOffset); 274 | 275 | return ResolvedAddr; 276 | } 277 | 278 | 279 | 280 | 281 | 282 | PVOID GetUserModule(IN PEPROCESS pProcess, IN PUNICODE_STRING ModuleName, IN BOOLEAN isWow64) 283 | { 284 | ASSERT(pProcess != NULL); 285 | if (pProcess == NULL) 286 | return NULL; 287 | 288 | // Protect from UserMode AV 289 | __try 290 | { 291 | LARGE_INTEGER time = { 0 }; 292 | time.QuadPart = -250ll * 10 * 1000; // 250 msec. 293 | 294 | // Wow64 process 295 | if (isWow64) 296 | { 297 | PPEB32 pPeb32 = (PPEB32)PsGetProcessWow64Process(pProcess); 298 | if (pPeb32 == NULL) 299 | { 300 | return NULL; 301 | } 302 | 303 | // Wait for loader a bit 304 | for (INT i = 0; !pPeb32->Ldr && i < 10; i++) 305 | { 306 | KeDelayExecutionThread(KernelMode, TRUE, &time); 307 | } 308 | 309 | // Still no loader 310 | if (!pPeb32->Ldr) 311 | { 312 | return NULL; 313 | } 314 | 315 | // Search in InLoadOrderModuleList 316 | for (PLIST_ENTRY32 pListEntry = (PLIST_ENTRY32)((PPEB_LDR_DATA32)pPeb32->Ldr)->InLoadOrderModuleList.Flink; 317 | pListEntry != &((PPEB_LDR_DATA32)pPeb32->Ldr)->InLoadOrderModuleList; 318 | pListEntry = (PLIST_ENTRY32)pListEntry->Flink) 319 | { 320 | UNICODE_STRING ustr; 321 | PLDR_DATA_TABLE_ENTRY32 pEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY32, InLoadOrderLinks); 322 | 323 | RtlUnicodeStringInit(&ustr, (PWCH)pEntry->BaseDllName.Buffer); 324 | 325 | if (RtlCompareUnicodeString(&ustr, ModuleName, TRUE) == 0) 326 | return (PVOID)pEntry->DllBase; 327 | } 328 | } 329 | // Native process 330 | else 331 | { 332 | PPEB pPeb = PsGetProcessPeb(pProcess); 333 | if (!pPeb) 334 | { 335 | return NULL; 336 | } 337 | 338 | // Wait for loader a bit 339 | for (INT i = 0; !pPeb->Ldr && i < 10; i++) 340 | { 341 | KeDelayExecutionThread(KernelMode, TRUE, &time); 342 | } 343 | 344 | // Still no loader 345 | if (!pPeb->Ldr) 346 | { 347 | return NULL; 348 | } 349 | 350 | // Search in InLoadOrderModuleList 351 | for (PLIST_ENTRY pListEntry = pPeb->Ldr->InLoadOrderModuleList.Flink; 352 | pListEntry != &pPeb->Ldr->InLoadOrderModuleList; 353 | pListEntry = pListEntry->Flink) 354 | { 355 | PLDR_DATA_TABLE_ENTRY pEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 356 | if (RtlCompareUnicodeString(&pEntry->BaseDllName, ModuleName, TRUE) == 0) 357 | return pEntry->DllBase; 358 | } 359 | } 360 | } 361 | __except (EXCEPTION_EXECUTE_HANDLER) 362 | { 363 | } 364 | 365 | return NULL; 366 | } 367 | 368 | 369 | 370 | HANDLE GetProcessPID(const wchar_t* NameOfProcess) 371 | { 372 | auto Status = STATUS_SUCCESS; 373 | UNICODE_STRING ClientName = { 0 }; 374 | HANDLE processID = nullptr; 375 | PVOID SystemProcessInfo = nullptr; 376 | DWORD buffer_size = NULL; 377 | 378 | 379 | 380 | RtlInitUnicodeString(&ClientName, L"UserModeClient.exe"); 381 | Status = ZwQuerySystemInformation(SystemProcessInformation, SystemProcessInfo, 0, &buffer_size); 382 | while (Status == STATUS_INFO_LENGTH_MISMATCH) 383 | { 384 | if (SystemProcessInfo) ExFreePool(SystemProcessInfo); 385 | SystemProcessInfo = ExAllocatePool(NonPagedPool, buffer_size); 386 | Status = ZwQuerySystemInformation(SystemProcessInformation, SystemProcessInfo, buffer_size, &buffer_size); 387 | } 388 | auto ProcessInformation = static_cast(SystemProcessInfo); 389 | for (;;) 390 | { 391 | 392 | if (FsRtlIsNameInExpression(&ClientName, &(ProcessInformation->ImageName), FALSE, NULL) == TRUE) 393 | { 394 | processID = ProcessInformation->ProcessId; 395 | break; 396 | } 397 | 398 | if (ProcessInformation->NextEntryOffset == 0) 399 | { 400 | break; 401 | } 402 | ProcessInformation = (PSYSTEM_PROCESS_INFORMATION)(((PUCHAR)ProcessInformation) + ProcessInformation->NextEntryOffset); 403 | } 404 | ExFreePool(SystemProcessInfo); 405 | return processID; 406 | 407 | } 408 | 409 | 410 | struct readOutput 411 | { 412 | BYTE buffer[240]; 413 | }; 414 | 415 | 416 | 417 | 418 | VOID ReadMemory(ULONG64 address, PVOID buffer, SIZE_T size, PEPROCESS process, PEPROCESS clientProcess, PVOID readBufferAddress) 419 | { 420 | { 421 | KAPC_STATE apc_state; 422 | KeStackAttachProcess(process, &apc_state); 423 | 424 | if (MmIsAddressValid((PVOID64)address) && MmIsAddressValid((PVOID64)(address + size))) 425 | { 426 | RtlCopyMemory(buffer, (PVOID64)address, size); 427 | } 428 | 429 | KeUnstackDetachProcess(&apc_state); 430 | } 431 | 432 | 433 | KAPC_STATE apc_state; 434 | KeStackAttachProcess(clientProcess, &apc_state); 435 | if (MmIsAddressValid((PVOID)readBufferAddress)) 436 | { 437 | 438 | KIRQL tempirql = KeRaiseIrqlToDpcLevel(); 439 | 440 | ULONG64 cr0 = __readcr0(); 441 | 442 | cr0 &= 0xfffffffffffeffff; 443 | __writecr0(cr0); 444 | 445 | _disable(); 446 | 447 | RtlCopyMemory(readBufferAddress, buffer, size); 448 | 449 | 450 | cr0 = __readcr0(); 451 | 452 | cr0 |= 0x10000; 453 | 454 | _enable(); 455 | 456 | __writecr0(cr0); 457 | 458 | KeLowerIrql(tempirql); 459 | } 460 | else 461 | { 462 | DbgPrint("address invalid!!! tried to read memory at: %p \n", readBufferAddress); 463 | } 464 | 465 | KeUnstackDetachProcess(&apc_state); 466 | 467 | } 468 | 469 | 470 | 471 | VOID WriteMemory(ULONG64 address, PVOID buffer, SIZE_T size, PEPROCESS process) 472 | { 473 | 474 | KAPC_STATE apc_state; 475 | KeStackAttachProcess(process, &apc_state); 476 | if (MmIsAddressValid((PVOID)address) && MmIsAddressValid((PVOID)(address + size))) 477 | { 478 | KIRQL tempirql = KeRaiseIrqlToDpcLevel(); 479 | 480 | ULONG64 cr0 = __readcr0(); 481 | 482 | cr0 &= 0xfffffffffffeffff; 483 | __writecr0(cr0); 484 | 485 | _disable(); 486 | 487 | RtlCopyMemory((PVOID64)address, buffer, size); 488 | 489 | cr0 = __readcr0(); 490 | 491 | cr0 |= 0x10000; 492 | 493 | _enable(); 494 | 495 | __writecr0(cr0); 496 | 497 | KeLowerIrql(tempirql); 498 | } 499 | KeUnstackDetachProcess(&apc_state); 500 | 501 | } 502 | 503 | 504 | 505 | --------------------------------------------------------------------------------