Changeset 52204 in vbox for trunk/src/VBox/HostDrivers
- Timestamp:
- Jul 26, 2014 11:22:44 AM (10 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/Makefile.kmk
r52169 r52204 293 293 $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2WeakV.cpp \ 294 294 $(VBOX_PATH_RUNTIME_SRC)/common/misc/zero.asm \ 295 $(VBOX_PATH_RUNTIME_SRC)/common/path/RTPathFilename.cpp \ 295 296 $(VBOX_PATH_RUNTIME_SRC)/common/string/memchr.asm \ 296 297 $(VBOX_PATH_RUNTIME_SRC)/common/string/memcmp.asm \ -
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
r52169 r52204 243 243 if (hStdOut != NULL) 244 244 { 245 # if 0 /* Windows 7 and earlier uses fake handles, with the last two bits set ((hStdOut & 3) == 3). */ 245 246 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 246 247 NtWriteFile(hStdOut, NULL /*Event*/, NULL /*ApcRoutine*/, NULL /*ApcContext*/, 247 248 &Ios, (PVOID)pch, (ULONG)cch, NULL /*ByteOffset*/, NULL /*Key*/); 249 # else 250 DWORD cbWritten; 251 WriteFile(hStdOut, pch, cch, &cbWritten, NULL); 252 # endif 248 253 } 249 254 #else -
trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
r52192 r52204 3422 3422 RTErrInfoInit(&ErrInfo, szErr, sizeof(szErr)); 3423 3423 3424 rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), &ErrInfo);3424 rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_VERIFY_ONLY, &ErrInfo); 3425 3425 if (RT_FAILURE(rc)) 3426 3426 RTLogWriteDebugger(szErr, strlen(szErr)); -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerify-win.h
r52160 r52204 30 30 #include <iprt/types.h> 31 31 #include <iprt/crypto/x509.h> 32 #ifndef SUP_CERTIFICATES_ONLY 33 # ifdef RT_OS_WINDOWS 34 # include <iprt/ldr.h> 35 # endif 36 #endif 37 32 38 33 39 RT_C_DECLS_BEGIN … … 37 43 DECLHIDDEN(int) supHardenedWinInitImageVerifier(PRTERRINFO pErrInfo); 38 44 DECLHIDDEN(void) supHardenedWinTermImageVerifier(void); 39 DECLHIDDEN(int) supHardenedWinVerifyProcess(HANDLE hProcess, HANDLE hThread, PRTERRINFO pErrInfo); 45 46 typedef enum SUPHARDNTVPKIND 47 { 48 SUPHARDNTVPKIND_VERIFY_ONLY = 1, 49 SUPHARDNTVPKIND_CHILD_PURIFICATION, 50 SUPHARDNTVPKIND_SELF_PURIFICATION, 51 SUPHARDNTVPKIND_32BIT_HACK = 0x7fffffff 52 } SUPHARDNTVPKIND; 53 DECLHIDDEN(int) supHardenedWinVerifyProcess(HANDLE hProcess, HANDLE hThread, SUPHARDNTVPKIND enmKind, PRTERRINFO pErrInfo); 40 54 41 55 DECLHIDDEN(bool) supHardViIsAppPatchDir(PCRTUTF16 pwszPath, uint32_t cwcName); 42 DECLHIDDEN(int) supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, bool *pfCacheable, PRTERRINFO pErrInfo); 43 DECLHIDDEN(int) supHardenedWinVerifyImageByHandleNoName(HANDLE hFile, uint32_t fFlags, PRTERRINFO pErrInfo); 56 57 /** 58 * SUP image verifier loader reader instance. 59 */ 60 typedef struct SUPHNTVIRDR 61 { 62 /** The core reader structure. */ 63 RTLDRREADER Core; 64 /** The file handle . */ 65 HANDLE hFile; 66 /** Current file offset. */ 67 RTFOFF off; 68 /** The file size. */ 69 RTFOFF cbFile; 70 /** Flags for the verification callback, SUPHNTVI_F_XXX. */ 71 uint32_t fFlags; 72 /** The executable timstamp in second since unix epoch. */ 73 uint64_t uTimestamp; 74 /** Log name. */ 75 char szFilename[1]; 76 } SUPHNTVIRDR; 77 /** Pointer to an SUP image verifier loader reader instance. */ 78 typedef SUPHNTVIRDR *PSUPHNTVIRDR; 79 DECLHIDDEN(int) supHardNtViRdrCreate(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PSUPHNTVIRDR *ppNtViRdr); 80 DECLHIDDEN(int) supHardenedWinVerifyImageByHandle(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, bool *pfCacheable, PRTERRINFO pErrInfo); 81 DECLHIDDEN(int) supHardenedWinVerifyImageByHandleNoName(HANDLE hFile, uint32_t fFlags, PRTERRINFO pErrInfo); 82 DECLHIDDEN(int) supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr, 83 bool *pfCacheable, PRTERRINFO pErrInfo); 44 84 /** @name SUPHNTVI_F_XXX - Flags for supHardenedWinVerifyImageByHandle. 45 85 * @{ */ -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyImage-win.cpp
r52160 r52204 74 74 * Structures and Typedefs * 75 75 *******************************************************************************/ 76 /**77 * SUP image verifier loader reader instance.78 */79 typedef struct SUPHNTVIRDR80 {81 /** The core reader structure. */82 RTLDRREADER Core;83 /** The file handle . */84 HANDLE hFile;85 /** Current file offset. */86 RTFOFF off;87 /** The file size. */88 RTFOFF cbFile;89 /** Flags for the verification callback, SUPHNTVI_F_XXX. */90 uint32_t fFlags;91 /** The executable timstamp in second since unix epoch. */92 uint64_t uTimestamp;93 /** Log name. */94 char szFilename[1];95 } SUPHNTVIRDR;96 /** Pointer to an SUP image verifier loader reader instance. */97 typedef SUPHNTVIRDR *PSUPHNTVIRDR;98 99 76 100 77 #ifdef IN_RING3 … … 349 326 * @param ppNtViRdr Where to store the reader instance on success. 350 327 */ 351 static intsupHardNtViRdrCreate(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PSUPHNTVIRDR *ppNtViRdr)328 DECLHIDDEN(int) supHardNtViRdrCreate(HANDLE hFile, PCRTUTF16 pwszName, uint32_t fFlags, PSUPHNTVIRDR *ppNtViRdr) 352 329 { 353 330 /* … … 882 859 883 860 /** 861 * Verifies the given loader image. 862 * 863 * @returns IPRT status code. 864 * @param hLdrMod File handle to the executable file. 865 * @param pwszName Full NT path to the DLL in question, used for dealing 866 * with unsigned system dlls as well as for error/logging. 867 * @param pNtViRdr The reader instance /w flags. 868 * @param pfCacheable Where to return whether the result can be cached. A 869 * valid value is always returned. Optional. 870 * @param pErrInfo Pointer to error info structure. Optional. 871 */ 872 DECLHIDDEN(int) supHardenedWinVerifyImageByLdrMod(RTLDRMOD hLdrMod, PCRTUTF16 pwszName, PSUPHNTVIRDR pNtViRdr, 873 bool *pfCacheable, PRTERRINFO pErrInfo) 874 { 875 #ifdef IN_RING3 876 /* Check that the caller has performed the necessary library initialization. */ 877 if (!RTCrX509Certificate_IsPresent(&g_BuildX509Cert)) 878 return RTErrInfoSet(pErrInfo, VERR_WRONG_ORDER, 879 "supHardenedWinVerifyImageByHandle: supHardenedWinInitImageVerifier was not called."); 880 #endif 881 882 /* 883 * Verify it. 884 * 885 * The PKCS #7 SignedData signature is checked in the callback. Any 886 * signing certificate restrictions are also enforced there. 887 * 888 * For the time being, we use the executable timestamp as the 889 * certificate validation date. We must query that first to avoid 890 * potential issues re-entering the loader code from the callback. 891 * 892 * Update: Save the first timestamp we validate with build cert and 893 * use this as a minimum timestamp for further build cert 894 * validations. This works around issues with old DLLs that 895 * we sign against with our certificate (crt, sdl, qt). 896 */ 897 int rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &pNtViRdr->uTimestamp, sizeof(pNtViRdr->uTimestamp)); 898 if (RT_SUCCESS(rc)) 899 { 900 #ifdef IN_RING3 /* Hack alert! (see above) */ 901 if ( (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING) 902 && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT) 903 && pNtViRdr->uTimestamp < g_uBuildTimestampHack) 904 pNtViRdr->uTimestamp = g_uBuildTimestampHack; 905 #endif 906 907 rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo); 908 909 #ifdef IN_RING3 /* Hack alert! (see above) */ 910 if ((pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) && g_uBuildTimestampHack == 0 && RT_SUCCESS(rc)) 911 g_uBuildTimestampHack = pNtViRdr->uTimestamp; 912 #endif 913 914 /* 915 * Microsoft doesn't sign a whole bunch of DLLs, so we have to 916 * ASSUME that a bunch of system DLLs are fine. 917 */ 918 if (rc == VERR_LDRVI_NOT_SIGNED) 919 rc = supHardNtViCheckIfNotSignedOk(hLdrMod, pwszName, pNtViRdr->fFlags, rc); 920 if (RT_FAILURE(rc)) 921 RTErrInfoAddF(pErrInfo, rc, ": %ls", pwszName); 922 923 /* 924 * Check for the signature checking enforcement, if requested to do so. 925 */ 926 if (RT_SUCCESS(rc) && (pNtViRdr->fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT)) 927 { 928 bool fEnforced = false; 929 int rc2 = RTLdrQueryProp(hLdrMod, RTLDRPROP_SIGNATURE_CHECKS_ENFORCED, &fEnforced, sizeof(fEnforced)); 930 if (RT_FAILURE(rc2)) 931 rc = RTErrInfoSetF(pErrInfo, rc2, "Querying RTLDRPROP_SIGNATURE_CHECKS_ENFORCED failed on %ls: %Rrc.", 932 pwszName, rc2); 933 else if (!fEnforced) 934 rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED, 935 "The image '%ls' was not linked with /IntegrityCheck.", pwszName); 936 } 937 } 938 else 939 RTErrInfoSetF(pErrInfo, rc, "RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on %ls: %Rrc", pwszName, rc); 940 941 #ifdef IN_RING3 942 /* 943 * Call the windows verify trust API if we've resolved it. 944 */ 945 if ( g_pfnWinVerifyTrust 946 && supR3HardNtViCanCallWinVerifyTrust(pNtViRdr->hFile, pwszName)) 947 { 948 if (pfCacheable) 949 *pfCacheable = g_pfnWinVerifyTrust != NULL; 950 if (rc != VERR_LDRVI_NOT_SIGNED) 951 { 952 if (rc == VINF_LDRVI_NOT_SIGNED) 953 { 954 if (pNtViRdr->fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION) 955 { 956 int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(pNtViRdr->hFile, pwszName, pNtViRdr->fFlags, pErrInfo, 957 g_pfnWinVerifyTrust); 958 SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc)); 959 rc = rc2; 960 } 961 else 962 { 963 AssertFailed(); 964 rc = VERR_LDRVI_NOT_SIGNED; 965 } 966 } 967 else if (RT_SUCCESS(rc)) 968 rc = supR3HardNtViCallWinVerifyTrust(pNtViRdr->hFile, pwszName, pNtViRdr->fFlags, pErrInfo, 969 g_pfnWinVerifyTrust); 970 else 971 { 972 int rc2 = supR3HardNtViCallWinVerifyTrust(pNtViRdr->hFile, pwszName, pNtViRdr->fFlags, pErrInfo, 973 g_pfnWinVerifyTrust); 974 AssertMsg(RT_FAILURE_NP(rc2), 975 ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>")); 976 } 977 } 978 } 979 #else /* !IN_RING3 */ 980 if (pfCacheable) 981 *pfCacheable = true; 982 #endif /* !IN_RING3 */ 983 984 return rc; 985 } 986 987 988 /** 884 989 * Verifies the given executable image. 885 990 * … … 899 1004 if (pfCacheable) 900 1005 *pfCacheable = false; 901 902 #ifdef IN_RING3903 /* Check that the caller has performed the necessary library initialization. */904 if (!RTCrX509Certificate_IsPresent(&g_BuildX509Cert))905 return RTErrInfoSet(pErrInfo, VERR_WRONG_ORDER,906 "supHardenedWinVerifyImageByHandle: supHardenedWinInitImageVerifier was not called.");907 #endif908 1006 909 1007 /* … … 926 1024 /* 927 1025 * Verify it. 928 *929 * The PKCS #7 SignedData signature is checked in the callback. Any930 * signing certificate restrictions are also enforced there.931 *932 * For the time being, we use the executable timestamp as the933 * certificate validation date. We must query that first to avoid934 * potential issues re-entering the loader code from the callback.935 *936 * Update: Save the first timestamp we validate with build cert and937 * use this as a minimum timestamp for further build cert938 * validations. This works around issues with old DLLs that939 * we sign against with our certificate (crt, sdl, qt).940 1026 */ 941 rc = RTLdrQueryProp(hLdrMod, RTLDRPROP_TIMESTAMP_SECONDS, &pNtViRdr->uTimestamp, sizeof(pNtViRdr->uTimestamp)); 942 if (RT_SUCCESS(rc)) 943 { 944 #ifdef IN_RING3 /* Hack alert! (see above) */ 945 if ( (fFlags & SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING) 946 && (fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT) 947 && pNtViRdr->uTimestamp < g_uBuildTimestampHack) 948 pNtViRdr->uTimestamp = g_uBuildTimestampHack; 949 #endif 950 951 rc = RTLdrVerifySignature(hLdrMod, supHardNtViCallback, pNtViRdr, pErrInfo); 952 953 #ifdef IN_RING3 /* Hack alert! (see above) */ 954 if ((fFlags & SUPHNTVI_F_REQUIRE_BUILD_CERT) && g_uBuildTimestampHack == 0 && RT_SUCCESS(rc)) 955 g_uBuildTimestampHack = pNtViRdr->uTimestamp; 956 #endif 957 958 /* 959 * Microsoft doesn't sign a whole bunch of DLLs, so we have to 960 * ASSUME that a bunch of system DLLs are fine. 961 */ 962 if (rc == VERR_LDRVI_NOT_SIGNED) 963 rc = supHardNtViCheckIfNotSignedOk(hLdrMod, pwszName, fFlags, rc); 964 if (RT_FAILURE(rc)) 965 RTErrInfoAddF(pErrInfo, rc, ": %ls", pwszName); 966 967 /* 968 * Check for the signature checking enforcement, if requested to do so. 969 */ 970 if (RT_SUCCESS(rc) && (fFlags & SUPHNTVI_F_REQUIRE_SIGNATURE_ENFORCEMENT)) 971 { 972 bool fEnforced = false; 973 int rc2 = RTLdrQueryProp(hLdrMod, RTLDRPROP_SIGNATURE_CHECKS_ENFORCED, &fEnforced, sizeof(fEnforced)); 974 if (RT_FAILURE(rc2)) 975 rc = RTErrInfoSetF(pErrInfo, rc2, "Querying RTLDRPROP_SIGNATURE_CHECKS_ENFORCED failed on %ls: %Rrc.", 976 pwszName, rc2); 977 else if (!fEnforced) 978 rc = RTErrInfoSetF(pErrInfo, VERR_SUP_VP_SIGNATURE_CHECKS_NOT_ENFORCED, 979 "The image '%ls' was not linked with /IntegrityCheck.", pwszName); 980 } 981 } 982 else 983 RTErrInfoSetF(pErrInfo, rc, "RTLdrQueryProp/RTLDRPROP_TIMESTAMP_SECONDS failed on %ls: %Rrc", pwszName, rc); 984 985 int rc2 = RTLdrClose(hLdrMod); AssertRC(rc2); 986 987 #ifdef IN_RING3 988 /* 989 * Call the windows verify trust API if we've resolved it. 990 */ 991 if ( g_pfnWinVerifyTrust 992 && supR3HardNtViCanCallWinVerifyTrust(hFile, pwszName)) 993 { 994 if (pfCacheable) 995 *pfCacheable = g_pfnWinVerifyTrust != NULL; 996 if (rc != VERR_LDRVI_NOT_SIGNED) 997 { 998 if (rc == VINF_LDRVI_NOT_SIGNED) 999 { 1000 if (fFlags & SUPHNTVI_F_ALLOW_CAT_FILE_VERIFICATION) 1001 { 1002 int rc2 = supR3HardNtViCallWinVerifyTrustCatFile(hFile, pwszName, fFlags, pErrInfo, 1003 g_pfnWinVerifyTrust); 1004 SUP_DPRINTF(("supR3HardNtViCallWinVerifyTrustCatFile -> %d (org %d)\n", rc2, rc)); 1005 rc = rc2; 1006 } 1007 else 1008 { 1009 AssertFailed(); 1010 rc = VERR_LDRVI_NOT_SIGNED; 1011 } 1012 } 1013 else if (RT_SUCCESS(rc)) 1014 rc = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust); 1015 else 1016 { 1017 int rc2 = supR3HardNtViCallWinVerifyTrust(hFile, pwszName, fFlags, pErrInfo, g_pfnWinVerifyTrust); 1018 AssertMsg(RT_FAILURE_NP(rc2), 1019 ("rc=%Rrc, rc2=%Rrc %s", rc, rc2, pErrInfo ? pErrInfo->pszMsg : "<no-err-info>")); 1020 } 1021 } 1022 } 1023 #else 1024 if (pfCacheable) 1025 *pfCacheable = true; 1026 #endif /* IN_RING3 */ 1027 rc = supHardenedWinVerifyImageByLdrMod(hLdrMod, pwszName, pNtViRdr, pfCacheable, pErrInfo); 1028 int rc2 = RTLdrClose(hLdrMod); AssertRC(rc2); 1027 1029 } 1028 1030 else -
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
r52169 r52204 39 39 #include <VBox/err.h> 40 40 #include <iprt/ctype.h> 41 #include <iprt/zero.h> 41 42 #include <iprt/param.h> 42 43 … … 108 109 /** This may be a 32-bit resource DLL. */ 109 110 bool f32bitResourceDll; 111 112 /** Load module associated with the image during content verfication. */ 113 RTLDRMOD hLdrMod; 114 /** The file reader. */ 115 PSUPHNTVIRDR pNtViRdr; 116 /** Image bits for lazy cleanup. */ 117 uint8_t *pbBits; 110 118 } SUPHNTVPIMAGE; 111 119 /** Pointer to image info from the virtual address space scan. */ … … 117 125 typedef struct SUPHNTVPSTATE 118 126 { 127 /** Type of verification to perform. */ 128 SUPHARDNTVPKIND enmKind; 119 129 /** The result. */ 120 130 int rcResult; 121 131 /** Number of images in aImages. */ 122 132 uint32_t cImages; 133 /** The process handle. */ 134 HANDLE hProcess; 123 135 /** Images found in the process. 124 136 * The array is large enough to hold the executable, all allowed DLLs, and one … … 284 296 285 297 286 static NTSTATUS supHardNtVpReadFile(HANDLE hFile, uint64_t off, void *pvBuf, size_t cbRead) 287 { 288 if ((ULONG)cbRead != cbRead) 289 return STATUS_INTEGER_OVERFLOW; 290 291 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 292 NTSTATUS rcNt = NtReadFile(hFile, 293 NULL /*hEvent*/, 294 NULL /*ApcRoutine*/, 295 NULL /*ApcContext*/, 296 &Ios, 297 pvBuf, 298 (ULONG)cbRead, 299 (PLARGE_INTEGER)&off, 300 NULL); 301 if (NT_SUCCESS(rcNt)) 302 rcNt = Ios.Status; 303 return rcNt; 298 static int supHardNtVpReadImage(PSUPHNTVPIMAGE pImage, uint64_t off, void *pvBuf, size_t cbRead) 299 { 300 return pImage->pNtViRdr->Core.pfnRead(&pImage->pNtViRdr->Core, pvBuf, cbRead, off); 304 301 } 305 302 … … 324 321 325 322 326 static int supHardNtVpFileMemCompare(PSUPHNTVPSTATE pThis, const void *pvFile, const void *pvMemory, size_t cbToCompare, 327 PSUPHNTVPIMAGE pImage, uint32_t uRva) 328 { 329 if (suplibHardenedMemComp(pvFile, pvMemory, cbToCompare) == 0) 330 return VINF_SUCCESS; 331 332 /* Find the exact location. */ 333 const uint8_t *pbFile = (const uint8_t *)pvFile; 334 const uint8_t *pbMemory = (const uint8_t *)pvMemory; 335 while (cbToCompare > 0 && *pbFile == *pbMemory) 336 { 337 cbToCompare--; 338 pbFile++; 339 pbMemory++; 340 uRva++; 341 } 342 343 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_MEMORY_VS_FILE_MISMATCH, 344 "%s: memory compare at %#x failed: %#x != %#x\n", pImage->pszName, uRva, *pbFile, *pbMemory); 345 } 323 #ifdef IN_RING3 324 static NTSTATUS supHardNtVpFileMemRestore(PSUPHNTVPSTATE pThis, PVOID pvRestoreAddr, uint8_t const *pbFile, uint32_t cbToRestore, 325 uint32_t fCorrectProtection) 326 { 327 PVOID pvProt = pvRestoreAddr; 328 SIZE_T cbProt = cbToRestore; 329 ULONG fOldProt = 0; 330 NTSTATUS rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, PAGE_READWRITE, &fOldProt); 331 if (NT_SUCCESS(rcNt)) 332 { 333 SIZE_T cbIgnored; 334 rcNt = NtWriteVirtualMemory(pThis->hProcess, pvRestoreAddr, pbFile, cbToRestore, &cbIgnored); 335 336 pvProt = pvRestoreAddr; 337 cbProt = cbToRestore; 338 NTSTATUS rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, fCorrectProtection, &fOldProt); 339 if (NT_SUCCESS(rcNt)) 340 rcNt = rcNt2; 341 } 342 return rcNt; 343 } 344 #endif /* IN_RING3 */ 345 346 347 typedef struct SUPHNTVPSKIPAREA 348 { 349 uint32_t uRva; 350 uint32_t cb; 351 } SUPHNTVPSKIPAREA; 352 typedef SUPHNTVPSKIPAREA *PSUPHNTVPSKIPAREA; 353 354 static int supHardNtVpFileMemCompareSection(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage, 355 uint32_t uRva, uint32_t cb, const uint8_t *pbFile, 356 int32_t iSh, PSUPHNTVPSKIPAREA paSkipAreas, uint32_t cSkipAreas, 357 uint32_t fCorrectProtection) 358 { 359 AssertCompileAdjacentMembers(SUPHNTVPSTATE, abMemory, abFile); /* Use both the memory and file buffers here. Parfait might hate me for this... */ 360 uint32_t const cbMemory = sizeof(pThis->abMemory) + sizeof(pThis->abFile); 361 uint8_t * const pbMemory = &pThis->abMemory[0]; 362 363 while (cb > 0) 364 { 365 uint32_t cbThis = RT_MIN(cb, cbMemory); 366 367 /* Clipping. */ 368 uint32_t uNextRva = uRva + cbThis; 369 if (cSkipAreas) 370 { 371 uint32_t uRvaEnd = uNextRva; 372 uint32_t i = cSkipAreas; 373 while (i-- > 0) 374 { 375 uint32_t uSkipEnd = paSkipAreas[i].uRva + paSkipAreas[i].cb; 376 if ( uRva < uSkipEnd 377 && uRvaEnd > paSkipAreas[i].uRva) 378 { 379 if (uRva < paSkipAreas[i].uRva) 380 { 381 cbThis = paSkipAreas[i].uRva - uRva; 382 uRvaEnd = paSkipAreas[i].uRva; 383 uNextRva = uSkipEnd; 384 } 385 else if (uRvaEnd >= uSkipEnd) 386 { 387 cbThis -= uSkipEnd - uRva; 388 uRva = uSkipEnd; 389 } 390 else 391 { 392 uNextRva = uSkipEnd; 393 cbThis = 0; 394 break; 395 } 396 } 397 } 398 } 399 400 /* Read the memory. */ 401 NTSTATUS rcNt = supHardNtVpReadMem(pThis->hProcess, pImage->uImageBase + uRva, pbMemory, cbThis); 402 if (!NT_SUCCESS(rcNt)) 403 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_MEMORY_READ_ERROR, 404 "%s: Error reading %#x bytes at %p (rva %#x, #%u, %.8s) from memory: %#x", 405 pImage->pszName, cbThis, pImage->uImageBase + uRva, uRva, iSh + 1, 406 iSh >= 0 ? (char *)pThis->aSecHdrs[iSh].Name : "headers", rcNt); 407 408 /* Do the compare. */ 409 if (memcmp(pbFile, pbMemory, cbThis) != 0) 410 { 411 const char *pachSectNm = iSh >= 0 ? (char *)pThis->aSecHdrs[iSh].Name : "headers"; 412 SUP_DPRINTF(("%s: Differences in section #%u (%s) between file and memory:\n", pImage->pszName, iSh + 1, pachSectNm)); 413 414 uint32_t off = 0; 415 while (off < cbThis && pbFile[off] == pbMemory[off]) 416 off++; 417 SUP_DPRINTF((" %p / %#09x: %02x != %02x\n", 418 pImage->uImageBase + uRva + off, uRva + off, pbFile[off], pbMemory[off])); 419 uint32_t offLast = off; 420 uint32_t cDiffs = 1; 421 for (uint32_t off2 = off + 1; off2 < cbThis; off2++) 422 if (pbFile[off2] != pbMemory[off2]) 423 { 424 SUP_DPRINTF((" %p / %#09x: %02x != %02x\n", 425 pImage->uImageBase + uRva + off2, uRva + off2, pbFile[off2], pbMemory[off2])); 426 cDiffs++; 427 offLast = off2; 428 } 429 430 #ifdef IN_RING3 431 if ( pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION 432 || pThis->enmKind == SUPHARDNTVPKIND_SELF_PURIFICATION) 433 { 434 PVOID pvRestoreAddr = (uint8_t *)pImage->uImageBase + uRva; 435 rcNt = supHardNtVpFileMemRestore(pThis, pvRestoreAddr, pbFile, cbThis, fCorrectProtection); 436 if (NT_SUCCESS(rcNt)) 437 SUP_DPRINTF((" Restored %#x bytes of original file content at %p\n", cbThis, pvRestoreAddr)); 438 else 439 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_MEMORY_VS_FILE_MISMATCH, 440 "%s: Failed to restore %#x bytes at %p (%#x, #%u, %s): %#x (cDiffs=%#x, first=%#x)", 441 pImage->pszName, cbThis, pvRestoreAddr, uRva, iSh + 1, pachSectNm, rcNt, 442 cDiffs, uRva + off); 443 } 444 else 445 #endif /* IN_RING3 */ 446 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_MEMORY_VS_FILE_MISMATCH, 447 "%s: %u differences between %#x and %#x in #%u (%.8s), first: %02x != %02x", 448 pImage->pszName, cDiffs, uRva + off, uRva + offLast, iSh + 1, 449 pachSectNm, pbFile[off], pbMemory[off]); 450 } 451 452 /* Advance. The clipping makes it a little bit complicated. */ 453 cbThis = uNextRva - uRva; 454 if (cbThis >= cb) 455 break; 456 cb -= cbThis; 457 pbFile += cbThis; 458 uRva = uNextRva; 459 } 460 return VINF_SUCCESS; 461 } 462 346 463 347 464 … … 351 468 uint32_t const cbOrg = cb; 352 469 if (!cb) 470 return VINF_SUCCESS; 471 if ( pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION 472 || pThis->enmKind == SUPHARDNTVPKIND_SELF_PURIFICATION) 353 473 return VINF_SUCCESS; 354 474 … … 398 518 * space scan. 399 519 * @param hProcess Handle to the process. 400 * @param hFile Handle to the image file.401 520 * @param pErrInfo Pointer to error info structure. Optional. 402 521 */ 403 static int supHardNtVpVerifyImageCompareMemory(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage, HANDLE hProcess, HANDLE hFile, 404 PRTERRINFO pErrInfo) 522 static int supHardNtVpVerifyImageMemoryCompare(PSUPHNTVPSTATE pThis, PSUPHNTVPIMAGE pImage, HANDLE hProcess, PRTERRINFO pErrInfo) 405 523 { 406 524 /* 407 525 * Read and find the file headers. 408 526 */ 409 NTSTATUS rcNt = supHardNtVpReadFile(hFile, 0, pThis->abFile, sizeof(pThis->abFile));410 if ( !NT_SUCCESS(rcNt))527 int rc = supHardNtVpReadImage(pImage, 0 /*off*/, pThis->abFile, sizeof(pThis->abFile)); 528 if (RT_FAILURE(rc)) 411 529 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_IMAGE_HDR_READ_ERROR, 412 "%s: Error reading image header: % #x", pImage->pszName, rcNt);530 "%s: Error reading image header: %Rrc", pImage->pszName, rc); 413 531 414 532 uint32_t offNtHdrs = 0; … … 473 591 "%s: SizeOfImage (%#x) isn't close enough to the mapping size (%#x)", 474 592 pImage->pszName, cbImage, pImage->cbImage); 593 if (cbImage != RTLdrSize(pImage->hLdrMod)) 594 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_BAD_IMAGE_SIZE, 595 "%s: SizeOfImage (%#x) differs from what RTLdrSize returns (%#zx)", 596 pImage->pszName, cbImage, RTLdrSize(pImage->hLdrMod)); 475 597 476 598 uint32_t const cbSectAlign = fIs32Bit ? pNtHdrs32->OptionalHeader.SectionAlignment : pNtHdrs->OptionalHeader.SectionAlignment; … … 501 623 502 624 /* 625 * Save some header fields we might be using later on. 626 */ 627 pImage->fImageCharecteristics = pNtHdrs->FileHeader.Characteristics; 628 pImage->fDllCharecteristics = fIs32Bit ? pNtHdrs32->OptionalHeader.DllCharacteristics : pNtHdrs->OptionalHeader.DllCharacteristics; 629 630 /* 631 * Correct the apisetschema image base, size and region rva. 632 */ 633 if (pImage->fApiSetSchemaOnlySection1) 634 { 635 pImage->uImageBase -= pThis->aSecHdrs[0].VirtualAddress; 636 pImage->cbImage += pThis->aSecHdrs[0].VirtualAddress; 637 pImage->aRegions[0].uRva = pThis->aSecHdrs[0].VirtualAddress; 638 } 639 640 /* 641 * Get relocated bits. 642 */ 643 pImage->pbBits = (uint8_t *)suplibHardenedAllocZ(cbImage); 644 if (RT_UNLIKELY(!pImage->pbBits)) 645 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_MEMORY, 646 "%s: Error allocating %#x bytes for fixed up image bits.", pImage->pszName, cbImage); 647 rc = RTLdrGetBits(pImage->hLdrMod, pImage->pbBits, pImage->uImageBase, NULL /*pfnGetImport*/, pThis); 648 /**@todo resolve import when not in SUPHARDNTVPKIND_CHILD_PURIFICATION mode. */ 649 if (RT_FAILURE(rc)) 650 return supHardNtVpSetInfo2(pThis, rc, "%s: RTLdrGetBits failed: %Rrc", pImage->pszName, rc); 651 652 /** @todo figure out if all windows versions do this... */ 653 if (fIs32Bit) 654 ((PIMAGE_NT_HEADERS32)&pImage->pbBits[offNtHdrs])->OptionalHeader.ImageBase = (uint32_t)pImage->uImageBase; 655 else 656 ((PIMAGE_NT_HEADERS)&pImage->pbBits[offNtHdrs])->OptionalHeader.ImageBase = pImage->uImageBase; 657 658 /* 659 * Figure out areas we should skip during comparison. 660 */ 661 uint32_t cSkipAreas = 0; 662 SUPHNTVPSKIPAREA aSkipAreas[2]; 663 if (pImage->fNtCreateSectionPatch) 664 { 665 RTLDRADDR uValue; 666 if (pThis->enmKind == SUPHARDNTVPKIND_VERIFY_ONLY) 667 { 668 /* Ignore our NtCreateSection hack. */ 669 rc = RTLdrGetSymbolEx(pImage->hLdrMod, pImage->pbBits, 0, "NtCreateSection", &uValue); 670 if (RT_FAILURE(rc)) 671 return supHardNtVpSetInfo2(pThis, rc, "%s: Failed to find 'NtCreateSection': %Rrc", pImage->pszName, rc); 672 aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue; 673 aSkipAreas[cSkipAreas++].cb = 16; 674 } 675 676 /* LdrSystemDllInitBlock is filled in by the kernel. It mainly contains addresses of 32-bit ntdll method for wow64. */ 677 rc = RTLdrGetSymbolEx(pImage->hLdrMod, pImage->pbBits, 0, "LdrSystemDllInitBlock", &uValue); 678 if (RT_SUCCESS(rc)) 679 { 680 aSkipAreas[cSkipAreas].uRva = (uint32_t)uValue; 681 aSkipAreas[cSkipAreas++].cb = RT_MAX(pImage->pbBits[(uint32_t)uValue], 0x50); 682 } 683 } 684 685 /* 503 686 * Compare the file header with the loaded bits. The loader will fiddle 504 687 * with image base, changing it to the actual load address. 505 688 */ 506 int rc;507 689 if (!pImage->fApiSetSchemaOnlySection1) 508 690 { 509 rcNt = supHardNtVpReadMem(hProcess, pImage->uImageBase, pThis->abMemory, cbHdrsFile); 510 if (!NT_SUCCESS(rcNt)) 511 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_MEMORY_READ_ERROR, 512 "%s: Error reading image header from memory: %#x", pImage->pszName, rcNt); 513 if (uImageBase != pImage->uImageBase) 514 { 515 if (fIs32Bit) 516 pNtHdrs32->OptionalHeader.ImageBase = (uint32_t)pImage->uImageBase; 517 else 518 pNtHdrs->OptionalHeader.ImageBase = pImage->uImageBase; 519 } 520 521 rc = supHardNtVpFileMemCompare(pThis, pThis->abFile, pThis->abMemory, cbHeaders, pImage, 0 /*uRva*/); 691 rc = supHardNtVpFileMemCompareSection(pThis, pImage, 0 /*uRva*/, cbHdrsFile, pImage->pbBits, -1, NULL, 0, PAGE_READONLY); 522 692 if (RT_FAILURE(rc)) 523 693 return rc; 694 524 695 rc = supHardNtVpCheckSectionProtection(pThis, pImage, 0 /*uRva*/, cbHdrsFile, PAGE_READONLY); 525 696 if (RT_FAILURE(rc)) … … 528 699 529 700 /* 530 * Save some header fields we might be using later on. 531 */ 532 pImage->fImageCharecteristics = pNtHdrs->FileHeader.Characteristics; 533 pImage->fDllCharecteristics = fIs32Bit ? pNtHdrs32->OptionalHeader.DllCharacteristics : pNtHdrs->OptionalHeader.DllCharacteristics; 534 535 /* 536 * Validate sections and check them against the mapping regions. 537 */ 538 uint32_t uRva = cbHdrsFile; 701 * Validate sections: 702 * - Check them against the mapping regions. 703 * - Check section bits according to enmKind. 704 */ 705 uint32_t fPrevProt = PAGE_READONLY; 706 uint32_t uRva = cbHdrsFile; 539 707 for (uint32_t i = 0; i < cSections; i++) 540 708 { … … 556 724 pImage->pszName, i, cbFile, cbMap, uSectRva); 557 725 558 /* Validate the protection . */726 /* Validate the protection and bits. */ 559 727 if (!pImage->fApiSetSchemaOnlySection1 || i == 0) 560 728 { 561 if (pImage->fApiSetSchemaOnlySection1)562 {563 pImage->uImageBase -= uSectRva;564 pImage->cbImage += uSectRva;565 pImage->aRegions[i].uRva = uSectRva;566 }567 568 729 uint32_t fProt; 569 730 switch (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)) … … 587 748 "%s: Section %u: Unexpected characteristics: %#x (uSectRva=%#x, cbMap=%#x)", 588 749 pImage->pszName, i, pThis->aSecHdrs[i].Characteristics, uSectRva, cbMap); 589 590 750 } 751 752 /* The section bits, only child purification verifies all bits . */ 753 if ( pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION 754 || (pThis->aSecHdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)) ) 755 { 756 rc = VINF_SUCCESS; 757 if (uRva < uSectRva && !pImage->fApiSetSchemaOnlySection1) /* Any gap worth checking? */ 758 rc = supHardNtVpFileMemCompareSection(pThis, pImage, uRva, uSectRva - uRva, pImage->pbBits + uRva, 759 i - 1, NULL, 0, fPrevProt); 760 if (RT_SUCCESS(rc)) 761 rc = supHardNtVpFileMemCompareSection(pThis, pImage, uSectRva, cbMap, pImage->pbBits + uSectRva, 762 i, aSkipAreas, cSkipAreas, fProt); 763 if (RT_SUCCESS(rc)) 764 { 765 uint32_t cbMapAligned = i + 1 < cSections && !pImage->fApiSetSchemaOnlySection1 766 ? RT_ALIGN_32(cbMap, cbSectAlign) : RT_ALIGN_32(cbMap, PAGE_SIZE); 767 if (cbMapAligned > cbMap) 768 rc = supHardNtVpFileMemCompareSection(pThis, pImage, uSectRva + cbMap, cbMapAligned - cbMap, 769 g_abRTZeroPage, i, NULL, 0, fProt); 770 } 771 if (RT_FAILURE(rc)) 772 return rc; 773 } 774 775 /* The protection (must be checked afterwards!). */ 591 776 rc = supHardNtVpCheckSectionProtection(pThis, pImage, uSectRva, RT_ALIGN_32(cbMap, PAGE_SIZE), fProt); 592 777 if (RT_FAILURE(rc)) 593 778 return rc; 779 780 fPrevProt = fProt; 594 781 } 595 782 … … 597 784 uRva = uSectRva + RT_ALIGN_32(cbMap, cbSectAlign); 598 785 } 599 600 /*601 * Check the mapping regions with the image to make sure someone didn't602 * fill executable code into some gap in the image.603 */604 /** @todo not vital. */605 606 607 /*608 * Compare executable code. If we're not loaded at the link address, we609 * need to load base relocations and apply them while making the compare.610 * A special case611 */612 /** @todo not vital. */613 614 786 615 787 return VINF_SUCCESS; … … 632 804 { 633 805 /* 634 * Open the image. 635 */ 636 HANDLE hFile = RTNT_INVALID_HANDLE_VALUE; 637 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 638 639 OBJECT_ATTRIBUTES ObjAttr; 640 InitializeObjectAttributes(&ObjAttr, &pImage->Name.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/); 641 #ifdef IN_RING0 642 ObjAttr.Attributes |= OBJ_KERNEL_HANDLE; 643 #endif 644 645 NTSTATUS rcNt = NtCreateFile(&hFile, 646 GENERIC_READ, 647 &ObjAttr, 648 &Ios, 649 NULL /* Allocation Size*/, 650 FILE_ATTRIBUTE_NORMAL, 651 FILE_SHARE_READ, 652 FILE_OPEN, 653 FILE_NON_DIRECTORY_FILE, 654 NULL /*EaBuffer*/, 655 0 /*EaLength*/); 656 if (NT_SUCCESS(rcNt)) 657 rcNt = Ios.Status; 658 if (!NT_SUCCESS(rcNt)) 659 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_IMAGE_FILE_OPEN_ERROR, 660 "Error opening image for scanning: %#x (name %ls)", rcNt, pImage->Name.UniStr.Buffer); 661 662 /* 663 * Validate the signature, then make an attempt at comparing memory and 664 * disk content. 665 */ 666 uint32_t fFlags = pImage->fDll ? 0 : SUPHNTVI_F_REQUIRE_BUILD_CERT; 667 if (pImage->f32bitResourceDll) 668 fFlags |= SUPHNTVI_F_RESOURCE_IMAGE; 669 int rc = supHardenedWinVerifyImageByHandle(hFile, pImage->Name.UniStr.Buffer, fFlags, NULL /*pfCacheable*/, pThis->pErrInfo); 670 if (RT_SUCCESS(rc)) 671 rc = supHardNtVpVerifyImageCompareMemory(pThis, pImage, hProcess, hFile, pThis->pErrInfo); 672 673 /* 674 * Clean up and return. 675 */ 676 rcNt = NtClose(hFile); 677 if (!NT_SUCCESS(rcNt) && RT_SUCCESS(rc)) 678 rc = supHardNtVpSetInfo2(pThis, VERR_SUP_VP_IMAGE_FILE_CLOSE_ERROR, 679 "Error closing image after scanning: %#x (name %ls)", rcNt, pImage->Name.UniStr.Buffer); 806 * Validate the file signature first, then do the memory compare. 807 */ 808 int rc; 809 if (pImage->hLdrMod != NIL_RTLDRMOD) 810 { 811 rc = supHardenedWinVerifyImageByLdrMod(pImage->hLdrMod, pImage->Name.UniStr.Buffer, pImage->pNtViRdr, 812 NULL /*pfCacheable*/, pThis->pErrInfo); 813 if (RT_SUCCESS(rc)) 814 { 815 rc = supHardNtVpVerifyImageMemoryCompare(pThis, pImage, hProcess, pThis->pErrInfo); 816 817 if (pImage->pbBits) 818 { 819 suplibHardenedFree(pImage->pbBits); 820 pImage->pbBits = NULL; 821 } 822 } 823 } 824 else 825 rc = supHardNtVpSetInfo2(pThis, VERR_OPEN_FAILED, "hLdrMod is NIL! Impossible!"); 680 826 return rc; 681 827 } … … 740 886 } 741 887 #endif /* !VBOX_WITHOUT_DEBUGGER_CHECKS */ 742 743 744 /**745 * Allocates and initalizes a process stat structure for process virtual memory746 * scanning.747 *748 * @returns Pointer to the state structure on success, NULL on failure.749 * @param pErrInfo Pointer to error info structure. Optional.750 */751 static PSUPHNTVPSTATE supHardNtVpCreateState(PRTERRINFO pErrInfo)752 {753 /*754 * Allocate the memory.755 */756 PSUPHNTVPSTATE pThis = (PSUPHNTVPSTATE)suplibHardenedAllocZ(sizeof(*pThis));757 if (pThis)758 {759 pThis->rcResult = VINF_SUCCESS;760 pThis->pErrInfo = pErrInfo;761 return pThis;762 }763 supHardNtVpSetInfo1(pErrInfo, VERR_NO_MEMORY, "Failed to allocate %zu bytes for state structures.", sizeof(*pThis));764 return NULL;765 }766 888 767 889 … … 909 1031 910 1032 /* 1033 * Checks for multiple mappings of the same DLL but with different image file paths. 1034 */ 1035 uint32_t i = pThis->cImages; 1036 while (i-- > 1) 1037 if (pImage->pszName == pThis->aImages[i].pszName) 1038 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_DUPLICATE_DLL_MAPPING, 1039 "Duplicate image entries for %s: %ls and %ls", 1040 pImage->pszName, pImage->Name.UniStr.Buffer, pThis->aImages[i].Name.UniStr.Buffer); 1041 1042 /* 911 1043 * Since it's a new image, we expect to be at the start of the mapping now. 912 1044 */ … … 928 1060 pImage->uImageBase = (uintptr_t)pMemInfo->AllocationBase; 929 1061 pImage->cbImage = pMemInfo->RegionSize; 1062 pImage->hLdrMod = NIL_RTLDRMOD; 1063 pImage->pNtViRdr = NULL; 930 1064 pImage->cRegions = 1; 931 1065 pImage->aRegions[0].uRva = 0; 932 1066 pImage->aRegions[0].cb = (uint32_t)pMemInfo->RegionSize; 933 1067 pImage->aRegions[0].fProt = pMemInfo->Protect; 1068 1069 if (suplibHardenedStrCmp(pImage->pszName, "ntdll.dll") == 0) 1070 pImage->fNtCreateSectionPatch = true; 1071 else if (suplibHardenedStrCmp(pImage->pszName, "apisetschema.dll") == 0) 1072 pImage->fApiSetSchemaOnlySection1 = true; /** @todo Check the ApiSetMap field in the PEB. */ 1073 #ifdef VBOX_PERMIT_MORE 1074 else if (suplibHardenedStrCmp(pImage->pszName, "acres.dll") == 0) 1075 pImage->f32bitResourceDll = true; 1076 #endif 934 1077 935 1078 return VINF_SUCCESS; … … 980 1123 pImage->cbImage = pImage->aRegions[iRegion].uRva + pImage->aRegions[iRegion].cb; 981 1124 pImage->cRegions++; 1125 pImage->fApiSetSchemaOnlySection1 = false; 982 1126 983 1127 return VINF_SUCCESS; … … 998 1142 static int supHardNtVpScanVirtualMemory(PSUPHNTVPSTATE pThis, HANDLE hProcess) 999 1143 { 1000 SUP_DPRINTF(("supHardNtVpScanVirtualMemory:\n")); 1144 SUP_DPRINTF(("supHardNtVpScanVirtualMemory: enmKind=%s\n", 1145 pThis->enmKind == SUPHARDNTVPKIND_VERIFY_ONLY ? "VERIFY_ONLY" : 1146 pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION ? "CHILD_PURIFICATION" : "SELF_PURIFICATION")); 1001 1147 1002 1148 uint32_t cXpExceptions = 0; … … 1101 1247 else if (MemInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) 1102 1248 { 1103 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FOUND_EXEC_MEMORY, 1104 "Found executable memory at %p (%p LB %#zx): type=%#x prot=%#x state=%#x aprot=%#x abase=%p", 1105 uPtrWhere, 1106 MemInfo.BaseAddress, 1107 MemInfo.RegionSize, 1108 MemInfo.Type, 1109 MemInfo.Protect, 1110 MemInfo.State, 1111 MemInfo.AllocationBase, 1112 MemInfo.AllocationProtect); 1249 SUP_DPRINTF((MemInfo.AllocationBase == MemInfo.BaseAddress 1250 ? " *%p-%p %#06x/%#06x %#09x !!\n" 1251 : " %p-%p %#06x/%#06x %#09x !!\n", 1252 MemInfo.BaseAddress, (uintptr_t)MemInfo.BaseAddress - MemInfo.RegionSize - 1, 1253 MemInfo.Protect, MemInfo.AllocationProtect, MemInfo.Type)); 1113 1254 # ifdef IN_RING3 1255 if (pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION) 1256 { 1257 /* 1258 * Free any private executable memory (sysplant.sys allocates executable memory). 1259 */ 1260 if (MemInfo.Type == MEM_PRIVATE) 1261 { 1262 SUP_DPRINTF(("supHardNtVpScanVirtualMemory: Freeing exec mem at %p (%p LB %#zx)\n", 1263 uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize)); 1264 PVOID pvFree = MemInfo.BaseAddress; 1265 SIZE_T cbFree = MemInfo.RegionSize; 1266 rcNt = NtFreeVirtualMemory(pThis->hProcess, &pvFree, &cbFree, MEM_RELEASE); 1267 if (!NT_SUCCESS(rcNt)) 1268 supHardNtVpSetInfo2(pThis, VERR_GENERAL_FAILURE, 1269 "NtFreeVirtualMemory (%p LB %#zx) failed: %#x", 1270 MemInfo.BaseAddress, MemInfo.RegionSize, rcNt); 1271 } 1272 /* 1273 * Unmap mapped memory, failing that, drop exec privileges. 1274 */ 1275 else if (MemInfo.Type == MEM_MAPPED) 1276 { 1277 SUP_DPRINTF(("supHardNtVpScanVirtualMemory: Unmapping exec mem at %p (%p/%p LB %#zx)\n", 1278 uPtrWhere, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize)); 1279 rcNt = NtUnmapViewOfSection(pThis->hProcess, MemInfo.AllocationBase); 1280 if (!NT_SUCCESS(rcNt)) 1281 { 1282 PVOID pvCopy = MemInfo.BaseAddress; 1283 SIZE_T cbCopy = MemInfo.RegionSize; 1284 NTSTATUS rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL); 1285 if (!NT_SUCCESS(rcNt2)) 1286 rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvCopy, &cbCopy, PAGE_READONLY, NULL); 1287 if (!NT_SUCCESS(rcNt2)) 1288 supHardNtVpSetInfo2(pThis, VERR_GENERAL_FAILURE, 1289 "NtUnmapViewOfSection (%p/%p LB %#zx) failed: %#x (%#x)", 1290 MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize, rcNt, rcNt2); 1291 } 1292 } 1293 else 1294 supHardNtVpSetInfo2(pThis, VERR_GENERAL_FAILURE, 1295 "Unknown executable memory type %#x at %p/%p LB %#zx", 1296 MemInfo.Type, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize); 1297 } 1298 else 1299 # endif /* IN_RING3 */ 1300 supHardNtVpSetInfo2(pThis, VERR_SUP_VP_FOUND_EXEC_MEMORY, 1301 "Found executable memory at %p (%p LB %#zx): type=%#x prot=%#x state=%#x aprot=%#x abase=%p", 1302 uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize, MemInfo.Type, MemInfo.Protect, 1303 MemInfo.State, MemInfo.AllocationBase, MemInfo.AllocationProtect); 1304 1305 # ifndef IN_RING3 1306 if (RT_FAILURE(pThis->rcResult)) 1307 return pThis->rcResult; 1308 # endif 1114 1309 /* Continue add more information about the problematic process. */ 1115 # else 1116 return pThis->rcResult; 1117 # endif 1118 } 1119 #endif 1310 } 1311 #endif /* VBOX_PERMIT_VISUAL_STUDIO_PROFILING */ 1120 1312 else 1121 1313 SUP_DPRINTF((MemInfo.AllocationBase == MemInfo.BaseAddress … … 1137 1329 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_TOO_MANY_MEMORY_REGIONS, 1138 1330 "Too many virtual memory regions.\n"); 1331 } 1332 1333 /** 1334 * Opens all the images with the IPRT loader, setting both pNtViRdr and hLdrMod 1335 * for each image. 1336 * 1337 * @returns VBox status code. 1338 * @param pThis The process scanning state structure. 1339 */ 1340 static int supHardNtVpOpenImages(PSUPHNTVPSTATE pThis) 1341 { 1342 unsigned i = pThis->cImages; 1343 while (i-- > 0) 1344 { 1345 PSUPHNTVPIMAGE pImage = &pThis->aImages[i]; 1346 1347 /* 1348 * Open the image file. 1349 */ 1350 HANDLE hFile = RTNT_INVALID_HANDLE_VALUE; 1351 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 1352 1353 OBJECT_ATTRIBUTES ObjAttr; 1354 InitializeObjectAttributes(&ObjAttr, &pImage->Name.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/); 1355 #ifdef IN_RING0 1356 ObjAttr.Attributes |= OBJ_KERNEL_HANDLE; 1357 #endif 1358 1359 NTSTATUS rcNt = NtCreateFile(&hFile, 1360 GENERIC_READ, 1361 &ObjAttr, 1362 &Ios, 1363 NULL /* Allocation Size*/, 1364 FILE_ATTRIBUTE_NORMAL, 1365 FILE_SHARE_READ, 1366 FILE_OPEN, 1367 FILE_NON_DIRECTORY_FILE, 1368 NULL /*EaBuffer*/, 1369 0 /*EaLength*/); 1370 if (NT_SUCCESS(rcNt)) 1371 rcNt = Ios.Status; 1372 if (!NT_SUCCESS(rcNt)) 1373 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_IMAGE_FILE_OPEN_ERROR, 1374 "Error opening image for scanning: %#x (name %ls)", rcNt, pImage->Name.UniStr.Buffer); 1375 1376 /* 1377 * Figure out validation flags we'll be using and create the reader 1378 * for this image. 1379 */ 1380 uint32_t fFlags = pImage->fDll ? 0 : SUPHNTVI_F_REQUIRE_BUILD_CERT; 1381 if (pImage->f32bitResourceDll) 1382 fFlags |= SUPHNTVI_F_RESOURCE_IMAGE; 1383 1384 PSUPHNTVIRDR pNtViRdr; 1385 int rc = supHardNtViRdrCreate(hFile, pImage->Name.UniStr.Buffer, fFlags, &pNtViRdr); 1386 if (RT_FAILURE(rc)) 1387 { 1388 NtClose(hFile); 1389 return rc; 1390 } 1391 pImage->pNtViRdr = pNtViRdr; 1392 1393 /* 1394 * Finally, open the image with the laoder. 1395 */ 1396 RTLDRMOD hLdrMod; 1397 RTLDRARCH enmArch = fFlags & SUPHNTVI_F_RC_IMAGE ? RTLDRARCH_X86_32 : RTLDRARCH_HOST; 1398 if (fFlags & SUPHNTVI_F_RESOURCE_IMAGE) 1399 enmArch = RTLDRARCH_WHATEVER; 1400 rc = RTLdrOpenWithReader(&pNtViRdr->Core, RTLDR_O_FOR_VALIDATION, enmArch, &hLdrMod, pThis->pErrInfo); 1401 if (RT_FAILURE(rc)) 1402 return supHardNtVpSetInfo2(pThis, rc, "RTLdrOpenWithReader failed: %Rrc (Image='%ls').", 1403 rc, pImage->Name.UniStr.Buffer); 1404 1405 pImage->hLdrMod = hLdrMod; 1406 } 1407 1408 return VINF_SUCCESS; 1139 1409 } 1140 1410 … … 1256 1526 { 1257 1527 /* 1258 * Check for duplicate entries .1528 * Check for duplicate entries (paranoia). 1259 1529 */ 1260 1530 uint32_t i = pThis->cImages; … … 1276 1546 uint32_t iNtDll = UINT32_MAX; 1277 1547 uint32_t iKernel32 = UINT32_MAX; 1278 uint32_t iApiSetSchema = UINT32_MAX;1279 1548 i = pThis->cImages; 1280 1549 while (i-- > 0) … … 1283 1552 else if (suplibHardenedStrCmp(pThis->aImages[i].pszName, "kernel32.dll") == 0) 1284 1553 iKernel32 = i; 1285 else if (suplibHardenedStrCmp(pThis->aImages[i].pszName, "apisetschema.dll") == 0)1286 iApiSetSchema = i;1287 #ifdef VBOX_PERMIT_MORE1288 else if (suplibHardenedStrCmp(pThis->aImages[i].pszName, "acres.dll") == 0)1289 pThis->aImages[i].f32bitResourceDll = true;1290 #endif1291 1554 if (iNtDll == UINT32_MAX) 1292 1555 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_NTDLL_MAPPING, 1293 1556 "The process has no NTDLL.DLL."); 1294 if (iKernel32 == UINT32_MAX )1557 if (iKernel32 == UINT32_MAX && pThis->enmKind != SUPHARDNTVPKIND_CHILD_PURIFICATION) 1295 1558 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_KERNEL32_MAPPING, 1296 1559 "The process has no KERNEL32.DLL."); 1297 1560 else if (iKernel32 != UINT32_MAX && pThis->enmKind == SUPHARDNTVPKIND_CHILD_PURIFICATION) 1561 return supHardNtVpSetInfo2(pThis, VERR_GENERAL_FAILURE, 1562 "The process already has KERNEL32.DLL loaded."); 1298 1563 1299 1564 /* … … 1303 1568 while (i-- > 0) 1304 1569 { 1305 pThis->aImages[i].fNtCreateSectionPatch = i == iNtDll;1306 pThis->aImages[i].fApiSetSchemaOnlySection1 = i == iApiSetSchema && pThis->aImages[i].cRegions == 1;1307 1308 1570 int rc = supHardNtVpVerifyImage(pThis, &pThis->aImages[i], hProcess); 1309 1571 if (RT_FAILURE(rc)) … … 1332 1594 * @param hProcess The process to verify. 1333 1595 * @param hThread A thread in the process (the caller). 1596 * @param enmKind The kind of process verification to perform. 1334 1597 * @param pErrInfo Pointer to error info structure. Optional. 1335 1598 */ 1336 DECLHIDDEN(int) supHardenedWinVerifyProcess(HANDLE hProcess, HANDLE hThread, PRTERRINFO pErrInfo) 1337 { 1599 DECLHIDDEN(int) supHardenedWinVerifyProcess(HANDLE hProcess, HANDLE hThread, SUPHARDNTVPKIND enmKind, PRTERRINFO pErrInfo) 1600 { 1601 /* 1602 * Some basic checks regarding threads and debuggers. We don't need 1603 * allocate any state memory for these. 1604 */ 1338 1605 int rc = supHardNtVpThread(hProcess, hThread, pErrInfo); 1339 1606 #ifndef VBOX_WITHOUT_DEBUGGER_CHECKS … … 1343 1610 if (RT_SUCCESS(rc)) 1344 1611 { 1345 PSUPHNTVPSTATE pThis = supHardNtVpCreateState(pErrInfo); 1612 /* 1613 * Allocate and initialize memory for the state. 1614 */ 1615 PSUPHNTVPSTATE pThis = (PSUPHNTVPSTATE)suplibHardenedAllocZ(sizeof(*pThis)); 1346 1616 if (pThis) 1347 1617 { 1618 pThis->enmKind = enmKind; 1619 pThis->rcResult = VINF_SUCCESS; 1620 pThis->hProcess = hProcess; 1621 pThis->pErrInfo = pErrInfo; 1622 1623 /* 1624 * Perform the verification. 1625 */ 1348 1626 rc = supHardNtVpScanVirtualMemory(pThis, hProcess); 1627 if (RT_SUCCESS(rc)) 1628 rc = supHardNtVpOpenImages(pThis); 1349 1629 if (RT_SUCCESS(rc)) 1350 1630 rc = supHardNtVpCheckExe(pThis, hProcess); … … 1352 1632 rc = supHardNtVpCheckDlls(pThis, hProcess); 1353 1633 1634 /* 1635 * Clean up the state. 1636 */ 1637 for (uint32_t i = 0; i < pThis->cImages; i++) 1638 { 1639 if (pThis->aImages[i].hLdrMod != NIL_RTLDRMOD) 1640 RTLdrClose(pThis->aImages[i].hLdrMod); 1641 else if (pThis->aImages[i].pNtViRdr) 1642 pThis->aImages[i].pNtViRdr->Core.pfnDestroy(&pThis->aImages[i].pNtViRdr->Core); 1643 } 1354 1644 suplibHardenedFree(pThis); 1355 1645 } 1356 1646 else 1357 rc = VERR_SUP_VP_NO_MEMORY_STATE; 1647 rc = supHardNtVpSetInfo1(pErrInfo, VERR_SUP_VP_NO_MEMORY_STATE, 1648 "Failed to allocate %zu bytes for state structures.", sizeof(*pThis)); 1358 1649 } 1359 1650 return rc; -
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52176 r52204 45 45 #include <iprt/initterm.h> 46 46 #include <iprt/param.h> 47 #include <iprt/path.h> 47 48 #include <iprt/zero.h> 48 49 … … 50 51 #include "win/SUPHardenedVerify-win.h" 51 52 #include "../SUPDrvIOC.h" 53 54 #ifndef IMAGE_SCN_TYPE_NOLOAD 55 # define IMAGE_SCN_TYPE_NOLOAD 0x00000002 56 #endif 52 57 53 58 … … 58 63 * This just needs to be unique enough to avoid most confusion with real 59 64 * executable names, there are other checks in place to make sure we've respanwed. */ 60 #define SUPR3_RESPAWN_1_ARG0 " 81954AF5-4D2F-31EB-A142-B7AF187A1C41-suplib-2ndchild"65 #define SUPR3_RESPAWN_1_ARG0 "0384ad8f-4f0c-d002-e3ae-5597cd55af98-suplib-2ndchild" 61 66 62 67 /** The first argument of a respawed stub when respawned for the second time. 63 68 * This just needs to be unique enough to avoid most confusion with real 64 69 * executable names, there are other checks in place to make sure we've respanwed. */ 65 #define SUPR3_RESPAWN_2_ARG0 " 81954AF5-4D2F-31EB-A142-B7AF187A1C41-suplib-3rdchild"70 #define SUPR3_RESPAWN_2_ARG0 "0384ad8f-4f0c-d002-e3ae-5597cd55af98-suplib-3rdchild" 66 71 67 72 /** Unconditional assertion. */ … … 962 967 /* 963 968 * Install a anti debugging hack before we continue. This prevents most 964 * notifications from ending up in the debugger. 969 * notifications from ending up in the debugger. (Also applied to the 970 * child process when respawning.) 965 971 */ 966 972 rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0); … … 1173 1179 { 1174 1180 RTErrInfoInitStatic(&g_ErrInfoStatic); 1175 int rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), &g_ErrInfoStatic.Core); 1181 int rc = supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), 1182 SUPHARDNTVPKIND_VERIFY_ONLY, &g_ErrInfoStatic.Core); 1176 1183 if (RT_FAILURE(rc)) 1177 1184 supR3HardenedFatalMsg("supR3HardenedWinVerifyProcess", kSupInitOp_Integrity, rc, … … 1730 1737 if (!NT_SUCCESS(rcNt)) 1731 1738 return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE, "NtWriteVirtualMemory/Peb failed: %#x", rcNt); 1732 1733 return VINF_SUCCESS;1734 }1735 1736 1737 DECLINLINE(PIMAGE_NT_HEADERS) supR3HardNtPuChFindNtHeaders(uint8_t *pbBuf, size_t cbBuf)1738 {1739 PIMAGE_DOS_HEADER pMzHdr = (PIMAGE_DOS_HEADER)pbBuf;1740 if (cbBuf >= sizeof(*pMzHdr))1741 {1742 if (pMzHdr->e_magic == IMAGE_DOS_SIGNATURE)1743 {1744 if (pMzHdr->e_lfanew >= cbBuf)1745 return NULL;1746 cbBuf -= pMzHdr->e_lfanew;1747 pbBuf += pMzHdr->e_lfanew;1748 }1749 }1750 1751 PIMAGE_NT_HEADERS pNtHdrs = (PIMAGE_NT_HEADERS)pbBuf;1752 if (cbBuf >= sizeof(IMAGE_NT_HEADERS))1753 {1754 if (pNtHdrs->Signature == IMAGE_NT_SIGNATURE)1755 return pNtHdrs;1756 }1757 return NULL;1758 }1759 1760 1761 static uint32_t supR3HardNtPuChFindFirstDiff(void const *pvBuf1, void const *pvBuf2, size_t cbBuf)1762 {1763 uint8_t const *pabBuf1 = (uint8_t const *)pvBuf1;1764 uint8_t const *pabBuf2 = (uint8_t const *)pvBuf2;1765 uint32_t off = 0;1766 while (off < cbBuf && pabBuf1[off] == pabBuf2[off])1767 off++;1768 return off;1769 }1770 1771 1772 static NTSTATUS supR3HardNtPuChRestoreImageBits(PSUPR3HARDNTPUCH pThis, PVOID pvChildAddr,1773 void const *pvFileBits, size_t cbToRestore, uint32_t fCorrectProtection)1774 {1775 PVOID pvProt = pvChildAddr;1776 SIZE_T cbProt = cbToRestore;1777 ULONG fOldProt = 0;1778 NTSTATUS rcNt = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, PAGE_READWRITE, &fOldProt);1779 if (NT_SUCCESS(rcNt))1780 {1781 SIZE_T cbIgnored;1782 rcNt = NtWriteVirtualMemory(pThis->hProcess, pvChildAddr, pvFileBits, cbToRestore, &cbIgnored);1783 1784 pvProt = pvChildAddr;1785 cbProt = cbToRestore;1786 NTSTATUS rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvProt, &cbProt, fCorrectProtection, &fOldProt);1787 if (NT_SUCCESS(rcNt))1788 rcNt = rcNt2;1789 }1790 return rcNt;1791 }1792 1793 1794 static int supR3HardNtPuChSanitizeImage(PSUPR3HARDNTPUCH pThis, PMEMORY_BASIC_INFORMATION pMemInfo)1795 {1796 /*1797 * Get the image name.1798 */1799 union1800 {1801 UNICODE_STRING UniStr;1802 uint8_t abPadding[4096];1803 } uBuf;1804 SIZE_T cbActual;1805 NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,1806 pMemInfo->BaseAddress,1807 MemorySectionName,1808 &uBuf,1809 sizeof(uBuf) - sizeof(WCHAR),1810 &cbActual);1811 if (!NT_SUCCESS(rcNt))1812 return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,1813 "NtQueryVirtualMemory/MemorySectionName failed for %p: %#x", pMemInfo->BaseAddress, rcNt);1814 uBuf.UniStr.Buffer[uBuf.UniStr.Length / sizeof(WCHAR)] = '\0';1815 SUP_DPRINTF(("supR3HardNtPuChSanitizeImage: %p '%ls'\n", pMemInfo->BaseAddress, uBuf.UniStr.Buffer));1816 1817 1818 /*1819 * Open the file.1820 */1821 HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;1822 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;1823 1824 OBJECT_ATTRIBUTES ObjAttr;1825 InitializeObjectAttributes(&ObjAttr, &uBuf.UniStr, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);1826 1827 rcNt = NtCreateFile(&hFile,1828 FILE_READ_DATA | SYNCHRONIZE,1829 &ObjAttr,1830 &Ios,1831 NULL /* Allocation Size*/,1832 FILE_ATTRIBUTE_NORMAL,1833 FILE_SHARE_READ,1834 FILE_OPEN,1835 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,1836 NULL /*EaBuffer*/,1837 0 /*EaLength*/);1838 if (NT_SUCCESS(rcNt))1839 rcNt = Ios.Status;1840 if (!NT_SUCCESS(rcNt))1841 return RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),1842 "NtCreateFile returned %#x opening '%ls'.", rcNt, uBuf.UniStr.Buffer);1843 1844 /*1845 * Read the headers, ASSUMES the stub isn't pushing the optional header out1846 * of a 4KB buffer. Also ASSUMEs that the file is more than 4KB in size.1847 */1848 int rc;1849 uint8_t abFile[_4K];1850 LARGE_INTEGER off;1851 off.QuadPart = 0;1852 rcNt = NtReadFile(hFile, NULL, NULL, NULL, &Ios, abFile, sizeof(abFile), &off, NULL);1853 if (NT_SUCCESS(rcNt))1854 rcNt = Ios.Status;1855 if (NT_SUCCESS(rcNt))1856 {1857 PIMAGE_NT_HEADERS pNtFile = supR3HardNtPuChFindNtHeaders(abFile, sizeof(abFile));1858 if (pNtFile)1859 {1860 /*1861 * Read the first 4KB of the process memory.1862 */1863 uint8_t abProc[_4K];1864 SIZE_T cbActualMem;1865 rcNt = NtReadVirtualMemory(pThis->hProcess, pMemInfo->BaseAddress, abProc, sizeof(abProc), &cbActualMem);1866 if (NT_SUCCESS(rcNt))1867 {1868 /*1869 * Watch out for apisetschema.dll, it only has section #11870 * mapped into the process.1871 */1872 if ( g_uNtVerCombined < SUP_NT_VER_W701873 || pThis->Peb.Diff3.W7.ApiSetMap != pMemInfo->BaseAddress1874 || !supR3HardNtIsNamedSystem32Dll(&uBuf.UniStr, "apisetschema.dll"))1875 {1876 PIMAGE_NT_HEADERS pNtProc = supR3HardNtPuChFindNtHeaders(abProc, sizeof(abProc));1877 if ((uintptr_t)pNtProc - (uintptr_t)abProc == (uintptr_t)pNtFile - (uintptr_t)abFile)1878 {1879 pNtFile->OptionalHeader.ImageBase = pNtProc->OptionalHeader.ImageBase;1880 1881 size_t cbCompare = RT_MIN(pNtFile->OptionalHeader.SizeOfHeaders, sizeof(abProc));1882 if (cbCompare < sizeof(abFile))1883 RT_BZERO(&abFile[cbCompare], sizeof(abFile) - cbCompare);1884 if (!memcmp(abFile, abProc, cbCompare))1885 rc = VINF_SUCCESS;1886 else1887 {1888 SUP_DPRINTF(("supR3HardNtPuChSanitizeImage: Header diff @%#x in ('%ls')\n",1889 supR3HardNtPuChFindFirstDiff(abFile, abProc, sizeof(abProc)), uBuf.UniStr.Buffer));1890 rc = supR3HardNtPuChRestoreImageBits(pThis, pMemInfo->BaseAddress, abFile, cbCompare, PAGE_READONLY);1891 }1892 }1893 else1894 rc = RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,1895 "PE header offset differs between file and memory: offProc=%p offFile=%p '%ls'\n",1896 (uintptr_t)pNtProc - (uintptr_t)abProc, (uintptr_t)pNtFile - (uintptr_t)abFile,1897 uBuf.UniStr.Buffer);1898 }1899 else1900 {1901 /*1902 * Validate the API set map.1903 */1904 }1905 }1906 else1907 rc = RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),1908 "NtReadVirtualMemory returned %#x read 4KB at %p ('%ls').", rcNt,1909 pMemInfo->BaseAddress, uBuf.UniStr.Buffer);1910 }1911 else1912 rc = RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),1913 "No PE header in the first 4KB of '%ls'.", rcNt, uBuf.UniStr.Buffer);1914 }1915 else1916 rc = RTErrInfoSetF(pThis->pErrInfo, RTErrConvertFromNtStatus(rcNt),1917 "NtReadFile returned %#x reading the header of '%ls'.", rcNt, uBuf.UniStr.Buffer);1918 1919 NtClose(hFile);1920 1921 return rc;1922 }1923 1924 1925 static int supR3HardNtPuChSanitizeMemory(PSUPR3HARDNTPUCH pThis)1926 {1927 /*1928 * Find and remove/disable any unwanted executable memory.1929 */1930 uint32_t cXpExceptions = 0;1931 uintptr_t cbAdvance = 0;1932 uintptr_t uPtrWhere = 0;1933 for (uint32_t i = 0; i < 1024; i++)1934 {1935 SIZE_T cbActual = 0;1936 MEMORY_BASIC_INFORMATION MemInfo = { 0, 0, 0, 0, 0, 0, 0 };1937 NTSTATUS rcNt = NtQueryVirtualMemory(pThis->hProcess,1938 (void const *)uPtrWhere,1939 MemoryBasicInformation,1940 &MemInfo,1941 sizeof(MemInfo),1942 &cbActual);1943 if (!NT_SUCCESS(rcNt))1944 break;1945 //SUP_DPRINTF(("supR3HardNtPuChSanitizeMemory: %p (%p LB %#zx): type=%#010x prot=%#06x state=%#07x aprot=%#06x abase=%p\n",1946 // uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize,MemInfo.Type,1947 // MemInfo.Protect, MemInfo.State, MemInfo.AllocationBase, MemInfo.AllocationProtect));1948 1949 if ( MemInfo.Type == SEC_IMAGE1950 || MemInfo.Type == SEC_PROTECTED_IMAGE1951 || MemInfo.Type == (SEC_IMAGE | SEC_PROTECTED_IMAGE))1952 {1953 /*1954 * Restore modified parts of the image from file.1955 */1956 if (MemInfo.BaseAddress == MemInfo.AllocationBase)1957 {1958 int rc = supR3HardNtPuChSanitizeImage(pThis, &MemInfo);1959 if (RT_FAILURE(rc))1960 return rc;1961 }1962 }1963 /*1964 * Executable memory outside an image is evil by definition.1965 */1966 else if (MemInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))1967 {1968 /*1969 * XP, W2K3 exception: Ignore the CSRSS read-only region as best we can.1970 */1971 if ( (MemInfo.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY))1972 == PAGE_EXECUTE_READ1973 && cXpExceptions == 01974 && (uintptr_t)MemInfo.BaseAddress >= UINT32_C(0x78000000)1975 /* && MemInfo.BaseAddress == pPeb->ReadOnlySharedMemoryBase */1976 && g_uNtVerCombined < SUP_MAKE_NT_VER_SIMPLE(6, 0) )1977 cXpExceptions++;1978 #ifndef VBOX_PERMIT_VISUAL_STUDIO_PROFILING1979 else1980 {1981 /*1982 * Free any private executable memory (sysplant.sys allocates executable memory).1983 */1984 if (MemInfo.Type == MEM_PRIVATE)1985 {1986 SUP_DPRINTF(("supR3HardNtPuChSanitizeMemory: Freeing exec mem at %p (%p LB %#zx)\n",1987 uPtrWhere, MemInfo.BaseAddress, MemInfo.RegionSize));1988 PVOID pvFree = MemInfo.BaseAddress;1989 SIZE_T cbFree = MemInfo.RegionSize;1990 rcNt = NtFreeVirtualMemory(pThis->hProcess, &pvFree, &cbFree, MEM_RELEASE);1991 if (!NT_SUCCESS(rcNt))1992 return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,1993 "NtFreeVirtualMemory (%p LB %#zx) failed: %#x",1994 MemInfo.BaseAddress, MemInfo.RegionSize, rcNt);1995 }1996 /*1997 * Unmap mapped memory, failing that, drop exec privileges.1998 */1999 else if (MemInfo.Type == MEM_MAPPED)2000 {2001 SUP_DPRINTF(("supR3HardNtPuChSanitizeMemory: Unmapping exec mem at %p (%p/%p LB %#zx)\n",2002 uPtrWhere, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize));2003 rcNt = NtUnmapViewOfSection(pThis->hProcess, MemInfo.AllocationBase);2004 if (!NT_SUCCESS(rcNt))2005 {2006 PVOID pvCopy = MemInfo.BaseAddress;2007 SIZE_T cbCopy = MemInfo.RegionSize;2008 NTSTATUS rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvCopy, &cbCopy, PAGE_NOACCESS, NULL);2009 if (!NT_SUCCESS(rcNt2))2010 rcNt2 = NtProtectVirtualMemory(pThis->hProcess, &pvCopy, &cbCopy, PAGE_READONLY, NULL);2011 if (!NT_SUCCESS(rcNt2))2012 return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,2013 "NtUnmapViewOfSection (%p/%p LB %#zx) failed: %#x (%#x)",2014 MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize, rcNt, rcNt2);2015 }2016 }2017 else2018 return RTErrInfoSetF(pThis->pErrInfo, VERR_GENERAL_FAILURE,2019 "Unknown executable memory type %#x at %p/%p LB %#zx",2020 MemInfo.Type, MemInfo.AllocationBase, MemInfo.BaseAddress, MemInfo.RegionSize);2021 }2022 #endif2023 }2024 2025 /*2026 * Advance.2027 */2028 cbAdvance = MemInfo.RegionSize;2029 if (uPtrWhere + cbAdvance <= uPtrWhere)2030 break;2031 uPtrWhere += MemInfo.RegionSize;2032 }2033 1739 2034 1740 return VINF_SUCCESS; … … 2153 1859 2154 1860 /* 2155 * Do the work .1861 * Do the work, the last bit we tag along with the process verfication code. 2156 1862 */ 2157 1863 int rc = supR3HardNtPuChScrewUpPebForInitialImageEvents(&This); … … 2161 1867 rc = supR3HardNtPuChSanitizePeb(&This); 2162 1868 if (RT_SUCCESS(rc)) 2163 rc = sup R3HardNtPuChSanitizeMemory(&This);1869 rc = supHardenedWinVerifyProcess(hProcess, hThread, SUPHARDNTVPKIND_CHILD_PURIFICATION, pErrInfo); 2164 1870 2165 1871 return rc; … … 2301 2007 #endif 2302 2008 2009 #ifndef VBOX_WITHOUT_DEBUGGER_CHECKS 2010 /* 2011 * Apply anti debugger notification trick to the thread. (Also done in 2012 * supR3HardenedWinInstallHooks.) 2013 */ 2014 rcNt = NtSetInformationThread(NtCurrentThread(), ThreadHideFromDebugger, NULL, 0); 2015 if (!NT_SUCCESS(rcNt)) 2016 { 2017 NtTerminateProcess(hProcess, DBG_TERMINATE_PROCESS); 2018 supR3HardenedError(rcNt, true /*fFatal*/, "NtSetInformationThread/ThreadHideFromDebugger failed: %#x\n", rcNt); 2019 } 2020 #endif 2303 2021 2304 2022 /* … … 2687 2405 2688 2406 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)) 2407 { 2408 /* Do a self purification to cure avast's weird NtOpenFile write-thru 2409 change in GetBinaryTypeW change in kernel32. */ 2410 supHardenedWinVerifyProcess(NtCurrentProcess(), NtCurrentThread(), SUPHARDNTVPKIND_SELF_PURIFICATION, NULL); 2411 2689 2412 supR3HardenedWinInstallHooks(); 2413 } 2690 2414 2691 2415 #ifndef VBOX_WITH_VISTA_NO_SP
Note:
See TracChangeset
for help on using the changeset viewer.