Index: trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp	(revision 52207)
+++ trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp	(revision 52213)
@@ -429,19 +429,19 @@
                     if (fIsVMMR0)
                     {
-                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);
+                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryInt", &VMMR0EntryInt);
                         if (RT_SUCCESS(rc))
-                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);
+                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryFast", &VMMR0EntryFast);
                         if (RT_SUCCESS(rc))
-                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);
+                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "VMMR0EntryEx", &VMMR0EntryEx);
                     }
                     else if (pszSrvReqHandler)
-                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);
+                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, pszSrvReqHandler, &SrvReqHandler);
                     if (RT_SUCCESS(rc))
                     {
-                        int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);
+                        int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "ModuleInit", &ModuleInit);
                         if (RT_FAILURE(rc2))
                             ModuleInit = 0;
 
-                        rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);
+                        rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, UINT32_MAX, "ModuleTerm", &ModuleTerm);
                         if (RT_FAILURE(rc2))
                             ModuleTerm = 0;
Index: trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp	(revision 52207)
+++ trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp	(revision 52213)
@@ -1665,5 +1665,6 @@
          */
 # ifdef DEBUG_bird
-        __debugbreak();
+        if (hrc != CERT_E_CHAINING /* Un-updated vistas, XPs, ++ */)
+            __debugbreak();
 # endif
         const char *pszErrConst = NULL;
@@ -1685,4 +1686,5 @@
             case TRUST_E_FAIL:                     pszErrConst = "TRUST_E_FAIL";                  break;
             case TRUST_E_EXPLICIT_DISTRUST:        pszErrConst = "TRUST_E_EXPLICIT_DISTRUST";     break;
+            case CERT_E_CHAINING:                  pszErrConst = "CERT_E_CHAINING";               break;
         }
         if (pszErrConst)
Index: trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp	(revision 52207)
+++ trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp	(revision 52213)
@@ -38,7 +38,9 @@
 #include <VBox/sup.h>
 #include <VBox/err.h>
+#include <iprt/alloca.h>
 #include <iprt/ctype.h>
+#include <iprt/param.h>
+#include <iprt/string.h>
 #include <iprt/zero.h>
-#include <iprt/param.h>
 
 #ifdef IN_RING0
@@ -134,4 +136,6 @@
     /** Number of images in aImages. */
     uint32_t                cImages;
+    /** The index of the last image we looked up. */
+    uint32_t                iImageHint;
     /** The process handle. */
     HANDLE                  hProcess;
@@ -512,4 +516,147 @@
 
 
+static DECLINLINE(bool) supHardNtVpIsModuleNameMatch(PSUPHNTVPIMAGE pImage, const char *pszModule)
+{
+    if (pImage->fDll)
+    {
+        const char *pszImageNm = pImage->pszName;
+        for (;;)
+        {
+            char chLeft  = *pszImageNm++;
+            char chRight = *pszModule++;
+            if (chLeft != chRight)
+            {
+                Assert(chLeft == RT_C_TO_LOWER(chLeft));
+                if (chLeft != RT_C_TO_LOWER(chRight))
+                {
+                    if (   chRight == '\0'
+                        && chLeft  == '.'
+                        && pszImageNm[0] == 'd'
+                        && pszImageNm[1] == 'l'
+                        && pszImageNm[2] == 'l'
+                        && pszImageNm[3] == '\0')
+                        return true;
+                    break;
+                }
+            }
+
+            if (chLeft == '\0')
+                return true;
+        }
+    }
+
+    return false;
+}
+
+
+/**
+ * Worker for supHardNtVpGetImport that looks up a module in the module table.
+ *
+ * @returns Pointer to the module if found, NULL if not found.
+ * @param   pThis               The process validator instance.
+ * @param   pszModule           The name of the module we're looking for.
+ */
+static PSUPHNTVPIMAGE supHardNtVpFindModule(PSUPHNTVPSTATE pThis, const char *pszModule)
+{
+    /*
+     * Check out the hint first.
+     */
+    if (   pThis->iImageHint < pThis->cImages
+        && supHardNtVpIsModuleNameMatch(&pThis->aImages[pThis->iImageHint], pszModule))
+        return &pThis->aImages[pThis->iImageHint];
+
+    /*
+     * Linear array search next.
+     */
+    uint32_t i = pThis->cImages;
+    while (i-- > 0)
+        if (supHardNtVpIsModuleNameMatch(&pThis->aImages[i], pszModule))
+        {
+            pThis->iImageHint = i;
+            return &pThis->aImages[i];
+        }
+
+    /* No cigar. */
+    return NULL;
+}
+
+
+/**
+ * @callback_method_impl{FNRTLDRIMPORT}
+ */
+static DECLCALLBACK(int) supHardNtVpGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol,
+                                              PRTLDRADDR pValue, void *pvUser)
+{
+    /*SUP_DPRINTF(("supHardNtVpGetImport: %s / %#x / %s.\n", pszModule, uSymbol, pszSymbol));*/
+    PSUPHNTVPSTATE pThis = (PSUPHNTVPSTATE)pvUser;
+
+    int rc = VERR_MODULE_NOT_FOUND;
+    PSUPHNTVPIMAGE pImage = supHardNtVpFindModule(pThis, pszModule);
+    if (pImage)
+    {
+        rc = RTLdrGetSymbolEx(pImage->hLdrMod, NULL, pImage->uImageBase, uSymbol, pszSymbol, pValue);
+        if (RT_SUCCESS(rc))
+            return rc;
+    }
+    /*
+     * API set hacks.
+     */
+    else if (!RTStrNICmp(pszModule, RT_STR_TUPLE("api-ms-win-")))
+    {
+        static const char * const s_apszDlls[] = { "ntdll.dll", "kernelbase.dll", "kernel32.dll" };
+        for (uint32_t i = 0; i < RT_ELEMENTS(s_apszDlls); i++)
+        {
+            pImage = supHardNtVpFindModule(pThis, s_apszDlls[i]);
+            if (pImage)
+            {
+                rc = RTLdrGetSymbolEx(pImage->hLdrMod, NULL, pImage->uImageBase, uSymbol, pszSymbol, pValue);
+                if (RT_SUCCESS(rc))
+                    return rc;
+                if (rc != VERR_SYMBOL_NOT_FOUND)
+                    break;
+            }
+        }
+    }
+
+    /*
+     * Deal with forwarders.
+     * ASSUMES no forwarders thru any api-ms-win-core-*.dll.
+     * ASSUMES forwarders are resolved after one redirection.
+     */
+    if (rc == VERR_LDR_FORWARDER)
+    {
+        size_t           cbInfo = RT_MIN((uint32_t)*pValue, sizeof(RTLDRIMPORTINFO) + 32);
+        PRTLDRIMPORTINFO pInfo  = (PRTLDRIMPORTINFO)alloca(cbInfo);
+        rc = RTLdrQueryForwarderInfo(pImage->hLdrMod, NULL, uSymbol, pszSymbol, pInfo, cbInfo);
+        if (RT_SUCCESS(rc))
+        {
+            rc = VERR_MODULE_NOT_FOUND;
+            pImage = supHardNtVpFindModule(pThis, pInfo->szModule);
+            if (pImage)
+            {
+                rc = RTLdrGetSymbolEx(pImage->hLdrMod, NULL, pImage->uImageBase, pInfo->iOrdinal, pInfo->pszSymbol, pValue);
+                if (RT_SUCCESS(rc))
+                    return rc;
+
+                SUP_DPRINTF(("supHardNtVpGetImport: Failed to find symbol '%s' in '%s' (forwarded from %s / %s): %Rrc\n",
+                             pInfo->pszSymbol, pInfo->szModule, pszModule, pszSymbol, rc));
+                if (rc == VERR_LDR_FORWARDER)
+                    rc = VERR_LDR_FORWARDER_CHAIN_TOO_LONG;
+            }
+            else
+                SUP_DPRINTF(("supHardNtVpGetImport: Failed to find forwarder module '%s' (%#x / %s; originally %s / %#x / %s): %Rrc\n",
+                             pInfo->szModule, pInfo->iOrdinal, pInfo->pszSymbol, pszModule, uSymbol, pszSymbol, rc));
+        }
+        else
+            SUP_DPRINTF(("supHardNtVpGetImport: RTLdrQueryForwarderInfo failed on symbol %#x/'%s' in '%s': %Rrc\n",
+                         uSymbol, pszSymbol, pszModule, rc));
+    }
+    else
+        SUP_DPRINTF(("supHardNtVpGetImport: Failed to find symbol %#x / '%s' in '%s': %Rrc\n",
+                     uSymbol, pszSymbol, pszModule, rc));
+    return rc;
+}
+
+
 /**
  * Compares process memory with the disk content.
@@ -648,6 +795,8 @@
         return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_MEMORY,
                                    "%s: Error allocating %#x bytes for fixed up image bits.", pImage->pszName, cbImage);
-    rc = RTLdrGetBits(pImage->hLdrMod, pImage->pbBits, pImage->uImageBase, NULL /*pfnGetImport*/, pThis);
-    /**@todo resolve import when not in SUPHARDNTVPKIND_CHILD_PURIFICATION mode. */
+    if (pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION)
+        rc = RTLdrGetBits(pImage->hLdrMod, pImage->pbBits, pImage->uImageBase, NULL /*pfnGetImport*/, pThis);
+    else
+        rc = RTLdrGetBits(pImage->hLdrMod, pImage->pbBits, pImage->uImageBase, supHardNtVpGetImport, pThis);
     if (RT_FAILURE(rc))
         return supHardNtVpSetInfo2(pThis, rc, "%s: RTLdrGetBits failed: %Rrc", pImage->pszName, rc);
@@ -666,5 +815,5 @@
      */
     uint32_t         cSkipAreas = 0;
-    SUPHNTVPSKIPAREA aSkipAreas[2];
+    SUPHNTVPSKIPAREA aSkipAreas[3];
     if (pImage->fNtCreateSectionPatch)
     {
@@ -673,5 +822,5 @@
         {
             /* Ignore our NtCreateSection hack. */
-            rc = RTLdrGetSymbolEx(pImage->hLdrMod, pImage->pbBits, 0, "NtCreateSection", &uValue);
+            rc = RTLdrGetSymbolEx(pImage->hLdrMod, pImage->pbBits, 0, UINT32_MAX, "NtCreateSection", &uValue);
             if (RT_FAILURE(rc))
                 return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'NtCreateSection': %Rrc", pImage->pszName, rc);
@@ -681,5 +830,5 @@
 
         /* LdrSystemDllInitBlock is filled in by the kernel. It mainly contains addresses of 32-bit ntdll method for wow64. */
-        rc = RTLdrGetSymbolEx(pImage->hLdrMod, pImage->pbBits, 0, "LdrSystemDllInitBlock", &uValue);
+        rc = RTLdrGetSymbolEx(pImage->hLdrMod, pImage->pbBits, 0, UINT32_MAX, "LdrSystemDllInitBlock", &uValue);
         if (RT_SUCCESS(rc))
         {
@@ -758,5 +907,6 @@
             /* The section bits, only child purification verifies all bits . */
             if (   pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION
-                || (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)) )
+                || (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE))
+                || (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) == IMAGE_SCN_MEM_READ)
             {
                 rc = VINF_SUCCESS;
@@ -1007,5 +1157,5 @@
     {
         /*
-         * Not a known DLL, executable?
+         * Not a known DLL, is it a known executable?
          */
         for (uint32_t i = 0; i < RT_ELEMENTS(g_apszSupNtVpAllowedVmExes); i++)
