VirtualBox

Ignore:
Timestamp:
Feb 27, 2015 4:25:52 PM (10 years ago)
Author:
vboxsync
Message:

SUPHardNt: Don't get confused and throw VERR_SUP_VP_NO_FOUND_NO_EXE_MAPPING at the user just because some app happened to start us using the DOS-8.3 filename (SFN) (open(SFN) + map may also cause confusion).

File:
1 edited

Legend:

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

    r54453 r54560  
    10901090
    10911091/**
     1092 * Checks whether the path could be containing alternative 8.3 names generated
     1093 * by NTFS, FAT, or other similar file systems.
     1094 *
     1095 * @returns Pointer to the first component that might be an 8.3 name, NULL if
     1096 *          not 8.3 path.
     1097 * @param   pwszPath        The path to check.
     1098 *
     1099 * @remarks This is making bad ASSUMPTION wrt to the naming scheme of 8.3 names,
     1100 *          however, non-tilde 8.3 aliases are probably rare enough to not be
     1101 *          worth all the extra code necessary to open each path component and
     1102 *          check if we've got the short name or not.
     1103 */
     1104DECLHIDDEN(PRTUTF16) supHardNtVpIsPossible8dot3Path(PCRTUTF16 pwszPath)
     1105{
     1106    PCRTUTF16 pwszName = pwszPath;
     1107    for (;;)
     1108    {
     1109        RTUTF16 wc = *pwszPath++;
     1110        if (wc == '~')
     1111        {
     1112            /* Could check more here before jumping to conclusions... */
     1113            if (pwszPath - pwszName <= 8+1+3)
     1114                return (PRTUTF16)pwszName;
     1115        }
     1116        else if (wc == '\\' || wc == '/' || wc == ':')
     1117            pwszName = pwszPath;
     1118        else if (wc == 0)
     1119            break;
     1120    }
     1121    return NULL;
     1122}
     1123
     1124
     1125/**
     1126 * Fixes up a path possibly containing one or more alternative 8-dot-3 style
     1127 * components.
     1128 *
     1129 * The path is fixed up in place.  Errors are ignored.
     1130 *
     1131 * @param   pUniStr     The path to fix up. MaximumLength is the max buffer
     1132 *                      length.
     1133 */
     1134DECLHIDDEN(void) supHardNtVpFix8dot3Path(PUNICODE_STRING pUniStr, bool fPathOnly)
     1135{
     1136    /*
     1137     * We could use FileNormalizedNameInformation here and slap the volume device
     1138     * path in front of the result, but it's only supported since windows 8.0
     1139     * according to some docs... So we expand all supicious names.
     1140     */
     1141    union fix8dot3tmp
     1142    {
     1143        FILE_BOTH_DIR_INFORMATION Info;
     1144        uint8_t abBuffer[sizeof(FILE_BOTH_DIR_INFORMATION) + 2048 * sizeof(WCHAR)];
     1145    } *puBuf = NULL;
     1146
     1147
     1148    PRTUTF16 pwszFix = pUniStr->Buffer;
     1149    while (*pwszFix)
     1150    {
     1151        pwszFix = supHardNtVpIsPossible8dot3Path(pwszFix);
     1152        if (pwszFix == NULL)
     1153            break;
     1154
     1155        RTUTF16 wc;
     1156        PRTUTF16 pwszFixEnd = pwszFix;
     1157        while ((wc = *pwszFixEnd) != '\0' && wc != '\\' && wc != '/')
     1158            pwszFixEnd++;
     1159        if (wc == '\0' && fPathOnly)
     1160            break;
     1161
     1162        if (!puBuf)
     1163        {
     1164            puBuf = (union fix8dot3tmp *)RTMemAlloc(sizeof(*puBuf));
     1165            if (!puBuf)
     1166                break;
     1167        }
     1168
     1169        RTUTF16 const wcSaved = *pwszFix;
     1170        *pwszFix = '\0';                     /* paranoia. */
     1171
     1172        UNICODE_STRING      NtDir;
     1173        NtDir.Buffer = pUniStr->Buffer;
     1174        NtDir.Length = NtDir.MaximumLength = (USHORT)((pwszFix - pUniStr->Buffer) * sizeof(WCHAR));
     1175
     1176        HANDLE              hDir  = RTNT_INVALID_HANDLE_VALUE;
     1177        IO_STATUS_BLOCK     Ios   = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     1178
     1179        OBJECT_ATTRIBUTES   ObjAttr;
     1180        InitializeObjectAttributes(&ObjAttr, &NtDir, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/);
     1181#ifdef IN_RING0
     1182        ObjAttr.Attributes |= OBJ_KERNEL_HANDLE;
     1183#endif
     1184
     1185        NTSTATUS rcNt = NtCreateFile(&hDir,
     1186                                     FILE_READ_DATA | SYNCHRONIZE,
     1187                                     &ObjAttr,
     1188                                     &Ios,
     1189                                     NULL /* Allocation Size*/,
     1190                                     FILE_ATTRIBUTE_NORMAL,
     1191                                     FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     1192                                     FILE_OPEN,
     1193                                     FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     1194                                     NULL /*EaBuffer*/,
     1195                                     0 /*EaLength*/);
     1196        *pwszFix = wcSaved;
     1197        if (NT_SUCCESS(rcNt))
     1198        {
     1199            RT_ZERO(*puBuf);
     1200
     1201            IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     1202            UNICODE_STRING  NtFilterStr;
     1203            NtFilterStr.Buffer = pwszFix;
     1204            NtFilterStr.Length = (USHORT)((uintptr_t)pwszFixEnd - (uintptr_t)pwszFix);
     1205            NtFilterStr.MaximumLength = NtFilterStr.Length;
     1206            rcNt = NtQueryDirectoryFile(hDir,
     1207                                        NULL /* Event */,
     1208                                        NULL /* ApcRoutine */,
     1209                                        NULL /* ApcContext */,
     1210                                        &Ios,
     1211                                        puBuf,
     1212                                        sizeof(*puBuf) - sizeof(WCHAR),
     1213                                        FileBothDirectoryInformation,
     1214                                        FALSE /*ReturnSingleEntry*/,
     1215                                        &NtFilterStr,
     1216                                        FALSE /*RestartScan */);
     1217            if (NT_SUCCESS(rcNt) && puBuf->Info.NextEntryOffset == 0) /* There shall only be one entry matching... */
     1218            {
     1219                uint32_t offName = puBuf->Info.FileNameLength / sizeof(WCHAR);
     1220                while (offName > 0  && puBuf->Info.FileName[offName - 1] != '\\' && puBuf->Info.FileName[offName - 1] != '/')
     1221                    offName--;
     1222                uint32_t cwcNameNew = (puBuf->Info.FileNameLength / sizeof(WCHAR)) - offName;
     1223                uint32_t cwcNameOld = (uint32_t)(pwszFixEnd - pwszFix);
     1224
     1225                if (cwcNameOld == cwcNameNew)
     1226                    memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
     1227                else if (   pUniStr->Length + cwcNameNew * sizeof(WCHAR) - cwcNameOld * sizeof(WCHAR) + sizeof(WCHAR)
     1228                         <= pUniStr->MaximumLength)
     1229                {
     1230                    size_t cwcLeft = pUniStr->Length - (pwszFixEnd - pUniStr->Buffer) * sizeof(WCHAR) + sizeof(WCHAR);
     1231                    memmove(&pwszFix[cwcNameNew], pwszFixEnd, cwcLeft * sizeof(WCHAR));
     1232                    pUniStr->Length -= (USHORT)(cwcNameOld * sizeof(WCHAR));
     1233                    pUniStr->Length += (USHORT)(cwcNameNew * sizeof(WCHAR));
     1234                    pwszFixEnd      -= cwcNameOld;
     1235                    pwszFixEnd      -= cwcNameNew;
     1236                    memcpy(pwszFix, &puBuf->Info.FileName[offName], cwcNameNew * sizeof(WCHAR));
     1237                }
     1238                /* else: ignore overflow. */
     1239            }
     1240            /* else: ignore failure. */
     1241
     1242            NtClose(hDir);
     1243        }
     1244
     1245        /* Advance */
     1246        pwszFix = pwszFixEnd;
     1247    }
     1248
     1249    if (puBuf)
     1250        RTMemFree(puBuf);
     1251}
     1252
     1253
     1254
     1255/**
    10921256 * Matches two UNICODE_STRING structures in a case sensitive fashion.
    10931257 *
     
    11331297 * Records an additional memory region for an image.
    11341298 *
     1299 * May trash pThis->abMemory.
     1300 *
    11351301 * @returns VBox status code.
    11361302 * @retval  VINF_OBJECT_DESTROYED if we've unmapped the image (child
     
    11381304 * @param   pThis               The process scanning state structure.
    11391305 * @param   pImage              The new image structure.  Only the unicode name
    1140  *                              buffer is valid.
     1306 *                              buffer is valid (it's zero-terminated).
    11411307 * @param   pMemInfo            The memory information for the image.
    11421308 */
     
    11441310{
    11451311    /*
     1312     * If the filename or path contains short names, we have to get the long
     1313     * path so that we will recognize the DLLs and their location.
     1314     */
     1315    PUNICODE_STRING pLongName = &pImage->Name.UniStr;
     1316    if (supHardNtVpIsPossible8dot3Path(pLongName->Buffer))
     1317    {
     1318        AssertCompile(sizeof(pThis->abMemory) > sizeof(pImage->Name));
     1319        PUNICODE_STRING pTmp = (PUNICODE_STRING)pThis->abMemory;
     1320        pTmp->MaximumLength = (USHORT)RT_MIN(_64K - 1, sizeof(pThis->abMemory) - sizeof(*pTmp)) - sizeof(RTUTF16);
     1321        pTmp->Length = pImage->Name.UniStr.Length;
     1322        pTmp->Buffer = (PRTUTF16)(pTmp + 1);
     1323        memcpy(pTmp->Buffer, pLongName->Buffer, pLongName->Length + sizeof(RTUTF16));
     1324
     1325        supHardNtVpFix8dot3Path(pTmp, false /*fPathOnly*/);
     1326        Assert(pTmp->Buffer[pTmp->Length / sizeof(RTUTF16)] == '\0');
     1327
     1328        pLongName = pTmp;
     1329    }
     1330
     1331    /*
    11461332     * Extract the final component.
    11471333     */
    1148     unsigned  cwcDirName   = pImage->Name.UniStr.Length / sizeof(WCHAR);
    1149     PCRTUTF16 pwszFilename = &pImage->Name.UniStr.Buffer[cwcDirName];
     1334    RTUTF16   wc;
     1335    unsigned  cwcDirName   = pLongName->Length / sizeof(WCHAR);
     1336    PCRTUTF16 pwcDirName   = &pLongName->Buffer[cwcDirName];
     1337    PCRTUTF16 pwszFilename = &pLongName->Buffer[cwcDirName];
    11501338    while (   cwcDirName > 0
    1151            && pwszFilename[-1] != '\\'
    1152            && pwszFilename[-1] != '/'
    1153            && pwszFilename[-1] != ':')
     1339           && (wc = pwszFilename[-1]) != '\\'
     1340           && wc != '/'
     1341           && wc != ':')
    11541342    {
    11551343        pwszFilename--;
     
    11581346    if (!*pwszFilename)
    11591347        return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_IMAGE_MAPPING_NAME,
    1160                                    "Empty filename (len=%u) for image at %p.", pImage->Name.UniStr.Length, pMemInfo->BaseAddress);
     1348                                   "Empty filename (len=%u) for image at %p.", pLongName->Length, pMemInfo->BaseAddress);
    11611349
    11621350    /*
     
    11641352     */
    11651353    while (   cwcDirName > 0
    1166            && (   pImage->Name.UniStr.Buffer[cwcDirName - 1] == '\\'
    1167                || pImage->Name.UniStr.Buffer[cwcDirName - 1] == '/'))
     1354           && (   pLongName->Buffer[cwcDirName - 1] == '\\'
     1355               || pLongName->Buffer[cwcDirName - 1] == '/'))
    11681356        cwcDirName--;
    11691357
     
    11811369            /* The directory name must match the one we've got for System32. */
    11821370            if (   (   cwcDirName * sizeof(WCHAR) != g_System32NtPath.UniStr.Length
    1183                     || suplibHardenedMemComp(pImage->Name.UniStr.Buffer,
    1184                                             g_System32NtPath.UniStr.Buffer,
    1185                                             cwcDirName * sizeof(WCHAR)) )
     1371                    || suplibHardenedMemComp(pLongName->Buffer, g_System32NtPath.UniStr.Buffer, cwcDirName * sizeof(WCHAR)) )
    11861372# ifdef VBOX_PERMIT_MORE
    11871373                && (   pImage->pszName[0] != 'a'
    11881374                    || pImage->pszName[1] != 'c'
    1189                     || !supHardViIsAppPatchDir(pImage->Name.UniStr.Buffer, pImage->Name.UniStr.Length / sizeof(WCHAR)) )
     1375                    || !supHardViIsAppPatchDir(pLongName->Buffer, pLongName->Length / sizeof(WCHAR)) )
    11901376# endif
    11911377                )
    11921378                return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NON_SYSTEM32_DLL,
    11931379                                           "Expected %ls to be loaded from %ls.",
    1194                                            pImage->Name.UniStr.Buffer, g_System32NtPath.UniStr.Buffer);
     1380                                           pLongName->Buffer, g_System32NtPath.UniStr.Buffer);
    11951381# ifdef VBOX_PERMIT_MORE
    11961382            if (g_uNtVerCombined < SUP_NT_VER_W70 && i >= VBOX_PERMIT_MORE_FIRST_IDX)
     
    12281414        {
    12291415            SUP_DPRINTF(("supHardNtVpScanVirtualMemory: Unmapping image mem at %p (%p LB %#zx) - '%ls'\n",
    1230                          pMemInfo->AllocationBase, pMemInfo->BaseAddress, pMemInfo->RegionSize));
     1416                         pMemInfo->AllocationBase, pMemInfo->BaseAddress, pMemInfo->RegionSize, pwszFilename));
    12311417            NTSTATUS rcNt = NtUnmapViewOfSection(pThis->hProcess, pMemInfo->AllocationBase);
    12321418            if (NT_SUCCESS(rcNt))
     
    12501436                                "component (or disable it) to prevent ADC from injecting itself into the VirtualBox VM processes. "
    12511437                                "See http://www.symantec.com/connect/articles/creating-application-control-exclusions-symantec-endpoint-protection-121"
    1252                                 , pImage->Name.UniStr.Buffer, pMemInfo->BaseAddress);
     1438                                , pLongName->Buffer, pMemInfo->BaseAddress);
    12531439            return pThis->rcResult = VERR_SUP_VP_SYSFER_DLL; /* Try make sure this is what the user sees first! */
    12541440        }
    12551441        return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NOT_KNOWN_DLL_OR_EXE,
    1256                                    "Unknown image file %ls at %p.", pImage->Name.UniStr.Buffer, pMemInfo->BaseAddress);
     1442                                   "Unknown image file %ls at %p.", pLongName->Buffer, pMemInfo->BaseAddress);
    12571443    }
    12581444
     
    13591545 *
    13601546 * This collects the locations of DLLs and the EXE, and verifies that executable
    1361  * memory is only associated with these.
     1547 * memory is only associated with these.  May trash pThis->abMemory.
    13621548 *
    13631549 * @returns VBox status code.
Note: See TracChangeset for help on using the changeset viewer.

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