VirtualBox

Changeset 52967 in vbox


Ignore:
Timestamp:
Oct 6, 2014 10:18:51 PM (10 years ago)
Author:
vboxsync
Message:

SUP: simplified the ntdll hooking / patching so we can avoid the jump table memory as it may end up where system dlls like kernel32 are supposed to be loaded (STATUS_CONFLICTING_ADDRESSES (0xc0000018) process init failure).

Location:
trunk/src/VBox/HostDrivers/Support
Files:
2 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h

    r52962 r52967  
    449449DECLHIDDEN(void)    supR3HardenedWinInitImports(void);
    450450DECLHIDDEN(void)    supR3HardenedWinInitImportsEarly(uintptr_t uNtDllAddr);
     451DECLHIDDEN(void)    supR3HardenedWinInitSyscalls(bool fReportErrors);
    451452DECLHIDDEN(PFNRT)   supR3HardenedWinGetRealDllSymbol(const char *pszDll, const char *pszProcedure);
    452453DECLHIDDEN(void)    supR3HardenedWinEnableThreadCreation(void);
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp

    r52966 r52967  
    843843                return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'NtCreateSection': %Rrc", pImage->pszName, rc);
    844844            aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue;
    845             aSkipAreas[cSkipAreas++].cb = 5 + (ARCH_BITS == 64);
     845            aSkipAreas[cSkipAreas++].cb = ARCH_BITS == 32 ? 5 : 12;
    846846
    847847            /* Ignore our LdrLoadDll hack. */
     
    850850                return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'LdrLoadDll': %Rrc", pImage->pszName, rc);
    851851            aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue;
    852             aSkipAreas[cSkipAreas++].cb = 5 + (ARCH_BITS == 64);
     852            aSkipAreas[cSkipAreas++].cb = ARCH_BITS == 32 ? 5 : 12;
    853853        }
    854854
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp

    r52962 r52967  
    228228/** @name Hook related variables.
    229229 * @{ */
    230 /** The jump back address of the patched NtCreateSection. */
    231 extern "C" PFNRT            g_pfnNtCreateSectionJmpBack = NULL;
    232230/** Pointer to the bit of assembly code that will perform the original
    233231 *  NtCreateSection operation. */
     
    238236/** The patched NtCreateSection bytes (for restoring). */
    239237static uint8_t              g_abNtCreateSectionPatch[16];
    240 #if 0
    241 /** The jump back address of the patched LdrLoadDll. */
    242 extern "C" PFNRT            g_pfnLdrLoadDllJmpBack = NULL;
    243 #endif
    244238/** Pointer to the bit of assembly code that will perform the original
    245239 *  LdrLoadDll operation. */
     
    320314                                         bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
    321315                                         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);
     316static void     supR3HardenedWinRegisterDllNotificationCallback(void);
     317static void     supR3HardenedWinReInstallHooks(bool fFirst);
     318DECLASM(void)   supR3HardenedEarlyProcessInitThunk(void);
    338319
    339320
     
    19891970    else
    19901971        SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
     1972
    19911973    supR3HardenedWinVerifyCacheProcessWvtTodos();
    19921974
     
    25282510    //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll);
    25292511
    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);
    25492517
    25502518    /*
     
    25562524    g_pbNtCreateSection = pbNtCreateSection;
    25572525    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 */
    25602528
    25612529#ifdef RT_ARCH_AMD64
     
    25632531     * Patch 64-bit hosts.
    25642532     */
    2565     PFNRT       pfnCallReal = NULL;
    2566     uint8_t     offJmpBack  = UINT8_MAX;
    2567 
    25682533    /* Pattern #1: XP64/W2K3-64 thru Windows 8.1
    25692534       0:000> u ntdll!NtCreateSection
     
    25752540       00000000`779f175b 0f1f440000      nop     dword ptr [rax+rax]
    25762541       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] == 0x8b
    2579         && pbNtCreateSection[ 2] == 0xd1
    2580         && pbNtCreateSection[ 3] == 0xb8 /* mov eax, 000000xxh */
    2581         && pbNtCreateSection[ 5] == 0x00
    2582         && pbNtCreateSection[ 6] == 0x00
    2583         && pbNtCreateSection[ 7] == 0x00
    2584         && pbNtCreateSection[ 8] == 0x0f /* syscall */
    2585         && pbNtCreateSection[ 9] == 0x05
    2586         && 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 SYSCALL
    2595         }
    2596     }
    2597     if (!pfnCallReal)
    2598         supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);
    2599 
    2600     g_pfnNtCreateSectionJmpBack         = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
    2601     *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
    26022542
    26032543    /* 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;
    26102549
    26112550#else
     
    26132552     * Patch 32-bit hosts.
    26142553     */
    2615     PFNRT       pfnCallReal = NULL;
    2616     uint8_t     offJmpBack  = UINT8_MAX;
    2617 
    26182554    /* Pattern #1: XP thru Windows 7
    26192555            kd> u ntdll!NtCreateSection
     
    26352571            6a15eacb 0f34            sysenter
    26362572            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 */
    26762574
    26772575    /* Assemble the patch. */
    2678     g_abNtCreateSectionPatch[0] = 0xe9;
     2576    g_abNtCreateSectionPatch[0] = 0xe9;  /* jmp rel32 */
    26792577    *(uint32_t *)&g_abNtCreateSectionPatch[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
    26802578                                              - (uintptr_t)&pbNtCreateSection[1+4];
     2579
    26812580#endif
    2682 
    2683     /*
    2684      * Exec page setup & management.
    2685      */
    2686     uint32_t offExecPage = 0;
    2687     memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
    26882581
    26892582    /*
     
    27002593    memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch));
    27012594
    2702 #ifdef RT_ARCH_AMD64
    2703     /*
    2704      * Patch 64-bit hosts.
    2705      */
    2706     /* Just use the disassembler to skip 6 bytes or more. */
    27072595    DISSTATE Dis;
    27082596    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)
    27112605    {
    27122606        cbInstr = 1;
     
    27332627
    27342628    /* 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;
    27422635
    27432636#else
     
    27452638     * Patch 32-bit hosts.
    27462639     */
    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. */
    27512641    while (offJmpBack < 5)
    27522642    {
     
    27652655    offExecPage += offJmpBack;
    27662656
    2767     g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9;
     2657    g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9; /* jmp rel32 */
    27682658    *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack]
    27692659                                                            - (uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage + 4];
     
    35243414    }
    35253415
     3416#if 0
    35263417    /*
    35273418     * Map kernel32.dll and kernelbase.dll (if applicable) into the process.
     
    35363427                       ? supR3HardNtPuChMapDllIntoChild(pThis, &NtName3, "KernelBase.dll")
    35373428                       : NULL;
     3429#endif
    35383430
    35393431    /*
     
    35433435    uint64_t uMsTsStart = supR3HardenedWinGetMilliTS();
    35443436    uint32_t cMsKludge = (g_fSupAdversaries & SUPHARDNT_ADVERSARY_SYMANTEC_SYSPLANT) ? 256 : g_fSupAdversaries ? 64 : 16;
     3437cMsKludge = 1024;
    35453438    do
    35463439    {
     
    35533446                 supR3HardenedWinGetMilliTS() - uMsTsStart));
    35543447
     3448#if 0
    35553449    /*
    35563450     * Unmap the image we mapped into the guest above.
     
    35603454    supR3HardNtPuChUnmapDllFromChild(pThis, pvNtDll2, "ntdll.dll[2nd]");
    35613455    supR3HardNtPuChUnmapDllFromChild(pThis, pvExe2, "executable[2nd]");
     3456#endif
    35623457
    35633458    /*
     
    56415536
    56425537    /*
     5538     * Set up the direct system calls so we can more easily hook NtCreateSection.
     5539     */
     5540    supR3HardenedWinInitSyscalls(true /*fReportErrors*/);
     5541
     5542    /*
    56435543     * Determine the executable path and name.  Will NOT determine the windows style
    56445544     * executable path here as we don't need it.
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm

    r52950 r52967  
    3232
    3333
    34 ; External data.
    35 extern NAME(g_pfnNtCreateSectionJmpBack)
    36 
    3734; External code.
    3835extern NAME(supR3HardenedEarlyProcessInit)
     
    4037
    4138BEGINCODE
    42 
    43 ;
    44 ; 64-bit
    45 ;
    46 %ifdef RT_ARCH_AMD64
    47  %macro supR3HardenedJmpBack_NtCreateSection_Xxx 1
    48  BEGINPROC supR3HardenedJmpBack_NtCreateSection_ %+ %1
    49         SEH64_END_PROLOGUE
    50         ; The code we replaced.
    51         mov     r10, rcx
    52         mov     eax, %1
    53 
    54         ; Jump back to the original code.
    55         jmp     [NAME(g_pfnNtCreateSectionJmpBack) wrt RIP]
    56  ENDPROC   supR3HardenedJmpBack_NtCreateSection_ %+ %1
    57  %endm
    58  %define SYSCALL(a_Num) supR3HardenedJmpBack_NtCreateSection_Xxx a_Num
    59  %include "NtCreateSection-template-amd64-syscall-type-1.h"
    60 
    61 %endif
    62 
    63 
    64 ;
    65 ; 32-bit.
    66 ;
    67 %ifdef RT_ARCH_X86
    68  %macro supR3HardenedJmpBack_NtCreateSection_Xxx 1
    69  BEGINPROC supR3HardenedJmpBack_NtCreateSection_ %+ %1
    70         ; The code we replaced.
    71         mov     eax, %1
    72 
    73         ; Jump back to the original code.
    74         jmp     [NAME(g_pfnNtCreateSectionJmpBack)]
    75  ENDPROC   supR3HardenedJmpBack_NtCreateSection_ %+ %1
    76  %endm
    77  %define SYSCALL(a_Num) supR3HardenedJmpBack_NtCreateSection_Xxx a_Num
    78  %include "NtCreateSection-template-x86-syscall-type-1.h"
    79 
    80 %endif
    81 
    8239
    8340
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainImports-win.cpp

    r52947 r52967  
    4848#define VBOX_HARDENED_STUB_WITHOUT_IMPORTS
    4949#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)
    5255#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, ...) \
    5457    supR3HardenedFatalMsg(a_szWhere, a_enmOp, a_rc, __VA_ARGS__)
    5558
     
    268271        pDll->pbImageBase = NULL; /* optional */
    269272    else
    270         SUPHNTIMP_ERROR(1, "supR3HardenedFindOrLoadModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,
     273        SUPHNTIMP_ERROR(false, 1, "supR3HardenedFindOrLoadModule", kSupInitOp_Misc, VERR_MODULE_NOT_FOUND,
    271274                        "Failed to locate %ls", pDll->pwszName);
    272275#else
    273276    HMODULE hmod = GetModuleHandleW(pDll->pwszName);
    274277    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,
    276279                        "Failed to locate %ls", pDll->pwszName);
    277280    pDll->pbImageBase = (uint8_t *)hmod;
     
    292295        offNtHdrs = pMzHdr->e_lfanew;
    293296        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,
    295298                            "%ls: e_lfanew=%#x, expected a lower value", pDll->pwszName, offNtHdrs);
    296299    }
     
    298301
    299302    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,
    301304                        "%ls: Invalid PE signature: %#x", pDll->pwszName, pNtHdrs->Signature);
    302305    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,
    304307                        "%ls: Unexpected optional header size: %#x", pDll->pwszName, pNtHdrs->FileHeader.SizeOfOptionalHeader);
    305308    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,
    307310                        "%ls: Unexpected optional header magic: %#x", pDll->pwszName, pNtHdrs->OptionalHeader.Magic);
    308311    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,
    310313                        "%ls: Unexpected number of RVA and sizes: %#x", pDll->pwszName, pNtHdrs->OptionalHeader.NumberOfRvaAndSizes);
    311314
     
    324327        || ExpDir.VirtualAddress >= pNtHdrs->OptionalHeader.SizeOfImage
    325328        || 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,
    327330                        "%ls: Missing or invalid export directory: %#lx LB %#x", pDll->pwszName, ExpDir.VirtualAddress, ExpDir.Size);
    328331    pDll->offExportDir = ExpDir.VirtualAddress;
     
    335338        || pExpDir->NumberOfNames     >= _1M
    336339        || 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,
    338341                        "%ls: NumberOfNames or/and NumberOfFunctions are outside the expected range: nof=%#x non=%#x\n",
    339342                        pDll->pwszName, pExpDir->NumberOfFunctions, pExpDir->NumberOfNames);
     
    344347        || pExpDir->AddressOfFunctions >= pNtHdrs->OptionalHeader.SizeOfImage
    345348        || 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,
    347350                           "%ls: Bad AddressOfFunctions: %#x\n", pDll->pwszName, pExpDir->AddressOfFunctions);
    348351    pDll->paoffExports = (uint32_t const *)&pDll->pbImageBase[pExpDir->AddressOfFunctions];
     
    351354        || pExpDir->AddressOfNames >= pNtHdrs->OptionalHeader.SizeOfImage
    352355        || 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,
    354357                           "%ls: Bad AddressOfNames: %#x\n", pDll->pwszName, pExpDir->AddressOfNames);
    355358    pDll->paoffNamedExports = (uint32_t const *)&pDll->pbImageBase[pExpDir->AddressOfNames];
     
    358361        || pExpDir->AddressOfNameOrdinals >= pNtHdrs->OptionalHeader.SizeOfImage
    359362        || 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,
    361364                           "%ls: Bad AddressOfNameOrdinals: %#x\n", pDll->pwszName, pExpDir->AddressOfNameOrdinals);
    362365    pDll->pau16NameOrdinals = (uint16_t const *)&pDll->pbImageBase[pExpDir->AddressOfNameOrdinals];
     
    364367
    365368
    366 static const char *supR3HardenedResolveImport(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport)
     369static const char *supR3HardenedResolveImport(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport, bool fReportErrors)
    367370{
    368371    /*
     
    376379        uint32_t offExpName  = pDll->paoffNamedExports[iCur];
    377380        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,
    379382                            "%ls: Bad export name entry: %#x (iCur=%#x)", pDll->pwszName, offExpName, iCur);
    380383
     
    405408                return (const char *)&pDll->pbImageBase[offExport];
    406409            }
    407             SUPHNTIMP_ERROR(14, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_BAD_EXE_FORMAT,
     410            SUPHNTIMP_ERROR(fReportErrors, 14, "supR3HardenedResolveImport", kSupInitOp_Misc, VERR_BAD_EXE_FORMAT,
    408411                            "%ls: Name ordinal for '%s' is out of bounds: %#x (max %#x)",
    409412                            pDll->pwszName, iExpOrdinal, pDll->cExports);
     
    413416
    414417    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,
    416419                        "%ls: Failed to resolve '%s'.", pDll->pwszName, pImport->pszName);
    417420    *pImport->ppfnImport = NULL;
     
    421424
    422425static void supR3HardenedDirectSyscall(PSUPHNTIMPDLL pDll, PCSUPHNTIMPFUNC pImport, PCSUPHNTIMPSYSCALL pSyscall,
    423                                        PSUPHNTLDRCACHEENTRY pLdrEntry, uint8_t *pbBits)
     426                                       PSUPHNTLDRCACHEENTRY pLdrEntry, uint8_t *pbBits, bool fReportErrors)
    424427{
    425428    /*
     
    436439    if (RT_FAILURE(rc))
    437440    {
    438         SUPHNTIMP_ERROR(16, "supR3HardenedDirectSyscall", kSupInitOp_Misc, rc,
     441        SUPHNTIMP_ERROR(fReportErrors, 16, "supR3HardenedDirectSyscall", kSupInitOp_Misc, rc,
    439442                        "%s: RTLdrGetSymbolEx failed on %s: %Rrc", pDll->pszName, pImport->pszName, rc);
    440443        return;
     
    541544    volatile uint8_t abCopy[16];
    542545    memcpy((void *)&abCopy[0], pbFunction, sizeof(abCopy));
    543     SUPHNTIMP_ERROR(17, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
     546    SUPHNTIMP_ERROR(fReportErrors, 17, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
    544547                    "%ls: supHardNtLdrCacheOpen failed: '%s': %.16Rhxs",
    545                     g_aSupNtImpDlls[iDll].pwszName, pImport->pszName, &abCopy[0]);
     548                    pDll->pwszName, pImport->pszName, &abCopy[0]);
    546549}
    547550
    548551
    549552/**
    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 */
     561DECLHIDDEN(void) supR3HardenedWinInitSyscalls(bool fReportErrors)
     562{
    635563    for (uint32_t iDll = 0; iDll < RT_ELEMENTS(g_aSupNtImpDlls); iDll++)
    636564        if (g_aSupNtImpDlls[iDll].paSyscalls)
     
    647575                    for (uint32_t i = 0; i < g_aSupNtImpDlls[iDll].cImports; i++)
    648576                        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);
    650578                }
    651579                else
    652                     SUPHNTIMP_ERROR(20, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
     580                    SUPHNTIMP_ERROR(fReportErrors, 20, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
    653581                                    "%ls: supHardNtLdrCacheEntryGetBits failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc);
    654582            }
    655583            else
    656                 SUPHNTIMP_ERROR(21, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
     584                SUPHNTIMP_ERROR(fReportErrors, 21, "supR3HardenedWinInitImports", kSupInitOp_Misc, rc,
    657585                                "%ls: supHardNtLdrCacheOpen failed: %Rrc '%s'.", g_aSupNtImpDlls[iDll].pwszName, rc);
    658586        }
     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 */
     596DECLHIDDEN(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 */
     635DECLHIDDEN(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);
    659675
    660676    /*
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette