Changeset 54560 in vbox for trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
- Timestamp:
- Feb 27, 2015 4:25:52 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPHardenedVerifyProcess-win.cpp
r54453 r54560 1090 1090 1091 1091 /** 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 */ 1104 DECLHIDDEN(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 */ 1134 DECLHIDDEN(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 /** 1092 1256 * Matches two UNICODE_STRING structures in a case sensitive fashion. 1093 1257 * … … 1133 1297 * Records an additional memory region for an image. 1134 1298 * 1299 * May trash pThis->abMemory. 1300 * 1135 1301 * @returns VBox status code. 1136 1302 * @retval VINF_OBJECT_DESTROYED if we've unmapped the image (child … … 1138 1304 * @param pThis The process scanning state structure. 1139 1305 * @param pImage The new image structure. Only the unicode name 1140 * buffer is valid .1306 * buffer is valid (it's zero-terminated). 1141 1307 * @param pMemInfo The memory information for the image. 1142 1308 */ … … 1144 1310 { 1145 1311 /* 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 /* 1146 1332 * Extract the final component. 1147 1333 */ 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]; 1150 1338 while ( cwcDirName > 0 1151 && pwszFilename[-1]!= '\\'1152 && pwszFilename[-1]!= '/'1153 && pwszFilename[-1]!= ':')1339 && (wc = pwszFilename[-1]) != '\\' 1340 && wc != '/' 1341 && wc != ':') 1154 1342 { 1155 1343 pwszFilename--; … … 1158 1346 if (!*pwszFilename) 1159 1347 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NO_IMAGE_MAPPING_NAME, 1160 "Empty filename (len=%u) for image at %p.", p Image->Name.UniStr.Length, pMemInfo->BaseAddress);1348 "Empty filename (len=%u) for image at %p.", pLongName->Length, pMemInfo->BaseAddress); 1161 1349 1162 1350 /* … … 1164 1352 */ 1165 1353 while ( cwcDirName > 0 1166 && ( p Image->Name.UniStr.Buffer[cwcDirName - 1] == '\\'1167 || p Image->Name.UniStr.Buffer[cwcDirName - 1] == '/'))1354 && ( pLongName->Buffer[cwcDirName - 1] == '\\' 1355 || pLongName->Buffer[cwcDirName - 1] == '/')) 1168 1356 cwcDirName--; 1169 1357 … … 1181 1369 /* The directory name must match the one we've got for System32. */ 1182 1370 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)) ) 1186 1372 # ifdef VBOX_PERMIT_MORE 1187 1373 && ( pImage->pszName[0] != 'a' 1188 1374 || pImage->pszName[1] != 'c' 1189 || !supHardViIsAppPatchDir(p Image->Name.UniStr.Buffer, pImage->Name.UniStr.Length / sizeof(WCHAR)) )1375 || !supHardViIsAppPatchDir(pLongName->Buffer, pLongName->Length / sizeof(WCHAR)) ) 1190 1376 # endif 1191 1377 ) 1192 1378 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NON_SYSTEM32_DLL, 1193 1379 "Expected %ls to be loaded from %ls.", 1194 p Image->Name.UniStr.Buffer, g_System32NtPath.UniStr.Buffer);1380 pLongName->Buffer, g_System32NtPath.UniStr.Buffer); 1195 1381 # ifdef VBOX_PERMIT_MORE 1196 1382 if (g_uNtVerCombined < SUP_NT_VER_W70 && i >= VBOX_PERMIT_MORE_FIRST_IDX) … … 1228 1414 { 1229 1415 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)); 1231 1417 NTSTATUS rcNt = NtUnmapViewOfSection(pThis->hProcess, pMemInfo->AllocationBase); 1232 1418 if (NT_SUCCESS(rcNt)) … … 1250 1436 "component (or disable it) to prevent ADC from injecting itself into the VirtualBox VM processes. " 1251 1437 "See http://www.symantec.com/connect/articles/creating-application-control-exclusions-symantec-endpoint-protection-121" 1252 , p Image->Name.UniStr.Buffer, pMemInfo->BaseAddress);1438 , pLongName->Buffer, pMemInfo->BaseAddress); 1253 1439 return pThis->rcResult = VERR_SUP_VP_SYSFER_DLL; /* Try make sure this is what the user sees first! */ 1254 1440 } 1255 1441 return supHardNtVpSetInfo2(pThis, VERR_SUP_VP_NOT_KNOWN_DLL_OR_EXE, 1256 "Unknown image file %ls at %p.", p Image->Name.UniStr.Buffer, pMemInfo->BaseAddress);1442 "Unknown image file %ls at %p.", pLongName->Buffer, pMemInfo->BaseAddress); 1257 1443 } 1258 1444 … … 1359 1545 * 1360 1546 * 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. 1362 1548 * 1363 1549 * @returns VBox status code.
Note:
See TracChangeset
for help on using the changeset viewer.