Changeset 52967 in vbox
- Timestamp:
- Oct 6, 2014 10:18:51 PM (10 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 2 deleted
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
r52962 r52967 449 449 DECLHIDDEN(void) supR3HardenedWinInitImports(void); 450 450 DECLHIDDEN(void) supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr); 451 DECLHIDDEN(void) supR3HardenedWinInitSyscalls(bool fReportErrors); 451 452 DECLHIDDEN(PFNRT) supR3HardenedWinGetRealDllSymbol(const char *pszDll, const char *pszProcedure); 452 453 DECLHIDDEN(void) supR3HardenedWinEnableThreadCreation(void); -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
r52966 r52967 843 843 return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'NtCreateSection': %Rrc", pImage->pszName, rc); 844 844 aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue; 845 aSkipAreas[cSkipAreas++].cb = 5 + (ARCH_BITS == 64);845 aSkipAreas[cSkipAreas++].cb = ARCH_BITS == 32 ? 5 : 12; 846 846 847 847 /* Ignore our LdrLoadDll hack. */ … … 850 850 return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'LdrLoadDll': %Rrc", pImage->pszName, rc); 851 851 aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue; 852 aSkipAreas[cSkipAreas++].cb = 5 + (ARCH_BITS == 64);852 aSkipAreas[cSkipAreas++].cb = ARCH_BITS == 32 ? 5 : 12; 853 853 } 854 854 -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52962 r52967 228 228 /** @name Hook related variables. 229 229 * @{ */ 230 /** The jump back address of the patched NtCreateSection. */231 extern "C" PFNRT g_pfnNtCreateSectionJmpBack = NULL;232 230 /** Pointer to the bit of assembly code that will perform the original 233 231 * NtCreateSection operation. */ … … 238 236 /** The patched NtCreateSection bytes (for restoring). */ 239 237 static uint8_t g_abNtCreateSectionPatch[16]; 240 #if 0241 /** The jump back address of the patched LdrLoadDll. */242 extern "C" PFNRT g_pfnLdrLoadDllJmpBack = NULL;243 #endif244 238 /** Pointer to the bit of assembly code that will perform the original 245 239 * LdrLoadDll operation. */ … … 320 314 bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust, 321 315 bool *pfQuietFailure); 322 static void supR3HardenedWinRegisterDllNotificationCallback(void); 323 static void supR3HardenedWinReInstallHooks(bool fFirst); 324 325 326 #ifdef RT_ARCH_AMD64 327 # define SYSCALL(a_Num) DECLASM(void) RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num)(void) 328 # include "NtCreateSection-template-amd64-syscall-type-1.h" 329 # undef SYSCALL 330 #endif 331 #ifdef RT_ARCH_X86 332 # define SYSCALL(a_Num) DECLASM(void) RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num)(void) 333 # include "NtCreateSection-template-x86-syscall-type-1.h" 334 # undef SYSCALL 335 #endif 336 337 DECLASM(void) supR3HardenedEarlyProcessInitThunk(void); 316 static void supR3HardenedWinRegisterDllNotificationCallback(void); 317 static void supR3HardenedWinReInstallHooks(bool fFirst); 318 DECLASM(void) supR3HardenedEarlyProcessInitThunk(void); 338 319 339 320 … … 1989 1970 else 1990 1971 SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath)); 1972 1991 1973 supR3HardenedWinVerifyCacheProcessWvtTodos(); 1992 1974 … … 2528 2510 //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll); 2529 2511 2530 2531 #ifdef RT_ARCH_AMD64 2532 /* 2533 * For 64-bit hosts we need some memory within a +/-2GB range of the 2534 * actual function to be able to patch it. 2535 */ 2536 uintptr_t uStart = RT_MAX((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll); 2537 size_t cbMem = _4K; 2538 void *pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart - _2G + PAGE_SIZE, -1, cbMem); 2539 if (!pvMem) 2540 { 2541 uintptr_t uStart = RT_MIN((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll); 2542 pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart + _2G - PAGE_SIZE, 1, cbMem); 2543 if (!pvMem) 2544 supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY, 2545 "Failed to allocate memory within the +/-2GB range from NTDLL.\n"); 2546 } 2547 uintptr_t *puJmpTab = (uintptr_t *)pvMem; 2548 #endif 2512 /* 2513 * Exec page setup & management. 2514 */ 2515 uint32_t offExecPage = 0; 2516 memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE); 2549 2517 2550 2518 /* … … 2556 2524 g_pbNtCreateSection = pbNtCreateSection; 2557 2525 memcpy(g_abNtCreateSectionPatch, pbNtCreateSection, sizeof(g_abNtCreateSectionPatch)); 2558 /** @todo This patch could be simplified iff we had our own syscall operational 2559 * from the get-go.*/2526 2527 g_pfnNtCreateSectionReal = NtCreateSection; /* our direct syscall */ 2560 2528 2561 2529 #ifdef RT_ARCH_AMD64 … … 2563 2531 * Patch 64-bit hosts. 2564 2532 */ 2565 PFNRT pfnCallReal = NULL;2566 uint8_t offJmpBack = UINT8_MAX;2567 2568 2533 /* Pattern #1: XP64/W2K3-64 thru Windows 8.1 2569 2534 0:000> u ntdll!NtCreateSection … … 2575 2540 00000000`779f175b 0f1f440000 nop dword ptr [rax+rax] 2576 2541 The variant is the value loaded into eax: W2K3=??, Vista=47h?, W7=47h, W80=48h, W81=49h */ 2577 if ( pbNtCreateSection[ 0] == 0x4c /* mov r10, rcx */2578 && pbNtCreateSection[ 1] == 0x8b2579 && pbNtCreateSection[ 2] == 0xd12580 && pbNtCreateSection[ 3] == 0xb8 /* mov eax, 000000xxh */2581 && pbNtCreateSection[ 5] == 0x002582 && pbNtCreateSection[ 6] == 0x002583 && pbNtCreateSection[ 7] == 0x002584 && pbNtCreateSection[ 8] == 0x0f /* syscall */2585 && pbNtCreateSection[ 9] == 0x052586 && pbNtCreateSection[10] == 0xc3 /* ret */2587 )2588 {2589 offJmpBack = 8; /* the 3rd instruction (syscall). */2590 switch (pbNtCreateSection[4])2591 {2592 # define SYSCALL(a_Num) case a_Num: pfnCallReal = RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num); break;2593 # include "NtCreateSection-template-amd64-syscall-type-1.h"2594 # undef SYSCALL2595 }2596 }2597 if (!pfnCallReal)2598 supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);2599 2600 g_pfnNtCreateSectionJmpBack = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);2601 *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;2602 2542 2603 2543 /* Assemble the patch. */ 2604 g_abNtCreateSectionPatch[0] = 0xff; 2605 g_abNtCreateSectionPatch[1] = 0x25; 2606 *(uint32_t *)&g_abNtCreateSectionPatch[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]); 2607 2608 *puJmpTab = (uintptr_t)supR3HardenedMonitor_NtCreateSection; 2609 puJmpTab++; 2544 g_abNtCreateSectionPatch[0] = 0x48; /* mov rax, qword */ 2545 g_abNtCreateSectionPatch[1] = 0xb8; 2546 *(uint64_t *)&g_abNtCreateSectionPatch[2] = (uint64_t)supR3HardenedMonitor_NtCreateSection; 2547 g_abNtCreateSectionPatch[10] = 0xff; /* jmp rax */ 2548 g_abNtCreateSectionPatch[11] = 0xe0; 2610 2549 2611 2550 #else … … 2613 2552 * Patch 32-bit hosts. 2614 2553 */ 2615 PFNRT pfnCallReal = NULL;2616 uint8_t offJmpBack = UINT8_MAX;2617 2618 2554 /* Pattern #1: XP thru Windows 7 2619 2555 kd> u ntdll!NtCreateSection … … 2635 2571 6a15eacb 0f34 sysenter 2636 2572 6a15eacd c3 ret 2637 The variable bit is the value loaded into eax: W81=154h 2638 Note! One nice thing here is that we can share code pattern #1. */ 2639 2640 if ( pbNtCreateSection[ 0] == 0xb8 /* mov eax, 000000xxh*/ 2641 && pbNtCreateSection[ 2] <= 0x02 2642 && pbNtCreateSection[ 3] == 0x00 2643 && pbNtCreateSection[ 4] == 0x00 2644 && ( ( pbNtCreateSection[ 5] == 0xba /* mov edx, offset SharedUserData!SystemCallStub */ 2645 && pbNtCreateSection[ 6] == 0x00 2646 && pbNtCreateSection[ 7] == 0x03 2647 && pbNtCreateSection[ 8] == 0xfe 2648 && pbNtCreateSection[ 9] == 0x7f 2649 && pbNtCreateSection[10] == 0xff /* call [edx] */ 2650 && pbNtCreateSection[11] == 0x12 2651 && pbNtCreateSection[12] == 0xc2 /* ret 1ch */ 2652 && pbNtCreateSection[13] == 0x1c 2653 && pbNtCreateSection[14] == 0x00) 2654 2655 || ( pbNtCreateSection[ 5] == 0xe8 /* call [$+3] */ 2656 && RT_ABS(*(int32_t *)&pbNtCreateSection[6]) < 0x10 2657 && pbNtCreateSection[10] == 0xc2 /* ret 1ch */ 2658 && pbNtCreateSection[11] == 0x1c 2659 && pbNtCreateSection[12] == 0x00 ) 2660 ) 2661 ) 2662 { 2663 offJmpBack = 5; /* the 2nd instruction. */ 2664 switch (*(uint32_t const *)&pbNtCreateSection[1]) 2665 { 2666 # define SYSCALL(a_Num) case a_Num: pfnCallReal = RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num); break; 2667 # include "NtCreateSection-template-x86-syscall-type-1.h" 2668 # undef SYSCALL 2669 } 2670 } 2671 if (!pfnCallReal) 2672 supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection); 2673 2674 g_pfnNtCreateSectionJmpBack = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack); 2675 *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal; 2573 The variable bit is the value loaded into eax: W81=154h */ 2676 2574 2677 2575 /* Assemble the patch. */ 2678 g_abNtCreateSectionPatch[0] = 0xe9; 2576 g_abNtCreateSectionPatch[0] = 0xe9; /* jmp rel32 */ 2679 2577 *(uint32_t *)&g_abNtCreateSectionPatch[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection 2680 2578 - (uintptr_t)&pbNtCreateSection[1+4]; 2579 2681 2580 #endif 2682 2683 /*2684 * Exec page setup & management.2685 */2686 uint32_t offExecPage = 0;2687 memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);2688 2581 2689 2582 /* … … 2700 2593 memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch)); 2701 2594 2702 #ifdef RT_ARCH_AMD642703 /*2704 * Patch 64-bit hosts.2705 */2706 /* Just use the disassembler to skip 6 bytes or more. */2707 2595 DISSTATE Dis; 2708 2596 uint32_t cbInstr; 2709 offJmpBack = 0; 2710 while (offJmpBack < 6) 2597 uint32_t offJmpBack = 0; 2598 2599 #ifdef RT_ARCH_AMD64 2600 /* 2601 * Patch 64-bit hosts. 2602 */ 2603 /* Just use the disassembler to skip 12 bytes or more. */ 2604 while (offJmpBack < 12) 2711 2605 { 2712 2606 cbInstr = 1; … … 2733 2627 2734 2628 /* Assemble the LdrLoadDll patch. */ 2735 Assert(offJmpBack >= 6); 2736 g_abLdrLoadDllPatch[0] = 0xff; 2737 g_abLdrLoadDllPatch[1] = 0x25; 2738 *(uint32_t *)&g_abLdrLoadDllPatch[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]); 2739 2740 *puJmpTab = (uintptr_t)supR3HardenedMonitor_LdrLoadDll; 2741 puJmpTab++; 2629 Assert(offJmpBack >= 12); 2630 g_abLdrLoadDllPatch[0] = 0x48; /* mov rax, qword */ 2631 g_abLdrLoadDllPatch[1] = 0xb8; 2632 *(uint64_t *)&g_abLdrLoadDllPatch[2] = (uint64_t)supR3HardenedMonitor_LdrLoadDll; 2633 g_abLdrLoadDllPatch[10] = 0xff; /* jmp rax */ 2634 g_abLdrLoadDllPatch[11] = 0xe0; 2742 2635 2743 2636 #else … … 2745 2638 * Patch 32-bit hosts. 2746 2639 */ 2747 /* Just use the disassembler to skip 6 bytes or more. */ 2748 DISSTATE Dis; 2749 uint32_t cbInstr; 2750 offJmpBack = 0; 2640 /* Just use the disassembler to skip 5 bytes or more. */ 2751 2641 while (offJmpBack < 5) 2752 2642 { … … 2765 2655 offExecPage += offJmpBack; 2766 2656 2767 g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9; 2657 g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9; /* jmp rel32 */ 2768 2658 *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack] 2769 2659 - (uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage + 4]; … … 3524 3414 } 3525 3415 3416 #if 0 3526 3417 /* 3527 3418 * Map kernel32.dll and kernelbase.dll (if applicable) into the process. … … 3536 3427 ? supR3HardNtPuChMapDllIntoChild(pThis, &NtName3, "KernelBase.dll") 3537 3428 : NULL; 3429 #endif 3538 3430 3539 3431 /* … … 3543 3435 uint64_t uMsTsStart = supR3HardenedWinGetMilliTS(); 3544 3436 uint32_t cMsKludge = (g_fSupAdversaries & SUPHARDNT_ADVERSARY_SYMANTEC_SYSPLANT) ? 256 : g_fSupAdversaries ? 64 : 16; 3437 cMsKludge = 1024; 3545 3438 do 3546 3439 { … … 3553 3446 supR3HardenedWinGetMilliTS() - uMsTsStart)); 3554 3447 3448 #if 0 3555 3449 /* 3556 3450 * Unmap the image we mapped into the guest above. … … 3560 3454 supR3HardNtPuChUnmapDllFromChild(pThis, pvNtDll2, "ntdll.dll[2nd]"); 3561 3455 supR3HardNtPuChUnmapDllFromChild(pThis, pvExe2, "executable[2nd]"); 3456 #endif 3562 3457 3563 3458 /* … … 5641 5536 5642 5537 /* 5538 * Set up the direct system calls so we can more easily hook NtCreateSection. 5539 */ 5540 supR3HardenedWinInitSyscalls(true /*fReportErrors*/); 5541 5542 /* 5643 5543 * Determine the executable path and name. Will NOT determine the windows style 5644 5544 * executable path here as we don't need it. -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm
r52950 r52967 32 32 33 33 34 ; External data.35 extern NAME(g_pfnNtCreateSectionJmpBack)36 37 34 ; External code. 38 35 extern NAME(supR3HardenedEarlyProcessInit) … … 40 37 41 38 BEGINCODE 42 43 ;44 ; 64-bit45 ;46 %ifdef RT_ARCH_AMD6447 %macro supR3HardenedJmpBack_NtCreateSection_Xxx 148 BEGINPROC supR3HardenedJmpBack_NtCreateSection_ %+ %149 SEH64_END_PROLOGUE50 ; The code we replaced.51 mov r10, rcx52 mov eax, %153 54 ; Jump back to the original code.55 jmp [NAME(g_pfnNtCreateSectionJmpBack) wrt RIP]56 ENDPROC supR3HardenedJmpBack_NtCreateSection_ %+ %157 %endm58 %define SYSCALL(a_Num) supR3HardenedJmpBack_NtCreateSection_Xxx a_Num59 %include "NtCreateSection-template-amd64-syscall-type-1.h"60 61 %endif62 63 64 ;65 ; 32-bit.66 ;67 %ifdef RT_ARCH_X8668 %macro supR3HardenedJmpBack_NtCreateSection_Xxx 169 BEGINPROC supR3HardenedJmpBack_NtCreateSection_ %+ %170 ; The code we replaced.71 mov eax, %172 73 ; Jump back to the original code.74 jmp [NAME(g_pfnNtCreateSectionJmpBack)]75 ENDPROC supR3HardenedJmpBack_NtCreateSection_ %+ %176 %endm77 %define SYSCALL(a_Num) supR3HardenedJmpBack_NtCreateSection_Xxx a_Num78 %include "NtCreateSection-template-x86-syscall-type-1.h"79 80 %endif81 82 39 83 40 -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp
r52947 r52967 48 48 #define VBOX_HARDENED_STUB_WITHOUT_IMPORTS 49 49 #ifdef VBOX_HARDENED_STUB_WITHOUT_IMPORTS 50 # define SUPHNTIMP_ERROR(a_id, a_szWhere, a_enmOp, a_rc, ...) \ 51 do { static const char s_szWhere[] = a_szWhere; *(char *)(uintptr_t)(a_id) += 1; __debugbreak(); } while (0) 50 # define SUPHNTIMP_ERROR(a_fReportErrors, a_id, a_szWhere, a_enmOp, a_rc, ...) \ 51 do { \ 52 if (a_fReportErrors) supR3HardenedFatalMsg(a_szWhere, a_enmOp, a_rc, __VA_ARGS__); \ 53 else { static const char s_szWhere[] = a_szWhere; *(char *)(uintptr_t)(a_id) += 1; __debugbreak(); } \ 54 } while (0) 52 55 #else 53 # define SUPHNTIMP_ERROR(a_ id, a_szWhere, a_enmOp, a_rc, ...) \56 # define SUPHNTIMP_ERROR(a_fReportErrors, a_id, a_szWhere, a_enmOp, a_rc, ...) \ 54 57 supR3HardenedFatalMsg(a_szWhere, a_enmOp, a_rc, __VA_ARGS__) 55 58 … … 268 271 pDll->pbImageBase = NULL; /* optional */ 269 272 else 270 SUPHNTIMP_ERROR( 1, "supR3HardenedFindOrLoadModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,273 SUPHNTIMP_ERROR(false, 1, "supR3HardenedFindOrLoadModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 271 274 "Failed to locate %ls", pDll->pwszName); 272 275 #else 273 276 HMODULE hmod = GetModuleHandleW(pDll->pwszName); 274 277 if (RT_UNLIKELY(!hmod && pDll->cImports)) 275 SUPHNTIMP_ERROR( 1, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,278 SUPHNTIMP_ERROR(true, 1, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 276 279 "Failed to locate %ls", pDll->pwszName); 277 280 pDll->pbImageBase = (uint8_t *)hmod; … … 292 295 offNtHdrs = pMzHdr->e_lfanew; 293 296 if (offNtHdrs > _2K) 294 SUPHNTIMP_ERROR( 2, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,297 SUPHNTIMP_ERROR(false, 2, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 295 298 "%ls: e_lfanew=%#x, expected a lower value", pDll->pwszName, offNtHdrs); 296 299 } … … 298 301 299 302 if (pNtHdrs->Signature != IMAGE_NT_SIGNATURE) 300 SUPHNTIMP_ERROR( 3, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,303 SUPHNTIMP_ERROR(false, 3, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 301 304 "%ls: Invalid PE signature: %#x", pDll->pwszName, pNtHdrs->Signature); 302 305 if (pNtHdrs->FileHeader.SizeOfOptionalHeader != sizeof(pNtHdrs->OptionalHeader)) 303 SUPHNTIMP_ERROR( 4, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,306 SUPHNTIMP_ERROR(false, 4, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 304 307 "%ls: Unexpected optional header size: %#x", pDll->pwszName, pNtHdrs->FileHeader.SizeOfOptionalHeader); 305 308 if (pNtHdrs->OptionalHeader.Magic != RT_CONCAT3(IMAGE_NT_OPTIONAL_HDR,ARCH_BITS,_MAGIC)) 306 SUPHNTIMP_ERROR( 5, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,309 SUPHNTIMP_ERROR(false, 5, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 307 310 "%ls: Unexpected optional header magic: %#x", pDll->pwszName, pNtHdrs->OptionalHeader.Magic); 308 311 if (pNtHdrs->OptionalHeader.NumberOfRvaAndSizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES) 309 SUPHNTIMP_ERROR( 6, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,312 SUPHNTIMP_ERROR(false, 6, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 310 313 "%ls: Unexpected number of RVA and sizes: %#x", pDll->pwszName, pNtHdrs->OptionalHeader.NumberOfRvaAndSizes); 311 314 … … 324 327 || ExpDir.VirtualAddress >= pNtHdrs->OptionalHeader.SizeOfImage 325 328 || ExpDir.VirtualAddress + ExpDir.Size > pNtHdrs->OptionalHeader.SizeOfImage) 326 SUPHNTIMP_ERROR( 7, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,329 SUPHNTIMP_ERROR(false, 7, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 327 330 "%ls: Missing or invalid export directory: %#lx LB %#x", pDll->pwszName, ExpDir.VirtualAddress, ExpDir.Size); 328 331 pDll->offExportDir = ExpDir.VirtualAddress; … … 335 338 || pExpDir->NumberOfNames >= _1M 336 339 || pExpDir->NumberOfNames < 1) 337 SUPHNTIMP_ERROR( 8, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,340 SUPHNTIMP_ERROR(false, 8, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 338 341 "%ls: NumberOfNames or/and NumberOfFunctions are outside the expected range: nof=%#x non=%#x\n", 339 342 pDll->pwszName, pExpDir->NumberOfFunctions, pExpDir->NumberOfNames); … … 344 347 || pExpDir->AddressOfFunctions >= pNtHdrs->OptionalHeader.SizeOfImage 345 348 || pExpDir->AddressOfFunctions + pDll->cExports * sizeof(uint32_t) > pNtHdrs->OptionalHeader.SizeOfImage) 346 SUPHNTIMP_ERROR( 9, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,349 SUPHNTIMP_ERROR(false, 9, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 347 350 "%ls: Bad AddressOfFunctions: %#x\n", pDll->pwszName, pExpDir->AddressOfFunctions); 348 351 pDll->paoffExports = (uint32_t const *)&pDll->pbImageBase[pExpDir->AddressOfFunctions]; … … 351 354 || pExpDir->AddressOfNames >= pNtHdrs->OptionalHeader.SizeOfImage 352 355 || pExpDir->AddressOfNames + pExpDir->NumberOfNames * sizeof(uint32_t) > pNtHdrs->OptionalHeader.SizeOfImage) 353 SUPHNTIMP_ERROR( 10, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,356 SUPHNTIMP_ERROR(false, 10, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 354 357 "%ls: Bad AddressOfNames: %#x\n", pDll->pwszName, pExpDir->AddressOfNames); 355 358 pDll->paoffNamedExports = (uint32_t const *)&pDll->pbImageBase[pExpDir->AddressOfNames]; … … 358 361 || pExpDir->AddressOfNameOrdinals >= pNtHdrs->OptionalHeader.SizeOfImage 359 362 || pExpDir->AddressOfNameOrdinals + pExpDir->NumberOfNames * sizeof(uint32_t) > pNtHdrs->OptionalHeader.SizeOfImage) 360 SUPHNTIMP_ERROR( 11, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE,363 SUPHNTIMP_ERROR(false, 11, "supR3HardenedParseModule", kSupInitOp_Misc, VERR_INVALID_EXE_SIGNATURE, 361 364 "%ls: Bad AddressOfNameOrdinals: %#x\n", pDll->pwszName, pExpDir->AddressOfNameOrdinals); 362 365 pDll->pau16NameOrdinals = (uint16_t const *)&pDll->pbImageBase[pExpDir->AddressOfNameOrdinals]; … … 364 367 365 368 366 static const char *supR3HardenedResolveImport(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport )369 static const char *supR3HardenedResolveImport(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport, bool fReportErrors) 367 370 { 368 371 /* … … 376 379 uint32_t offExpName = pDll->paoffNamedExports[iCur]; 377 380 if (RT_UNLIKELY(offExpName < pDll->offEndSectHdrs || offExpName >= pDll->cbImage)) 378 SUPHNTIMP_ERROR( 12, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_SYMBOL_NOT_FOUND,381 SUPHNTIMP_ERROR(fReportErrors, 12, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_SYMBOL_NOT_FOUND, 379 382 "%ls: Bad export name entry: %#x (iCur=%#x)", pDll->pwszName, offExpName, iCur); 380 383 … … 405 408 return (const char *)&pDll->pbImageBase[offExport]; 406 409 } 407 SUPHNTIMP_ERROR( 14, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_BAD_EXE_FORMAT,410 SUPHNTIMP_ERROR(fReportErrors, 14, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_BAD_EXE_FORMAT, 408 411 "%ls: Name ordinal for '%s' is out of bounds: %#x (max %#x)", 409 412 pDll->pwszName, iExpOrdinal, pDll->cExports); … … 413 416 414 417 if (!pImport->fOptional) 415 SUPHNTIMP_ERROR( 15, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_SYMBOL_NOT_FOUND,418 SUPHNTIMP_ERROR(fReportErrors, 15, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_SYMBOL_NOT_FOUND, 416 419 "%ls: Failed to resolve '%s'.", pDll->pwszName, pImport->pszName); 417 420 *pImport->ppfnImport = NULL; … … 421 424 422 425 static void supR3HardenedDirectSyscall(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport, PCSUPHNTIMPSYSCALL pSyscall, 423 PSUPHNTLDRCACHEENTRY pLdrEntry, uint8_t *pbBits )426 PSUPHNTLDRCACHEENTRY pLdrEntry, uint8_t *pbBits, bool fReportErrors) 424 427 { 425 428 /* … … 436 439 if (RT_FAILURE(rc)) 437 440 { 438 SUPHNTIMP_ERROR( 16, "supR3HardenedDirectSyscall", kSupInitOp_Misc, rc,441 SUPHNTIMP_ERROR(fReportErrors, 16, "supR3HardenedDirectSyscall", kSupInitOp_Misc, rc, 439 442 "%s: RTLdrGetSymbolEx failed on %s: %Rrc", pDll->pszName, pImport->pszName, rc); 440 443 return; … … 541 544 volatile uint8_t abCopy[16]; 542 545 memcpy((void *)&abCopy[0], pbFunction, sizeof(abCopy)); 543 SUPHNTIMP_ERROR( 17, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,546 SUPHNTIMP_ERROR(fReportErrors, 17, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc, 544 547 "%ls: supHardNtLdrCacheOpen failed: '%s': %.16Rhxs", 545 g_aSupNtImpDlls[iDll].pwszName, pImport->pszName, &abCopy[0]);548 pDll->pwszName, pImport->pszName, &abCopy[0]); 546 549 } 547 550 548 551 549 552 /** 550 * Resolves NtDll functions we can trust calling before process init. 551 * 552 * @param uNtDllAddr The address of the NTDLL. 553 */ 554 DECLHIDDEN(void) supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr) 555 { 556 /* 557 * NTDLL is the first entry in the list. 558 */ 559 g_aSupNtImpDlls[0].pbImageBase = (uint8_t const *)uNtDllAddr; 560 supR3HardenedParseModule(&g_aSupNtImpDlls[0]); 561 for (uint32_t i = 0; i < g_aSupNtImpDlls[0].cImports; i++) 562 if (!g_aSupNtImpDlls[0].paImports[i].pfnEarlyDummy) 563 { 564 const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &g_aSupNtImpDlls[0].paImports[i]); 565 if (pszForwarder) 566 SUPHNTIMP_ERROR(32, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 567 "ntdll: Failed to resolve forwarder '%s'.", pszForwarder); 568 } 569 else 570 *g_aSupNtImpDlls[0].paImports[i].ppfnImport = g_aSupNtImpDlls[0].paImports[i].pfnEarlyDummy; 571 572 /* 573 * Pointer the other imports at the early init stubs. 574 */ 575 for (uint32_t iDll = 1; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 576 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 577 if (!g_aSupNtImpDlls[iDll].paImports[i].fOptional) 578 *g_aSupNtImpDlls[iDll].paImports[i].ppfnImport = g_aSupNtImpDlls[iDll].paImports[i].pfnEarlyDummy; 579 else 580 *g_aSupNtImpDlls[iDll].paImports[i].ppfnImport = NULL; 581 } 582 583 584 /** 585 * Resolves imported functions, esp. system calls from NTDLL. 586 * 587 * This crap is necessary because there are sandboxing products out there that 588 * will mess with system calls we make, just like any other wannabe userland 589 * rootkit. Kudos to microsoft for not providing a generic system call hook API 590 * in the kernel mode, which I guess is what forcing these kind of products to 591 * do ugly userland hacks that doesn't really hold water. 592 */ 593 DECLHIDDEN(void) supR3HardenedWinInitImports(void) 594 { 595 /* 596 * Find the DLLs we will be needing first (forwarders). 597 */ 598 for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 599 { 600 supR3HardenedFindOrLoadModule(&g_aSupNtImpDlls[iDll]); 601 if (g_aSupNtImpDlls[iDll].pbImageBase) 602 supR3HardenedParseModule(&g_aSupNtImpDlls[iDll]); 603 } 604 605 /* 606 * Resolve the functions. 607 */ 608 for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 609 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 610 { 611 const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[iDll], &g_aSupNtImpDlls[iDll].paImports[i]); 612 if (pszForwarder) 613 { 614 const char *pszDot = strchr(pszForwarder, '.'); 615 size_t cchDllName = pszDot - pszForwarder; 616 SUPHNTIMPFUNC Tmp = g_aSupNtImpDlls[iDll].paImports[i]; 617 Tmp.pszName = pszDot + 1; 618 if (cchDllName == sizeof("ntdll") - 1 && RTStrNICmp(pszForwarder, RT_STR_TUPLE("ntdll")) == 0) 619 supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &Tmp); 620 else if (cchDllName == sizeof("kernelbase") - 1 && RTStrNICmp(pszForwarder, RT_STR_TUPLE("kernelbase")) == 0) 621 supR3HardenedResolveImport(&g_aSupNtImpDlls[1], &Tmp); 622 else 623 SUPHNTIMP_ERROR(18, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 624 "%ls: Failed to resolve forwarder '%s'.", g_aSupNtImpDlls[iDll].pwszName, pszForwarder); 625 } 626 } 627 628 /* 629 * Check out system calls and try do them directly if we can. 630 * In order to do this though, we need to access the DLL on disk as we 631 * cannot trust the memory content to be unpatched. 632 * 633 * Note! It's too early to validate any signatures. 634 */ 553 * Check out system calls and do the directly instead of via NtDll. 554 * 555 * We need to have access to the on disk NTDLL.DLL file as we do not trust the 556 * stuff we find in memory. Too early to verify signatures though. 557 * 558 * @param fReportErrors Whether we've got the machinery for reporting 559 * errors going already. 560 */ 561 DECLHIDDEN(void) supR3HardenedWinInitSyscalls(bool fReportErrors) 562 { 635 563 for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 636 564 if (g_aSupNtImpDlls[iDll].paSyscalls) … … 647 575 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 648 576 supR3HardenedDirectSyscall(&g_aSupNtImpDlls[iDll], &g_aSupNtImpDlls[iDll].paImports[i], 649 &g_aSupNtImpDlls[iDll].paSyscalls[i], pLdrEntry, pbBits );577 &g_aSupNtImpDlls[iDll].paSyscalls[i], pLdrEntry, pbBits, fReportErrors); 650 578 } 651 579 else 652 SUPHNTIMP_ERROR( 20, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,580 SUPHNTIMP_ERROR(fReportErrors, 20, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc, 653 581 "%ls: supHardNtLdrCacheEntryGetBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc); 654 582 } 655 583 else 656 SUPHNTIMP_ERROR( 21, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,584 SUPHNTIMP_ERROR(fReportErrors, 21, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc, 657 585 "%ls: supHardNtLdrCacheOpen failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc); 658 586 } 587 } 588 589 590 591 /** 592 * Resolves NtDll functions we can trust calling before process init. 593 * 594 * @param uNtDllAddr The address of the NTDLL. 595 */ 596 DECLHIDDEN(void) supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr) 597 { 598 /* 599 * NTDLL is the first entry in the list. 600 */ 601 g_aSupNtImpDlls[0].pbImageBase = (uint8_t const *)uNtDllAddr; 602 supR3HardenedParseModule(&g_aSupNtImpDlls[0]); 603 for (uint32_t i = 0; i < g_aSupNtImpDlls[0].cImports; i++) 604 if (!g_aSupNtImpDlls[0].paImports[i].pfnEarlyDummy) 605 { 606 const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &g_aSupNtImpDlls[0].paImports[i], false); 607 if (pszForwarder) 608 SUPHNTIMP_ERROR(false, 32, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 609 "ntdll: Failed to resolve forwarder '%s'.", pszForwarder); 610 } 611 else 612 *g_aSupNtImpDlls[0].paImports[i].ppfnImport = g_aSupNtImpDlls[0].paImports[i].pfnEarlyDummy; 613 614 /* 615 * Pointer the other imports at the early init stubs. 616 */ 617 for (uint32_t iDll = 1; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 618 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 619 if (!g_aSupNtImpDlls[iDll].paImports[i].fOptional) 620 *g_aSupNtImpDlls[iDll].paImports[i].ppfnImport = g_aSupNtImpDlls[iDll].paImports[i].pfnEarlyDummy; 621 else 622 *g_aSupNtImpDlls[iDll].paImports[i].ppfnImport = NULL; 623 } 624 625 626 /** 627 * Resolves imported functions, esp. system calls from NTDLL. 628 * 629 * This crap is necessary because there are sandboxing products out there that 630 * will mess with system calls we make, just like any other wannabe userland 631 * rootkit. Kudos to microsoft for not providing a generic system call hook API 632 * in the kernel mode, which I guess is what forcing these kind of products to 633 * do ugly userland hacks that doesn't really hold water. 634 */ 635 DECLHIDDEN(void) supR3HardenedWinInitImports(void) 636 { 637 /* 638 * Find the DLLs we will be needing first (forwarders). 639 */ 640 for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 641 { 642 supR3HardenedFindOrLoadModule(&g_aSupNtImpDlls[iDll]); 643 if (g_aSupNtImpDlls[iDll].pbImageBase) 644 supR3HardenedParseModule(&g_aSupNtImpDlls[iDll]); 645 } 646 647 /* 648 * Resolve the functions. 649 */ 650 for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++) 651 for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++) 652 { 653 const char *pszForwarder = supR3HardenedResolveImport(&g_aSupNtImpDlls[iDll], &g_aSupNtImpDlls[iDll].paImports[i], 654 false); 655 if (pszForwarder) 656 { 657 const char *pszDot = strchr(pszForwarder, '.'); 658 size_t cchDllName = pszDot - pszForwarder; 659 SUPHNTIMPFUNC Tmp = g_aSupNtImpDlls[iDll].paImports[i]; 660 Tmp.pszName = pszDot + 1; 661 if (cchDllName == sizeof("ntdll") - 1 && RTStrNICmp(pszForwarder, RT_STR_TUPLE("ntdll")) == 0) 662 supR3HardenedResolveImport(&g_aSupNtImpDlls[0], &Tmp, false); 663 else if (cchDllName == sizeof("kernelbase") - 1 && RTStrNICmp(pszForwarder, RT_STR_TUPLE("kernelbase")) == 0) 664 supR3HardenedResolveImport(&g_aSupNtImpDlls[1], &Tmp, false); 665 else 666 SUPHNTIMP_ERROR(false, 18, "supR3HardenedWinInitImports", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND, 667 "%ls: Failed to resolve forwarder '%s'.", g_aSupNtImpDlls[iDll].pwszName, pszForwarder); 668 } 669 } 670 671 /* 672 * Do system calls directly. 673 */ 674 supR3HardenedWinInitSyscalls(false); 659 675 660 676 /*
Note:
See TracChangeset
for help on using the changeset viewer.