├── README.md └── HideDrv1.cpp /README.md: -------------------------------------------------------------------------------- 1 | # HideDriverTesting 2 | Only for Stress Testing 3 | 4 | Credit: 5 | https://www.unknowncheats.me/forum/anti-cheat-bypass/495236-improved-driver-hider.html 6 | -------------------------------------------------------------------------------- /HideDrv1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | This driver hider is made and tested for Windows 11 21H2 RTM. Tested on 4/4/2022. 9 | This hides your driver from: 10 | MmUnloadedDrivers 11 | PsLoadedModuleList 12 | PiDDBCacheTable 13 | Driver object list 14 | 15 | You'll have to handle these yourself: 16 | ExpCovUnloadedDrivers (very rarely used) 17 | MmVerifierData 18 | .. and anything else 19 | */ 20 | //0xb0 bytes (sizeof) 21 | typedef struct _MM_DRIVER_VERIFIER_DATA 22 | { 23 | ULONG Level; //0x0 24 | volatile ULONG RaiseIrqls; //0x4 25 | volatile ULONG AcquireSpinLocks; //0x8 26 | volatile ULONG SynchronizeExecutions; //0xc 27 | volatile ULONG AllocationsAttempted; //0x10 28 | volatile ULONG AllocationsSucceeded; //0x14 29 | volatile ULONG AllocationsSucceededSpecialPool; //0x18 30 | ULONG AllocationsWithNoTag; //0x1c 31 | ULONG TrimRequests; //0x20 32 | ULONG Trims; //0x24 33 | ULONG AllocationsFailed; //0x28 34 | volatile ULONG AllocationsFailedDeliberately; //0x2c 35 | volatile ULONG AllocationFreed; //0x30 36 | volatile ULONG Loads; //0x34 37 | volatile ULONG Unloads; //0x38 38 | ULONG UnTrackedPool; //0x3c 39 | ULONG UserTrims; //0x40 40 | volatile ULONG CurrentPagedPoolAllocations; //0x44 41 | volatile ULONG CurrentNonPagedPoolAllocations; //0x48 42 | ULONG PeakPagedPoolAllocations; //0x4c 43 | ULONG PeakNonPagedPoolAllocations; //0x50 44 | volatile ULONGLONG PagedBytes; //0x58 45 | volatile ULONGLONG NonPagedBytes; //0x60 46 | ULONGLONG PeakPagedBytes; //0x68 47 | ULONGLONG PeakNonPagedBytes; //0x70 48 | volatile ULONG BurstAllocationsFailedDeliberately; //0x78 49 | ULONG SessionTrims; //0x7c 50 | volatile ULONG OptionChanges; //0x80 51 | volatile ULONG VerifyMode; //0x84 52 | struct _UNICODE_STRING PreviousBucketName; //0x88 53 | volatile ULONG ExecutePoolTypes; //0x98 54 | volatile ULONG ExecutePageProtections; //0x9c 55 | volatile ULONG ExecutePageMappings; //0xa0 56 | volatile ULONG ExecuteWriteSections; //0xa4 57 | volatile ULONG SectionAlignmentFailures; //0xa8 58 | volatile ULONG IATInExecutableSection; //0xac 59 | } MM_DRIVER_VERIFIER_DATA, * PMM_DRIVER_VERIFIER_DATA; 60 | 61 | //0xa0 bytes (sizeof) 62 | typedef struct _KLDR_DATA_TABLE_ENTRY 63 | { 64 | struct _LIST_ENTRY InLoadOrderLinks; //0x0 65 | VOID* ExceptionTable; //0x10 66 | ULONG ExceptionTableSize; //0x18 67 | VOID* GpValue; //0x20 68 | struct _NON_PAGED_DEBUG_INFO* NonPagedDebugInfo; //0x28 69 | VOID* DllBase; //0x30 70 | VOID* EntryPoint; //0x38 71 | ULONG SizeOfImage; //0x40 72 | struct _UNICODE_STRING FullDllName; //0x48 73 | struct _UNICODE_STRING BaseDllName; //0x58 74 | ULONG Flags; //0x68 75 | USHORT LoadCount; //0x6c 76 | union 77 | { 78 | USHORT SignatureLevel : 4; //0x6e 79 | USHORT SignatureType : 3; //0x6e 80 | USHORT Frozen : 2; //0x6e 81 | USHORT HotPatch : 1; //0x6e 82 | USHORT Unused : 6; //0x6e 83 | USHORT EntireField; //0x6e 84 | } u1; //0x6e 85 | VOID* SectionPointer; //0x70 86 | ULONG CheckSum; //0x78 87 | ULONG CoverageSectionSize; //0x7c 88 | VOID* CoverageSection; //0x80 89 | VOID* LoadedImports; //0x88 90 | union 91 | { 92 | VOID* Spare; //0x90 93 | struct _KLDR_DATA_TABLE_ENTRY* NtDataTableEntry; //0x90 94 | }; 95 | ULONG SizeOfImageNotRounded; //0x98 96 | ULONG TimeDateStamp; //0x9c 97 | } _KLDR_DATA_TABLE_ENTRY, * PKLDR_DATA_TABLE_ENTRY; 98 | 99 | ULONG64 count = 0; 100 | 101 | __forceinline void log_success(const char* fmt, ...) 102 | { 103 | va_list args; 104 | va_start(args, fmt); 105 | vDbgPrintExWithPrefix("[SUCCESS] ", DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, fmt, args); 106 | va_end(args); 107 | 108 | count++; 109 | } 110 | 111 | __forceinline void log_debug(const char* fmt, ...) 112 | { 113 | va_list args; 114 | va_start(args, fmt); 115 | vDbgPrintExWithPrefix("[DEBUG] ", DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, fmt, args); 116 | va_end(args); 117 | 118 | count++; 119 | } 120 | 121 | __forceinline void log_error(const char* fmt, ...) 122 | { 123 | va_list args; 124 | va_start(args, fmt); 125 | vDbgPrintExWithPrefix("[ERROR] ", DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, fmt, args); 126 | va_end(args); 127 | 128 | count++; 129 | } 130 | 131 | __forceinline PVOID get_ntoskrnl_export(PCWSTR export_name) 132 | { 133 | UNICODE_STRING export_string; 134 | RtlInitUnicodeString(&export_string, export_name); 135 | 136 | return MmGetSystemRoutineAddress(&export_string); 137 | } 138 | 139 | __forceinline PKLDR_DATA_TABLE_ENTRY get_ldr_entry(PCWSTR base_dll_name) 140 | { 141 | UNICODE_STRING base_dll_name_string; 142 | RtlInitUnicodeString(&base_dll_name_string, base_dll_name); 143 | 144 | PLIST_ENTRY PsLoadedModuleList = (PLIST_ENTRY)get_ntoskrnl_export(L"PsLoadedModuleList"); 145 | 146 | /* Is PsLoadedModuleList null? */ 147 | if (!PsLoadedModuleList) 148 | { 149 | return NULL; 150 | } 151 | 152 | /* Start iterating at LIST_ENTRY.Flink */ 153 | PKLDR_DATA_TABLE_ENTRY iter_ldr_entry = (PKLDR_DATA_TABLE_ENTRY)PsLoadedModuleList->Flink; 154 | 155 | /* If LIST_ENTRY.Flink = beginning, then it's the last entry */ 156 | while ((PLIST_ENTRY)iter_ldr_entry != PsLoadedModuleList) 157 | { 158 | if (!RtlCompareUnicodeString(&iter_ldr_entry->BaseDllName, &base_dll_name_string, TRUE)) 159 | { 160 | return iter_ldr_entry; 161 | } 162 | 163 | /* Move on to the next entry */ 164 | iter_ldr_entry = (PKLDR_DATA_TABLE_ENTRY)iter_ldr_entry->InLoadOrderLinks.Flink; 165 | } 166 | 167 | return NULL; 168 | } 169 | 170 | ULONG64 MmVerifierData_offset = 0xC29E20; 171 | ULONG64 MiProcessLoaderEntry_offset = 0x209FEC; 172 | ULONG64 PiDDBLock_offset = 0xC45E20; 173 | ULONG64 PiDDBCacheList_Offset = 0xD3D940; 174 | ULONG64 PiDDBCacheTable_offset = 0xD3DD50; 175 | ULONG64 g_KernelHashBucketList_offset = 0xBC080; 176 | ULONG64 g_HashCacheLock_offset = 0x31FC0; 177 | ULONG64 MmLastUnloadedDriver_offset = 0xC29708; 178 | ULONG64 MmUnloadedDrivers_offset = 0xC29710; 179 | ULONG64 PsLoadedModuleResource_offset = 0xC29B20; 180 | ULONG64 PoolBigPageTable_offset = 0xC15710; 181 | ULONG64 PoolBigPageTableSize_offset = 0xC15728; 182 | 183 | // entry remover unimplemented 184 | ULONG64 MiLargePageDriverBuffer_offset = 0xC29720; 185 | ULONG64 MiLargePageDriverBufferLength_offset = 0xD69158; 186 | 187 | // Set this yourself 188 | ULONG timestamp = 0; 189 | 190 | typedef struct _PiDDBCacheEntry 191 | { 192 | LIST_ENTRY List; 193 | UNICODE_STRING DriverName; 194 | ULONG TimeDateStamp; 195 | NTSTATUS LoadStatus; 196 | char _0x0028[16]; // data from the shim engine, or uninitialized memory for custom drivers 197 | } PiDDBCacheEntry, * NPiDDBCacheEntry; 198 | 199 | __forceinline BOOLEAN remove_PiDDBCacheTable_entry(PUNICODE_STRING driver_name, ULONG timestamp) 200 | { 201 | PVOID PiDDBLock = (PVOID)((ULONG64)get_ldr_entry(L"ntosknrl.exe") + (ULONG64)PiDDBLock_offset); 202 | PRTL_AVL_TABLE PiDDBCacheTable = (PRTL_AVL_TABLE)((ULONG64)get_ldr_entry(L"ntosknrl.exe") + (ULONG64)PiDDBCacheTable_offset); 203 | 204 | if (!ExAcquireResourceExclusiveLite(PiDDBLock, TRUE)) 205 | { 206 | log_error("Couldn't get PiDDBLock.\n"); 207 | } 208 | 209 | PiDDBCacheEntry search_entry = { 0 }; 210 | search_entry.DriverName = *driver_name; 211 | search_entry.TimeDateStamp = timestamp; 212 | 213 | PiDDBCacheEntry* result_entry = (PiDDBCacheEntry*)RtlLookupElementGenericTableAvl(PiDDBCacheTable, (PVOID)&search_entry); 214 | if (!result_entry) 215 | { 216 | log_error("Failed to find driver \"%wZ\" with timestamp %X within PiDDBCacheTable.\n", driver_name, timestamp); 217 | ExReleaseResourceLite(PiDDBLock); 218 | return FALSE; 219 | } 220 | 221 | PLIST_ENTRY previous = result_entry->List.Blink; 222 | PLIST_ENTRY next = result_entry->List.Flink; 223 | 224 | previous->Flink = next; 225 | next->Blink = previous; 226 | 227 | ExReleaseResourceLite(PiDDBLock); 228 | 229 | if (!RtlDeleteElementGenericTableAvl(PiDDBCacheTable, result_entry)) 230 | { 231 | log_error("Unlinked driver entry from PiDDBCacheTable, but failed to delete it.\n"); 232 | return FALSE; 233 | } 234 | 235 | PiDDBCacheTable->DeleteCount--; 236 | 237 | ExReleaseResourceLite(PiDDBLock); 238 | 239 | return TRUE; 240 | } 241 | 242 | #define MI_UNLOADED_DRIVERS 50 243 | typedef struct _MM_UNLOADED_DRIVER 244 | { 245 | UNICODE_STRING Name; 246 | PVOID ModuleStart; 247 | PVOID ModuleEnd; 248 | ULONG64 UnloadTime; 249 | } MM_UNLOADED_DRIVER, * PMM_UNLOADED_DRIVER; 250 | 251 | __forceinline BOOLEAN is_MmUnloadedDrivers_empty(PMM_UNLOADED_DRIVER Entry) 252 | { 253 | if (Entry->Name.MaximumLength == 0 || 254 | Entry->Name.Length == 0 || 255 | Entry->Name.Buffer == NULL) 256 | { 257 | return TRUE; 258 | } 259 | 260 | return FALSE; 261 | } 262 | 263 | __forceinline BOOLEAN is_MmUnloadedDrivers_filled(PMM_UNLOADED_DRIVER MmUnloadedDrivers) 264 | { 265 | for (ULONG i = 0; i < MI_UNLOADED_DRIVERS; ++i) 266 | { 267 | if (is_MmUnloadedDrivers_empty(&MmUnloadedDrivers[i])) 268 | { 269 | return FALSE; 270 | } 271 | } 272 | 273 | return TRUE; 274 | } 275 | 276 | __forceinline BOOLEAN remove_MmUnloadedDrivers_entry(PUNICODE_STRING driver_name) 277 | { 278 | PMM_UNLOADED_DRIVER MmUnloadedDrivers = (PMM_UNLOADED_DRIVER)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + MmUnloadedDrivers_offset); 279 | PULONG MmLastUnloadedDriver = (PULONG)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + MmLastUnloadedDriver_offset); 280 | 281 | PVOID PsLoadedModuleResource = (PVOID)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + PsLoadedModuleResource_offset); 282 | 283 | if (!ExAcquireResourceExclusiveLite(PsLoadedModuleResource, TRUE)) 284 | { 285 | log_error("Couldn't get PsLoadedModuleResource.\n"); 286 | return FALSE; 287 | } 288 | 289 | BOOLEAN modified = FALSE; 290 | BOOLEAN filled = is_MmUnloadedDrivers_filled(MmUnloadedDrivers); 291 | 292 | for (ULONG i = 0; i < MI_UNLOADED_DRIVERS; ++i) 293 | { 294 | PMM_UNLOADED_DRIVER current_entry = &MmUnloadedDrivers[i]; 295 | 296 | if (modified) 297 | { 298 | PMM_UNLOADED_DRIVER previous_entry = &MmUnloadedDrivers[i - 1]; 299 | 300 | if (i == MI_UNLOADED_DRIVERS - 1UL) 301 | { 302 | RtlFillMemory(current_entry, sizeof(MM_UNLOADED_DRIVER), 0); 303 | } 304 | } 305 | else if (RtlEqualUnicodeString(driver_name, ¤t_entry->Name, TRUE)) 306 | { 307 | 308 | PVOID BufferPool = current_entry->Name.Buffer; 309 | RtlFillMemory(current_entry, sizeof(MM_UNLOADED_DRIVER), 0); 310 | ExFreePoolWithTag(BufferPool, 'TDmM'); 311 | 312 | *MmLastUnloadedDriver = (filled ? MI_UNLOADED_DRIVERS : *MmLastUnloadedDriver) - 1; 313 | modified = TRUE; 314 | } 315 | } 316 | if (modified) 317 | { 318 | ULONG64 previous_time = 0; 319 | 320 | 321 | for (LONG index = MI_UNLOADED_DRIVERS - 2; index >= 0; --index) 322 | { 323 | PMM_UNLOADED_DRIVER current_entry = &MmUnloadedDrivers[index]; 324 | if (is_MmUnloadedDrivers_empty(current_entry)) 325 | { 326 | continue; 327 | } 328 | 329 | if (previous_time != 0 && current_entry->UnloadTime > previous_time) 330 | { 331 | current_entry->UnloadTime = previous_time - 100; 332 | } 333 | 334 | previous_time = current_entry->UnloadTime; 335 | } 336 | 337 | remove_MmUnloadedDrivers_entry(driver_name, FALSE); 338 | } 339 | 340 | return modified ? TRUE : FALSE; 341 | } 342 | 343 | typedef struct _HashBucketEntry 344 | { 345 | struct _HashBucketEntry* Next; 346 | UNICODE_STRING DriverName; 347 | ULONG CertHash[5]; 348 | } HashBucketEntry, * PHashBucketEntry; 349 | 350 | __forceinline BOOLEAN remove_KernelHashBucketList_entry(PUNICODE_STRING driver_name) 351 | { 352 | HashBucketEntry* g_KernelHashBucketList = (HashBucketEntry*)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + g_KernelHashBucketList_offset); 353 | PVOID g_HashCacheLock = (PVOID)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + g_HashCacheLock_offset); 354 | 355 | if (!ExAcquireResourceExclusiveLite(g_HashCacheLock, TRUE)) 356 | { 357 | log_error("Failed to get g_HashCacheLock.\n"); 358 | return FALSE; 359 | } 360 | 361 | HashBucketEntry* current_entry = g_KernelHashBucketList; 362 | HashBucketEntry* previous_entry = g_KernelHashBucketList; 363 | 364 | while (current_entry) 365 | { 366 | if (RtlCompareUnicodeString(¤t_entry->DriverName, driver_name, FALSE)) 367 | { 368 | log_success("Found driver \"%wZ\" within g_KernelHashBucketList.\n", driver_name); 369 | previous_entry->Next = current_entry->Next; 370 | ExReleaseResourceLite(g_HashCacheLock); 371 | return TRUE; 372 | } 373 | 374 | if (current_entry->Next == g_KernelHashBucketList) 375 | { 376 | log_error("Couldn't find driver \"%wZ\" within g_KernelHashBucketList.\n", driver_name); 377 | ExReleaseResourceLite(g_HashCacheLock); 378 | return FALSE; 379 | } 380 | 381 | if (!RtlCompareUnicodeString(¤t_entry->DriverName, driver_name, FALSE)) 382 | { 383 | continue; 384 | } 385 | 386 | previous_entry = current_entry; 387 | current_entry = current_entry->Next; 388 | } 389 | 390 | log_error("Couldn't find driver \"%wZ\" within g_KernelHashBucketList.\n", driver_name); 391 | ExReleaseResourceLite(g_HashCacheLock); 392 | return FALSE; 393 | } 394 | 395 | //0x20 bytes (sizeof) 396 | typedef struct _POOL_TRACKER_BIG_PAGES 397 | { 398 | volatile ULONGLONG Va; //0x0 399 | ULONG Key; //0x8 400 | ULONG Pattern : 8; //0xc 401 | ULONG PoolType : 12; //0xc 402 | ULONG SlushSize : 12; //0xc 403 | ULONGLONG NumberOfBytes; //0x10 404 | PEPROCESS ProcessBilled; //0x18 405 | } POOL_TRACKER_BIG_PAGES, *PPOOL_TRACKER_BIG_PAGES; 406 | 407 | #define POOL_BIG_TABLE_ENTRY_FREE 0x1 408 | 409 | // Also returns true if not in big pool tracker 410 | __forceinline BOOLEAN remove_PoolBigPageTracker_entry(ULONG64 base_address) 411 | { 412 | POOL_TRACKER_BIG_PAGES* pool_big_page_tracker = (POOL_TRACKER_BIG_PAGES*)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + PoolBigPageTable_offset); 413 | PULONG64 pool_big_page_tracker_size = (PULONG64*)((ULONG64)get_ldr_entry(L"ntoskrnl.exe") + PoolBigPageTableSize_offset); 414 | 415 | for (ULONG64 i = 0; i < *pool_big_page_tracker_size; i++) 416 | { 417 | /*if (pool_big_page_tracker[i].Va & POOL_BIG_TABLE_ENTRY_FREE) 418 | { 419 | continue; 420 | } 421 | */ 422 | 423 | if (pool_big_page_tracker[i].Va = base_address || pool_big_page_tracker[i].Va == (base_address + 0x1ULL)) 424 | { 425 | pool_big_page_tracker[i].Va = 0x1ULL; 426 | pool_big_page_tracker[i].NumberOfBytes = 0x0ULL; 427 | return TRUE; 428 | } 429 | } 430 | 431 | return TRUE; 432 | } 433 | 434 | NTSTATUS GsDriverEntry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path) 435 | { 436 | // Remove driver from all 4 tables/lists 437 | if (!remove_MmUnloadedDrivers_entry(&driver_object->DriverName)) 438 | { 439 | log_error("Failed to remove driver \"%wZ\" from MmUnloadedDrivers.\n", &driver_object->DriverName); 440 | return STATUS_UNSUCCESSFUL; 441 | } 442 | 443 | if (!remove_PiDDBCacheTable_entry(&driver_object->DriverName, timestamp)) 444 | { 445 | log_error("Failed to remove driver \"%wZ\" from PiDDBCacheTable.\n", &driver_object->DriverName); 446 | return STATUS_UNSUCCESSFUL; 447 | } 448 | 449 | if (!remove_KernelHashBucketList_entry(&driver_object->DriverName)) 450 | { 451 | log_error("Failed to remove driver \"%wZ\" from g_KernelHashBucketList.\n", &driver_object->DriverName); 452 | return STATUS_UNSUCCESSFUL; 453 | } 454 | 455 | PKLDR_DATA_TABLE_ENTRY current_driver_ldr_entry = driver_object->DriverSection; 456 | 457 | if (!remove_PoolBigPageTracker_entry((ULONG64)current_driver_ldr_entry->DllBase)) 458 | { 459 | log_error("Failed to remove driver with base address %llX from PoolBigPageTracker.\n", current_driver_ldr_entry->DllBase); 460 | return STATUS_UNSUCCESSFUL; 461 | } 462 | 463 | log_success("Removed driver \"%wZ\" with base address %llX from:\n\t->MmUnloadedDrivers\n\t->PiDDBCacheTable\n\t->g_KernelHashBucketList\n\t->PoolBigPageTracker\n\n", 464 | driver_object->DriverName, current_driver_ldr_entry->DllBase); 465 | 466 | // Mark this driver object temporary, so it can be deleted soon. 467 | ObMakeTemporaryObject(driver_object); 468 | log_success("Marked current driver object temporary for deletion.\n"); 469 | 470 | // Remove loader entry from PsLoadedModuleList 471 | VOID(NTAPI * MiProcessLoaderEntry)(PKLDR_DATA_TABLE_ENTRY LdrEntry, BOOLEAN Insert); 472 | 473 | 474 | MiProcessLoaderEntry = ((ULONG64)current_driver_ldr_entry + MiProcessLoaderEntry_offset); 475 | MiProcessLoaderEntry((PKLDR_DATA_TABLE_ENTRY)driver_object->DriverSection, FALSE); 476 | log_success("Removed loader entry from PsLoadedModuleList.\n"); 477 | 478 | return STATUS_SUCCESS; 479 | } 480 | --------------------------------------------------------------------------------