Changeset 70338 in vbox for trunk/src/VBox/Debugger
- Timestamp:
- Dec 25, 2017 5:38:40 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 119938
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGPlugInWinNt.cpp
r69500 r70338 54 54 uint32_t DllBase; 55 55 uint32_t EntryPoint; 56 /** @note This field is not a size in NT 3.1. It's NULL for images loaded by the 57 * boot loader, for other images it looks like some kind of pointer. */ 56 58 uint32_t SizeOfImage; 57 59 struct … … 195 197 /** 32-bit (true) or 64-bit (false) */ 196 198 bool f32Bit; 199 /** Set if NT 3.1 was detected. 200 * This implies both Misc.VirtualSize and NTMTE32::SizeOfImage are zero. */ 201 bool fNt31; 197 202 198 203 /** The NT version. */ … … 394 399 * @param cShs Number of headers. 395 400 * @param cbImage The image size reported by NT. 401 * @param cbImageFromHdr The image size by the linker in the header. 396 402 * @param uRvaRsrc The RVA of the resource directory. UINT32_MAX if 397 403 * no resource directory. 398 404 * @param cbSectAlign The section alignment specified in the header. 405 * @param fNt31 Set if NT 3.1. Needed for chopped off HAL. 399 406 * @param pcbImageCorrect The corrected image size. This is derived from 400 407 * cbImage and virtual range of the section tables. … … 406 413 */ 407 414 static bool dbgDiggerWinNtCheckSectHdrsAndImgSize(PCIMAGE_SECTION_HEADER paShs, uint32_t cShs, uint32_t cbImage, 408 uint32_t uRvaRsrc, uint32_t cbSectAlign, uint32_t *pcbImageCorrect) 415 uint32_t cbImageFromHdr, uint32_t uRvaRsrc, uint32_t cbSectAlign, 416 bool fNt31, uint32_t *pcbImageCorrect) 409 417 { 410 418 *pcbImageCorrect = cbImage; … … 421 429 continue; 422 430 431 /* Tweak to determine the virtual size if the linker didn't set it (NT 3.1). */ 432 /** @todo this isn't really perfect. cbImage is kind of wrong... */ 433 uint32_t cbVirtual = paShs[i].Misc.VirtualSize; 434 if (cbVirtual == 0) 435 { 436 for (uint32_t j = i + 1; j < cShs; j++) 437 if (!(paShs[j].Characteristics & IMAGE_SCN_TYPE_NOLOAD) 438 && paShs[j].VirtualAddress > paShs[i].VirtualAddress) 439 { 440 cbVirtual = paShs[j].VirtualAddress - paShs[i].VirtualAddress; 441 break; 442 } 443 if (!cbVirtual) 444 { 445 if (paShs[i].VirtualAddress < cbImageFromHdr) 446 cbVirtual = cbImageFromHdr - paShs[i].VirtualAddress; 447 else if (paShs[i].SizeOfRawData > 0) 448 cbVirtual = RT_ALIGN(paShs[i].SizeOfRawData, _4K); 449 } 450 } 451 423 452 /* Check that sizes are within the same range and that both sizes and 424 453 addresses are within reasonable limits. */ 425 if ( RT_ALIGN( paShs[i].Misc.VirtualSize, _64K) < RT_ALIGN(paShs[i].SizeOfRawData, _64K)426 || paShs[i].Misc.VirtualSize>= _1G427 || paShs[i].SizeOfRawData 428 { 429 Log(("DigWinNt: Section header #%u has a VirtualSize=%#xand SizeOfRawData=%#x, that's too much data!\n",430 i, paShs[i]. Misc.VirtualSize, paShs[i].SizeOfRawData));454 if ( RT_ALIGN(cbVirtual, _64K) < RT_ALIGN(paShs[i].SizeOfRawData, _64K) 455 || cbVirtual >= _1G 456 || paShs[i].SizeOfRawData >= _1G) 457 { 458 Log(("DigWinNt: Section header #%u (%.8s) has a VirtualSize=%#x (%#x) and SizeOfRawData=%#x, that's too much data!\n", 459 i, paShs[i].Name, cbVirtual, paShs[i].Misc.VirtualSize, paShs[i].SizeOfRawData)); 431 460 return false; 432 461 } 433 uint32_t uRvaEnd = paShs[i].VirtualAddress + paShs[i].Misc.VirtualSize;462 uint32_t uRvaEnd = paShs[i].VirtualAddress + cbVirtual; 434 463 if (uRvaEnd >= _1G || uRvaEnd < paShs[i].VirtualAddress) 435 464 { 436 Log(("DigWinNt: Section header #%u has a VirtualSize=%#xand VirtualAddr=%#x, %#x in total, that's too much!\n",437 i, paShs[i]. Misc.VirtualSize, paShs[i].VirtualAddress, uRvaEnd));465 Log(("DigWinNt: Section header #%u (%.8s) has a VirtualSize=%#x (%#x) and VirtualAddr=%#x, %#x in total, that's too much!\n", 466 i, paShs[i].Name, cbVirtual, paShs[i].Misc.VirtualSize, paShs[i].VirtualAddress, uRvaEnd)); 438 467 return false; 439 468 } … … 445 474 446 475 /* Check that the section is within the image. */ 447 if (uRvaEnd > cbImage )476 if (uRvaEnd > cbImage && fNt31) 448 477 { 449 478 Log(("DigWinNt: Section header #%u has a virtual address range beyond the image: %#x TO %#x cbImage=%#x\n", … … 496 525 PCIMAGE_SECTION_HEADER paShs = (PCIMAGE_SECTION_HEADER)(pbBuf + offShs); 497 526 if ( offShs + cbShs <= RT_MIN(cbImage, cbBuf) 498 && dbgDiggerWinNtCheckSectHdrsAndImgSize(paShs, cShs, cbImage, uRvaRsrc,499 WINNT_UNION(pThis, pHdrs, OptionalHeader.SectionAlignment),500 &pRdr->cbCorrectImageSize))527 && dbgDiggerWinNtCheckSectHdrsAndImgSize(paShs, cShs, cbImage, WINNT_UNION(pThis, pHdrs, OptionalHeader.SizeOfImage), 528 uRvaRsrc, WINNT_UNION(pThis, pHdrs, OptionalHeader.SectionAlignment), 529 pThis->fNt31, &pRdr->cbCorrectImageSize)) 501 530 { 502 531 pRdr->cMappings = 0; … … 594 623 595 624 /* 625 * NT 3.1 doesn't set the image size in the MTEs, so a little 626 * bit of tweaking is necessary here. 627 */ 628 uint32_t const cbImageValidate = !pThis->fNt31 ? cbImage : _64M; 629 630 /* 596 631 * Do some basic validation first. 597 632 * This is the usual exteremely verbose and messy code... 598 633 */ 599 634 Assert(cbBuf >= sizeof(IMAGE_NT_HEADERS64)); 600 if ( cbImage < sizeof(IMAGE_NT_HEADERS64)635 if ( (cbImage < sizeof(IMAGE_NT_HEADERS64) && !pThis->fNt31) 601 636 || cbImage >= _1M * 256) 602 637 { … … 614 649 pHdrs = (PCNTHDRS)pbBuf; 615 650 } 616 else if ( pMzHdr->e_lfanew >= cbImage 651 else if ( pMzHdr->e_lfanew >= cbImageValidate 617 652 || pMzHdr->e_lfanew < sizeof(*pMzHdr) 618 || pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) > cbImage )653 || pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) > cbImageValidate) 619 654 { 620 655 Log(("DigWinNt: %s: PE header to far into image: %#x cbImage=%#x\n", pszName, pMzHdr->e_lfanew, cbImage)); … … 664 699 } 665 700 uint32_t cbImageFromHdr = WINNT_UNION(pThis, pHdrs, OptionalHeader.SizeOfImage); 666 if (RT_ALIGN(cbImageFromHdr, _4K) != RT_ALIGN(cbImage, _4K)) 701 if (pThis->fNt31) 702 cbImage = RT_ALIGN(cbImageFromHdr, _4K); 703 else if (RT_ALIGN(cbImageFromHdr, _4K) != RT_ALIGN(cbImage, _4K)) 667 704 { 668 705 Log(("DigWinNt: %s: Invalid OH.SizeOfImage: %#x, expected %#x\n", pszName, cbImageFromHdr, cbImage)); … … 822 859 DBGFR3AddrFromFlat(pUVM, &Addr, pThis->f32Bit ? NTKUSERSHAREDDATA_WINNT32 : NTKUSERSHAREDDATA_WINNT64); 823 860 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &Addr, &u, PAGE_SIZE); 824 if (RT_FAILURE(rc)) 861 if (RT_SUCCESS(rc)) 862 { 863 pThis->NtProductType = u.UserSharedData.ProductTypeIsValid && u.UserSharedData.NtProductType <= kNtProductType_Server 864 ? (NTPRODUCTTYPE)u.UserSharedData.NtProductType 865 : kNtProductType_Invalid; 866 pThis->NtMajorVersion = u.UserSharedData.NtMajorVersion; 867 pThis->NtMinorVersion = u.UserSharedData.NtMinorVersion; 868 } 869 else if (pThis->fNt31) 870 { 871 pThis->NtProductType = kNtProductType_WinNt; 872 pThis->NtMajorVersion = 3; 873 pThis->NtMinorVersion = 1; 874 } 875 else 876 { 877 Log(("DigWinNt: Error reading KUSER_SHARED_DATA: %Rrc\n", rc)); 825 878 return rc; 826 pThis->NtProductType = u.UserSharedData.ProductTypeIsValid && u.UserSharedData.NtProductType <= kNtProductType_Server 827 ? (NTPRODUCTTYPE)u.UserSharedData.NtProductType 828 : kNtProductType_Invalid; 829 pThis->NtMajorVersion = u.UserSharedData.NtMajorVersion; 830 pThis->NtMinorVersion = u.UserSharedData.NtMinorVersion; 879 } 831 880 832 881 /* … … 862 911 break; 863 912 } 864 if ( !WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, DllBase)) 865 || WINNT_UNION(pThis, &Mte, SizeOfImage) > _1M*256 866 || WINNT_UNION(pThis, &Mte, EntryPoint) - WINNT_UNION(pThis, &Mte, DllBase) > WINNT_UNION(pThis, &Mte, SizeOfImage) ) 913 if (!WINNT_VALID_ADDRESS(pThis, WINNT_UNION(pThis, &Mte, DllBase))) 914 { 915 Log(("DigWinNt: Bad Mte at %RGv - DllBase=%llx\n", Addr.FlatPtr, WINNT_UNION(pThis, &Mte, DllBase) )); 916 break; 917 } 918 919 uint32_t const cbImageMte = !pThis->fNt31 ? WINNT_UNION(pThis, &Mte, SizeOfImage) : 0; 920 if ( !pThis->fNt31 921 && ( cbImageMte > _256M 922 || WINNT_UNION(pThis, &Mte, EntryPoint) - WINNT_UNION(pThis, &Mte, DllBase) > cbImageMte) ) 867 923 { 868 924 Log(("DigWinNt: Bad Mte at %RGv - EntryPoint=%llx SizeOfImage=%x DllBase=%llx\n", 869 Addr.FlatPtr, WINNT_UNION(pThis, &Mte, EntryPoint), WINNT_UNION(pThis, &Mte, SizeOfImage), WINNT_UNION(pThis, &Mte, DllBase)));925 Addr.FlatPtr, WINNT_UNION(pThis, &Mte, EntryPoint), cbImageMte, WINNT_UNION(pThis, &Mte, DllBase))); 870 926 break; 871 927 } … … 898 954 DBGFADDRESS ImageAddr; 899 955 DBGFR3AddrFromFlat(pUVM, &ImageAddr, WINNT_UNION(pThis, &Mte, DllBase)); 900 uint32_t cbImageBuf = RT_MIN(sizeof(u), WINNT_UNION(pThis, &Mte, SizeOfImage));956 uint32_t cbImageBuf = RT_MIN(sizeof(u), RT_MAX(cbImageMte, _4K)); 901 957 rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &ImageAddr, &u, cbImageBuf); 902 958 if (RT_SUCCESS(rc)) … … 905 961 pszName, 906 962 &ImageAddr, 907 WINNT_UNION(pThis, &Mte, SizeOfImage),963 cbImageMte, 908 964 &u.au8[0], 909 965 sizeof(u)); … … 950 1006 * in the PsLoadedModuleList we can easily validate the list head and report 951 1007 * success. 1008 * 1009 * Note! We ASSUME the section name is 8 byte aligned. 952 1010 */ 953 1011 CPUMMODE enmMode = DBGFR3CpuGetMode(pUVM, 0 /*idCpu*/); … … 959 1017 KernelAddr.FlatPtr += PAGE_SIZE) 960 1018 { 1019 bool fNt31 = false; 1020 DBGFADDRESS const RetryAddress = KernelAddr; 961 1021 int rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, uEnd - KernelAddr.FlatPtr, 962 1, "PAGELK\0", sizeof("PAGELK\0"), &KernelAddr); 1022 8, "PAGELK\0", sizeof("PAGELK\0"), &KernelAddr); 1023 if ( rc == VERR_DBGF_MEM_NOT_FOUND 1024 && enmMode != CPUMMODE_LONG) 1025 { 1026 /* NT3.1 didn't have a PAGELK section, so look for _TEXT instead. The 1027 following VirtualSize is zero, so check for that too. */ 1028 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &RetryAddress, uEnd - RetryAddress.FlatPtr, 1029 8, "_TEXT\0\0\0\0\0\0", sizeof("_TEXT\0\0\0\0\0\0"), &KernelAddr); 1030 fNt31 = true; 1031 } 963 1032 if (RT_FAILURE(rc)) 964 1033 break; … … 989 1058 uMte.v32.DllBase = KernelAddr.FlatPtr; 990 1059 uMte.v32.EntryPoint = KernelAddr.FlatPtr + pHdrs->OptionalHeader.AddressOfEntryPoint; 991 uMte.v32.SizeOfImage = pHdrs->OptionalHeader.SizeOfImage;1060 uMte.v32.SizeOfImage = !fNt31 ? pHdrs->OptionalHeader.SizeOfImage : 0; /* NT 3.1 didn't set the size. */ 992 1061 DBGFADDRESS HitAddr; 993 1062 rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, uEnd - KernelAddr.FlatPtr, … … 1032 1101 pThis->PsLoadedModuleListAddr = Addr; 1033 1102 pThis->f32Bit = true; 1103 pThis->fNt31 = fNt31; 1034 1104 return true; 1035 1105 } … … 1117 1187 pThis->PsLoadedModuleListAddr = Addr; 1118 1188 pThis->f32Bit = false; 1189 pThis->fNt31 = false; 1119 1190 return true; 1120 1191 }
Note:
See TracChangeset
for help on using the changeset viewer.