- Timestamp:
- Jul 15, 2014 2:32:21 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/win/SUPR3HardenedMain-win.cpp
r52030 r52039 464 464 465 465 /** 466 * Checks whether the path could be containing alternative 8.3 names generated 467 * by NTFS, FAT, or other similar file systems. 468 * 469 * @returns Pointer to the first component that might be an 8.3 name, NULL if 470 * not 8.3 path. 471 * @param pwszPath The path to check. 472 */ 473 static PRTUTF16 supR3HardenedWinIsPossible8dot3Path(PCRTUTF16 pwszPath) 474 { 475 PCRTUTF16 pwszName = pwszPath; 476 for (;;) 477 { 478 RTUTF16 wc = *pwszPath++; 479 if (wc == '~') 480 { 481 /* Could check more here before jumping to conclusions... */ 482 if (pwszPath - pwszName <= 8+1+3) 483 return (PRTUTF16)pwszName; 484 } 485 else if (wc == '\\' || wc == '/' || wc == ':') 486 pwszName = pwszPath; 487 else if (wc == 0) 488 break; 489 } 490 return NULL; 491 } 492 493 494 /** 495 * Fixes up a path possibly containing one or more alternative 8-dot-3 style 496 * components. 497 * 498 * The path is fixed up in place. Errors are ignored. 499 * 500 * @param hFile The handle to the file which path we're fixing up. 501 * @param pUniStr The path to fix up. MaximumLength is the max buffer 502 * length. 503 */ 504 static void supR3HardenedWinFix8dot3Path(HANDLE hFile, PUNICODE_STRING pUniStr) 505 { 506 /* 507 * We could use FileNormalizedNameInformation here and slap the volume device 508 * path in front of the result, but it's only supported since windows 8.0 509 * according to some docs... So we expand all supicious names. 510 */ 511 PRTUTF16 pwszFix = pUniStr->Buffer; 512 while (*pwszFix) 513 { 514 pwszFix = supR3HardenedWinIsPossible8dot3Path(pwszFix); 515 if (pwszFix == NULL) 516 break; 517 518 RTUTF16 wc; 519 PRTUTF16 pwszFixEnd = pwszFix; 520 while ((wc = *pwszFixEnd) != '\0' && wc != '\\' && wc != '//') 521 pwszFixEnd++; 522 if (wc == '\0') 523 break; 524 525 RTUTF16 const wcSaved = *pwszFix; 526 *pwszFix = '\0'; /* paranoia. */ 527 528 UNICODE_STRING NtDir; 529 NtDir.Buffer = pUniStr->Buffer; 530 NtDir.Length = NtDir.MaximumLength = (USHORT)((pwszFix - pUniStr->Buffer) * sizeof(WCHAR)); 531 532 HANDLE hDir = RTNT_INVALID_HANDLE_VALUE; 533 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 534 535 OBJECT_ATTRIBUTES ObjAttr; 536 InitializeObjectAttributes(&ObjAttr, &NtDir, OBJ_CASE_INSENSITIVE, NULL /*hRootDir*/, NULL /*pSecDesc*/); 537 538 NTSTATUS rcNt = NtCreateFile(&hDir, 539 FILE_READ_DATA | SYNCHRONIZE, 540 &ObjAttr, 541 &Ios, 542 NULL /* Allocation Size*/, 543 FILE_ATTRIBUTE_NORMAL, 544 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 545 FILE_OPEN, 546 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, 547 NULL /*EaBuffer*/, 548 0 /*EaLength*/); 549 *pwszFix = wcSaved; 550 if (NT_SUCCESS(rcNt)) 551 { 552 union 553 { 554 FILE_BOTH_DIR_INFORMATION Info; 555 uint8_t abBuffer[sizeof(FILE_BOTH_DIR_INFORMATION) + 2048 * sizeof(WCHAR)]; 556 } uBuf; 557 RT_ZERO(uBuf); 558 559 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; 560 UNICODE_STRING NtFilterStr; 561 NtFilterStr.Buffer = pwszFix; 562 NtFilterStr.Length = (USHORT)((uintptr_t)pwszFixEnd - (uintptr_t)pwszFix); 563 NtFilterStr.MaximumLength = NtFilterStr.Length; 564 rcNt = NtQueryDirectoryFile(hDir, 565 NULL /* Event */, 566 NULL /* ApcRoutine */, 567 NULL /* ApcContext */, 568 &Ios, 569 &uBuf, 570 sizeof(uBuf) - sizeof(WCHAR), 571 FileBothDirectoryInformation, 572 FALSE /*ReturnSingleEntry*/, 573 &NtFilterStr, 574 FALSE /*RestartScan */); 575 if (NT_SUCCESS(rcNt) && uBuf.Info.NextEntryOffset == 0) /* There shall only be one entry matching... */ 576 { 577 uint32_t offName = uBuf.Info.FileNameLength / sizeof(WCHAR); 578 while (offName > 0 && uBuf.Info.FileName[offName - 1] != '\\' && uBuf.Info.FileName[offName - 1] != '/') 579 offName--; 580 uint32_t cwcNameNew = (uBuf.Info.FileNameLength / sizeof(WCHAR)) - offName; 581 uint32_t cwcNameOld = pwszFixEnd - pwszFix; 582 583 if (cwcNameOld == cwcNameNew) 584 memcpy(pwszFix, &uBuf.Info.FileName[offName], cwcNameNew * sizeof(WCHAR)); 585 else if ( pUniStr->Length + cwcNameNew * sizeof(WCHAR) - cwcNameOld * sizeof(WCHAR) + sizeof(WCHAR) 586 <= pUniStr->MaximumLength) 587 { 588 size_t cwcLeft = pUniStr->Length - (pwszFixEnd - pUniStr->Buffer) * sizeof(WCHAR) + sizeof(WCHAR); 589 memmove(&pwszFix[cwcNameNew], pwszFixEnd, cwcLeft * sizeof(WCHAR)); 590 pUniStr->Length -= (USHORT)(cwcNameOld * sizeof(WCHAR)); 591 pUniStr->Length += (USHORT)(cwcNameNew * sizeof(WCHAR)); 592 pwszFixEnd -= cwcNameOld; 593 pwszFixEnd -= cwcNameNew; 594 memcpy(pwszFix, &uBuf.Info.FileName[offName], cwcNameNew * sizeof(WCHAR)); 595 } 596 /* else: ignore overflow. */ 597 } 598 /* else: ignore failure. */ 599 600 NtClose(hDir); 601 } 602 603 /* Advance */ 604 pwszFix = pwszFixEnd; 605 } 606 } 607 608 609 610 /** 466 611 * Hook that monitors NtCreateSection calls. 467 612 * … … 506 651 fImage, fExecMap, fExecProt); 507 652 return rcNt; 653 } 654 655 if (supR3HardenedWinIsPossible8dot3Path(uBuf.UniStr.Buffer)) 656 { 657 uBuf.UniStr.MaximumLength = sizeof(uBuf) - 128; 658 supR3HardenedWinFix8dot3Path(hFile, &uBuf.UniStr); 508 659 } 509 660 … … 864 1015 && pbNtCreateSection[ 9] == 0x05 865 1016 && pbNtCreateSection[10] == 0xc3 /* ret */ 1017 1018 /* b8 22 35 ed 0 48 63 c0 ff e0 c3 f 1f 44 0 0 - necros2 - agnitum firewall? */ 866 1019 ) 867 1020 {
Note:
See TracChangeset
for help on using the changeset viewer.