VirtualBox

儲存庫 vbox 的更動 52403


忽略:
時間撮記:
2014-8-18 下午08:35:32 (10 年 以前)
作者:
vboxsync
訊息:

SUP,IPRT: Extended RTLdrQueryPropEx with a pvBits parameter, RTLDRPROP_IMPORT_COUNT and RTLDRPROP_IMPORT_MODULE. Hook LdrLoadDll to validate DLLs before they get to NtCreateSection and the loader code/data can be messed up (windows 7 / 32-bit crash). Allow the kernel to buffer the log file, no real need that each write hits the disk.

位置:
trunk
檔案:
修改 14 筆資料

圖例:

未更動
新增
刪除
  • trunk/include/iprt/ldr.h

    r52213 r52403  
    10021002    RTLDRPROP_SIGNATURE_CHECKS_ENFORCED,
    10031003
     1004    /** Number of import or needed modules. */
     1005    RTLDRPROP_IMPORT_COUNT,
     1006    /** Import module by index (32-bit) stored in the buffer. */
     1007    RTLDRPROP_IMPORT_MODULE,
     1008
    10041009    /** End of valid properties.  */
    10051010    RTLDRPROP_END,
     
    10241029 * @param   hLdrMod         The module handle.
    10251030 * @param   enmLdrProp      The property to query.
    1026  * @param   pvBuf           Pointer to the return buffer.
    1027  * @param   cbBuf           The size of the return buffer.
     1031 * @param   pvBuf           Pointer to the input / output buffer.  In most cases
     1032 *                          it's only used for returning data.
     1033 * @param   cbBuf           The size of the buffer.
    10281034 */
    10291035RTDECL(int) RTLdrQueryProp(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf);
     
    10461052 * @param   hLdrMod         The module handle.
    10471053 * @param   enmLdrProp      The property to query.
    1048  * @param   pvBuf           Pointer to the return buffer.
    1049  * @param   cbBuf           The size of the return buffer.
     1054 * @param   pvBits          Optional pointer to bits returned by
     1055 *                          RTLdrGetBits().  This can be utilized by some module
     1056 *                          interpreters to reduce memory consumption and file
     1057 *                          access.
     1058 * @param   pvBuf           Pointer to the input / output buffer.  In most cases
     1059 *                          it's only used for returning data.
     1060 * @param   cbBuf           The size of the buffer.
    10501061 * @param   pcbRet          Where to return the amount of data returned.  On
    10511062 *                          buffer size errors, this is set to the correct size.
    10521063 *                          Optional.
    10531064 */
    1054 RTDECL(int) RTLdrQueryPropEx(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbBuf);
     1065RTDECL(int) RTLdrQueryPropEx(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBits, void *pvBuf, size_t cbBuf, size_t *pcbBuf);
    10551066
    10561067
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r52373 r52403  
    204204
    205205if "$(KBUILD_TARGET)" == "win" && defined(VBOX_WITH_HARDENING) ## @todo some of this move up.
    206  SUPR3HardenedStatic_DEFS += IN_RT IN_RT_R3 IN_RT_STATIC IPRT_NO_CRT RT_WITH_NOCRT_ALIASES LOG_DISABLED IPRT_NO_ERROR_DATA
     206 SUPR3HardenedStatic_DEFS += \
     207        IN_RT \
     208        IN_RT_R3 \
     209        IN_RT_STATIC \
     210        IN_DIS \
     211        DIS_CORE_ONLY \
     212        IPRT_NO_CRT \
     213        RT_WITH_NOCRT_ALIASES \
     214        LOG_DISABLED \
     215        IPRT_NO_ERROR_DATA
    207216 SUPR3HardenedStatic_DEFS.win += LDR_ONLY_PE __STRALIGN_H_
    208217
     
    331340        $(VBOX_PATH_RUNTIME_SRC)/generic/memsafer-generic.cpp \
    332341        $(VBOX_PATH_RUNTIME_SRC)/generic/uuid-generic.cpp \
     342       \
     343        ../../Disassembler/DisasmCore.cpp \
     344        ../../Disassembler/DisasmTables.cpp \
     345        ../../Disassembler/DisasmTablesX64.cpp \
     346        ../../Disassembler/DisasmReg.cpp
    333347
    334348 SUPR3HardenedStatic_SOURCES.amd64 += \
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp

    r52366 r52403  
    975975                                                NULL,
    976976                                                OPEN_ALWAYS,
    977                                                 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
     977                                                FILE_ATTRIBUTE_NORMAL /*| FILE_FLAG_WRITE_THROUGH*/,
    978978                                                NULL);
    979979                    RTUtf16Free(pwszPath);
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h

    r52375 r52403  
    4343DECLHIDDEN(int)     supHardenedWinInitImageVerifier(PRTERRINFO pErrInfo);
    4444DECLHIDDEN(void)    supHardenedWinTermImageVerifier(void);
     45DECLHIDDEN(void)    supR3HardenedWinVerifyCacheScheduleImports(RTLDRMOD hLdrMod, PCRTUTF16 pwszName);
    4546DECLHIDDEN(void)    supR3HardenedWinVerifyCachePreload(PCRTUTF16 pwszName);
     47
    4648
    4749typedef enum SUPHARDNTVPKIND
     
    8385/** Pointer to an SUP image verifier loader reader instance. */
    8486typedef SUPHNTVIRDR *PSUPHNTVIRDR;
    85 DECLHIDDEN(int) supHardNtViRdrCreate(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PSUPHNTVIRDR *ppNtViRdr);
    86 DECLHIDDEN(int) supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, bool *pfCacheable, PRTERRINFO pErrInfo);
    87 DECLHIDDEN(int) supHardenedWinVerifyImageByHandleNoName(HANDLE hFile, uint32_t fFlags, PRTERRINFO pErrInfo);
    88 DECLHIDDEN(int) supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr,
    89                                                   bool *pfCacheable, PRTERRINFO pErrInfo);
     87DECLHIDDEN(int)  supHardNtViRdrCreate(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PSUPHNTVIRDR *ppNtViRdr);
     88DECLHIDDEN(bool) supHardenedWinIsWinVerifyTrustCallable(void);
     89DECLHIDDEN(int)  supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags,
     90                                                   bool *pfWinVerifyTrust, PRTERRINFO pErrInfo);
     91DECLHIDDEN(int)  supHardenedWinVerifyImageByHandleNoName(HANDLE hFile, uint32_t fFlags, PRTERRINFO pErrInfo);
     92DECLHIDDEN(int)  supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr,
     93                                                   bool *pfWinVerifyTrust, PRTERRINFO pErrInfo);
    9094/** @name SUPHNTVI_F_XXX - Flags for supHardenedWinVerifyImageByHandle.
    9195 * @{ */
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp

    r52376 r52403  
    173173/** Pointer to CryptCATCatalogInfoFromContext. */
    174174PFNCRYPTCATCATALOGINFOFROMCONTEXT       g_pfnCryptCATCatalogInfoFromContext;
     175
     176/** Indicates active WinVerifyTrust thread. */
     177static uint32_t volatile                g_idActiveThread = UINT32_MAX;
     178
    175179#endif
    176180
     
    957961 *
    958962 * @returns IPRT status code.
    959  * @param   hLdrMod     File handle to the executable file.
    960  * @param   pwszName    Full NT path to the DLL in question, used for dealing
    961  *                      with unsigned system dlls as well as for error/logging.
    962  * @param   pNtViRdr    The reader instance /w flags.
    963  * @param   pfCacheable Where to return whether the result can be cached.  A
    964  *                      valid value is always returned. Optional.
    965  * @param   pErrInfo    Pointer to error info structure. Optional.
     963 * @param   hLdrMod             File handle to the executable file.
     964 * @param   pwszName            Full NT path to the DLL in question, used for
     965 *                              dealing with unsigned system dlls as well as for
     966 *                              error/logging.
     967 * @param   pNtViRdr            The reader instance /w flags.
     968 * @param   pfWinVerifyTrust    Where to return whether WinVerifyTrust was used.
     969 * @param   pErrInfo            Pointer to error info structure. Optional.
    966970 */
    967971DECLHIDDEN(int) supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr,
    968                                                   bool *pfCacheable, PRTERRINFO pErrInfo)
    969 {
     972                                                  bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
     973{
     974    if (pfWinVerifyTrust)
     975        *pfWinVerifyTrust = false;
     976
    970977#ifdef IN_RING3
    971978    /* Check that the caller has performed the necessary library initialization. */
     
    10471054      * Call the windows verify trust API if we've resolved it and aren't in
    10481055      * some obvious recursion.  Assumes the loader semaphore will reduce the
    1049       * risk of concurrency here, so no TLS, only a single static variable.
     1056      * risk of concurrency here, so no TLS, only a single global variable.
    10501057      */
    10511058    if (g_pfnWinVerifyTrust)
    10521059    {
    1053         static uint32_t volatile s_idActiveThread = UINT32_MAX;
    10541060        uint32_t const idCurrentThread = GetCurrentThreadId();
    1055         if (s_idActiveThread != idCurrentThread)
     1061        if (g_idActiveThread != idCurrentThread)
    10561062        {
    1057             ASMAtomicCmpXchgU32(&s_idActiveThread, idCurrentThread, UINT32_MAX);
    1058 
    1059             if (pfCacheable)
    1060                 *pfCacheable = g_pfnWinVerifyTrust != NULL;
     1063            ASMAtomicCmpXchgU32(&g_idActiveThread, idCurrentThread, UINT32_MAX);
     1064
     1065            if (pfWinVerifyTrust)
     1066                *pfWinVerifyTrust = true;
     1067
    10611068            if (rc != VERR_LDRVI_NOT_SIGNED)
    10621069            {
     
    10911098            }
    10921099
    1093             ASMAtomicCmpXchgU32(&s_idActiveThread, UINT32_MAX, idCurrentThread);
     1100            ASMAtomicCmpXchgU32(&g_idActiveThread, UINT32_MAX, idCurrentThread);
    10941101        }
    10951102        else
    10961103            SUP_DPRINTF(("Detected WinVerifyTrust recursion: rc=%Rrc '%ls'.\n", rc, pwszName));
    10971104    }
    1098 #else  /* !IN_RING3 */
    1099     if (pfCacheable)
    1100         *pfCacheable = true;
    1101 #endif /* !IN_RING3 */
     1105#endif /* IN_RING3 */
     1106
     1107#ifdef IN_SUP_HARDENED_R3
     1108    /*
     1109     * Hook for the LdrLoadDll code to schedule scanning of imports.
     1110     */
     1111    if (RT_SUCCESS(rc))
     1112        supR3HardenedWinVerifyCacheScheduleImports(hLdrMod, pwszName);
     1113#endif
    11021114
    11031115    return rc;
     
    11091121 *
    11101122 * @returns IPRT status code.
    1111  * @param   hFile       File handle to the executable file.
    1112  * @param   pwszName    Full NT path to the DLL in question, used for dealing
    1113  *                      with unsigned system dlls as well as for error/logging.
    1114  * @param   fFlags      Flags, SUPHNTVI_F_XXX.
    1115  * @param   pfCacheable Where to return whether the result can be cached.  A
    1116  *                      valid value is always returned. Optional.
    1117  * @param   pErrInfo    Pointer to error info structure. Optional.
     1123 * @param   hFile               File handle to the executable file.
     1124 * @param   pwszName            Full NT path to the DLL in question, used for
     1125 *                              dealing with unsigned system dlls as well as for
     1126 *                              error/logging.
     1127 * @param   fFlags              Flags, SUPHNTVI_F_XXX.
     1128 * @param   pfWinVerifyTrust    Where to return whether WinVerifyTrust was used.
     1129 * @param   pErrInfo            Pointer to error info structure. Optional.
    11181130 */
    11191131DECLHIDDEN(int) supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags,
    1120                                                   bool *pfCacheable, PRTERRINFO pErrInfo)
    1121 {
    1122     /* Clear the cacheable indicator as it needs to be valid in all return paths. */
    1123     if (pfCacheable)
    1124         *pfCacheable = false;
    1125 
     1132                                                  bool *pfWinVerifyTrust, PRTERRINFO pErrInfo)
     1133{
    11261134    /*
    11271135     * Create a reader instance.
     
    11441152             * Verify it.
    11451153             */
    1146             rc = supHardenedWinVerifyImageByLdrMod(hLdrMod, pwszName, pNtViRdr, pfCacheable, pErrInfo);
     1154            rc = supHardenedWinVerifyImageByLdrMod(hLdrMod, pwszName, pNtViRdr, pfWinVerifyTrust, pErrInfo);
    11471155            int rc2 = RTLdrClose(hLdrMod); AssertRC(rc2);
    11481156        }
     
    11501158            supHardNtViRdrDestroy(&pNtViRdr->Core);
    11511159    }
    1152     SUP_DPRINTF(("supHardenedWinVerifyImageByHandle: -> %d %s(%ls)\n", rc, pfCacheable && *pfCacheable ? "cacheable ": "", pwszName));
     1160    SUP_DPRINTF(("supHardenedWinVerifyImageByHandle: -> %d (%ls)%s\n",
     1161                 rc, pwszName, pfWinVerifyTrust && *pfWinVerifyTrust ? "WinVerifyTrust" : ""));
    11531162    return rc;
    11541163}
     
    11881197        uBuf.UniStr.Buffer = (WCHAR *)L"TODO3";
    11891198
    1190     return supHardenedWinVerifyImageByHandle(hFile, uBuf.UniStr.Buffer, fFlags, NULL /*pfCacheable*/, pErrInfo);
     1199    return supHardenedWinVerifyImageByHandle(hFile, uBuf.UniStr.Buffer, fFlags, NULL /*pfWinVerifyTrust*/, pErrInfo);
     1200}
     1201#endif /* IN_RING3 */
     1202
     1203
     1204#ifdef IN_RING3
     1205/**
     1206 * Checks if WinVerifyTrust is callable on the current thread.
     1207 *
     1208 * Used by the main code to figure whether it makes sense to try revalidate an
     1209 * image that hasn't passed thru WinVerifyTrust yet.
     1210 *
     1211 * @returns true if callable on current thread, false if not.
     1212 */
     1213DECLHIDDEN(bool) supHardenedWinIsWinVerifyTrustCallable(void)
     1214{
     1215    return g_pfnWinVerifyTrust != NULL
     1216        && g_idActiveThread != GetCurrentThreadId();
    11911217}
    11921218#endif /* IN_RING3 */
     
    17551781{
    17561782    WCHAR wszName[200+60];
    1757     UINT cwcDir = GetSystemWindowsDirectoryW(wszName, RT_ELEMENTS(wszName) - 60);
    1758     memcpy(&wszName[cwcDir], RT_STR_TUPLE(L"\\System32\\"));
    1759     RTUtf16CopyAscii(&wszName[cwcDir + sizeof("\\System32\\") - 1], RT_ELEMENTS(wszName) - cwcDir, pszName);
     1783    UINT cwcDir = GetSystemDirectoryW(wszName, RT_ELEMENTS(wszName) - 60);
     1784    wszName[cwcDir] = '\\';
     1785    RTUtf16CopyAscii(&wszName[cwcDir + 1], RT_ELEMENTS(wszName) - cwcDir, pszName);
    17601786
    17611787    DWORD fFlags = 0;
     
    19441970     */
    19451971    supR3HardenedWinRetrieveTrustedRootCAs();
    1946 
    1947 # ifdef IN_SUP_HARDENED_R3
    1948     /*
    1949      * Do some verify cache preloading.  The MS Visual C++ CRT DLLs works
    1950      * around recursion issues with WinVerifyTrust on 32-bit windows 7.
    1951      */
    1952     SUP_DPRINTF(("preloading part 2...\n"));
    1953 #  if 0 /* Seeing if this helps with the later Win7/32 issue... apparently not :-/ */
    1954     supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\cfgmgr32.dll");
    1955     supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\devobj.dll");
    1956     supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\setupapi.dll");
    1957     supR3HardenedWinLoadSystem32Dll("setupapi.dll");
    1958     supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\rsaenh.dll");
    1959     supR3HardenedWinLoadSystem32Dll("rsaenh.dll");
    1960 #  endif
    1961 
    1962     WCHAR wszPath[260+16];
    1963     supR3HardenedWinVerifyCachePreload(L"\\SystemRoot\\System32\\apphelp.dll");
    1964     memcpy(wszPath, g_SupLibHardenedExeNtPath.UniStr.Buffer, g_SupLibHardenedExeNtPath.UniStr.Length);
    1965     static char const *s_apszAppDlls[] =
    1966     {
    1967         NULL,
    1968         "VBoxRT.dll",
    1969 #  if _MSC_VER < 1600
    1970         "msvcr90.dll",  "msvcp90.dll",
    1971 #  elif _MSC_VER < 1700
    1972         "msvcr100.dll", "msvcp100.dll",
    1973 #  elif _MSC_VER < 1800
    1974         "msvcr110.dll", "msvcp110.dll",
    1975 #  elif _MSC_VER < 1900
    1976         "msvcr120.dll", "msvcp120.dll",
    1977 #  elif _MSC_VER < 1900
    1978         "msvcr130.dll", "msvcp130.dll",
    1979 #  else
    1980 #   error "Unsupported compiler version."
    1981 #  endif
    1982     };
    1983     s_apszAppDlls[0] = pszProgName;
    1984     for (uint32_t i = 0; i < RT_ELEMENTS(s_apszAppDlls); i++)
    1985     {
    1986         RTUtf16CopyAscii(&wszPath[g_offSupLibHardenedExeNtName], 300 - g_offSupLibHardenedExeNtName, s_apszAppDlls[i]);
    1987         supR3HardenedWinVerifyCachePreload(wszPath);
    1988     }
    1989     SUP_DPRINTF(("preloading part 2 - done.\n"));
    1990 # endif
    19911972}
    19921973
     
    22082189             */
    22092190            fTryNextPolicy = false;
     2191            bool fFreshContext = false;
    22102192            BOOL fRc;
    22112193            HCATADMIN hCatAdmin = ASMAtomicXchgPtr(&s_aHashes[i].hCachedCatAdmin, NULL);
    22122194            if (hCatAdmin)
     2195            {
     2196                SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Cached context %p\n", hCatAdmin));
     2197                fFreshContext = false;
    22132198                fRc = TRUE;
    2214             else if (g_pfnCryptCATAdminAcquireContext2)
    2215                 fRc = g_pfnCryptCATAdminAcquireContext2(&hCatAdmin, &s_aPolicies[iPolicy], s_aHashes[i].pszAlgorithm,
    2216                                                         NULL /*pStrongHashPolicy*/, 0 /*dwFlags*/);
     2199            }
    22172200            else
    2218                 fRc = g_pfnCryptCATAdminAcquireContext(&hCatAdmin, &s_aPolicies[iPolicy], 0 /*dwFlags*/);
     2201            {
     2202l_fresh_context:
     2203                fFreshContext = true;
     2204                if (g_pfnCryptCATAdminAcquireContext2)
     2205                    fRc = g_pfnCryptCATAdminAcquireContext2(&hCatAdmin, &s_aPolicies[iPolicy], s_aHashes[i].pszAlgorithm,
     2206                                                            NULL /*pStrongHashPolicy*/, 0 /*dwFlags*/);
     2207                else
     2208                    fRc = g_pfnCryptCATAdminAcquireContext(&hCatAdmin, &s_aPolicies[iPolicy], 0 /*dwFlags*/);
     2209                SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: New context %p\n", hCatAdmin));
     2210            }
    22192211            if (fRc)
    22202212            {
     
    22502242                            if (!hCatInfo)
    22512243                            {
     2244                                if (!fFreshContext)
     2245                                {
     2246                                    SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: Retrying with fresh context (CryptCATAdminEnumCatalogFromHash -> %u; iCat=%#x)\n", GetLastError(), iCat));
     2247                                    if (hCatInfoPrev != NULL)
     2248                                        g_pfnCryptCATAdminReleaseCatalogContext(hCatAdmin, hCatInfoPrev, 0 /*dwFlags*/);
     2249                                    g_pfnCryptCATAdminReleaseContext(hCatAdmin, 0 /*dwFlags*/);
     2250                                    goto l_fresh_context;
     2251                                }
    22522252                                if (iCat == 0)
    22532253                                    SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile: CryptCATAdminEnumCatalogFromHash failed %u\n", GetLastError()));
     
    23052305                                                       "WinVerifyTrust failed with hrc=%#x on '%ls' and .cat-file='%ls'.",
    23062306                                                       hrc, pwszWinPath, CatInfo.wszCatalogFile);
    2307                                     fTryNextPolicy = (hrc == CERT_E_UNTRUSTEDROOT);
     2307                                    fTryNextPolicy |= (hrc == CERT_E_UNTRUSTEDROOT);
    23082308                                }
    23092309
  • trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp

    r52373 r52403  
    823823     */
    824824    uint32_t         cSkipAreas = 0;
    825     SUPHNTVPSKIPAREA aSkipAreas[3];
     825    SUPHNTVPSKIPAREA aSkipAreas[4];
    826826    if (pImage->fNtCreateSectionPatch)
    827827    {
     
    834834                return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'NtCreateSection': %Rrc", pImage->pszName, rc);
    835835            aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue;
    836             aSkipAreas[cSkipAreas++].cb = 16;
     836            aSkipAreas[cSkipAreas++].cb = 5 + (ARCH_BITS == 64);
     837
     838            /* Ignore our LdrLoadDll hack. */
     839            rc = RTLdrGetSymbolEx(pImage->pCacheEntry->hLdrMod, pbBits, 0, UINT32_MAX, "LdrLoadDll", &uValue);
     840            if (RT_FAILURE(rc))
     841                return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'LdrLoadDll': %Rrc", pImage->pszName, rc);
     842            aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue;
     843            aSkipAreas[cSkipAreas++].cb = 5 + (ARCH_BITS == 64);
    837844        }
    838845
     
    844851            aSkipAreas[cSkipAreas++].cb = RT_MAX(pbBits[(uint32_t)uValue], 0x50);
    845852        }
     853
     854        Assert(cSkipAreas <= RT_ELEMENTS(aSkipAreas));
    846855    }
    847856
     
    907916                    fProt = PAGE_EXECUTE;
    908917                    break;
     918                case IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE:
     919                    /* Only the executable is allowed to have this section,
     920                       and it's protected after we're done patching. */
     921                    if (!pImage->fDll)
     922                    {
     923                        if (pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION)
     924                            fProt = PAGE_EXECUTE_READWRITE;
     925                        else
     926                            fProt = PAGE_EXECUTE_READ;
     927                        break;
     928                    }
    909929                default:
    910930                    return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_UNEXPECTED_SECTION_FLAGS,
     
    915935            /* The section bits, only child purification verifies all bits . */
    916936            if (   pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION
    917                 || (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE))
     937                || (   (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE))
     938                    && !(pThis->aSecHdrs[i].Characteristics & IMAGE_SCN_MEM_WRITE))
    918939                || (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) == IMAGE_SCN_MEM_READ)
    919940            {
     
    15001521    if (!pEntry->fVerified)
    15011522    {
    1502         rc = supHardenedWinVerifyImageByLdrMod(pEntry->hLdrMod, pwszName, pEntry->pNtViRdr, NULL /*pfCacheable*/, pErrInfo);
     1523        rc = supHardenedWinVerifyImageByLdrMod(pEntry->hLdrMod, pwszName, pEntry->pNtViRdr, NULL /*pfWinVerifyTrust*/, pErrInfo);
    15031524        pEntry->fVerified = RT_SUCCESS(rc);
    15041525    }
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp

    r52375 r52403  
    4141#include <VBox/sup.h>
    4242#include <VBox/err.h>
     43#include <VBox/dis.h>
    4344#include <iprt/ctype.h>
    4445#include <iprt/string.h>
     
    125126    /** Pointer to the next entry with the same hash value. */
    126127    struct VERIFIERCACHEENTRY * volatile pNext;
     128    /** Next entry in the WinVerifyTrust todo list. */
     129    struct VERIFIERCACHEENTRY * volatile pNextTodoWvt;
     130
    127131    /** The file handle. */
    128132    HANDLE                  hFile;
     
    135139    /** Whether IndexNumber is valid  */
    136140    bool                    fIndexNumberValid;
     141    /** Whether verified by WinVerifyTrust. */
     142    bool volatile           fWinVerifyTrust;
    137143    /** cwcPath * sizeof(RTUTF16). */
    138144    uint16_t                cbPath;
     
    142148/** Pointer to an image verifier path entry. */
    143149typedef VERIFIERCACHEENTRY *PVERIFIERCACHEENTRY;
     150
     151
     152/**
     153 * Name of an import DLL that we need to check out.
     154 */
     155typedef struct VERIFIERCACHEIMPORT
     156{
     157    /** Pointer to the next DLL in the list. */
     158    struct VERIFIERCACHEIMPORT * volatile pNext;
     159    /** The length of pwszAltSearchDir if available. */
     160    uint32_t                cwcAltSearchDir;
     161    /** This points the directory containing the DLL needing it, this will be
     162     * NULL for a System32 DLL. */
     163    PWCHAR                  pwszAltSearchDir;
     164    /** The name of the import DLL (variable length). */
     165    char                    szName[1];
     166} VERIFIERCACHEIMPORT;
     167/** Pointer to a import DLL that needs checking out. */
     168typedef VERIFIERCACHEIMPORT *PVERIFIERCACHEIMPORT;
    144169
    145170
     
    171196static NTSTATUS (NTAPI *    g_pfnNtCreateSectionReal)(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
    172197                                                      PLARGE_INTEGER, ULONG, ULONG, HANDLE);
     198#if 0
     199/** The jump back address of the patched LdrLoadDll. */
     200extern "C" PFNRT            g_pfnLdrLoadDllJmpBack = NULL;
     201#endif
     202/** Pointer to the bit of assembly code that will perform the original
     203 *  LdrLoadDll operation. */
     204static NTSTATUS (NTAPI *    g_pfnLdrLoadDllReal)(PWSTR, PULONG, PUNICODE_STRING, PHANDLE);
    173205/** The hash table of verifier cache . */
    174206static VERIFIERCACHEENTRY * volatile g_apVerifierCache[128];
     207/** Queue of cached images which needs WinVerifyTrust to check them. */
     208static VERIFIERCACHEENTRY * volatile g_pVerifierCacheTodoWvt = NULL;
     209/** Queue of cached images which needs their imports checked. */
     210static VERIFIERCACHEIMPORT * volatile g_pVerifierCacheTodoImports = NULL;
    175211/** @ */
    176212
    177213/** Static error info structure used during init. */
    178214static RTERRINFOSTATIC      g_ErrInfoStatic;
     215
     216/** In the assembly file. */
     217extern "C" uint8_t          g_abSupHardReadWriteExecPage[PAGE_SIZE];
    179218
    180219
     
    182221*   Internal Functions                                                         *
    183222*******************************************************************************/
     223static NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
     224                                         bool *pfCallRealApi, const char *pszCaller);
     225
    184226#ifdef RT_ARCH_AMD64
    185227# define SYSCALL(a_Num) DECLASM(void) RT_CONCAT(supR3HardenedJmpBack_NtCreateSection_,a_Num)(void)
     
    351393
    352394/**
    353  * Calculates the hash value for the given UTF-16 string.
     395 * Calculates the hash value for the given UTF-16 path string.
    354396 *
    355397 * @returns Hash value.
     
    365407    {
    366408        RTUTF16 wc = *pwc++;
     409        if (wc < 0x80)
     410            wc = wc != '/' ? RT_C_TO_LOWER(wc) : '\\';
    367411        uHash = wc + (uHash << 6) + (uHash << 16) - uHash;
    368412    }
    369413    return uHash;
    370414}
     415
     416
     417/**
     418 * Calculates the hash value for a directory + filename combo as if they were
     419 * one single string.
     420 *
     421 * @returns Hash value.
     422 * @param   pawcDir             The directory name.
     423 * @param   cwcDir              The length of the directory name. RTSTR_MAX if
     424 *                              not available.
     425 * @param   pszName             The import name (UTF-8).
     426 */
     427static uint32_t supR3HardenedWinVerifyCacheHashDirAndFile(PCRTUTF16 pawcDir, uint32_t cwcDir, const char *pszName)
     428{
     429    uint32_t uHash = 0;
     430    while (cwcDir-- > 0)
     431    {
     432        RTUTF16 wc = *pawcDir++;
     433        if (wc < 0x80)
     434            wc = wc != '/' ? RT_C_TO_LOWER(wc) : '\\';
     435        uHash = wc + (uHash << 6) + (uHash << 16) - uHash;
     436    }
     437
     438    unsigned char ch = '\\';
     439    uHash = ch + (uHash << 6) + (uHash << 16) - uHash;
     440
     441    while ((ch = *pszName++) != '\0')
     442    {
     443        ch = RT_C_TO_LOWER(ch);
     444        uHash = ch + (uHash << 6) + (uHash << 16) - uHash;
     445    }
     446
     447    return uHash;
     448}
     449
     450
     451/**
     452 * Verify string cache compare function.
     453 *
     454 * @returns true if the strings match, false if not.
     455 * @param   pawcLeft            The left hand string.
     456 * @param   pawcRight           The right hand string.
     457 * @param   cwcToCompare        The number of chars to compare.
     458 */
     459static bool supR3HardenedWinVerifyCacheIsMatch(PCRTUTF16 pawcLeft, PCRTUTF16 pawcRight, uint32_t cwcToCompare)
     460{
     461    /* Try a quick memory compare first. */
     462    if (memcmp(pawcLeft, pawcRight, cwcToCompare * sizeof(RTUTF16)) == 0)
     463        return true;
     464
     465    /* Slow char by char compare. */
     466    while (cwcToCompare-- > 0)
     467    {
     468        RTUTF16 wcLeft  = *pawcLeft++;
     469        RTUTF16 wcRight = *pawcRight++;
     470        if (wcLeft != wcRight)
     471        {
     472            wcLeft = wcLeft  != '/' ? RT_C_TO_LOWER(wcLeft)  : '\\';
     473            wcLeft = wcRight != '/' ? RT_C_TO_LOWER(wcRight) : '\\';
     474            if (wcLeft != wcRight)
     475                return false;
     476        }
     477    }
     478
     479    return true;
     480}
     481
    371482
    372483
     
    378489 *                              the cache or closed.
    379490 * @param   rc                  The verifier result.
    380  * @param   fCacheable          Whether this is a cacheable result.  Passed in
    381  *                              here instead of being handled by the caller to
    382  *                              save code duplication.
    383  * @param   fForceCacheable     Overrides the main state and @a fCacheable.
    384  */
    385 static void supR3HardenedWinVerifyCacheInsert(PCUNICODE_STRING pUniStr, HANDLE hFile, int rc, bool fCacheable,
    386                                               bool fForceCacheable)
    387 {
    388     /*
    389      * Don't cache anything until we've got the WinVerifyTrust API up and running.
    390      */
    391     if (   (   g_enmSupR3HardenedMainState >= SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY
    392             && fCacheable)
    393         || fForceCacheable)
    394     {
     491 * @param   fWinVerifyTrust     Whether verified by WinVerifyTrust or not.
     492 */
     493static void supR3HardenedWinVerifyCacheInsert(PCUNICODE_STRING pUniStr, HANDLE hFile, int rc, bool fWinVerifyTrust)
     494{
     495    /*
     496     * Allocate and initalize a new entry.
     497     */
     498    PVERIFIERCACHEENTRY pEntry = (PVERIFIERCACHEENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
     499                                                                sizeof(VERIFIERCACHEENTRY) + pUniStr->Length);
     500    if (pEntry)
     501    {
     502        pEntry->pNext           = NULL;
     503        pEntry->pNextTodoWvt    = NULL;
     504        pEntry->hFile           = hFile;
     505        pEntry->rc              = rc;
     506        pEntry->uHash           = supR3HardenedWinVerifyCacheHashPath(pUniStr);
     507        pEntry->fWinVerifyTrust = fWinVerifyTrust;
     508        pEntry->cbPath          = pUniStr->Length;
     509        memcpy(pEntry->wszPath, pUniStr->Buffer, pUniStr->Length);
     510        pEntry->wszPath[pUniStr->Length / sizeof(WCHAR)] = '\0';
     511        pEntry->fIndexNumberValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &pEntry->IndexNumber);
     512
    395513        /*
    396          * Allocate and initalize a new entry.
     514         * Try insert it, careful with concurrent code as well as potential duplicates.
    397515         */
    398         PVERIFIERCACHEENTRY pEntry = (PVERIFIERCACHEENTRY)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
    399                                                                     sizeof(VERIFIERCACHEENTRY) + pUniStr->Length);
    400         if (pEntry)
    401         {
    402             pEntry->pNext   = NULL;
    403             pEntry->hFile   = hFile;
    404             pEntry->rc      = rc;
    405             pEntry->uHash   = supR3HardenedWinVerifyCacheHashPath(pUniStr);
    406             pEntry->cbPath  = pUniStr->Length;
    407             memcpy(pEntry->wszPath, pUniStr->Buffer, pUniStr->Length);
    408             pEntry->wszPath[pUniStr->Length / sizeof(WCHAR)] = '\0';
    409             pEntry->fIndexNumberValid = supR3HardenedWinVerifyCacheGetIndexNumber(hFile, &pEntry->IndexNumber);
    410 
    411             /*
    412              * Try insert it, careful with concurrent code as well as potential duplicates.
    413              */
    414             uint32_t iHashTab = pEntry->uHash % RT_ELEMENTS(g_apVerifierCache);
    415             VERIFIERCACHEENTRY * volatile *ppEntry = &g_apVerifierCache[iHashTab];
    416             for (;;)
     516        uint32_t iHashTab = pEntry->uHash % RT_ELEMENTS(g_apVerifierCache);
     517        VERIFIERCACHEENTRY * volatile *ppEntry = &g_apVerifierCache[iHashTab];
     518        for (;;)
     519        {
     520            if (ASMAtomicCmpXchgPtr(ppEntry, pEntry, NULL))
    417521            {
    418                 if (ASMAtomicCmpXchgPtr(ppEntry, pEntry, NULL))
    419                 {
    420                     SUP_DPRINTF(("supR3HardenedWinVerifyCacheInsert: %ls\n", pUniStr->Buffer));
    421                     return;
    422                 }
    423 
    424                 PVERIFIERCACHEENTRY pOther = *ppEntry;
    425                 if (!pOther)
    426                     continue;
    427                 if (   pOther->uHash  == pEntry->uHash
    428                     && pOther->cbPath == pEntry->cbPath
    429                     && memcmp(pOther->wszPath, pEntry->wszPath, pEntry->cbPath) == 0)
    430                     break;
    431                 ppEntry = &pOther->pNext;
     522                if (!fWinVerifyTrust)
     523                    do
     524                        pEntry->pNextTodoWvt = g_pVerifierCacheTodoWvt;
     525                    while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoWvt, pEntry, pEntry->pNextTodoWvt));
     526
     527                SUP_DPRINTF(("supR3HardenedWinVerifyCacheInsert: %ls\n", pUniStr->Buffer));
     528                return;
    432529            }
    433530
    434             /* Duplicate entry. */
     531            PVERIFIERCACHEENTRY pOther = *ppEntry;
     532            if (!pOther)
     533                continue;
     534            if (   pOther->uHash  == pEntry->uHash
     535                && pOther->cbPath == pEntry->cbPath
     536                && memcmp(pOther->wszPath, pEntry->wszPath, pEntry->cbPath) == 0)
     537                break;
     538            ppEntry = &pOther->pNext;
     539        }
     540
     541        /* Duplicate entry. */
    435542#ifdef DEBUG_bird
    436             __debugbreak();
     543        __debugbreak();
    437544#endif
    438             HeapFree(GetProcessHeap(), 0 /* dwFlags*/, pEntry);
    439         }
     545        HeapFree(GetProcessHeap(), 0 /* dwFlags*/, pEntry);
    440546    }
    441547    NtClose(hFile);
     
    461567        if (   pCur->uHash  == uHash
    462568            && pCur->cbPath == cbPath
    463             && memcmp(pCur->wszPath, pwszPath, cbPath) == 0)
     569            && supR3HardenedWinVerifyCacheIsMatch(pCur->wszPath, pwszPath, cbPath / sizeof(RTUTF16)))
    464570        {
    465571
     
    478584    }
    479585    return NULL;
     586}
     587
     588
     589/**
     590 * Looks up an import DLL in the verifier hash table.
     591 *
     592 * @return  Pointer to the entry on if found, NULL if not.
     593 * @param   pawcDir             The directory name.
     594 * @param   cwcDir              The length of the directory name.
     595 * @param   pszName             The import name (UTF-8).
     596 */
     597static PVERIFIERCACHEENTRY supR3HardenedWinVerifyCacheLookupImport(PCRTUTF16 pawcDir, uint32_t cwcDir, const char *pszName)
     598{
     599    uint32_t            uHash    = supR3HardenedWinVerifyCacheHashDirAndFile(pawcDir, cwcDir, pszName);
     600    uint32_t            iHashTab = uHash % RT_ELEMENTS(g_apVerifierCache);
     601    uint32_t const      cbPath   = (uint32_t)((cwcDir + 1 + strlen(pszName)) * sizeof(RTUTF16));
     602    PVERIFIERCACHEENTRY pCur     = g_apVerifierCache[iHashTab];
     603    while (pCur)
     604    {
     605        if (   pCur->uHash  == uHash
     606            && pCur->cbPath == cbPath)
     607        {
     608            if (supR3HardenedWinVerifyCacheIsMatch(pCur->wszPath, pawcDir, cwcDir))
     609            {
     610                if (pCur->wszPath[cwcDir] == '\\' || pCur->wszPath[cwcDir] == '/')
     611                {
     612                    if (RTUtf16ICmpAscii(&pCur->wszPath[cwcDir + 1], pszName))
     613                    {
     614                        return pCur;
     615                    }
     616                }
     617            }
     618        }
     619
     620        pCur = pCur->pNext;
     621    }
     622    return NULL;
     623}
     624
     625
     626/**
     627 * Schedules the import DLLs for verification and entry into the cache.
     628 *
     629 * @param   hLdrMod             The loader module which imports should be
     630 *                              scheduled for verification.
     631 * @param   pwszName            The full NT path of the module.
     632 */
     633DECLHIDDEN(void) supR3HardenedWinVerifyCacheScheduleImports(RTLDRMOD hLdrMod, PCRTUTF16 pwszName)
     634{
     635    /*
     636     * Any imports?
     637     */
     638    uint32_t cImports;
     639    int rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_IMPORT_COUNT, NULL /*pvBits*/, &cImports, sizeof(cImports), NULL);
     640    if (RT_SUCCESS(rc))
     641    {
     642        if (cImports)
     643        {
     644            /*
     645             * Figure out the DLL directory from pwszName.
     646             */
     647            PCRTUTF16 pawcDir = pwszName;
     648            uint32_t  cwcDir = 0;
     649            uint32_t  i = 0;
     650            RTUTF16   wc;
     651            while ((wc = pawcDir[i++]) != '\0')
     652                if ((wc == '\\' || wc == '/' || wc == ':') && cwcDir + 2 != i)
     653                    cwcDir = i - 1;
     654            if (   g_System32NtPath.UniStr.Length / sizeof(WCHAR) == cwcDir
     655                && supR3HardenedWinVerifyCacheIsMatch(pawcDir, g_System32NtPath.UniStr.Buffer, cwcDir))
     656                pawcDir = NULL;
     657
     658            /*
     659             * Enumerate the imports.
     660             */
     661            for (i = 0; i < cImports; i++)
     662            {
     663                union
     664                {
     665                    char        szName[256];
     666                    uint32_t    iImport;
     667                } uBuf;
     668                uBuf.iImport = i;
     669                rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_IMPORT_MODULE, NULL /*pvBits*/, &uBuf, sizeof(uBuf), NULL);
     670                if (RT_SUCCESS(rc))
     671                {
     672                    /*
     673                     * Skip kernel32, ntdll and API set stuff.
     674                     */
     675                    RTStrToLower(uBuf.szName);
     676                    if (   RTStrCmp(uBuf.szName, "kernel32.dll") == 0
     677                        || RTStrCmp(uBuf.szName, "kernelbase.dll") == 0
     678                        || RTStrCmp(uBuf.szName, "ntdll.dll") == 0
     679                        || RTStrNCmp(uBuf.szName, RT_STR_TUPLE("api-ms-win-")) == 0 )
     680                    {
     681                        continue;
     682                    }
     683
     684                    /*
     685                     * Skip to the next one if it's already in the cache.
     686                     */
     687                    if (supR3HardenedWinVerifyCacheLookupImport(g_System32NtPath.UniStr.Buffer,
     688                                                                g_System32NtPath.UniStr.Length / sizeof(WCHAR),
     689                                                                uBuf.szName) != NULL)
     690                    {
     691                        SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for system32\n", uBuf.szName));
     692                        continue;
     693                    }
     694                    if (supR3HardenedWinVerifyCacheLookupImport(g_SupLibHardenedExeNtPath.UniStr.Buffer,
     695                                                                g_offSupLibHardenedExeNtName,
     696                                                                uBuf.szName) != NULL)
     697                    {
     698                        SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for appdir\n", uBuf.szName));
     699                        continue;
     700                    }
     701                    if (pawcDir && supR3HardenedWinVerifyCacheLookupImport(pawcDir, cwcDir, uBuf.szName) != NULL)
     702                    {
     703                        SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: '%s' cached for dll dir\n", uBuf.szName));
     704                        continue;
     705                    }
     706
     707                    /* We could skip already scheduled modules, but that'll require serialization and extra work... */
     708
     709                    /*
     710                     * Add it to the todo list.
     711                     */
     712                    SUP_DPRINTF(("supR3HardenedWinVerifyCacheScheduleImports: Import todo: #%u '%s'.\n", i, uBuf.szName));
     713                    uint32_t cbName        = (uint32_t)strlen(uBuf.szName) + 1;
     714                    uint32_t cbNameAligned = RT_ALIGN_32(cbName, sizeof(RTUTF16));
     715                    uint32_t cbNeeded      = RT_OFFSETOF(VERIFIERCACHEIMPORT, szName[cbNameAligned])
     716                                           + (pawcDir ? (cwcDir + 1) * sizeof(RTUTF16) : 0);
     717                    PVERIFIERCACHEIMPORT pImport = (PVERIFIERCACHEIMPORT)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbNeeded);
     718                    if (pImport)
     719                    {
     720                        /* Init it. */
     721                        memcpy(pImport->szName, uBuf.szName, cbName);
     722                        if (!pawcDir)
     723                        {
     724                            pImport->cwcAltSearchDir  = 0;
     725                            pImport->pwszAltSearchDir = NULL;
     726                        }
     727                        else
     728                        {
     729                            pImport->cwcAltSearchDir = cwcDir;
     730                            pImport->pwszAltSearchDir = (PRTUTF16)&pImport->szName[cbNameAligned];
     731                            memcpy(pImport->pwszAltSearchDir, pawcDir, cwcDir * sizeof(RTUTF16));
     732                            pImport->pwszAltSearchDir[cwcDir] = '\0';
     733                        }
     734
     735                        /* Insert it. */
     736                        do
     737                            pImport->pNext = g_pVerifierCacheTodoImports;
     738                        while (!ASMAtomicCmpXchgPtr(&g_pVerifierCacheTodoImports, pImport, pImport->pNext));
     739                    }
     740                }
     741                else
     742                    SUP_DPRINTF(("RTLDRPROP_IMPORT_MODULE failed with rc=%Rrc i=%#x on '%ls'\n", rc, i, pwszName));
     743            }
     744        }
     745        else
     746            SUP_DPRINTF(("'%ls' has no imports\n", pwszName));
     747    }
     748    else
     749        SUP_DPRINTF(("RTLDRPROP_IMPORT_COUNT failed with rc=%Rrc on '%ls'\n", rc, pwszName));
     750}
     751
     752
     753/**
     754 * Processes the list of import todos.
     755 */
     756static void supR3HardenedWinVerifyCacheProcessImportTodos(void)
     757{
     758    /*
     759     * Work until we've got nothing more todo.
     760     */
     761    for (;;)
     762    {
     763        PVERIFIERCACHEIMPORT pTodo = ASMAtomicXchgPtrT(&g_pVerifierCacheTodoImports, NULL, PVERIFIERCACHEIMPORT);
     764        if (!pTodo)
     765            break;
     766        do
     767        {
     768            PVERIFIERCACHEIMPORT pCur = pTodo;
     769            pTodo = pTodo->pNext;
     770
     771            /*
     772             * Not in the cached already?
     773             */
     774            if (   !supR3HardenedWinVerifyCacheLookupImport(g_System32NtPath.UniStr.Buffer,
     775                                                            g_System32NtPath.UniStr.Length / sizeof(WCHAR),
     776                                                            pCur->szName)
     777                && !supR3HardenedWinVerifyCacheLookupImport(g_SupLibHardenedExeNtPath.UniStr.Buffer,
     778                                                            g_offSupLibHardenedExeNtName,
     779                                                            pCur->szName)
     780                && (   pCur->cwcAltSearchDir == 0
     781                    || !supR3HardenedWinVerifyCacheLookupImport(pCur->pwszAltSearchDir, pCur->cwcAltSearchDir, pCur->szName)) )
     782            {
     783                /*
     784                 * Try locate the imported DLL and open it.
     785                 */
     786                SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: Processing '%s'...\n", pCur->szName));
     787
     788                NTSTATUS    rcNt;
     789                HANDLE      hFile = INVALID_HANDLE_VALUE;
     790                RTUTF16     wszPath[260 + 260]; /* Assumes we've limited the import name length to 256. */
     791                AssertCompile(sizeof(wszPath) > sizeof(g_System32NtPath));
     792                struct
     793                {
     794                    PRTUTF16 pawcDir;
     795                    uint32_t cwcDir;
     796                } Tmp, aDirs[] =
     797                {
     798                    { g_System32NtPath.UniStr.Buffer,           g_System32NtPath.UniStr.Length / sizeof(WCHAR) },
     799                    { g_SupLibHardenedExeNtPath.UniStr.Buffer,  g_offSupLibHardenedExeNtName - 1 },
     800                    { pCur->pwszAltSearchDir,                   pCur->cwcAltSearchDir },
     801                };
     802
     803                /* Search System32 first, unless it's a 'V*' or 'm*' name, the latter for msvcrt.  */
     804                if (   pCur->szName[0] == 'v'
     805                    || pCur->szName[0] == 'V'
     806                    || pCur->szName[0] == 'm'
     807                    || pCur->szName[0] == 'M')
     808                {
     809                    Tmp      = aDirs[0];
     810                    aDirs[0] = aDirs[1];
     811                    aDirs[1] = Tmp;
     812                }
     813
     814                for (uint32_t i = 0; i < RT_ELEMENTS(aDirs); i++)
     815                {
     816                    if (aDirs[i].pawcDir && aDirs[i].cwcDir && aDirs[i].cwcDir < RT_ELEMENTS(wszPath) / 3 * 2)
     817                    {
     818                        memcpy(wszPath, aDirs[i].pawcDir, aDirs[i].cwcDir * sizeof(RTUTF16));
     819                        uint32_t cwc = aDirs[i].cwcDir;
     820                        wszPath[cwc++] = '\\';
     821                        size_t   cwcName  = RT_ELEMENTS(wszPath) - cwc;
     822                        PRTUTF16 pwszName = &wszPath[cwc];
     823                        int rc = RTStrToUtf16Ex(pCur->szName, RTSTR_MAX, &pwszName, cwcName, &cwcName);
     824                        if (RT_SUCCESS(rc))
     825                        {
     826                            IO_STATUS_BLOCK     Ios   = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     827                            UNICODE_STRING      NtName;
     828                            NtName.Buffer        = wszPath;
     829                            NtName.Length        = (USHORT)((cwc + cwcName) * sizeof(WCHAR));
     830                            NtName.MaximumLength = NtName.Length + sizeof(WCHAR);
     831                            OBJECT_ATTRIBUTES   ObjAttr;
     832                            InitializeObjectAttributes(&ObjAttr, &NtName, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
     833
     834                            rcNt = NtCreateFile(&hFile,
     835                                                FILE_READ_DATA | READ_CONTROL | SYNCHRONIZE,
     836                                                &ObjAttr,
     837                                                &Ios,
     838                                                NULL /* Allocation Size*/,
     839                                                FILE_ATTRIBUTE_NORMAL,
     840                                                FILE_SHARE_READ,
     841                                                FILE_OPEN,
     842                                                FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
     843                                                NULL /*EaBuffer*/,
     844                                                0 /*EaLength*/);
     845                            if (NT_SUCCESS(rcNt))
     846                                rcNt = Ios.Status;
     847                            if (NT_SUCCESS(rcNt))
     848                                break;
     849                            hFile = INVALID_HANDLE_VALUE;
     850                        }
     851                        else
     852                            SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: RTStrToUtf16Ex failed: %Rrc\n", rc));
     853                    }
     854                }
     855
     856                /*
     857                 * If we successfully opened it, verify it and cache the result.
     858                 */
     859                if (hFile != INVALID_HANDLE_VALUE)
     860                {
     861                    SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' -> '%ls'\n", pCur->szName, wszPath));
     862
     863                    ULONG fAccess = 0;
     864                    ULONG fProtect = 0;
     865                    bool  fCallRealApi = false;
     866                    rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi, "Imports");
     867                    NtClose(hFile);
     868                }
     869                else
     870                    SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: Failed to locate '%s'\n", pCur->szName));
     871            }
     872            else
     873                SUP_DPRINTF(("supR3HardenedWinVerifyCacheProcessImportTodos: '%s' is in the cache.\n", pCur->szName));
     874
     875            HeapFree(GetProcessHeap(), 0 /* dwFlags*/, pCur);
     876        } while (pTodo);
     877    }
    480878}
    481879
     
    6251023
    6261024
    627 static NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect, bool *pfCallRealApi,
    628                                          bool fForceCacheable)
     1025static NTSTATUS supR3HardenedScreenImage(HANDLE hFile, bool fImage, PULONG pfAccess, PULONG pfProtect,
     1026                                         bool *pfCallRealApi, const char *pszCaller)
    6291027{
    6301028    *pfCallRealApi = false;
     
    6441042    if (!NT_SUCCESS(rcNt))
    6451043    {
    646         supR3HardenedError(VINF_SUCCESS, false, "NtCreateSection: NtQueryObject -> %#x (fImage=%d fProtect=%#x fAccess=%#x)\n",
    647                            fImage, *pfProtect, *pfAccess);
     1044        supR3HardenedError(VINF_SUCCESS, false,
     1045                           "supR3HardenedScreenImage/%s: NtQueryObject -> %#x (fImage=%d fProtect=%#x fAccess=%#x)\n",
     1046                           pszCaller, fImage, *pfProtect, *pfAccess);
    6481047        return rcNt;
    6491048    }
     
    6591058     */
    6601059    PVERIFIERCACHEENTRY pCacheHit = supR3HardenedWinVerifyCacheLookup(&uBuf.UniStr, hFile);
    661     if (pCacheHit)
    662     {
    663         SUP_DPRINTF(("NtCreateSection: cache hit (%Rrc) on %ls\n", pCacheHit->rc, pCacheHit->wszPath));
     1060    if (   pCacheHit
     1061        && (   pCacheHit->fWinVerifyTrust
     1062            || RT_FAILURE(pCacheHit->rc)
     1063            || g_enmSupR3HardenedMainState < SUPR3HARDENEDMAINSTATE_VERIFY_TRUST_READY
     1064            || !supHardenedWinIsWinVerifyTrustCallable() ) )
     1065    {
     1066        SUP_DPRINTF(("supR3HardenedScreenImage/%s: cache hit (%Rrc) on %ls\n", pszCaller, pCacheHit->rc, pCacheHit->wszPath));
    6641067        if (RT_SUCCESS(pCacheHit->rc))
    6651068        {
     
    6671070            return STATUS_SUCCESS;
    6681071        }
    669         supR3HardenedError(VINF_SUCCESS, false, "NtCreateSection: cached rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls\n",
    670                            pCacheHit->rc, fImage, *pfProtect, *pfAccess, uBuf.UniStr.Buffer);
     1072        supR3HardenedError(VINF_SUCCESS, false,
     1073                           "supR3HardenedScreenImage/%s: cached rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls\n",
     1074                           pszCaller, pCacheHit->rc, fImage, *pfProtect, *pfAccess, uBuf.UniStr.Buffer);
    6711075        return STATUS_TRUST_FAILURE;
    6721076    }
     
    7081112            {
    7091113                supR3HardenedError(VINF_SUCCESS, false,
    710                                    "NtCreateSection: Failed to duplicate and open the file: rcNt=%#x hFile=%p %ls\n",
    711                                    rcNt, hFile, uBuf.UniStr.Buffer);
     1114                                   "supR3HardenedScreenImage/%s: Failed to duplicate and open the file: rcNt=%#x hFile=%p %ls\n",
     1115                                   pszCaller, rcNt, hFile, uBuf.UniStr.Buffer);
    7121116                return rcNt;
    7131117            }
     
    7221126            {
    7231127                supR3HardenedError(VINF_SUCCESS, false,
    724                                    "NtCreateSection: Re-opened has different ID that input: %#llx vx %#llx (%ls)\n",
    725                                    rcNt, idMyFile.QuadPart, idInFile.QuadPart, uBuf.UniStr.Buffer);
     1128                                   "supR3HardenedScreenImage/%s: Re-opened has different ID that input: %#llx vx %#llx (%ls)\n",
     1129                                   pszCaller, rcNt, idMyFile.QuadPart, idInFile.QuadPart, uBuf.UniStr.Buffer);
    7261130                NtClose(hMyFile);
    7271131                return STATUS_TRUST_FAILURE;
     
    7301134        else
    7311135        {
    732             SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: NtDuplicateObject -> %#x\n", rcNt));
     1136            SUP_DPRINTF(("supR3HardenedScreenImage/%s: NtDuplicateObject -> %#x\n", pszCaller, rcNt));
    7331137#ifdef DEBUG
    7341138
    735             supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_NtCreateSection: NtDuplicateObject(,%#x,) failed: %#x\n", hFile, rcNt);
     1139            supR3HardenedError(VINF_SUCCESS, false,
     1140                               "supR3HardenedScreenImage/%s: NtDuplicateObject(,%#x,) failed: %#x\n", pszCaller, hFile, rcNt);
    7361141#endif
    7371142            hMyFile = hFile;
     
    7551160             * Drop all executable access to the mapping and let it continue.
    7561161             */
    757             SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: Applying the drop-exec-kludge for '%ls'\n", uBuf.UniStr.Buffer));
     1162            SUP_DPRINTF(("supR3HardenedScreenImage/%s: Applying the drop-exec-kludge for '%ls'\n", pszCaller, uBuf.UniStr.Buffer));
    7581163            if (*pfAccess & SECTION_MAP_EXECUTE)
    7591164                *pfAccess = (*pfAccess & ~SECTION_MAP_EXECUTE) | SECTION_MAP_READ;
     
    8211226    {
    8221227        supR3HardenedError(VINF_SUCCESS, false,
    823                            "supR3HardenedMonitor_NtCreateSection: Not a trusted location: '%ls' (fImage=%d fProtect=%#x fAccess=%#x)",
    824                             uBuf.UniStr.Buffer, fImage, *pfAccess, *pfProtect);
     1228                           "supR3HardenedScreenImage/%s: Not a trusted location: '%ls' (fImage=%d fProtect=%#x fAccess=%#x)",
     1229                            pszCaller, uBuf.UniStr.Buffer, fImage, *pfAccess, *pfProtect);
    8251230        if (hMyFile != hFile)
    8261231            NtClose(hMyFile);
     
    8351240    RTErrInfoInit(&ErrInfo, (char *)&uBuf.abBuffer[cbNameBuf], sizeof(uBuf) - cbNameBuf);
    8361241
    837     bool fCacheable = true;
    838     int rc = supHardenedWinVerifyImageByHandle(hMyFile, uBuf.UniStr.Buffer, fFlags, &fCacheable, &ErrInfo);
     1242    bool fWinVerifyTrust = false;
     1243    int rc = supHardenedWinVerifyImageByHandle(hMyFile, uBuf.UniStr.Buffer, fFlags, &fWinVerifyTrust, &ErrInfo);
    8391244    if (RT_FAILURE(rc))
    8401245    {
    8411246        supR3HardenedError(VINF_SUCCESS, false,
    842                            "supR3HardenedMonitor_NtCreateSection: rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls: %s\n",
    843                            rc, fImage, *pfAccess, *pfProtect, uBuf.UniStr.Buffer, ErrInfo.pszMsg);
     1247                           "supR3HardenedScreenImage/%s: rc=%Rrc fImage=%d fProtect=%#x fAccess=%#x %ls: %s\n",
     1248                           pszCaller, rc, fImage, *pfAccess, *pfProtect, uBuf.UniStr.Buffer, ErrInfo.pszMsg);
    8441249        if (hMyFile != hFile)
    8451250            NtClose(hMyFile);
    8461251        return STATUS_TRUST_FAILURE;
    8471252    }
    848     if (hMyFile != hFile)
    849         supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fCacheable, fForceCacheable);
     1253
     1254    /*
     1255     * Insert or update the cache.
     1256     */
     1257    if (!pCacheHit)
     1258    {
     1259        if (hMyFile != hFile)
     1260            supR3HardenedWinVerifyCacheInsert(&uBuf.UniStr, hMyFile, rc, fWinVerifyTrust);
     1261    }
     1262    else
     1263    {
     1264        if (fWinVerifyTrust)
     1265            pCacheHit->fWinVerifyTrust = true;
     1266        if (hMyFile != hFile)
     1267            NtClose(hMyFile);
     1268    }
    8501269
    8511270    *pfCallRealApi = true;
     
    8891308    if (!NT_SUCCESS(rcNt))
    8901309    {
    891         SUP_DPRINTF(("supR3HardenedWinPreScreenImage: Error %#x opening '%ls'.\n", rcNt, pwszName));
     1310        SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: Error %#x opening '%ls'.\n", rcNt, pwszName));
    8921311        return;
    8931312    }
     
    8971316    bool  fCallRealApi;
    8981317    //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: scanning %ls\n", pwszName));
    899     supR3HardenedScreenImage(hFile, false, &fAccess, &fProtect, &fCallRealApi, true /* fForceCacheable */);
     1318    supR3HardenedScreenImage(hFile, false, &fAccess, &fProtect, &fCallRealApi, "preload");
    9001319    //SUP_DPRINTF(("supR3HardenedWinVerifyCachePreload: done %ls\n", pwszName));
    9011320
     
    9301349        if (fImage || fExecMap || fExecProt)
    9311350        {
     1351            DWORD dwSavedLastError = GetLastError();
     1352
    9321353            bool fCallRealApi;
    9331354            //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 1\n"));
    934             NTSTATUS rcNt = supR3HardenedScreenImage(hFile, fImage, &fAccess, &fProtect, &fCallRealApi, false /*fForceCacheable*/);
     1355            NTSTATUS rcNt = supR3HardenedScreenImage(hFile, fImage, &fAccess, &fProtect, &fCallRealApi, "NtCreateSection");
    9351356            //SUP_DPRINTF(("supR3HardenedMonitor_NtCreateSection: 2 rcNt=%#x fCallRealApi=%#x\n", rcNt, fCallRealApi));
     1357
     1358            SetLastError(dwSavedLastError);
     1359
    9361360            if (!NT_SUCCESS(rcNt))
    9371361                return rcNt;
     
    9391363            if (!fCallRealApi)
    9401364                return STATUS_TRUST_FAILURE;
     1365
    9411366        }
    9421367    }
     
    9471372    return g_pfnNtCreateSectionReal(phSection, fAccess, pObjAttribs, pcbSection, fProtect, fAttribs, hFile);
    9481373}
     1374
     1375
     1376/**
     1377 * Hooks that intercepts LdrLoadDll calls.
     1378 *
     1379 * Two purposes:
     1380 *      -# Enforce our own search path restrictions.
     1381 *      -# Prevalidate DLLs about to be loaded so we don't upset the loader data
     1382 *         by doing it from within the NtCreateSection hook (WinVerifyTrust
     1383 *         seems to be doing harm there on W7/32).
     1384 *
     1385 * @returns
     1386 * @param   pwszSearchPath      The search path to use.
     1387 * @param   pfFlags             Flags on input. DLL characteristics or something
     1388 *                              on return?
     1389 * @param   pName               The name of the module.
     1390 * @param   phMod               Where the handle of the loaded DLL is to be
     1391 *                              returned to the caller.
     1392 */
     1393static NTSTATUS NTAPI
     1394supR3HardenedMonitor_LdrLoadDll(PWSTR pwszSearchPath, PULONG pfFlags, PUNICODE_STRING pName, PHANDLE phMod)
     1395{
     1396    DWORD dwSavedLastError = GetLastError();
     1397
     1398    /*
     1399     * Reject things we don't want to deal with.
     1400     */
     1401    if (!pName || pName->Length == 0)
     1402    {
     1403        supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: name is NULL or have a zero length.\n");
     1404        return STATUS_INVALID_PARAMETER;
     1405    }
     1406    SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: pName=%.*ls *pfFlags=%#x pwszSearchPath=%ls\n",
     1407                 (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer, pfFlags ? *pfFlags : UINT32_MAX, pwszSearchPath));
     1408
     1409    /*
     1410     * Reject long paths that's close to the 260 limit without looking.
     1411     */
     1412    if (pName->Length > 256 * sizeof(WCHAR))
     1413    {
     1414        supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: too long name: %#x bytes\n", pName->Length);
     1415        return STATUS_NAME_TOO_LONG;
     1416    }
     1417
     1418    /*
     1419     * Absolute path?
     1420     */
     1421    bool            fSkipValidation = false;
     1422    WCHAR           wszPath[260];
     1423    UNICODE_STRING  ResolvedName;
     1424    if (   (   pName->Length >= 4 * sizeof(WCHAR)
     1425            && RT_C_IS_ALPHA(pName->Buffer[0])
     1426            && pName->Buffer[1] == ':'
     1427            && RTPATH_IS_SLASH(pName->Buffer[2]) )
     1428        || (   pName->Length >= 1 * sizeof(WCHAR)
     1429            && RTPATH_IS_SLASH(pName->Buffer[1]) )
     1430       )
     1431    {
     1432        memcpy(wszPath, pName->Buffer, pName->Length);
     1433        wszPath[pName->Length / sizeof(WCHAR)] = '\0';
     1434    }
     1435    /*
     1436     * Not an absolute path.  Check if it's one of those special API set DLLs.
     1437     */
     1438    else if (supHardViUtf16PathStartsWithEx(pName->Buffer, pName->Length / sizeof(WCHAR),
     1439                                            L"api-ms-win-", 11, false /*fCheckSlash*/))
     1440    {
     1441        memcpy(wszPath, pName->Buffer, pName->Length);
     1442        wszPath[pName->Length / sizeof(WCHAR)] = '\0';
     1443        fSkipValidation = true;
     1444    }
     1445    /*
     1446     * Not an absolute path or special API set.  There are two alternatives
     1447     * now, either there is no path at all or there is a relative path.  We
     1448     * will resolve it to an absolute path in either case, failing the call
     1449     * if we can't. If there isn't a path.
     1450     */
     1451    else
     1452    {
     1453        PCWCHAR  pawcName     = pName->Buffer;
     1454        uint32_t cwcName      = pName->Length / sizeof(WCHAR);
     1455        uint32_t offLastSlash = UINT32_MAX;
     1456        uint32_t offLastDot   = UINT32_MAX;
     1457        for (uint32_t i = 0; i < cwcName; i++)
     1458            switch (pawcName[i])
     1459            {
     1460                case '\\':
     1461                case '/':
     1462                    offLastSlash = i;
     1463                    offLastDot = UINT32_MAX;
     1464                    break;
     1465                case '.':
     1466                    offLastDot = i;
     1467                    break;
     1468            }
     1469
     1470        bool const fNeedDllSuffix = offLastDot == UINT32_MAX && offLastSlash == UINT32_MAX;
     1471
     1472        if (offLastDot != UINT32_MAX && offLastDot == cwcName - 1)
     1473            cwcName--;
     1474
     1475        /*
     1476         * Reject relative paths for now as they might be breakout attempts.
     1477         */
     1478        if (offLastSlash != UINT32_MAX)
     1479        {
     1480            supR3HardenedError(VINF_SUCCESS, false,
     1481                               "supR3HardenedMonitor_LdrLoadDll: relative name not permitted: %.*ls\n",
     1482                               cwcName, pawcName);
     1483            return STATUS_OBJECT_NAME_INVALID;
     1484        }
     1485
     1486        /*
     1487         * Search for the DLL.  Only System32 is allowed as the target of
     1488         * a search on the API level, all VBox calls will have full paths.
     1489         */
     1490        UINT cwc = GetSystemDirectoryW(wszPath, RT_ELEMENTS(wszPath) - 32);
     1491        if (!cwc)
     1492        {
     1493            supR3HardenedError(VINF_SUCCESS, false,
     1494                               "supR3HardenedMonitor_LdrLoadDll: GetSystemDirectoryW failed: %u\n", GetLastError());
     1495            return STATUS_UNEXPECTED_IO_ERROR;
     1496        }
     1497        if (cwc + 1 + cwcName + fNeedDllSuffix * 4 >= RT_ELEMENTS(wszPath))
     1498        {
     1499            supR3HardenedError(VINF_SUCCESS, false,
     1500                               "supR3HardenedMonitor_LdrLoadDll: Name too long (system32): %.*ls\n", cwcName, pawcName);
     1501            return STATUS_NAME_TOO_LONG;
     1502        }
     1503        wszPath[cwc++] = '\\';
     1504        memcpy(&wszPath[cwc], pawcName, cwcName * sizeof(WCHAR));
     1505        cwc += cwcName;
     1506        if (!fNeedDllSuffix)
     1507            wszPath[cwc] = '\0';
     1508        else
     1509        {
     1510            memcpy(&wszPath[cwc], L".dll", 5 * sizeof(WCHAR));
     1511            cwc += 4;
     1512        }
     1513
     1514        ResolvedName.Buffer = wszPath;
     1515        ResolvedName.Length = (USHORT)(cwc * sizeof(WCHAR));
     1516        ResolvedName.MaximumLength = ResolvedName.Length + sizeof(WCHAR);
     1517
     1518        SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: '%.*ls' -> '%.*ls'\n",
     1519                     (unsigned)pName->Length / sizeof(WCHAR), pName->Buffer,
     1520                     ResolvedName.Length / sizeof(WCHAR), ResolvedName.Buffer));
     1521        pName = &ResolvedName;
     1522    }
     1523
     1524    NTSTATUS rcNt;
     1525    if (!fSkipValidation)
     1526    {
     1527        /*
     1528         * Try open the file.  If this fails, never mind, just pass it on to
     1529         * the real API as we've replaced any searchable name with a full name
     1530         * and the real API can come up with a fitting status code for it.
     1531         */
     1532        HANDLE hFile = CreateFileW(wszPath, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecurityAttributes*/,
     1533                                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
     1534        if (hFile != INVALID_HANDLE_VALUE)
     1535        {
     1536            ULONG fAccess = 0;
     1537            ULONG fProtect = 0;
     1538            bool  fCallRealApi = false;
     1539            rcNt = supR3HardenedScreenImage(hFile, true /*fImage*/, &fAccess, &fProtect, &fCallRealApi, "LdrLoadDll");
     1540            NtClose(hFile);
     1541            if (!NT_SUCCESS(rcNt))
     1542            {
     1543                supR3HardenedError(VINF_SUCCESS, false, "supR3HardenedMonitor_LdrLoadDll: rejecting '%ls': rcNt=%#x", wszPath, rcNt);
     1544                return rcNt;
     1545            }
     1546
     1547            supR3HardenedWinVerifyCacheProcessImportTodos();
     1548        }
     1549        else
     1550        {
     1551            DWORD dwErr = GetLastError();
     1552            SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: error opening '%ls': %u\n", wszPath, dwErr));
     1553        }
     1554    }
     1555
     1556    /*
     1557     * Screened successfully enough.  Call the real thing.
     1558     */
     1559    SetLastError(dwSavedLastError);
     1560    rcNt = g_pfnLdrLoadDllReal(pwszSearchPath, pfFlags, pName, phMod);
     1561
     1562    /* Log the result. */
     1563    dwSavedLastError = GetLastError();
     1564    if (NT_SUCCESS(rcNt) && phMod)
     1565        SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x hMod=%p '%ls'\n", rcNt, *phMod, wszPath));
     1566    else
     1567        SUP_DPRINTF(("supR3HardenedMonitor_LdrLoadDll: returns rcNt=%#x '%ls'\n", rcNt, wszPath));
     1568    SetLastError(dwSavedLastError);
     1569
     1570    return rcNt;
     1571}
     1572
    9491573
    9501574
     
    10591683
    10601684
     1685static void supR3HardenedWinHookFailed(const char *pszWhich, uint8_t const *pbPrologue)
     1686{
     1687    supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
     1688                          "Failed to install %s monitor: %x %x %x %x  %x %x %x %x  %x %x %x %x  %x %x %x %x\n "
     1689#ifdef RT_ARCH_X86
     1690                          "(It is also possible you are running 32-bit VirtualBox under 64-bit windows.)\n"
     1691#endif
     1692                          ,
     1693                          pszWhich,
     1694                          pbPrologue[0],  pbPrologue[1],  pbPrologue[2],  pbPrologue[3],
     1695                          pbPrologue[4],  pbPrologue[5],  pbPrologue[6],  pbPrologue[7],
     1696                          pbPrologue[8],  pbPrologue[9],  pbPrologue[10], pbPrologue[11],
     1697                          pbPrologue[12], pbPrologue[13], pbPrologue[14], pbPrologue[15]);
     1698}
     1699
     1700
    10611701/**
    10621702 * Install hooks for intercepting calls dealing with mapping shared libraries
     
    10671707 * @remarks We assume we're alone in this process, so no seralizing trickery is
    10681708 *          necessary when installing the patch.
     1709 *
     1710 * @remarks We would normally just copy the prologue sequence somewhere and add
     1711 *          a jump back at the end of it. But because we wish to avoid
     1712 *          allocating executable memory, we need to have preprepared assembly
     1713 *          "copies".  This makes the non-system call patching a little tedious
     1714 *            and inflexible.
    10691715 */
    10701716DECLHIDDEN(void) supR3HardenedWinInstallHooks(void)
     
    11021748
    11031749    /*
    1104      * Locate the routine.
     1750     * Locate the routines first so we can allocate memory that's near enough.
    11051751     */
    11061752    HMODULE hmodNtDll = GetModuleHandleW(L"NTDLL");
     
    11091755    FARPROC pfnNtCreateSection = GetProcAddress(hmodNtDll, "NtCreateSection");
    11101756    SUPR3HARDENED_ASSERT(pfnNtCreateSection != NULL);
    1111     SUPR3HARDENED_ASSERT(pfnNtCreateSection == (FARPROC)NtCreateSection);
    1112 
    1113     uint8_t * const pbNtCreateSection = (uint8_t *)(uintptr_t)pfnNtCreateSection;
     1757    //SUPR3HARDENED_ASSERT(pfnNtCreateSection == (FARPROC)NtCreateSection);
     1758
     1759    FARPROC pfnLdrLoadDll = GetProcAddress(hmodNtDll, "LdrLoadDll");
     1760    SUPR3HARDENED_ASSERT(pfnLdrLoadDll != NULL);
     1761    //SUPR3HARDENED_ASSERT(pfnLdrLoadDll == (FARPROC)LdrLoadDll);
     1762
    11141763
    11151764#ifdef RT_ARCH_AMD64
     
    11181767     * actual function to be able to patch it.
    11191768     */
    1120     size_t cbMem = _4K;
    1121     void  *pvMem = supR3HardenedWinAllocHookMemory((uintptr_t)pfnNtCreateSection,
    1122                                                    (uintptr_t)pfnNtCreateSection - _2G + PAGE_SIZE,
    1123                                                    -1, cbMem);
     1769    uintptr_t uStart = RT_MAX((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll);
     1770    size_t    cbMem  = _4K;
     1771    void  *pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart - _2G + PAGE_SIZE, -1, cbMem);
    11241772    if (!pvMem)
    11251773    {
    1126         pvMem = supR3HardenedWinAllocHookMemory((uintptr_t)pfnNtCreateSection,
    1127                                                 (uintptr_t)pfnNtCreateSection + _2G - PAGE_SIZE,
    1128                                                 1, cbMem);
     1774        uintptr_t uStart = RT_MIN((uintptr_t)pfnNtCreateSection, (uintptr_t)pfnLdrLoadDll);
     1775        pvMem = supR3HardenedWinAllocHookMemory(uStart, uStart + _2G - PAGE_SIZE, 1, cbMem);
    11291776        if (!pvMem)
    11301777            supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
     
    11321779    }
    11331780    uintptr_t *puJmpTab = (uintptr_t *)pvMem;
    1134 
     1781#endif
     1782
     1783    /*
     1784     * Hook #1 - NtCreateSection.
     1785     * Purpose: Validate everything that can be mapped into the process before
     1786     *          it's mapped and we still have a file handle to work with.
     1787     */
     1788    uint8_t * const pbNtCreateSection = (uint8_t *)(uintptr_t)pfnNtCreateSection;
     1789
     1790#ifdef RT_ARCH_AMD64
    11351791    /*
    11361792     * Patch 64-bit hosts.
     
    11701826        }
    11711827    }
    1172 
    1173     if (pfnCallReal)
    1174     {
    1175         g_pfnNtCreateSectionJmpBack         = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
    1176         *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
    1177         *puJmpTab                           = (uintptr_t)supR3HardenedMonitor_NtCreateSection;
    1178 
    1179         DWORD dwOldProt;
    1180         SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
    1181                                                             PAGE_EXECUTE_READWRITE, &dwOldProt));
    1182         pbNtCreateSection[0] = 0xff;
    1183         pbNtCreateSection[1] = 0x25;
    1184         *(uint32_t *)&pbNtCreateSection[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]);
    1185 
    1186         SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
    1187                                                             PAGE_EXECUTE_READ, &dwOldProt));
    1188         return;
    1189     }
     1828    if (!pfnCallReal)
     1829        supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);
     1830
     1831    g_pfnNtCreateSectionJmpBack         = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
     1832    *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
     1833    *puJmpTab                           = (uintptr_t)supR3HardenedMonitor_NtCreateSection;
     1834
     1835    DWORD dwOldProt;
     1836    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
     1837                                                        PAGE_EXECUTE_READWRITE, &dwOldProt));
     1838    pbNtCreateSection[0] = 0xff;
     1839    pbNtCreateSection[1] = 0x25;
     1840    *(uint32_t *)&pbNtCreateSection[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbNtCreateSection[2+4]);
     1841
     1842    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
     1843                                                        PAGE_EXECUTE_READ, &dwOldProt));
     1844    puJmpTab++;
    11901845
    11911846#else
     
    12491904        }
    12501905    }
    1251 
    1252     if (pfnCallReal)
    1253     {
    1254         g_pfnNtCreateSectionJmpBack         = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
    1255         *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
    1256 
    1257         DWORD dwOldProt;
    1258         SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
    1259                                                             PAGE_EXECUTE_READWRITE, &dwOldProt));
    1260         pbNtCreateSection[0] = 0xe9;
    1261         *(uint32_t *)&pbNtCreateSection[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
    1262                                            - (uintptr_t)&pbNtCreateSection[1+4];
    1263 
    1264         SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
    1265                                                             PAGE_EXECUTE_READ, &dwOldProt));
    1266         return;
    1267     }
     1906    if (!pfnCallReal)
     1907        supR3HardenedWinHookFailed("NtCreateSection", pbNtCreateSection);
     1908
     1909    g_pfnNtCreateSectionJmpBack         = (PFNRT)(uintptr_t)(pbNtCreateSection + offJmpBack);
     1910    *(PFNRT *)&g_pfnNtCreateSectionReal = pfnCallReal;
     1911
     1912    DWORD dwOldProt;
     1913    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
     1914                                                        PAGE_EXECUTE_READWRITE, &dwOldProt));
     1915    pbNtCreateSection[0] = 0xe9;
     1916    *(uint32_t *)&pbNtCreateSection[1] = (uintptr_t)supR3HardenedMonitor_NtCreateSection
     1917                                       - (uintptr_t)&pbNtCreateSection[1+4];
     1918
     1919    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbNtCreateSection, 16,
     1920                                                        PAGE_EXECUTE_READ, &dwOldProt));
    12681921#endif
    12691922
    1270     supR3HardenedFatalMsg("supR3HardenedWinInstallHooks", kSupInitOp_Misc, VERR_NO_MEMORY,
    1271                           "Failed to install NtCreateSection monitor: %x %x %x %x  %x %x %x %x  %x %x %x %x  %x %x %x %x\n "
    1272 #ifdef RT_ARCH_X86
    1273                           "(It is also possible you are running 32-bit VirtualBox under 64-bit windows.)\n"
     1923    /*
     1924     * Hook #2 - LdrLoadDll
     1925     * Purpose: (a) Enforce LdrLoadDll search path constraints, and (b) pre-validate
     1926     *          DLLs so we can avoid calling WinVerifyTrust from the first hook,
     1927     *          and thus avoiding messing up the loader data on some installations.
     1928     *
     1929     * This differs from the above function in that is no a system call and
     1930     * we're at the mercy of the compiler.
     1931     */
     1932    uint8_t * const pbLdrLoadDll = (uint8_t *)(uintptr_t)pfnLdrLoadDll;
     1933    uint32_t        offExecPage  = 0;
     1934    memset(g_abSupHardReadWriteExecPage, 0xcc, PAGE_SIZE);
     1935
     1936#ifdef RT_ARCH_AMD64
     1937    /*
     1938     * Patch 64-bit hosts.
     1939     */
     1940# if 0
     1941    /* Pattern #1:
     1942         Windows 8.1:
     1943            0:000> u ntdll!LdrLoadDll
     1944            ntdll!LdrLoadDll:
     1945            00007ffa`814ccd44 488bc4          mov     rax,rsp
     1946            00007ffa`814ccd47 48895808        mov     qword ptr [rax+8],rbx
     1947            00007ffa`814ccd4b 48896810        mov     qword ptr [rax+10h],rbp
     1948            00007ffa`814ccd4f 48897018        mov     qword ptr [rax+18h],rsi
     1949            00007ffa`814ccd53 48897820        mov     qword ptr [rax+20h],rdi
     1950            00007ffa`814ccd57 4156            push    r14
     1951            00007ffa`814ccd59 4883ec70        sub     rsp,70h
     1952            00007ffa`814ccd5d f6059cd2100009  test    byte ptr [ntdll!LdrpDebugFlags (00007ffa`815da000)],9
     1953     */
     1954    if (   pbLdrLoadDll[0] == 0x48 /* mov rax,rsp */
     1955        && pbLdrLoadDll[1] == 0x8b
     1956        && pbLdrLoadDll[2] == 0xc4
     1957        && pbLdrLoadDll[3] == 0x48 /* mov qword ptr [rax+8],rbx */
     1958        && pbLdrLoadDll[4] == 0x89
     1959        && pbLdrLoadDll[5] == 0x58
     1960        && pbLdrLoadDll[6] == 0x08)
     1961    {
     1962        offJmpBack = 7; /* the 3rd instruction. */
     1963        pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
     1964    }
     1965    /*
     1966       Pattern #2:
     1967         Windows 8.0:
     1968            0:000> u ntdll_w8_64!LdrLoadDll
     1969            ntdll_w8_64!LdrLoadDll:
     1970            00007ffa`52ffa7c0 48895c2408      mov     qword ptr [rsp+8],rbx
     1971            00007ffa`52ffa7c5 4889742410      mov     qword ptr [rsp+10h],rsi
     1972            00007ffa`52ffa7ca 48897c2418      mov     qword ptr [rsp+18h],rdi
     1973            00007ffa`52ffa7cf 55              push    rbp
     1974            00007ffa`52ffa7d0 4156            push    r14
     1975            00007ffa`52ffa7d2 4157            push    r15
     1976            00007ffa`52ffa7d4 488bec          mov     rbp,rsp
     1977            00007ffa`52ffa7d7 4883ec60        sub     rsp,60h
     1978            00007ffa`52ffa7db 8b05df321000    mov     eax,dword ptr [ntdll_w8_64!LdrpDebugFlags (00007ffa`530fdac0)]
     1979            00007ffa`52ffa7e1 4d8bf1          mov     r14,r9
     1980
     1981     */
     1982    else if (   pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+8],rbx */
     1983             && pbLdrLoadDll[1] == 0x89
     1984             && pbLdrLoadDll[2] == 0x5c
     1985             && pbLdrLoadDll[3] == 0x24
     1986             && pbLdrLoadDll[4] == 0x08
     1987             && pbLdrLoadDll[5] == 0x48 /* mov qword ptr [rsp+10h],rsi */
     1988             && pbLdrLoadDll[6] == 0x89
     1989             && pbLdrLoadDll[7] == 0x74
     1990             && pbLdrLoadDll[8] == 0x24
     1991             && pbLdrLoadDll[9] == 0x10)
     1992    {
     1993        offJmpBack = 10; /* the 3rd instruction. */
     1994        pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
     1995    }
     1996    /*
     1997       Pattern #3:
     1998         Windows 7:
     1999            ntdll_w7_64!LdrLoadDll:
     2000            00000000`58be4a20 48895c2410      mov     qword ptr [rsp+10h],rbx
     2001            00000000`58be4a25 48896c2418      mov     qword ptr [rsp+18h],rbp
     2002            00000000`58be4a2a 56              push    rsi
     2003            00000000`58be4a2b 57              push    rdi
     2004            00000000`58be4a2c 4154            push    r12
     2005            00000000`58be4a2e 4883ec50        sub     rsp,50h
     2006            00000000`58be4a32 f605976e100009  test    byte ptr [ntdll_w7_64!ShowSnaps (00000000`58ceb8d0)],9
     2007            00000000`58be4a39 498bf1          mov     rsi,r9
     2008
     2009     */
     2010    else if (   pbLdrLoadDll[0] == 0x48 /* mov qword ptr [rsp+10h],rbx */
     2011             && pbLdrLoadDll[1] == 0x89
     2012             && pbLdrLoadDll[2] == 0x5c
     2013             && pbLdrLoadDll[3] == 0x24
     2014             && pbLdrLoadDll[4] == 0x10)
     2015    {
     2016        offJmpBack = 5; /* the 2nd instruction. */
     2017        pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type3;
     2018    }
     2019    /*
     2020       Pattern #4:
     2021         Windows Vista:
     2022            0:000> u ntdll_vista_64!LdrLoadDll
     2023            ntdll_vista_64!LdrLoadDll:
     2024            00000000`58c11f60 fff3            push    rbx
     2025            00000000`58c11f62 56              push    rsi
     2026            00000000`58c11f63 57              push    rdi
     2027            00000000`58c11f64 4154            push    r12
     2028            00000000`58c11f66 4155            push    r13
     2029            00000000`58c11f68 4156            push    r14
     2030            00000000`58c11f6a 4157            push    r15
     2031            00000000`58c11f6c 4881ecb0020000  sub     rsp,2B0h
     2032            00000000`58c11f73 488b05367b0e00  mov     rax,qword ptr [ntdll_vista_64!_security_cookie (00000000`58cf9ab0)]
     2033            00000000`58c11f7a 4833c4          xor     rax,rsp
     2034            00000000`58c11f7d 48898424a0020000 mov     qword ptr [rsp+2A0h],rax
     2035
     2036     */
     2037    else if (   pbLdrLoadDll[0] == 0xff /* push rbx */
     2038             && pbLdrLoadDll[1] == 0xf3
     2039             && pbLdrLoadDll[2] == 0x56 /* push rsi */
     2040             && pbLdrLoadDll[3] == 0x57 /* push rdi */
     2041             && pbLdrLoadDll[4] == 0x41 /* push r12 */
     2042             && pbLdrLoadDll[5] == 0x54)
     2043    {
     2044        offJmpBack = 6; /* the 5th instruction. */
     2045        pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type4;
     2046    }
     2047    /*
     2048       Pattern #5:
     2049         Windows XP64:
     2050            0:000> u ntdll!LdrLoadDll
     2051            ntdll!LdrLoadDll:
     2052            00000000`78efa580 4c8bdc          mov     r11,rsp
     2053            00000000`78efa583 4881ece8020000  sub     rsp,2E8h
     2054            00000000`78efa58a 49895bf8        mov     qword ptr [r11-8],rbx
     2055            00000000`78efa58e 498973f0        mov     qword ptr [r11-10h],rsi
     2056            00000000`78efa592 49897be8        mov     qword ptr [r11-18h],rdi
     2057            00000000`78efa596 4d8963e0        mov     qword ptr [r11-20h],r12
     2058            00000000`78efa59a 4d896bd8        mov     qword ptr [r11-28h],r13
     2059            00000000`78efa59e 4d8973d0        mov     qword ptr [r11-30h],r14
     2060            00000000`78efa5a2 4d897bc8        mov     qword ptr [r11-38h],r15
     2061            00000000`78efa5a6 488b051bd10a00  mov     rax,qword ptr [ntdll!_security_cookie (00000000`78fa76c8)]
     2062            00000000`78efa5ad 48898424a0020000 mov     qword ptr [rsp+2A0h],rax
     2063            00000000`78efa5b5 4d8bf9          mov     r15,r9
     2064            00000000`78efa5b8 4c8bf2          mov     r14,rdx
     2065            00000000`78efa5bb 4c8be9          mov     r13,rcx
     2066            00000000`78efa5be 4c89442458      mov     qword ptr [rsp+58h],r8
     2067            00000000`78efa5c3 66c74424680000  mov     word ptr [rsp+68h],0
     2068
     2069     */
     2070    else if (   pbLdrLoadDll[0] == 0x4c /* mov r11,rsp */
     2071             && pbLdrLoadDll[1] == 0x8b
     2072             && pbLdrLoadDll[2] == 0xdc
     2073             && pbLdrLoadDll[3] == 0x48 /* sub rsp,2e8h */
     2074             && pbLdrLoadDll[4] == 0x81
     2075             && pbLdrLoadDll[5] == 0xec
     2076             && pbLdrLoadDll[6] == 0xe8
     2077             && pbLdrLoadDll[7] == 0x02
     2078             && pbLdrLoadDll[8] == 0x00
     2079             && pbLdrLoadDll[9] == 0x00)
     2080    {
     2081        offJmpBack = 10; /* the 3rd instruction. */
     2082        pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type5;
     2083    }
     2084    else
     2085        supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
     2086# else
     2087    /* Just use the disassembler to skip 6 bytes or more. */
     2088    DISSTATE Dis;
     2089    uint32_t cbInstr;
     2090    offJmpBack = 0;
     2091    while (offJmpBack < 6)
     2092    {
     2093        cbInstr = 1;
     2094        int rc = DISInstr(pbLdrLoadDll + offJmpBack, DISCPUMODE_64BIT, &Dis, &cbInstr);
     2095        if (   RT_FAILURE(rc)
     2096            || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW))
     2097            || (Dis.ModRM.Bits.Mod == 0 && Dis.ModRM.Bits.Rm == 5 /* wrt RIP */) )
     2098            supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
     2099        offJmpBack += cbInstr;
     2100    }
     2101# endif
     2102
     2103    /* Assemble the code for resuming the call.*/
     2104    *(PFNRT *)&g_pfnLdrLoadDllReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage];
     2105
     2106    memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbLdrLoadDll, offJmpBack);
     2107    offExecPage += offJmpBack;
     2108
     2109    g_abSupHardReadWriteExecPage[offExecPage++] = 0xff; /* jmp qword [$+8 wrt RIP] */
     2110    g_abSupHardReadWriteExecPage[offExecPage++] = 0x25;
     2111    *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = RT_ALIGN_32(offExecPage + 4, 8) - (offExecPage + 4);
     2112    offExecPage = RT_ALIGN_32(offExecPage + 4, 8);
     2113    *(uint64_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack];
     2114    offExecPage = RT_ALIGN_32(offJmpBack + 8, 16);
     2115
     2116    /* Patch the function. */
     2117    *puJmpTab = (uintptr_t)supR3HardenedMonitor_LdrLoadDll;
     2118
     2119    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READWRITE, &dwOldProt));
     2120
     2121    Assert(offJmpBack >= 6);
     2122    pbLdrLoadDll[0] = 0xff;
     2123    pbLdrLoadDll[1] = 0x25;
     2124    *(uint32_t *)&pbLdrLoadDll[2] = (uint32_t)((uintptr_t)puJmpTab - (uintptr_t)&pbLdrLoadDll[2+4]);
     2125
     2126    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READ, &dwOldProt));
     2127    puJmpTab++;
     2128
     2129#else
     2130    /*
     2131     * Patch 32-bit hosts.
     2132     */
     2133# if 0
     2134    /* Pattern #1:
     2135          Windows 7:
     2136            0:000> u ntdll!LdrLoadDll
     2137            ntdll!LdrLoadDll:
     2138            77aff585 8bff            mov     edi,edi
     2139            77aff587 55              push    ebp
     2140            77aff588 8bec            mov     ebp,esp
     2141            77aff58a 51              push    ecx
     2142            77aff58b 51              push    ecx
     2143            77aff58c a1f8bdaf77      mov     eax,dword ptr [ntdll!LdrpLogLevelStateTable+0x24 (77afbdf8)]
     2144
     2145          Windows 8 rtm:
     2146            0:000:x86> u ntdll_67150000!LdrLoadDll
     2147            ntdll_67150000!LdrLoadDll:
     2148            67189f3f 8bff            mov     edi,edi
     2149            67189f41 55              push    ebp
     2150            67189f42 8bec            mov     ebp,esp
     2151            67189f44 8b0d10eb2467    mov     ecx,dword ptr [ntdll_67150000!LdrpDebugFlags (6724eb10)]
     2152
     2153          Windows 8.1:
     2154            0:000:x86> u ntdll_w81_32!LdrLoadDll
     2155            ntdll_w81_32!LdrLoadDll:
     2156            6718aade 8bff            mov     edi,edi
     2157            6718aae0 55              push    ebp
     2158            6718aae1 8bec            mov     ebp,esp
     2159            6718aae3 83ec14          sub     esp,14h
     2160            6718aae6 f6050040246709  test    byte ptr [ntdll_w81_32!LdrpDebugFlags (67244000)],9
     2161
     2162       Pattern #2:
     2163          Windows XP:
     2164            0:000:x86> u ntdll_xp!LdrLoadDll
     2165            ntdll_xp!LdrLoadDll:
     2166            77f569d2 6858020000      push    258h
     2167            77f569d7 68d866f777      push    offset ntdll_xp!`string'+0x12c (77f766d8)
     2168            77f569dc e83bb20200      call    ntdll_xp!_SEH_prolog (77f81c1c)
     2169            77f569e1 33db            xor     ebx,ebx
     2170            77f569e3 66895de0        mov     word ptr [ebp-20h],bx
     2171            77f569e7 33c0            xor     eax,eax
     2172            77f569e9 8d7de2          lea     edi,[ebp-1Eh]
     2173            77f569ec ab              stos    dword ptr es:[edi]
     2174
     2175          Windows Server 2003:
     2176            0:000:x86> u ntdll_w2k3_32!LdrLoadDll
     2177            ntdll_w2k3_32!LdrLoadDll:
     2178            7c833f63 6840020000      push    240h
     2179            7c833f68 68b040837c      push    offset ntdll_w2k3_32!`string'+0x12c (7c8340b0)
     2180            7c833f6d e8a942ffff      call    ntdll_w2k3_32!_SEH_prolog (7c82821b)
     2181            7c833f72 a13077887c      mov     eax,dword ptr [ntdll_w2k3_32!__security_cookie (7c887730)]
     2182            7c833f77 8945e4          mov     dword ptr [ebp-1Ch],eax
     2183            7c833f7a 8b4508          mov     eax,dword ptr [ebp+8]
     2184            7c833f7d 8985b0fdffff    mov     dword ptr [ebp-250h],eax
     2185            7c833f83 8b450c          mov     eax,dword ptr [ebp+0Ch]
     2186
     2187          Windows Vista SP0 & SP1:
     2188            0:000:x86> u ntdll_vista_sp0_32!LdrLoadDll
     2189            ntdll_vista_sp0_32!LdrLoadDll:
     2190            69b0eb00 6844020000      push    244h
     2191            69b0eb05 6838e9b269      push    offset ntdll_vista_sp0_32! ?? ::FNODOBFM::`string'+0x39e (69b2e938)
     2192            69b0eb0a e835420300      call    ntdll_vista_sp0_32!_SEH_prolog4_GS (69b42d44)
     2193            69b0eb0f 8b4508          mov     eax,dword ptr [ebp+8]
     2194            69b0eb12 8985acfdffff    mov     dword ptr [ebp-254h],eax
     2195            69b0eb18 8b450c          mov     eax,dword ptr [ebp+0Ch]
     2196            69b0eb1b 8985c0fdffff    mov     dword ptr [ebp-240h],eax
     2197            69b0eb21 8b4510          mov     eax,dword ptr [ebp+10h]
     2198         */
     2199
     2200    if (   pbLdrLoadDll[0] == 0x8b /* mov edi, edi - for hot patching */
     2201        && pbLdrLoadDll[1] == 0xff
     2202        && pbLdrLoadDll[2] == 0x55 /* push ebp */
     2203        && pbLdrLoadDll[3] == 0x8b /* mov  ebp,esp */
     2204        && pbLdrLoadDll[4] == 0xec)
     2205    {
     2206        offJmpBack = 5; /* the 3rd instruction. */
     2207        pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type1;
     2208    }
     2209    else if (pbLdrLoadDll[0] == 0x68 /* push dword XXXXXXXX */)
     2210    {
     2211        offJmpBack = 5;
     2212        pfnCallReal = supR3HardenedJmpBack_LdrLoadDll_Type2;
     2213        g_supR3HardenedJmpBack_LdrLoadDll_Type2_PushDword = *(uint32_t const *)&pbLdrLoadDll[1];
     2214    }
     2215    else
     2216        supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
     2217
     2218    g_pfnLdrLoadDllJmpBack = (PFNRT)(uintptr_t)(pbLdrLoadDll + offJmpBack);
     2219    *(PFNRT *)&g_pfnLdrLoadDllReal = pfnCallReal;
     2220
     2221# else
     2222    /* Just use the disassembler to skip 6 bytes or more. */
     2223    DISSTATE Dis;
     2224    uint32_t cbInstr;
     2225    offJmpBack = 0;
     2226    while (offJmpBack < 5)
     2227    {
     2228        cbInstr = 1;
     2229        int rc = DISInstr(pbLdrLoadDll + offJmpBack, DISCPUMODE_32BIT, &Dis, &cbInstr);
     2230        if (   RT_FAILURE(rc)
     2231            || (Dis.pCurInstr->fOpType & (DISOPTYPE_CONTROLFLOW)) )
     2232            supR3HardenedWinHookFailed("LdrLoadDll", pbLdrLoadDll);
     2233        offJmpBack += cbInstr;
     2234    }
     2235
     2236    /* Assemble the code for resuming the call.*/
     2237    *(PFNRT *)&g_pfnLdrLoadDllReal = (PFNRT)(uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage];
     2238
     2239    memcpy(&g_abSupHardReadWriteExecPage[offExecPage], pbLdrLoadDll, offJmpBack);
     2240    offExecPage += offJmpBack;
     2241
     2242    g_abSupHardReadWriteExecPage[offExecPage++] = 0xe9;
     2243    *(uint32_t *)&g_abSupHardReadWriteExecPage[offExecPage] = (uintptr_t)&pbLdrLoadDll[offJmpBack]
     2244                                                            - (uintptr_t)&g_abSupHardReadWriteExecPage[offExecPage + 4];
     2245    offExecPage = RT_ALIGN_32(offJmpBack + 4, 16);
     2246
     2247# endif
     2248
     2249    /* Patch LdrLoadDLl. */
     2250    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16,
     2251                                                        PAGE_EXECUTE_READWRITE, &dwOldProt));
     2252    Assert(offJmpBack >= 5);
     2253    pbLdrLoadDll[0] = 0xe9;
     2254    *(uint32_t *)&pbLdrLoadDll[1] = (uintptr_t)supR3HardenedMonitor_LdrLoadDll - (uintptr_t)&pbLdrLoadDll[1+4];
     2255
     2256    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), pbLdrLoadDll, 16, PAGE_EXECUTE_READ, &dwOldProt));
    12742257#endif
    1275                           ,
    1276                           pbNtCreateSection[0],  pbNtCreateSection[1],  pbNtCreateSection[2],  pbNtCreateSection[3],
    1277                           pbNtCreateSection[4],  pbNtCreateSection[5],  pbNtCreateSection[6],  pbNtCreateSection[7],
    1278                           pbNtCreateSection[8],  pbNtCreateSection[9],  pbNtCreateSection[10], pbNtCreateSection[11],
    1279                           pbNtCreateSection[12], pbNtCreateSection[13], pbNtCreateSection[14], pbNtCreateSection[15]);
     2258
     2259    /*
     2260     * Seal the rwx page.
     2261     */
     2262    SUPR3HARDENED_ASSERT_WIN32_SUCCESS(VirtualProtectEx(NtCurrentProcess(), g_abSupHardReadWriteExecPage, PAGE_SIZE,
     2263                                                        PAGE_EXECUTE_READ, &dwOldProt));
    12802264}
    12812265
  • trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMainA-win.asm

    r52374 r52403  
    151151%include "import-template-kernel32.h"
    152152
     153
     154;
     155; For simplified LdrLoadDll patching we define a special writable, readable and
     156; exectuable section of 4KB where we can put jump back code.
     157;
     158section .rwxpg bss execute read write align=4096
     159GLOBALNAME g_abSupHardReadWriteExecPage
     160        resb    4096
     161
  • trunk/src/VBox/HostDrivers/Support/win/import-template-kernel32.h

    r52366 r52403  
    1111SUPHARNT_IMPORT_STDCALL(GetProcAddress, 8)
    1212SUPHARNT_IMPORT_STDCALL(GetProcessHeap, 0)
     13SUPHARNT_IMPORT_STDCALL(GetSystemDirectoryW, 8)
    1314SUPHARNT_IMPORT_STDCALL(GetTickCount, 0)
    1415SUPHARNT_IMPORT_STDCALL(HeapAlloc, 12)
     
    1819SUPHARNT_IMPORT_STDCALL(LoadLibraryExW, 12)
    1920SUPHARNT_IMPORT_STDCALL(OutputDebugStringA, 4)
     21SUPHARNT_IMPORT_STDCALL(SetLastError, 4)
    2022SUPHARNT_IMPORT_STDCALL(Sleep, 4)
    2123SUPHARNT_IMPORT_STDCALL(VirtualProtectEx, 20)
    2224SUPHARNT_IMPORT_STDCALL(WriteFile, 20)
     25
  • trunk/src/VBox/Runtime/common/ldr/ldrEx.cpp

    r52213 r52403  
    590590RTDECL(int) RTLdrQueryProp(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf)
    591591{
    592     return RTLdrQueryPropEx(hLdrMod, enmProp, pvBuf, cbBuf, NULL);
     592    return RTLdrQueryPropEx(hLdrMod, enmProp, NULL /*pvBits*/, pvBuf, cbBuf, NULL);
    593593}
    594594RT_EXPORT_SYMBOL(RTLdrQueryProp);
    595595
    596596
    597 RTDECL(int) RTLdrQueryPropEx(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet)
     597RTDECL(int) RTLdrQueryPropEx(RTLDRMOD hLdrMod, RTLDRPROP enmProp, void *pvBits, void *pvBuf, size_t cbBuf, size_t *pcbRet)
    598598{
    599599    AssertMsgReturn(rtldrIsValid(hLdrMod), ("hLdrMod=%p\n", hLdrMod), RTLDRENDIAN_INVALID);
     
    629629            AssertReturn(cbBuf == sizeof(bool), VERR_INVALID_PARAMETER);
    630630            break;
     631        case RTLDRPROP_IMPORT_COUNT:
     632            *pcbRet = sizeof(uint32_t);
     633            AssertReturn(cbBuf == sizeof(uint32_t), VERR_INVALID_PARAMETER);
     634            break;
     635        case RTLDRPROP_IMPORT_MODULE:
     636            *pcbRet = sizeof(uint32_t);
     637            AssertReturn(cbBuf >= sizeof(uint32_t), VERR_INVALID_PARAMETER);
     638            break;
    631639
    632640        default:
     
    640648    if (!pMod->pOps->pfnQueryProp)
    641649        return VERR_NOT_SUPPORTED;
    642     return pMod->pOps->pfnQueryProp(pMod, enmProp, pvBuf, cbBuf, pcbRet);
     650    return pMod->pOps->pfnQueryProp(pMod, enmProp, pvBits, pvBuf, cbBuf, pcbRet);
    643651}
    644652RT_EXPORT_SYMBOL(RTLdrQueryPropEx);
  • trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp

    r52213 r52403  
    310310                && pThis->paSections[0].SizeOfRawData > 0)
    311311                offFirstRawData = pThis->paSections[0].PointerToRawData;
    312             if (offFile > offFirstRawData)
     312            if (offFile >= offFirstRawData)
    313313                cbToRead = 0;
    314314            else if (offFile + cbToRead > offFirstRawData)
    315                 cbToRead = offFile + cbToRead - offFirstRawData;
     315                cbToRead = offFile - offFirstRawData;
    316316        }
    317317        else
    318318        {
    319319            /* Find the matching section and its mapping size. */
    320             uint32_t j         = 0;
    321             uint32_t cbMapping = 0;
     320            uint32_t j          = 0;
     321            uint32_t cbMapping  = 0;
     322            uint32_t offSection = 0;
    322323            while (j < pThis->cSections)
    323324            {
    324325                cbMapping = (j + 1 < pThis->cSections ? pThis->paSections[j + 1].VirtualAddress : pThis->cbImage)
    325326                          - pThis->paSections[j].VirtualAddress;
    326                 if (uRva - pThis->paSections[j].VirtualAddress < cbMapping)
     327                offSection = uRva - pThis->paSections[j].VirtualAddress;
     328                if (offSection < cbMapping)
    327329                    break;
    328330                j++;
     
    332334
    333335            /* Adjust the sizes and calc the file offset. */
    334             if (cbToAdv > cbMapping)
    335                 cbToAdv = cbToRead = cbMapping;
     336            if (offSection + cbToAdv > cbMapping)
     337                cbToAdv = cbToRead = cbMapping - offSection;
     338
    336339            if (   pThis->paSections[j].PointerToRawData > 0
    337340                && pThis->paSections[j].SizeOfRawData > 0)
    338341            {
    339                 offFile = uRva - pThis->paSections[j].VirtualAddress;
     342                offFile = offSection;
    340343                if (offFile + cbToRead > pThis->paSections[j].SizeOfRawData)
    341344                    cbToRead = pThis->paSections[j].SizeOfRawData - offFile;
     
    366369
    367370        /* Advance */
    368         if (cbMem == cbToRead)
     371        if (cbMem <= cbToAdv)
    369372            break;
    370         cbMem -= cbToRead;
    371         pbMem += cbToRead;
    372         uRva  += cbToRead;
     373        cbMem -= cbToAdv;
     374        pbMem += cbToAdv;
     375        uRva  += cbToAdv;
    373376    }
    374377
     
    433436                           uint32_t cbMem, void const **ppvMem)
    434437{
    435     if (uRva == NIL_RTLDRADDR || uRva > pThis->cbImage)
     438    if (   uRva == NIL_RTLDRADDR
     439        || uRva         > pThis->cbImage
     440        || cbMem        > pThis->cbImage
     441        || uRva + cbMem > pThis->cbImage)
    436442    {
    437443        if (offFile < 0 || offFile >= UINT32_MAX)
     
    455461        return;
    456462
    457     if (pvBits        && (uintptr_t)pvBits        - (uintptr_t)pvMem < pThis->cbImage)
     463    if (pvBits        && (uintptr_t)pvMem - (uintptr_t)pvBits        < pThis->cbImage)
    458464        return;
    459     if (pThis->pvBits && (uintptr_t)pThis->pvBits - (uintptr_t)pvMem < pThis->cbImage)
     465    if (pThis->pvBits && (uintptr_t)pvMem - (uintptr_t)pThis->pvBits < pThis->cbImage)
    460466        return;
    461467
     
    17231729}
    17241730
     1731/**
     1732 * Worker for rtLdrPE_QueryProp that retrievs the name of an import DLL.
     1733 *
     1734 * @returns IPRT status code. If VERR_BUFFER_OVERFLOW, pcbBuf is required size.
     1735 * @param   pThis           The PE module instance.
     1736 * @param   pvBits          Image bits if the caller had them available, NULL if
     1737 *                          not. Saves a couple of file accesses.
     1738 * @param   iImport         The index of the import table descriptor to fetch
     1739 *                          the name from.
     1740 * @param   pvBuf           The output buffer.
     1741 * @param   cbBuf           The buffer size.
     1742 * @param   pcbRet          Where to return the number of bytes we've returned
     1743 *                          (or in case of VERR_BUFFER_OVERFLOW would have).
     1744 */
     1745static int rtLdrPE_QueryImportModule(PRTLDRMODPE pThis, void const *pvBits, uint32_t iImport,
     1746                                     void *pvBuf, size_t cbBuf, size_t *pcbRet)
     1747{
     1748    /*
     1749     * Check the index first, converting it to an RVA.
     1750     */
     1751    int rc;
     1752    if (iImport < pThis->ImportDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR))
     1753    {
     1754        uint32_t offEntry = iImport * sizeof(IMAGE_IMPORT_DESCRIPTOR) + pThis->ImportDir.VirtualAddress;
     1755
     1756        /*
     1757         * Retrieve the import table descriptor.
     1758         */
     1759        PCIMAGE_IMPORT_DESCRIPTOR pImpDesc;
     1760        rc = rtldrPEReadPartByRva(pThis, pvBits, offEntry, sizeof(*pImpDesc), (void const **)&pImpDesc);
     1761        if (RT_SUCCESS(rc))
     1762        {
     1763            if (   pImpDesc->Name >= pThis->cbHeaders
     1764                && pImpDesc->Name < pThis->cbImage)
     1765            {
     1766                /*
     1767                 * Limit the name to 1024 bytes (more than enough for everyone).
     1768                 */
     1769                uint32_t cchNameMax = pThis->cbImage - pImpDesc->Name;
     1770                if (cchNameMax > 1024)
     1771                    cchNameMax = 1024;
     1772                char *pszName;
     1773                rc = rtldrPEReadPartByRva(pThis, pvBits, pImpDesc->Name, cchNameMax, (void const **)&pszName);
     1774                if (RT_SUCCESS(rc))
     1775                {
     1776                    /*
     1777                     * Make sure it's null terminated and valid UTF-8 encoding.
     1778                     *
     1779                     * Which encoding this really is isn't defined, I think,
     1780                     * but we need to make sure we don't get bogus UTF-8 into
     1781                     * the process, so making sure it's valid UTF-8 is a good
     1782                     * as anything else since it covers ASCII.
     1783                     */
     1784                    size_t cchName = RTStrNLen(pszName, cchNameMax);
     1785                    if (cchName < cchNameMax)
     1786                    {
     1787                        rc = RTStrValidateEncodingEx(pszName, cchName, 0 /*fFlags*/);
     1788                        if (RT_SUCCESS(rc))
     1789                        {
     1790                            /*
     1791                             * Copy out the result and we're done.
     1792                             * (We have to do all the cleanup code though, so no return success here.)
     1793                             */
     1794                            *pcbRet = cchName + 1;
     1795                            if (cbBuf >= cchName + 1)
     1796                                memcpy(pvBuf, pszName, cchName + 1);
     1797                            else
     1798                                rc = VERR_BUFFER_OVERFLOW;
     1799                        }
     1800                    }
     1801                    else
     1802                        rc = VERR_BAD_EXE_FORMAT;
     1803                    rtldrPEFreePart(pThis, pvBits, pszName);
     1804                }
     1805            }
     1806            else
     1807                rc = VERR_BAD_EXE_FORMAT;
     1808            rtldrPEFreePart(pThis, pvBits, pImpDesc);
     1809        }
     1810    }
     1811    else
     1812        rc = VERR_NOT_FOUND;
     1813
     1814    if (RT_SUCCESS(rc))
     1815        return VINF_SUCCESS;
     1816
     1817    *pcbRet = 0;
     1818    return rc;
     1819}
     1820
    17251821
    17261822/** @interface_method_impl{RTLDROPS,pfnQueryProp} */
    1727 static DECLCALLBACK(int) rtldrPE_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet)
     1823static DECLCALLBACK(int) rtldrPE_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void const *pvBits,
     1824                                           void *pvBuf, size_t cbBuf, size_t *pcbRet)
    17281825{
    17291826    PRTLDRMODPE pModPe = (PRTLDRMODPE)pMod;
     
    17651862                          && (pModPe->fDllCharacteristics & IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY);
    17661863            break;
     1864
     1865        case RTLDRPROP_IMPORT_COUNT:
     1866            Assert(cbBuf == sizeof(uint32_t));
     1867            Assert(*pcbRet == cbBuf);
     1868            *(uint32_t *)pvBuf = pModPe->ImportDir.Size / sizeof(IMAGE_IMPORT_DESCRIPTOR);
     1869            if (*(uint32_t *)pvBuf > 0)
     1870                *(uint32_t *)pvBuf -= 1; /* The last entry is a NULL entry. */
     1871            /** @todo Is there some linkers out there that doesn't generiate a
     1872             *        terminator entry? */
     1873            break;
     1874
     1875        case RTLDRPROP_IMPORT_MODULE:
     1876            Assert(cbBuf >= sizeof(uint32_t));
     1877            return rtLdrPE_QueryImportModule(pModPe, pvBits, *(uint32_t *)pvBuf, pvBuf, cbBuf, pcbRet);
    17671878
    17681879        default:
  • trunk/src/VBox/Runtime/common/ldr/ldrkStuff.cpp

    r52213 r52403  
    840840
    841841/** @interface_method_impl{RTLDROPS,pfnQueryProp} */
    842 static DECLCALLBACK(int) rtkldr_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet)
     842static DECLCALLBACK(int) rtkldr_QueryProp(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void const *pvBits,
     843                                          void *pvBuf, size_t cbBuf, size_t *pcbRet)
    843844{
    844845    PRTLDRMODKLDR pThis = (PRTLDRMODKLDR)pMod;
  • trunk/src/VBox/Runtime/include/internal/ldr.h

    r52213 r52403  
    359359     * @param   pMod            Pointer to the loader module structure.
    360360     * @param   enmLdrProp      The property to query (valid).
    361      * @param   pvBuf           Pointer to the return buffer (valid).
    362      * @param   cbBuf           The size of the return buffer (valid as per
     361     * @param   pvBits          Pointer to the bits returned by
     362     *                          RTLDROPS::pfnGetBits(), optional.
     363     * @param   pvBuf           Pointer to the input / output buffer. This is valid.
     364     *                          Normally only used for returning data, but in some
     365     *                          cases it also holds input.
     366     * @param   cbBuf           The size of the buffer (valid as per
    363367     *                          property).
    364368     * @param   pcbRet          The number of bytes actually returned.  If
     
    366370     *                          required buffer size.
    367371     */
    368     DECLCALLBACKMEMBER(int, pfnQueryProp)(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void *pvBuf, size_t cbBuf, size_t *pcbRet);
     372    DECLCALLBACKMEMBER(int, pfnQueryProp)(PRTLDRMODINTERNAL pMod, RTLDRPROP enmProp, void const *pvBits,
     373                                          void *pvBuf, size_t cbBuf, size_t *pcbRet);
    369374
    370375    /**
  • trunk/src/VBox/Runtime/tools/RTSignTool.cpp

    r52049 r52403  
    153153    void      *pvBuf = RTMemAlloc(cbBuf);
    154154    size_t     cbRet = 0;
    155     rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, pvBuf, cbBuf, &cbRet);
     155    rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbRet);
    156156    if (rc == VERR_BUFFER_OVERFLOW && cbRet < _4M && cbRet > 0)
    157157    {
     
    159159        cbBuf = cbRet;
    160160        pvBuf = RTMemAlloc(cbBuf);
    161         rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, pvBuf, cbBuf, &cbRet);
     161        rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbRet);
    162162    }
    163163    if (RT_SUCCESS(rc))
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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