VirtualBox

Ignore:
Timestamp:
Oct 6, 2014 1:30:20 PM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
96395
Message:

SUP: Use LdrRegisterDllNotification when available to make sure we see all DLLs and get a chance to restore our NtDll hooks.

Location:
trunk/src/VBox/HostDrivers/Support/win
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp

    r52949 r52953  
    229229static NTSTATUS (NTAPI *    g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
    230230                                                      PLARGE_INTEGER, ULONG, ULONG, HANDLE);
     231/** Pointer to the NtCreateSection function in NtDll (for patching purposes). */
     232static uint8_t             *g_pbNtCreateSection;
     233/** The patched NtCreateSection bytes (for restoring). */
     234static uint8_t              g_abNtCreateSectionPatch[16];
    231235#if 0
    232236/** The jump back address of the patched LdrLoadDll. */
     
    236240 *  LdrLoadDll operation. */
    237241static NTSTATUS (NTAPI *    g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE);
     242/** Pointer to the LdrLoadDll function in NtDll (for patching purposes). */
     243static uint8_t             *g_pbLdrLoadDll;
     244/** The patched LdrLoadDll bytes (for restoring). */
     245static uint8_t              g_abLdrLoadDllPatch[16];
     246
    238247/** The hash table of verifier cache . */
    239248static PVERIFIERCACHEENTRY  volatile g_apVerifierCache[128];
     
    248257/** @ */
    249258
     259/** Positive if the DLL notification callback has been registered, counts
     260 * registration attempts as negative. */
     261static int                  g_cDllNotificationRegistered = 0;
     262/** The registration cookie of the DLL notification callback. */
     263static PVOID                g_pvDllNotificationCookie = NULL;
    250264
    251265/** Static error info structure used during init. */
     
    301315                                         bool *pfCallRealApi, const char *pszCaller, bool fAvoidWinVerifyTrust,
    302316                                         bool *pfQuietFailure);
     317static void supR3HardenedWinRegisterDllNotificationCallback(void);
     318static void supR3HardenedWinReInstallHooks(bool fFirst);
     319
    303320
    304321#ifdef RT_ARCH_AMD64
     
    16671684
    16681685    /*
     1686     * Make sure the DLL notification callback is registered.  If we could, we
     1687     * would've done this during early process init, but due to lack of heap
     1688     * and uninitialized loader lock, it's not possible that early on.
     1689     *
     1690     * The callback protects our NtDll hooks from getting unhooked by
     1691     * "friendly" fire from the AV crowd.
     1692     */
     1693    supR3HardenedWinRegisterDllNotificationCallback();
     1694
     1695    /*
    16691696     * Process WinVerifyTrust todo before and after.
    16701697     */
     
    19651992
    19661993
     1994/**
     1995 * DLL load and unload notification callback.
     1996 *
     1997 * This is a safety against our LdrLoadDll hook being replaced by protection
     1998 * software.  Though, we prefer the LdrLoadDll hook to this one as it allows us
     1999 * to call WinVerifyTrust more freely.
     2000 *
     2001 * @param   ulReason    The reason we're called, see
     2002 *                      LDR_DLL_NOTIFICATION_REASON_XXX.
     2003 * @param   pData       Reason specific data.  (Format is currently the same for
     2004 *                      both load and unload.)
     2005 * @param   pvUser      User parameter (ignored).
     2006 *
     2007 * @remarks Vista and later.
     2008 * @remarks The loader lock is held when we're called, at least on Windows 7.
     2009 */
     2010static VOID CALLBACK supR3HardenedDllNotificationCallback(ULONG ulReason, PCLDR_DLL_NOTIFICATION_DATA pData, PVOID pvUser)
     2011{
     2012    NOREF(pvUser);
     2013
     2014    /*
     2015     * Screen the image on load.  We will normally get a verification cache
     2016     * hit here because of the LdrLoadDll and NtCreateSection hooks, so it
     2017     * should be relatively cheap to recheck.  In case our NtDll patches
     2018     * got re
     2019     *
     2020     * This ASSUMES that we get informed after the fact as indicated by the
     2021     * available documentation.
     2022     */
     2023    if (ulReason == LDR_DLL_NOTIFICATION_REASON_LOADED)
     2024    {
     2025        SUP_DPRINTF(("supR3HardenedDllNotificationCallback: load   %p LB %#010x %.*ls [fFlags=%#x]\n",
     2026                     pData->Loaded.DllBase, pData->Loaded.SizeOfImage,
     2027                     pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
     2028                     pData->Loaded.Flags));
     2029
     2030        /* Convert the windows path to an NT path and open it. */
     2031        HANDLE          hRootDir;
     2032        UNICODE_STRING  NtPathUniStr;
     2033        int rc = RTNtPathFromWinUtf16Ex(&NtPathUniStr, &hRootDir, pData->Loaded.FullDllName->Buffer,
     2034                                        pData->Loaded.FullDllName->Length / sizeof(WCHAR));
     2035        if (RT_FAILURE(rc))
     2036        {
     2037            supR3HardenedFatal("supR3HardenedDllNotificationCallback: RTNtPathFromWinUtf16Ex failed on '%.*ls': %Rrc\n",
     2038                               pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer, rc);
     2039            return;
     2040        }
     2041
     2042        HANDLE              hFile = RTNT_INVALID_HANDLE_VALUE;
     2043        IO_STATUS_BLOCK     Ios   = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     2044        OBJECT_ATTRIBUTES   ObjAttr;
     2045        InitializeObjectAttributes(&ObjAttr, &NtPathUniStr, OBJ_CASE_INSENSITIVE, hRootDir, NULL /*pSecDesc*/);
     2046
     2047        NTSTATUS rcNt = NtCreateFile(&hFile,
     2048                                     FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
     2049                                     &ObjAttr,
     2050                                     &Ios,
     2051                                     NULL /* Allocation Size*/,
     2052                                     FILE_ATTRIBUTE_NORMAL,
     2053                                     FILE_SHARE_READ,
     2054                                     FILE_OPEN,
     2055                                     FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
     2056                                     NULL /*EaBuffer*/,
     2057                                     0 /*EaLength*/);
     2058        if (NT_SUCCESS(rcNt))
     2059            rcNt = Ios.Status;
     2060        if (!NT_SUCCESS(rcNt))
     2061        {
     2062            supR3HardenedFatal("supR3HardenedDllNotificationCallback: NtCreateFile failed on '%.*ls' / '%.*ls': %#x\n",
     2063                               pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
     2064                               NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt);
     2065            RTNtPathFree(&NtPathUniStr, &hRootDir);
     2066            return;
     2067        }
     2068
     2069        /* Do the screening. */
     2070        ULONG fAccess = 0;
     2071        ULONG fProtect = 0;
     2072        bool  fCallRealApi = false;
     2073        bool  fQuietFailure = false;
     2074        rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi,
     2075                                        "LdrLoadDll", true /*fAvoidWinVerifyTrust*/, &fQuietFailure);
     2076        NtClose(hFile);
     2077        if (!NT_SUCCESS(rcNt))
     2078        {
     2079            supR3HardenedFatal("supR3HardenedDllNotificationCallback: supR3HardenedScreenImage failed on '%.*ls' / '%.*ls': %#x\n",
     2080                               pData->Loaded.FullDllName->Length / sizeof(WCHAR), pData->Loaded.FullDllName->Buffer,
     2081                               NtPathUniStr.Length / sizeof(WCHAR), NtPathUniStr.Buffer, rcNt);
     2082            RTNtPathFree(&NtPathUniStr, &hRootDir);
     2083            return;
     2084        }
     2085        RTNtPathFree(&NtPathUniStr, &hRootDir);
     2086    }
     2087    /*
     2088     * Log the unload call.
     2089     */
     2090    else if (ulReason == LDR_DLL_NOTIFICATION_REASON_UNLOADED)
     2091    {
     2092        SUP_DPRINTF(("supR3HardenedDllNotificationCallback: Unload %p LB %#010x %.*ls [flags=%#x]\n",
     2093                     pData->Unloaded.DllBase, pData->Unloaded.SizeOfImage,
     2094                     pData->Unloaded.FullDllName->Length / sizeof(WCHAR), pData->Unloaded.FullDllName->Buffer,
     2095                     pData->Unloaded.Flags));
     2096    }
     2097    /*
     2098     * Just log things we don't know and then return without caching anything.
     2099     */
     2100    else
     2101    {
     2102        static uint32_t s_cLogEntries = 0;
     2103        if (s_cLogEntries++ < 32)
     2104            SUP_DPRINTF(("supR3HardenedDllNotificationCallback: ulReason=%u pData=%p\n", ulReason, pData));
     2105        return;
     2106    }
     2107
     2108    /*
     2109     * Use this opportunity to make sure our NtDll patches are still in place,
     2110     * since they may be replaced by indecent protection software solutions.
     2111     */
     2112    supR3HardenedWinReInstallHooks(false /*fFirstCall */);
     2113}
     2114
     2115
     2116/**
     2117 * Registers the DLL notification callback if it hasn't already been registered.
     2118 */
     2119static void supR3HardenedWinRegisterDllNotificationCallback(void)
     2120{
     2121    /*
     2122     * The notification API was added in Vista, so it's an optional (weak) import.
     2123     */
     2124    if (   LdrRegisterDllNotification != NULL
     2125        && g_cDllNotificationRegistered <= 0
     2126        && g_cDllNotificationRegistered > -32)
     2127    {
     2128        NTSTATUS rcNt = LdrRegisterDllNotification(0, supR3HardenedDllNotificationCallback, NULL, &g_pvDllNotificationCookie);
     2129        if (NT_SUCCESS(rcNt))
     2130        {
     2131            SUP_DPRINTF(("Registered Dll notification callback with NTDLL.\n"));
     2132            g_cDllNotificationRegistered = 1;
     2133        }
     2134        else
     2135        {
     2136            supR3HardenedError(rcNt, false /*fFatal*/, "LdrRegisterDllNotification failed: %#x\n", rcNt);
     2137            g_cDllNotificationRegistered--;
     2138        }
     2139    }
     2140}
     2141
     2142
    19672143#ifdef RT_ARCH_AMD64
    19682144/**
     
    22102386
    22112387/**
     2388 * Installs or reinstalls the NTDLL patches.
     2389 */
     2390static void supR3HardenedWinReInstallHooks(bool fFirstCall)
     2391{
     2392    struct
     2393    {
     2394        size_t          cbPatch;
     2395        uint8_t const  *pabPatch;
     2396        uint8_t       **ppbApi;
     2397        const char     *pszName;
     2398    } const s_aPatches[] =
     2399    {
     2400        { sizeof(g_abNtCreateSectionPatch), g_abNtCreateSectionPatch, &g_pbNtCreateSection, "NtCreateSection" },
     2401        { sizeof(g_abLdrLoadDllPatch),      g_abLdrLoadDllPatch,      &g_pbLdrLoadDll,      "LdrLoadDll"      },
     2402    };
     2403
     2404    ULONG fAmIAlone = ~(ULONG)0;
     2405
     2406    for (uint32_t i = 0; i < RT_ELEMENTS(s_aPatches); i++)
     2407    {
     2408        uint8_t *pbApi = *s_aPatches[i].ppbApi;
     2409        if (memcmp(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch) != 0)
     2410        {
     2411            /*
     2412             * Log the incident if it's not the initial call.
     2413             */
     2414            static uint32_t volatile s_cTimes = 0;
     2415            if (!fFirstCall && s_cTimes < 128)
     2416            {
     2417                s_cTimes++;
     2418                SUP_DPRINTF(("supR3HardenedWinReInstallHooks: Reinstalling %s (%p: %.*Rhxs).\n",
     2419                             s_aPatches[i].pszName, pbApi, s_aPatches[i].cbPatch, pbApi));
     2420            }
     2421
     2422            Assert(s_aPatches[i].cbPatch >= 4);
     2423
     2424            SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READWRITE));
     2425
     2426            /*
     2427             * If we're alone, just memcpy the patch in.
     2428             */
     2429
     2430#if 0 /* For testing purposes. */
     2431            if (fAmIAlone == ~(ULONG)0)
     2432            {
     2433                ULONG cbIgn = 0;
     2434                NTSTATUS rcNt = NtQueryInformationThread(NtCurrentThread(), ThreadAmILastThread,
     2435                                                         &fAmIAlone, sizeof(fAmIAlone), &cbIgn);
     2436                fAmIAlone = NT_SUCCESS(rcNt) && fAmIAlone != 0;
     2437            }
     2438#else
     2439            fAmIAlone = 0;
     2440#endif
     2441            if (fAmIAlone)
     2442                memcpy(pbApi, s_aPatches[i].pabPatch, s_aPatches[i].cbPatch);
     2443            else
     2444            {
     2445                /*
     2446                 * Not alone.  Start by injecting a JMP $-2, then waste some
     2447                 * CPU cycles to get the other threads a good chance of getting
     2448                 * out of the code before we replace it.
     2449                 */
     2450                RTUINT32U uJmpDollarMinus;
     2451                uJmpDollarMinus.au8[0] = 0xeb;
     2452                uJmpDollarMinus.au8[1] = 0xfe;
     2453                uJmpDollarMinus.au8[2] = pbApi[2];
     2454                uJmpDollarMinus.au8[3] = pbApi[3];
     2455                ASMAtomicXchgU32((uint32_t volatile *)pbApi, uJmpDollarMinus.u);
     2456
     2457                NtYieldExecution();
     2458                NtYieldExecution();
     2459
     2460                /* Copy in the tail bytes of the patch, then xchg the jmp $-2. */
     2461                if (s_aPatches[i].cbPatch > 4)
     2462                    memcpy(&pbApi[4], &s_aPatches[i].pabPatch[4], s_aPatches[i].cbPatch - 4);
     2463                ASMAtomicXchgU32((uint32_t volatile *)pbApi, *(uint32_t *)s_aPatches[i].pabPatch);
     2464            }
     2465
     2466            SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbApi, s_aPatches[i].cbPatch, PAGE_EXECUTE_READ));
     2467        }
     2468    }
     2469}
     2470
     2471
     2472/**
    22122473 * Install hooks for intercepting calls dealing with mapping shared libraries
    22132474 * into the process.
     
    22242485 *            and inflexible.
    22252486 */
    2226 DECLHIDDEN(void) supR3HardenedWinInstallHooks(void)
     2487static void supR3HardenedWinInstallHooks(void)
    22272488{
    22282489    NTSTATUS rcNt;
    2229 
    2230 #ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
    2231     /*
    2232      * Install a anti debugging hack before we continue.  This prevents most
    2233      * notifications from ending up in the debugger. (Also applied to the
    2234      * child process when respawning.)
    2235      */
    2236     rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
    2237     if (!NT_SUCCESS(rcNt))
    2238         supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
    2239                               "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
    2240 #endif
    22412490
    22422491    /*
     
    22942543     */
    22952544    uint8_t * const pbNtCreateSection = (uint8_t *)(uintptr_t)pfnNtCreateSection;
     2545    g_pbNtCreateSection = pbNtCreateSection;
     2546    memcpy(g_abNtCreateSectionPatch, pbNtCreateSection, sizeof(g_abNtCreateSectionPatch));
     2547/** @todo This patch could be simplified iff we had our own syscall operational
     2548 *        from the get-go. */
    22962549
    22972550#ifdef RT_ARCH_AMD64
     
    23212574        && pbNtCreateSection[ 9] == 0x05
    23222575        && pbNtCreateSection[10] == 0xc3 /* ret */
    2323 
    2324 /* b8 22 35 ed 0 48 63 c0 ff e0 c3 f 1f 44 0 0 - necros2 - agnitum firewall? */
    23252576       )
    23262577    {
     
    23382589    g_pfnNtCreateSectionJmpBack         = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
    23392590    *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
    2340     *puJmpTab                           = (uintptr_t)supR3HardenedMonitor_NtCreateSection;
    2341 
    2342     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READWRITE));
    2343 
    2344     pbNtCreateSection[0] = 0xff;
    2345     pbNtCreateSection[1] = 0x25;
    2346     *(uint32_t *)&pbNtCreateSection[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]);
    2347 
    2348     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READ));
     2591
     2592    /* Assemble the patch. */
     2593    g_abNtCreateSectionPatch[0] = 0xff;
     2594    g_abNtCreateSectionPatch[1] = 0x25;
     2595    *(uint32_t *)&g_abNtCreateSectionPatch[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]);
     2596
     2597    *puJmpTab = (uintptr_t)supR3HardenedMonitor_NtCreateSection;
    23492598    puJmpTab++;
    23502599
     
    24152664    *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
    24162665
    2417     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READWRITE));
    2418 
    2419     pbNtCreateSection[0] = 0xe9;
    2420     *(uint32_t *)&pbNtCreateSection[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
    2421                                        - (uintptr_t)&pbNtCreateSection[1+4];
    2422 
    2423     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbNtCreateSection, 16, PAGE_EXECUTE_READ));
    2424 
     2666    /* Assemble the patch. */
     2667    g_abNtCreateSectionPatch[0] = 0xe9;
     2668    *(uint32_t *)&g_abNtCreateSectionPatch[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
     2669                                              - (uintptr_t)&pbNtCreateSection[1+4];
    24252670#endif
     2671
     2672    /*
     2673     * Exec page setup & management.
     2674     */
     2675    uint32_t offExecPage = 0;
     2676    memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
    24262677
    24272678    /*
     
    24352686     */
    24362687    uint8_t * const pbLdrLoadDll = (uint8_t *)(uintptr_t)pfnLdrLoadDll;
    2437     uint32_t        offExecPage  = 0;
    2438     memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
     2688    g_pbLdrLoadDll = pbLdrLoadDll;
     2689    memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch));
    24392690
    24402691#ifdef RT_ARCH_AMD64
     
    24422693     * Patch 64-bit hosts.
    24432694     */
    2444 # if 0
    2445     /* Pattern #1:
    2446          Windows 8.1:
    2447             0:000> u ntdll!LdrLoadDll
    2448             ntdll!LdrLoadDll:
    2449             00007ffa`814ccd44 488bc4          mov     rax,rsp
    2450             00007ffa`814ccd47 48895808        mov     qword ptr [rax+8],rbx
    2451             00007ffa`814ccd4b 48896810        mov     qword ptr [rax+10h],rbp
    2452             00007ffa`814ccd4f 48897018        mov     qword ptr [rax+18h],rsi
    2453             00007ffa`814ccd53 48897820        mov     qword ptr [rax+20h],rdi
    2454             00007ffa`814ccd57 4156            push    r14
    2455             00007ffa`814ccd59 4883ec70        sub     rsp,70h
    2456             00007ffa`814ccd5d f6059cd2100009  test    byte ptr [ntdll!LdrpDebugFlags (00007ffa`815da000)],9
    2457      */
    2458     if (   pbLdrLoadDll[0] == 0x48 /* mov rax,rsp */
    2459         && pbLdrLoadDll[1] == 0x8b
    2460         && pbLdrLoadDll[2] == 0xc4
    2461         && pbLdrLoadDll[3] == 0x48 /* mov qword ptr [rax+8],rbx */
    2462         && pbLdrLoadDll[4] == 0x89
    2463         && pbLdrLoadDll[5] == 0x58
    2464         && pbLdrLoadDll[6] == 0x08)
    2465     {
    2466         offJmpBack = 7; /* the 3rd instruction. */
    2467         pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
    2468     }
    2469     /*
    2470        Pattern #2:
    2471          Windows 8.0:
    2472             0:000> u ntdll_w8_64!LdrLoadDll
    2473             ntdll_w8_64!LdrLoadDll:
    2474             00007ffa`52ffa7c0 48895c2408      mov     qword ptr [rsp+8],rbx
    2475             00007ffa`52ffa7c5 4889742410      mov     qword ptr [rsp+10h],rsi
    2476             00007ffa`52ffa7ca 48897c2418      mov     qword ptr [rsp+18h],rdi
    2477             00007ffa`52ffa7cf 55              push    rbp
    2478             00007ffa`52ffa7d0 4156            push    r14
    2479             00007ffa`52ffa7d2 4157            push    r15
    2480             00007ffa`52ffa7d4 488bec          mov     rbp,rsp
    2481             00007ffa`52ffa7d7 4883ec60        sub     rsp,60h
    2482             00007ffa`52ffa7db 8b05df321000    mov     eax,dword ptr [ntdll_w8_64!LdrpDebugFlags (00007ffa`530fdac0)]
    2483             00007ffa`52ffa7e1 4d8bf1          mov     r14,r9
    2484 
    2485      */
    2486     else if (   pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+8],rbx */
    2487              && pbLdrLoadDll[1] == 0x89
    2488              && pbLdrLoadDll[2] == 0x5c
    2489              && pbLdrLoadDll[3] == 0x24
    2490              && pbLdrLoadDll[4] == 0x08
    2491              && pbLdrLoadDll[5] == 0x48 /* mov qword ptr [rsp+10h],rsi */
    2492              && pbLdrLoadDll[6] == 0x89
    2493              && pbLdrLoadDll[7] == 0x74
    2494              && pbLdrLoadDll[8] == 0x24
    2495              && pbLdrLoadDll[9] == 0x10)
    2496     {
    2497         offJmpBack = 10; /* the 3rd instruction. */
    2498         pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
    2499     }
    2500     /*
    2501        Pattern #3:
    2502          Windows 7:
    2503             ntdll_w7_64!LdrLoadDll:
    2504             00000000`58be4a20 48895c2410      mov     qword ptr [rsp+10h],rbx
    2505             00000000`58be4a25 48896c2418      mov     qword ptr [rsp+18h],rbp
    2506             00000000`58be4a2a 56              push    rsi
    2507             00000000`58be4a2b 57              push    rdi
    2508             00000000`58be4a2c 4154            push    r12
    2509             00000000`58be4a2e 4883ec50        sub     rsp,50h
    2510             00000000`58be4a32 f605976e100009  test    byte ptr [ntdll_w7_64!ShowSnaps (00000000`58ceb8d0)],9
    2511             00000000`58be4a39 498bf1          mov     rsi,r9
    2512 
    2513      */
    2514     else if (   pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+10h],rbx */
    2515              && pbLdrLoadDll[1] == 0x89
    2516              && pbLdrLoadDll[2] == 0x5c
    2517              && pbLdrLoadDll[3] == 0x24
    2518              && pbLdrLoadDll[4] == 0x10)
    2519     {
    2520         offJmpBack = 5; /* the 2nd instruction. */
    2521         pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type3;
    2522     }
    2523     /*
    2524        Pattern #4:
    2525          Windows Vista:
    2526             0:000> u ntdll_vista_64!LdrLoadDll
    2527             ntdll_vista_64!LdrLoadDll:
    2528             00000000`58c11f60 fff3            push    rbx
    2529             00000000`58c11f62 56              push    rsi
    2530             00000000`58c11f63 57              push    rdi
    2531             00000000`58c11f64 4154            push    r12
    2532             00000000`58c11f66 4155            push    r13
    2533             00000000`58c11f68 4156            push    r14
    2534             00000000`58c11f6a 4157            push    r15
    2535             00000000`58c11f6c 4881ecb0020000  sub     rsp,2B0h
    2536             00000000`58c11f73 488b05367b0e00  mov     rax,qword ptr [ntdll_vista_64!_security_cookie (00000000`58cf9ab0)]
    2537             00000000`58c11f7a 4833c4          xor     rax,rsp
    2538             00000000`58c11f7d 48898424a0020000 mov     qword ptr [rsp+2A0h],rax
    2539 
    2540      */
    2541     else if (   pbLdrLoadDll[0] == 0xff /* push rbx */
    2542              && pbLdrLoadDll[1] == 0xf3
    2543              && pbLdrLoadDll[2] == 0x56 /* push rsi */
    2544              && pbLdrLoadDll[3] == 0x57 /* push rdi */
    2545              && pbLdrLoadDll[4] == 0x41 /* push r12 */
    2546              && pbLdrLoadDll[5] == 0x54)
    2547     {
    2548         offJmpBack = 6; /* the 5th instruction. */
    2549         pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type4;
    2550     }
    2551     /*
    2552        Pattern #5:
    2553          Windows XP64:
    2554             0:000> u ntdll!LdrLoadDll
    2555             ntdll!LdrLoadDll:
    2556             00000000`78efa580 4c8bdc          mov     r11,rsp
    2557             00000000`78efa583 4881ece8020000  sub     rsp,2E8h
    2558             00000000`78efa58a 49895bf8        mov     qword ptr [r11-8],rbx
    2559             00000000`78efa58e 498973f0        mov     qword ptr [r11-10h],rsi
    2560             00000000`78efa592 49897be8        mov     qword ptr [r11-18h],rdi
    2561             00000000`78efa596 4d8963e0        mov     qword ptr [r11-20h],r12
    2562             00000000`78efa59a 4d896bd8        mov     qword ptr [r11-28h],r13
    2563             00000000`78efa59e 4d8973d0        mov     qword ptr [r11-30h],r14
    2564             00000000`78efa5a2 4d897bc8        mov     qword ptr [r11-38h],r15
    2565             00000000`78efa5a6 488b051bd10a00  mov     rax,qword ptr [ntdll!_security_cookie (00000000`78fa76c8)]
    2566             00000000`78efa5ad 48898424a0020000 mov     qword ptr [rsp+2A0h],rax
    2567             00000000`78efa5b5 4d8bf9          mov     r15,r9
    2568             00000000`78efa5b8 4c8bf2          mov     r14,rdx
    2569             00000000`78efa5bb 4c8be9          mov     r13,rcx
    2570             00000000`78efa5be 4c89442458      mov     qword ptr [rsp+58h],r8
    2571             00000000`78efa5c3 66c74424680000  mov     word ptr [rsp+68h],0
    2572 
    2573      */
    2574     else if (   pbLdrLoadDll[0] == 0x4c /* mov r11,rsp */
    2575              && pbLdrLoadDll[1] == 0x8b
    2576              && pbLdrLoadDll[2] == 0xdc
    2577              && pbLdrLoadDll[3] == 0x48 /* sub rsp,2e8h */
    2578              && pbLdrLoadDll[4] == 0x81
    2579              && pbLdrLoadDll[5] == 0xec
    2580              && pbLdrLoadDll[6] == 0xe8
    2581              && pbLdrLoadDll[7] == 0x02
    2582              && pbLdrLoadDll[8] == 0x00
    2583              && pbLdrLoadDll[9] == 0x00)
    2584     {
    2585         offJmpBack = 10; /* the 3rd instruction. */
    2586         pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type5;
    2587     }
    2588     else
    2589         supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
    2590 # else
    25912695    /* Just use the disassembler to skip 6 bytes or more. */
    25922696    DISSTATE Dis;
     
    26032707        offJmpBack += cbInstr;
    26042708    }
    2605 # endif
    26062709
    26072710    /* Assemble the code for resuming the call.*/
     
    26182721    offExecPage = RT_ALIGN_32(offJmpBack + 8, 16);
    26192722
    2620     /* Patch the function. */
     2723    /* Assemble the LdrLoadDll patch. */
     2724    Assert(offJmpBack >= 6);
     2725    g_abLdrLoadDllPatch[0] = 0xff;
     2726    g_abLdrLoadDllPatch[1] = 0x25;
     2727    *(uint32_t *)&g_abLdrLoadDllPatch[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]);
     2728
    26212729    *puJmpTab = (uintptr_t)supR3HardenedMonitor_LdrLoadDll;
    2622 
    2623     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READWRITE));
    2624 
    2625     Assert(offJmpBack >= 6);
    2626     pbLdrLoadDll[0] = 0xff;
    2627     pbLdrLoadDll[1] = 0x25;
    2628     *(uint32_t *)&pbLdrLoadDll[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]);
    2629 
    2630     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READ));
    26312730    puJmpTab++;
    26322731
     
    26352734     * Patch 32-bit hosts.
    26362735     */
    2637 # if 0
    2638     /* Pattern #1:
    2639           Windows 7:
    2640             0:000> u ntdll!LdrLoadDll
    2641             ntdll!LdrLoadDll:
    2642             77aff585 8bff            mov     edi,edi
    2643             77aff587 55              push    ebp
    2644             77aff588 8bec            mov     ebp,esp
    2645             77aff58a 51              push    ecx
    2646             77aff58b 51              push    ecx
    2647             77aff58c a1f8bdaf77      mov     eax,dword ptr [ntdll!LdrpLogLevelStateTable+0x24 (77afbdf8)]
    2648 
    2649           Windows 8 rtm:
    2650             0:000:x86> u ntdll_67150000!LdrLoadDll
    2651             ntdll_67150000!LdrLoadDll:
    2652             67189f3f 8bff            mov     edi,edi
    2653             67189f41 55              push    ebp
    2654             67189f42 8bec            mov     ebp,esp
    2655             67189f44 8b0d10eb2467    mov     ecx,dword ptr [ntdll_67150000!LdrpDebugFlags (6724eb10)]
    2656 
    2657           Windows 8.1:
    2658             0:000:x86> u ntdll_w81_32!LdrLoadDll
    2659             ntdll_w81_32!LdrLoadDll:
    2660             6718aade 8bff            mov     edi,edi
    2661             6718aae0 55              push    ebp
    2662             6718aae1 8bec            mov     ebp,esp
    2663             6718aae3 83ec14          sub     esp,14h
    2664             6718aae6 f6050040246709  test    byte ptr [ntdll_w81_32!LdrpDebugFlags (67244000)],9
    2665 
    2666        Pattern #2:
    2667           Windows XP:
    2668             0:000:x86> u ntdll_xp!LdrLoadDll
    2669             ntdll_xp!LdrLoadDll:
    2670             77f569d2 6858020000      push    258h
    2671             77f569d7 68d866f777      push    offset ntdll_xp!`string'+0x12c (77f766d8)
    2672             77f569dc e83bb20200      call    ntdll_xp!_SEH_prolog (77f81c1c)
    2673             77f569e1 33db            xor     ebx,ebx
    2674             77f569e3 66895de0        mov     word ptr [ebp-20h],bx
    2675             77f569e7 33c0            xor     eax,eax
    2676             77f569e9 8d7de2          lea     edi,[ebp-1Eh]
    2677             77f569ec ab              stos    dword ptr es:[edi]
    2678 
    2679           Windows Server 2003:
    2680             0:000:x86> u ntdll_w2k3_32!LdrLoadDll
    2681             ntdll_w2k3_32!LdrLoadDll:
    2682             7c833f63 6840020000      push    240h
    2683             7c833f68 68b040837c      push    offset ntdll_w2k3_32!`string'+0x12c (7c8340b0)
    2684             7c833f6d e8a942ffff      call    ntdll_w2k3_32!_SEH_prolog (7c82821b)
    2685             7c833f72 a13077887c      mov     eax,dword ptr [ntdll_w2k3_32!__security_cookie (7c887730)]
    2686             7c833f77 8945e4          mov     dword ptr [ebp-1Ch],eax
    2687             7c833f7a 8b4508          mov     eax,dword ptr [ebp+8]
    2688             7c833f7d 8985b0fdffff    mov     dword ptr [ebp-250h],eax
    2689             7c833f83 8b450c          mov     eax,dword ptr [ebp+0Ch]
    2690 
    2691           Windows Vista SP0 & SP1:
    2692             0:000:x86> u ntdll_vista_sp0_32!LdrLoadDll
    2693             ntdll_vista_sp0_32!LdrLoadDll:
    2694             69b0eb00 6844020000      push    244h
    2695             69b0eb05 6838e9b269      push    offset ntdll_vista_sp0_32! ?? ::FNODOBFM::`string'+0x39e (69b2e938)
    2696             69b0eb0a e835420300      call    ntdll_vista_sp0_32!_SEH_prolog4_GS (69b42d44)
    2697             69b0eb0f 8b4508          mov     eax,dword ptr [ebp+8]
    2698             69b0eb12 8985acfdffff    mov     dword ptr [ebp-254h],eax
    2699             69b0eb18 8b450c          mov     eax,dword ptr [ebp+0Ch]
    2700             69b0eb1b 8985c0fdffff    mov     dword ptr [ebp-240h],eax
    2701             69b0eb21 8b4510          mov     eax,dword ptr [ebp+10h]
    2702          */
    2703 
    2704     if (   pbLdrLoadDll[0] == 0x8b /* mov edi, edi - for hot patching */
    2705         && pbLdrLoadDll[1] == 0xff
    2706         && pbLdrLoadDll[2] == 0x55 /* push ebp */
    2707         && pbLdrLoadDll[3] == 0x8b /* mov  ebp,esp */
    2708         && pbLdrLoadDll[4] == 0xec)
    2709     {
    2710         offJmpBack = 5; /* the 3rd instruction. */
    2711         pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
    2712     }
    2713     else if (pbLdrLoadDll[0] == 0x68 /* push dword XXXXXXXX */)
    2714     {
    2715         offJmpBack = 5;
    2716         pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
    2717         g_supR3HardenedJmpBack_LdrLoadDll_Type2_PushDword = *(uint32_t const *)&pbLdrLoadDll[1];
    2718     }
    2719     else
    2720         supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
    2721 
    2722     g_pfnLdrLoadDllJmpBack = (PFNRT)(uintptr_t)(pbLdrLoadDll + offJmpBack);
    2723     *(PFNRT *)&g_pfnLdrLoadDllReal = pfnCallReal;
    2724 
    2725 # else
    27262736    /* Just use the disassembler to skip 6 bytes or more. */
    27272737    DISSTATE Dis;
     
    27492759    offExecPage = RT_ALIGN_32(offJmpBack + 4, 16);
    27502760
    2751 # endif
    2752 
    2753     /* Patch LdrLoadDLl. */
    2754     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READWRITE));
     2761    /* Assemble the LdrLoadDll patch. */
     2762    memcpy(g_abLdrLoadDllPatch, pbLdrLoadDll, sizeof(g_abLdrLoadDllPatch));
    27552763    Assert(offJmpBack >= 5);
    2756     pbLdrLoadDll[0] = 0xe9;
    2757     *(uint32_t *)&pbLdrLoadDll[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4];
    2758 
    2759     SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(pbLdrLoadDll, 16, PAGE_EXECUTE_READ));
     2764    g_abLdrLoadDllPatch[0] = 0xe9;
     2765    *(uint32_t *)&g_abLdrLoadDllPatch[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4];
    27602766#endif
    27612767
     
    27642770     */
    27652771    SUPR3HARDENED_ASSERT_NT_SUCCESS(supR3HardenedWinProtectMemory(g_abSupHardReadWriteExecPage, PAGE_SIZE, PAGE_EXECUTE_READ));
     2772
     2773    /*
     2774     * Install the patches.
     2775     */
     2776    supR3HardenedWinReInstallHooks(true /*fFirstCall*/);
    27662777}
    27672778
     
    41434154    /*
    41444155     * Apply anti debugger notification trick to the thread.  (Also done in
    4145      * supR3HardenedWinInstallHooks.)
     4156     * supR3HardenedWinInit.)
    41464157     */
    41474158    rcNt = NtSetInformationThread(hThread, ThreadHideFromDebugger, NULL, 0);
     
    46614672
    46624673/**
    4663  * Initializes the windows verficiation bits.
     4674 * Initializes the windows verficiation bits and other things we're better off
     4675 * doing after main() has passed on it's data.
     4676 *
    46644677 * @param   fFlags          The main flags.
    46654678 * @param   fAvastKludge    Whether to apply the avast kludge.
     
    46674680DECLHIDDEN(void) supR3HardenedWinInit(uint32_t fFlags, bool fAvastKludge)
    46684681{
     4682#ifndef VBOX_WITHOUT_DEBUGGER_CHECKS
     4683    /*
     4684     * Install a anti debugging hack before we continue.  This prevents most
     4685     * notifications from ending up in the debugger. (Also applied to the
     4686     * child process when respawning.)
     4687     */
     4688    rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0);
     4689    if (!NT_SUCCESS(rcNt))
     4690        supR3HardenedFatalMsg("supR3HardenedWinInit", kSupInitOp_Misc, VERR_GENERAL_FAILURE,
     4691                              "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt);
     4692#endif
     4693
    46694694    /*
    46704695     * Init the verifier.
     
    54745499
    54755500    /*
     5501     * If we've done early init already, register the DLL load notification
     5502     * callback and reinstall the NtDll patches.
     5503     */
     5504    if (g_fSupEarlyProcessInit)
     5505    {
     5506        supR3HardenedWinRegisterDllNotificationCallback();
     5507        supR3HardenedWinReInstallHooks(false /*fFirstCall */);
     5508    }
     5509
     5510    /*
    54765511     * Call the C/C++ main function.
    54775512     */
     
    56165651
    56175652    /*
     5653     * Reinstall the NtDll patches since there is a slight possibility that
     5654     * someone undid them while we where busy opening the device.
     5655     */
     5656    supR3HardenedWinReInstallHooks(false /*fFirstCall */);
     5657
     5658    /*
    56185659     * Restore the LdrInitializeThunk code so we can initialize the process
    56195660     * normally when we return.
  • trunk/src/VBox/HostDrivers/Support/win/import-template-ntdll.h

    r52949 r52953  
    5656SUPHARNT_IMPORT_SYSCALL(NtWriteVirtualMemory, 20)
    5757SUPHARNT_IMPORT_SYSCALL(NtYieldExecution, 0)
    58 
    59 SUPHARNT_IMPORT_STDCALL_EARLY(NtCreateSection, 28)
    60 SUPHARNT_IMPORT_STDCALL_EARLY(NtQueryVolumeInformationFile, 20)
     58SUPHARNT_IMPORT_SYSCALL(NtCreateSection, 28)
     59SUPHARNT_IMPORT_SYSCALL(NtQueryVolumeInformationFile, 20)
    6160
    6261SUPHARNT_IMPORT_STDCALL_EARLY(LdrInitializeThunk, 12)
     62SUPHARNT_IMPORT_STDCALL_EARLY_OPTIONAL(LdrRegisterDllNotification, 16)
    6363
    6464SUPHARNT_IMPORT_STDCALL(RtlAddAccessAllowedAce, 16)
Note: See TracChangeset for help on using the changeset viewer.

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