Changeset 80212 in vbox for trunk/src/VBox/HostDrivers/Support/win
- Timestamp:
- Aug 9, 2019 1:11:21 PM (5 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support/win
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
r77816 r80212 873 873 */ 874 874 uint32_t cSkipAreas = 0; 875 SUPHNTVPSKIPAREA aSkipAreas[ 5];875 SUPHNTVPSKIPAREA aSkipAreas[6]; 876 876 if (pImage->fNtCreateSectionPatch) 877 877 { … … 898 898 if (RT_FAILURE(rc)) 899 899 return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'LdrInitializeThunk': %Rrc", pImage->pszName, rc); 900 aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue; 901 aSkipAreas[cSkipAreas++].cb = 14; 902 903 /* Ignore our patched KiUserApcDispatcher hack. */ 904 rc = RTLdrGetSymbolEx(pImage->pCacheEntry->hLdrMod, pbBits, 0, UINT32_MAX, "KiUserApcDispatcher", &uValue); 905 if (RT_FAILURE(rc)) 906 return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'KiUserApcDispatcher': %Rrc", pImage->pszName, rc); 900 907 aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue; 901 908 aSkipAreas[cSkipAreas++].cb = 14; … … 1519 1526 /* 1520 1527 * In the BSOD workaround mode, we need to make a copy of the memory before 1521 * freeing it. 1528 * freeing it. Bird abuses this code for logging purposes too. 1522 1529 */ 1523 1530 uintptr_t uCopySrc = (uintptr_t)pvFree; 1524 1531 size_t cbCopy = 0; 1525 1532 void *pvCopy = NULL; 1526 if (pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW)1533 //if (pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW) 1527 1534 { 1528 1535 cbCopy = cbFree; … … 1538 1545 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_REPLACE_VIRTUAL_MEMORY_FAILED, 1539 1546 "Error reading data from original alloc: %#x (%p LB %#zx)", rcNt, uCopySrc, cbCopy, rcNt); 1540 supR3HardenedLogFlush(); 1547 for (size_t off = 0; off < cbCopy; off += 256) 1548 { 1549 size_t const cbChunk = RT_MIN(256, cbCopy - off); 1550 void const *pvChunk = (uint8_t const *)pvCopy + off; 1551 if (!ASMMemIsZero(pvChunk, cbChunk)) 1552 SUP_DPRINTF(("%.*RhxD\n", cbChunk, pvChunk)); 1553 } 1554 if (pThis->fFlags & SUPHARDNTVP_F_EXEC_ALLOC_REPLACE_WITH_RW) 1555 supR3HardenedLogFlush(); 1541 1556 } 1542 1557 -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r79642 r80212 292 292 /** Pointer to the bit of assembly code that will perform the original 293 293 * NtCreateSection operation. */ 294 static NTSTATUS (NTAPI *g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,294 static NTSTATUS (NTAPI *g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES, 295 295 PLARGE_INTEGER, ULONG, ULONG, HANDLE); 296 296 /** Pointer to the NtCreateSection function in NtDll (for patching purposes). */ … … 300 300 /** Pointer to the bit of assembly code that will perform the original 301 301 * LdrLoadDll operation. */ 302 static NTSTATUS (NTAPI *g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE);302 static NTSTATUS (NTAPI *g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE); 303 303 /** Pointer to the LdrLoadDll function in NtDll (for patching purposes). */ 304 304 static uint8_t *g_pbLdrLoadDll; 305 305 /** The patched LdrLoadDll bytes (for restoring). */ 306 306 static uint8_t g_abLdrLoadDllPatch[16]; 307 308 /** Pointer to the bit of assembly code that will perform the original 309 * KiUserApcDispatcher operation. */ 310 static VOID (NTAPI *g_pfnKiUserApcDispatcherReal)(void); 311 /** Pointer to the KiUserApcDispatcher function in NtDll (for patching 312 * purposes). */ 313 static uint8_t *g_pbKiUserApcDispatcher; 314 /** The patched KiUserApcDispatcher bytes (for restoring). */ 315 static uint8_t g_abKiUserApcDispatcherPatch[16]; 316 /** Pointer to the LdrInitializeThunk function in NtDll for 317 * supR3HardenedMonitor_KiUserApcDispatcher_C() to use for APC vetting. */ 318 static uintptr_t g_pfnLdrInitializeThunk; 307 319 308 320 /** The hash table of verifier cache . */ … … 379 391 /** Sophos Endpoint Defense. */ 380 392 #define SUPHARDNT_ADVERSARY_SOPHOS RT_BIT_32(18) 393 /** VMware horizon view agent. */ 394 #define SUPHARDNT_ADVERSARY_HORIZON_VIEW_AGENT RT_BIT_32(19) 381 395 /** Unknown adversary detected while waiting on child. */ 382 396 #define SUPHARDNT_ADVERSARY_UNKNOWN RT_BIT_32(31) … … 393 407 static void supR3HardenedWinReInstallHooks(bool fFirst); 394 408 DECLASM(void) supR3HardenedEarlyProcessInitThunk(void); 409 DECLASM(void) supR3HardenedMonitor_KiUserApcDispatcher(void); 395 410 396 411 … … 2461 2476 2462 2477 2478 /** 2479 * Dummy replacement routine we use for passifying unwanted user APC 2480 * callbacks during early process initialization. 2481 * 2482 * @sa supR3HardenedMonitor_KiUserApcDispatcher_C 2483 */ 2484 static VOID NTAPI supR3HardenedWinDummyApcRoutine(PVOID pvArg1, PVOID pvArg2, PVOID pvArg3) 2485 { 2486 SUP_DPRINTF(("supR3HardenedWinDummyApcRoutine: pvArg1=%p pvArg2=%p pvArg3=%p\n", pvArg1, pvArg2, pvArg3)); 2487 RT_NOREF(pvArg1, pvArg2, pvArg3); 2488 } 2489 2490 2491 /** 2492 * This is called when ntdll!KiUserApcDispatcher is invoked (via 2493 * supR3HardenedMonitor_KiUserApcDispatcher). 2494 * 2495 * The parent process hooks KiUserApcDispatcher before the guest starts 2496 * executing. There should only be one APC request dispatched while the process 2497 * is being initialized, and that's the one calling ntdll!LdrInitializeThunk. 2498 * 2499 * @returns Where to go to run the original code. 2500 * @param pvApcArgs The APC dispatcher arguments. 2501 */ 2502 DECLASM(uintptr_t) supR3HardenedMonitor_KiUserApcDispatcher_C(void *pvApcArgs) 2503 { 2504 #ifdef RT_ARCH_AMD64 2505 PCONTEXT pCtx = (PCONTEXT)pvApcArgs; 2506 uintptr_t *ppfnRoutine = (uintptr_t *)&pCtx->P4Home; 2507 #else 2508 struct X86APCCTX 2509 { 2510 uintptr_t pfnRoutine; 2511 uintptr_t pvCtx; 2512 uintptr_t pvUser1; 2513 uintptr_t pvUser2; 2514 CONTEXT Ctx; 2515 } *pCtx = (struct X86APCCTX *)pvApcArgs; 2516 uintptr_t *ppfnRoutine = &pCtx->pfnRoutine; 2517 #endif 2518 uintptr_t pfnRoutine = *ppfnRoutine; 2519 2520 if (g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_HARDENED_MAIN_CALLED) 2521 { 2522 if (pfnRoutine == g_pfnLdrInitializeThunk) /* Note! we could use this to detect thread creation too. */ 2523 SUP_DPRINTF(("supR3HardenedMonitor_KiUserApcDispatcher_C: pfnRoutine=%p enmState=%d - okay\n", 2524 pfnRoutine, g_enmSupR3HardenedMainState)); 2525 else 2526 { 2527 *ppfnRoutine = (uintptr_t)supR3HardenedWinDummyApcRoutine; 2528 SUP_DPRINTF(("supR3HardenedMonitor_KiUserApcDispatcher_C: pfnRoutine=%p enmState=%d -> supR3HardenedWinDummyApcRoutine\n", 2529 pfnRoutine, g_enmSupR3HardenedMainState)); 2530 } 2531 } 2532 return (uintptr_t)g_pfnKiUserApcDispatcherReal; 2533 } 2534 2535 2463 2536 static void supR3HardenedWinHookFailed(const char *pszWhich, uint8_t const *pbPrologue) 2464 2537 { … … 2622 2695 } const s_aPatches[] = 2623 2696 { 2624 { sizeof(g_abNtCreateSectionPatch), g_abNtCreateSectionPatch, &g_pbNtCreateSection, "NtCreateSection" }, 2625 { sizeof(g_abLdrLoadDllPatch), g_abLdrLoadDllPatch, &g_pbLdrLoadDll, "LdrLoadDll" }, 2697 { sizeof(g_abNtCreateSectionPatch), g_abNtCreateSectionPatch, &g_pbNtCreateSection, "NtCreateSection" }, 2698 { sizeof(g_abLdrLoadDllPatch), g_abLdrLoadDllPatch, &g_pbLdrLoadDll, "LdrLoadDll" }, 2699 { sizeof(g_abKiUserApcDispatcherPatch), g_abKiUserApcDispatcherPatch, &g_pbKiUserApcDispatcher, "KiUserApcDispatcher" }, 2626 2700 }; 2627 2701 … … 2732 2806 //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll); 2733 2807 2808 PFNRT pfnKiUserApcDispatcher = supR3HardenedWinGetRealDllSymbol("ntdll.dll", "KiUserApcDispatcher"); 2809 SUPR3HARDENED_ASSERT(pfnKiUserApcDispatcher != NULL); 2810 g_pfnLdrInitializeThunk = (uintptr_t)supR3HardenedWinGetRealDllSymbol("ntdll.dll", "LdrInitializeThunk"); 2811 SUPR3HARDENED_ASSERT(g_pfnLdrInitializeThunk != NULL); 2812 2734 2813 /* 2735 2814 * Exec page setup & management. … … 2887 2966 g_abLdrLoadDllPatch[0] = 0xe9; 2888 2967 *(uint32_t *)&g_abLdrLoadDllPatch[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4]; 2968 #endif 2969 2970 /* 2971 * Hook #3 - KiUserApcDispatcher 2972 * Purpose: Prevent user APC to memory we (or our parent) has freed from 2973 * crashing the process. Also ensures no code injection via user 2974 * APC during process init given the way we're vetting the APCs. 2975 * 2976 * This differs from the first function in that is no a system call and 2977 * we're at the mercy of the handwritten assembly. 2978 */ 2979 uint8_t * const pbKiUserApcDispatcher = (uint8_t *)(uintptr_t)pfnKiUserApcDispatcher; 2980 g_pbKiUserApcDispatcher = pbKiUserApcDispatcher; 2981 memcpy(g_abKiUserApcDispatcherPatch, pbKiUserApcDispatcher, sizeof(g_abKiUserApcDispatcherPatch)); 2982 2983 #ifdef RT_ARCH_AMD64 2984 /* 2985 * Patch 64-bit hosts. 2986 */ 2987 /* Just use the disassembler to skip 12 bytes or more. */ 2988 offJmpBack = 0; 2989 while (offJmpBack < 12) 2990 { 2991 cbInstr = 1; 2992 int rc = DISInstr(pbKiUserApcDispatcher + offJmpBack, DISCPUMODE_64BIT, &Dis, &cbInstr); 2993 if ( RT_FAILURE(rc) 2994 || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW)) 2995 || (Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */) ) 2996 supR3HardenedWinHookFailed("KiUserApcDispatcher", pbKiUserApcDispatcher); 2997 offJmpBack += cbInstr; 2998 } 2999 3000 /* Assemble the code for resuming the call.*/ 3001 *(PFNRT *)&g_pfnKiUserApcDispatcherReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage]; 3002 3003 memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbKiUserApcDispatcher, offJmpBack); 3004 offExecPage += offJmpBack; 3005 3006 g_abSupHardReadWriteExecPage[offExecPage++] = 0xff; /* jmp qword [$+8 wrt RIP] */ 3007 g_abSupHardReadWriteExecPage[offExecPage++] = 0x25; 3008 *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = RT_ALIGN_32(offExecPage + 4, 8) - (offExecPage + 4); 3009 offExecPage = RT_ALIGN_32(offExecPage + 4, 8); 3010 *(uint64_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbKiUserApcDispatcher[offJmpBack]; 3011 offExecPage = RT_ALIGN_32(offExecPage + 8, 16); 3012 3013 /* Assemble the KiUserApcDispatcher patch. */ 3014 Assert(offJmpBack >= 12); 3015 g_abKiUserApcDispatcherPatch[0] = 0x48; /* mov rax, qword */ 3016 g_abKiUserApcDispatcherPatch[1] = 0xb8; 3017 *(uint64_t *)&g_abKiUserApcDispatcherPatch[2] = (uint64_t)supR3HardenedMonitor_KiUserApcDispatcher; 3018 g_abKiUserApcDispatcherPatch[10] = 0xff; /* jmp rax */ 3019 g_abKiUserApcDispatcherPatch[11] = 0xe0; 3020 3021 #else 3022 /* 3023 * Patch 32-bit hosts. 3024 */ 3025 /* Just use the disassembler to skip 5 bytes or more. */ 3026 offJmpBack = 0; 3027 while (offJmpBack < 5) 3028 { 3029 cbInstr = 1; 3030 int rc = DISInstr(pbKiUserApcDispatcher + offJmpBack, DISCPUMODE_32BIT, &Dis, &cbInstr); 3031 if ( RT_FAILURE(rc) 3032 || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW)) ) 3033 supR3HardenedWinHookFailed("KiUserApcDispatcher", pbKiUserApcDispatcher); 3034 offJmpBack += cbInstr; 3035 } 3036 3037 /* Assemble the code for resuming the call.*/ 3038 *(PFNRT *)&g_pfnKiUserApcDispatcherReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage]; 3039 3040 memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbKiUserApcDispatcher, offJmpBack); 3041 offExecPage += offJmpBack; 3042 3043 g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9; /* jmp rel32 */ 3044 *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbKiUserApcDispatcher[offJmpBack] 3045 - (uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage + 4]; 3046 offExecPage = RT_ALIGN_32(offExecPage + 4, 16); 3047 3048 /* Assemble the KiUserApcDispatcher patch. */ 3049 memcpy(g_abKiUserApcDispatcherPatch, pbKiUserApcDispatcher, sizeof(g_abKiUserApcDispatcherPatch)); 3050 Assert(offJmpBack >= 5); 3051 g_abKiUserApcDispatcherPatch[0] = 0xe9; 3052 *(uint32_t *)&g_abKiUserApcDispatcherPatch[1] = (uintptr_t)supR3HardenedMonitor_KiUserApcDispatcher - (uintptr_t)&pbKiUserApcDispatcher[1+4]; 2889 3053 #endif 2890 3054 … … 3018 3182 PRTERRINFO pErrInfo) 3019 3183 { 3020 SUP_DPRINTF(("supR3HardNtEnableThreadCreation :\n"));3184 SUP_DPRINTF(("supR3HardNtEnableThreadCreationEx:\n")); 3021 3185 SUPR3HARDENED_ASSERT(cbBackup == 16); 3022 3186 … … 3027 3191 if (!NT_SUCCESS(rcNt)) 3028 3192 return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, 3029 "supR3HardNt DisableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt);3193 "supR3HardNtEnableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk failed: %#x", rcNt); 3030 3194 3031 3195 SIZE_T cbIgnored; … … 3033 3197 if (!NT_SUCCESS(rcNt)) 3034 3198 return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, 3035 "supR3HardNtEnableThreadCreation : NtWriteVirtualMemory/LdrInitializeThunk[restore] failed: %#x",3199 "supR3HardNtEnableThreadCreationEx: NtWriteVirtualMemory/LdrInitializeThunk[restore] failed: %#x", 3036 3200 rcNt); 3037 3201 … … 3041 3205 if (!NT_SUCCESS(rcNt)) 3042 3206 return RTErrInfoSetF(pErrInfo, VERR_GENERAL_FAILURE, 3043 "supR3HardNtEnableThreadCreation : NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x",3207 "supR3HardNtEnableThreadCreationEx: NtProtectVirtualMemory/LdrInitializeThunk[restore] failed: %#x", 3044 3208 rcNt); 3045 3209 … … 5814 5978 5815 5979 { SUPHARDNT_ADVERSARY_SOPHOS, "SophosED" }, /* Not verified. */ 5980 5981 { SUPHARDNT_ADVERSARY_HORIZON_VIEW_AGENT, "vmwicpdr" }, 5816 5982 }; 5817 5983 … … 5940 6106 5941 6107 { SUPHARDNT_ADVERSARY_SOPHOS, L"\\SystemRoot\\System32\\drivers\\SophosED.sys" }, // not verified 6108 6109 { SUPHARDNT_ADVERSARY_HORIZON_VIEW_AGENT, L"\\SystemRoot\\System32\\drivers\\vmwicpdr.sys" }, 6110 { SUPHARDNT_ADVERSARY_HORIZON_VIEW_AGENT, L"\\SystemRoot\\System32\\drivers\\ftsjail.sys" }, 5942 6111 }; 5943 6112 … … 6208 6377 supR3HardenedWinRegisterDllNotificationCallback(); 6209 6378 supR3HardenedWinReInstallHooks(false /*fFirstCall */); 6379 6380 /* 6381 * Flush user APCs before the g_enmSupR3HardenedMainState changes 6382 * and disables the APC restrictions. 6383 */ 6384 NtTestAlert(); 6210 6385 } 6211 6386 … … 6327 6502 LARGE_INTEGER Timeout; 6328 6503 Timeout.QuadPart = -1200000000; /* 120 second */ 6329 rcNt = pfnNtWaitForSingleObject(hEvtChild, FALSE /*Alertable */, &Timeout);6504 rcNt = pfnNtWaitForSingleObject(hEvtChild, FALSE /*Alertable (never alertable before hooking!) */, &Timeout); 6330 6505 if (rcNt != STATUS_SUCCESS) 6331 6506 return 0x34; /* crash */ -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm
r76553 r80212 34 34 ; External code. 35 35 extern NAME(supR3HardenedEarlyProcessInit) 36 extern NAME(supR3HardenedMonitor_KiUserApcDispatcher_C) 36 37 37 38 … … 107 108 ENDPROC supR3HardenedEarlyProcessInitThunk 108 109 110 111 ;; 112 ; Hook for KiUserApcDispatcher that validates user APC calls during early process 113 ; init to prevent calls going to or referring to executable memory we've freed 114 ; already. 115 ; 116 ; We just call C code here, just like supR3HardenedEarlyProcessInitThunk does. 117 ; 118 ; @sa supR3HardenedMonitor_KiUserApcDispatcher_C 119 ; 120 BEGINPROC supR3HardenedMonitor_KiUserApcDispatcher 121 ; 122 ; Prologue. 123 ; 124 125 ; Reserve space for the "return" address. 126 push 0 127 128 ; Create a stack frame, saving xBP. 129 push xBP 130 SEH64_PUSH_xBP 131 mov xBP, xSP 132 SEH64_SET_FRAME_xBP 0 ; probably wrong... 133 134 ; Save all volatile registers. 135 push xAX 136 push xCX 137 push xDX 138 %ifdef RT_ARCH_AMD64 139 push r8 140 push r9 141 push r10 142 push r11 143 %endif 144 145 ; Reserve spill space and align the stack. 146 sub xSP, 20h 147 and xSP, ~0fh 148 SEH64_END_PROLOGUE 149 150 ; 151 ; Call the C/C++ code that does the actual work. This returns the 152 ; resume address in xAX, which we put in the "return" stack position. 153 ; 154 ; On AMD64, a CONTEXT structure is found at our RSP address when we're called. 155 ; On x86, there a 16 byte structure containing the two routines and their 156 ; arguments followed by a CONTEXT structure. 157 ; 158 lea xCX, [xBP + xCB + xCB] 159 %ifdef RT_ARCH_X86 160 mov [xSP], xCX 161 %endif 162 call NAME(supR3HardenedMonitor_KiUserApcDispatcher_C) 163 mov [xBP + xCB], xAX 164 165 ; 166 ; Restore volatile registers. 167 ; 168 mov xAX, [xBP - xCB*1] 169 mov xCX, [xBP - xCB*2] 170 mov xDX, [xBP - xCB*3] 171 %ifdef RT_ARCH_AMD64 172 mov r8, [xBP - xCB*4] 173 mov r9, [xBP - xCB*5] 174 mov r10, [xBP - xCB*6] 175 mov r11, [xBP - xCB*7] 176 %endif 177 ; 178 ; Use the leave instruction to restore xBP and set up xSP to point at 179 ; the resume address. Then use the 'ret' instruction to execute the 180 ; original KiUserApcDispatcher code as if we've never been here... 181 ; 182 leave 183 ret 184 ENDPROC supR3HardenedMonitor_KiUserApcDispatcher 109 185 110 186 -
trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h
r67979 r80212 51 51 SUPHARNT_IMPORT_SYSCALL(NtTerminateProcess, 8) 52 52 SUPHARNT_IMPORT_SYSCALL(NtTerminateThread, 8) 53 SUPHARNT_IMPORT_SYSCALL(NtTestAlert, 0) 53 54 SUPHARNT_IMPORT_SYSCALL(NtUnmapViewOfSection, 8) 54 55 SUPHARNT_IMPORT_SYSCALL(NtWaitForMultipleObjects, 20)
Note:
See TracChangeset
for help on using the changeset viewer.