VirtualBox

Changeset 105532 in vbox for trunk


Ignore:
Timestamp:
Jul 27, 2024 12:55:53 AM (6 months ago)
Author:
vboxsync
Message:

Debugger/DBGPlugInWinNt: Detect winload.exe and the dll part of the bootmgr, also be able to locate the NT kernel after winload has loaded it. bugref:10727

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Debugger/DBGPlugInWinNt.cpp

    r104611 r105532  
    268268    uint32_t            NtBuildNumber;
    269269
     270    /** The address of the bootmgr image if early during boot. */
     271    DBGFADDRESS         BootMgrAddr;
     272    /** The address of the winload.exe image if early during boot.
     273     * When this is set, f32Bit has also been determined.  */
     274    DBGFADDRESS         WinLoadAddr;
     275
    270276    /** The address of the ntoskrnl.exe image. */
    271277    DBGFADDRESS         KernelAddr;
     
    365371
    366372#ifdef VBOX_DEBUGGER_WITH_WIN_DBG_PRINT_HOOKING
     373
    367374/**
    368375 * Queries the string from guest memory with the pointer in the given register, sanitizing it.
     
    662669        LogRel(("DigWinNt/DbgPrint: Failed to resolve kernel address space handle\n"));
    663670}
    664 #endif
     671
     672#endif /* VBOX_DEBUGGER_WITH_WIN_DBG_PRINT_HOOKING */
    665673
    666674/**
     
    850858
    851859/**
     860 * Checks if the given headers are for the BootMgr image loaded very early
     861 * during the BIOS boot process.
     862 */
     863static bool dbgDiggerWinNtIsBootMgr(PUVM pUVM, PCVMMR3VTABLE pVMM, PCDBGFADDRESS pAddr,
     864                                    uint8_t const *pbHdrs, size_t cbHdrs, uint32_t *pcbImage)
     865{
     866    if (pcbImage)
     867        *pcbImage = 0;
     868
     869    /*
     870     * Check and skip the DOS header.
     871     */
     872    AssertReturn(sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS32) < cbHdrs, false);
     873    IMAGE_DOS_HEADER const * const pMzHdr = (IMAGE_DOS_HEADER const *)pbHdrs;
     874    if (   pMzHdr->e_magic  != IMAGE_DOS_SIGNATURE
     875        || pMzHdr->e_lfanew < 0x40
     876        || pMzHdr->e_lfanew > 0x400)
     877        return false;
     878
     879    /*
     880     * Check the NT headers.
     881     */
     882    AssertReturn(pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS32) <= cbHdrs, false);
     883    IMAGE_NT_HEADERS32 const * const pHdrs = (PCIMAGE_NT_HEADERS32)&pbHdrs[pMzHdr->e_lfanew];
     884    if (pHdrs->Signature != IMAGE_NT_SIGNATURE)
     885        return false;
     886    /* Not so many sections here, typically 3: */
     887    if (   pHdrs->FileHeader.NumberOfSections <= 1
     888        || pHdrs->FileHeader.NumberOfSections >= 6)
     889        return false;
     890    if (   pHdrs->FileHeader.Machine              != IMAGE_FILE_MACHINE_I386
     891        || pHdrs->FileHeader.SizeOfOptionalHeader != sizeof(pHdrs->OptionalHeader))
     892        return false;
     893    if (pHdrs->OptionalHeader.Magic               != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
     894        return false;
     895    if (pHdrs->OptionalHeader.NumberOfRvaAndSizes != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
     896        return false;
     897    /* Special subsystem with version 1.0: */
     898    /** @todo which subsystem type does pre win11 use?  (this is win11/amd64)  */
     899    if (pHdrs->OptionalHeader.Subsystem           != IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
     900        return false;
     901    if (   pHdrs->OptionalHeader.MajorSubsystemVersion != 1
     902        || pHdrs->OptionalHeader.MinorSubsystemVersion != 0)
     903        return false;
     904    /* Image OS version and windows version value are all zero: */
     905    if (   pHdrs->OptionalHeader.MajorOperatingSystemVersion != 0
     906        || pHdrs->OptionalHeader.MinorOperatingSystemVersion != 0
     907        || pHdrs->OptionalHeader.Win32VersionValue           != 0)
     908        return false;
     909    /* DLL image with 32-bit machine code: */
     910    if (   (pHdrs->FileHeader.Characteristics & (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_32BIT_MACHINE))
     911        !=                                      (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL | IMAGE_FILE_32BIT_MACHINE))
     912        return false;
     913    /* No imports: */
     914    if (   pHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0
     915        || pHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size    != 0)
     916        return false;
     917    /* Has a bunch of exports ('BootLib.dll'), for win11/amd64 it's 2630 bytes: */
     918    IMAGE_DATA_DIRECTORY const ExpRvaSize = pHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; /* cache for later */
     919    if (ExpRvaSize.Size < 1024)
     920        return false;
     921    if ((uint64_t)ExpRvaSize.VirtualAddress + ExpRvaSize.Size > pHdrs->OptionalHeader.SizeOfImage)
     922        return false;
     923    /* Check the image size is reasonable (win11/amd64 is 872448): */
     924    /** @todo adjust for older windows versions...  */
     925    if (   pHdrs->OptionalHeader.SizeOfImage < _64K
     926        || pHdrs->OptionalHeader.SizeOfImage > _4M)
     927        return false;
     928    /* The image base is 0x00400000 (relocations typically stripped): */
     929    if (pHdrs->OptionalHeader.ImageBase != UINT32_C(0x00400000))
     930        return false;
     931
     932    /*
     933     * Final check is that export directory name is 'BootLib.dll'.
     934     */
     935    static char const       s_szBootLibDll[] = "BootLib.dll";
     936    DBGFADDRESS             Addr2;
     937    IMAGE_EXPORT_DIRECTORY  ExpDir;
     938    int rc = pVMM->pfnDBGFR3MemRead(pUVM, 0,
     939                                    pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr2, pAddr->FlatPtr + ExpRvaSize.VirtualAddress),
     940                                    &ExpDir, sizeof(ExpDir));
     941    if (RT_FAILURE(rc))
     942        return false;
     943    /* There ought to be a few named exports here (win11 has 94): */
     944    if (ExpDir.NumberOfNames < 48 || ExpDir.NumberOfNames > _4K)
     945        return false;
     946
     947    if (   ExpDir.Name < pMzHdr->e_lfanew + pHdrs->OptionalHeader.SizeOfHeaders
     948        || (uint64_t)ExpDir.Name + sizeof(s_szBootLibDll) > pHdrs->OptionalHeader.SizeOfImage)
     949        return false;
     950
     951    char szActualName[sizeof(s_szBootLibDll)];
     952    rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr2, pAddr->FlatPtr + ExpDir.Name),
     953                                &szActualName, sizeof(szActualName));
     954    if (RT_FAILURE(rc))
     955        return false;
     956    if (szActualName[sizeof(s_szBootLibDll) - 1] != '\0')
     957        return false;
     958    if (RTStrICmpAscii(szActualName, s_szBootLibDll) != 0)
     959        return false;
     960
     961    if (pcbImage)
     962        *pcbImage = pHdrs->OptionalHeader.SizeOfImage;
     963    return true;
     964}
     965
     966
     967/**
     968 * Checks if the given headers are for the WinLoad.exe/efi image loaded very
     969 * early during the BIOS or EFI boot process.
     970 */
     971static bool dbgDiggerWinNtIsWinLoad(PUVM pUVM, PCVMMR3VTABLE pVMM, PCDBGFADDRESS pAddr, uint8_t const *pbHdrs, size_t cbHdrs,
     972                                    bool *pf32Bit, uint32_t *pcbImage, uint32_t *puNtMajorVersion, uint32_t *puNtMinorVersion)
     973{
     974    if (pf32Bit)
     975        *pf32Bit = false;
     976    if (pcbImage)
     977        *pcbImage = 0;
     978    if (puNtMajorVersion)
     979        *puNtMajorVersion = 0;
     980    if (puNtMinorVersion)
     981        *puNtMinorVersion = 0;
     982
     983    /*
     984     * Check and skip the DOS header.
     985     */
     986    AssertReturn(sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS64) < cbHdrs, false);
     987    IMAGE_DOS_HEADER const * const pMzHdr = (IMAGE_DOS_HEADER const *)pbHdrs;
     988    if (   pMzHdr->e_magic  != IMAGE_DOS_SIGNATURE
     989        || pMzHdr->e_lfanew < 0x40
     990        || pMzHdr->e_lfanew > 0x400)
     991        return false;
     992
     993    /*
     994     * Check the NT headers.
     995     *
     996     * ASSUMES that the 64-bit and 32-bit optional headers match up to
     997     * SizeOfStackReserve, if you exclude ImageBase and BaseOfData.
     998     */
     999    AssertReturn(pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) <= cbHdrs, false);
     1000    IMAGE_NT_HEADERS32 const * const pHdrs32 = (PCIMAGE_NT_HEADERS32)&pbHdrs[pMzHdr->e_lfanew];
     1001    IMAGE_NT_HEADERS64 const * const pHdrs64 = (PCIMAGE_NT_HEADERS64)&pbHdrs[pMzHdr->e_lfanew];
     1002    if (pHdrs32->Signature != IMAGE_NT_SIGNATURE)
     1003        return false;
     1004    /* There are a few extra sections here, but not too many: */
     1005    if (   pHdrs32->FileHeader.NumberOfSections <= 4
     1006        || pHdrs32->FileHeader.NumberOfSections >= 15)
     1007        return false;
     1008    bool f32Bit;
     1009    if (pHdrs32->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
     1010        f32Bit = true;
     1011    else if (pHdrs32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
     1012        f32Bit = false;
     1013    else
     1014        return false;
     1015    if (pHdrs32->FileHeader.SizeOfOptionalHeader != (f32Bit ? sizeof(IMAGE_OPTIONAL_HEADER32) : sizeof(IMAGE_OPTIONAL_HEADER64)))
     1016        return false;
     1017    if (pHdrs32->OptionalHeader.Magic            != (f32Bit ? IMAGE_NT_OPTIONAL_HDR32_MAGIC   : IMAGE_NT_OPTIONAL_HDR64_MAGIC))
     1018        return false;
     1019    /* Special subsystem with version 6.0 or later: */
     1020    /** @todo which subsystem type does pre win11 use?  (this is win11/amd64)  */
     1021    if (pHdrs32->OptionalHeader.Subsystem        != IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
     1022        return false;
     1023    if (pHdrs32->OptionalHeader.MajorSubsystemVersion < 6)
     1024        return false;
     1025    /* Image OS version and windows version value are all zero: */
     1026    if (   pHdrs32->OptionalHeader.MajorOperatingSystemVersion != 0
     1027        || pHdrs32->OptionalHeader.MinorOperatingSystemVersion != 0
     1028        || pHdrs32->OptionalHeader.Win32VersionValue           != 0)
     1029        return false;
     1030    /* DLL image: */
     1031    if (   (pHdrs32->FileHeader.Characteristics & (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))
     1032        !=                                        (IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DLL))
     1033        return false;
     1034    /* Check the image size is reasonable (win11/amd64 is 1769472 for BIOS and ~2MB for EFI): */
     1035    /** @todo adjust for older windows versions...  */
     1036    if (   pHdrs32->OptionalHeader.SizeOfImage < _1M
     1037        || pHdrs32->OptionalHeader.SizeOfImage > _8M)
     1038        return false;
     1039
     1040    /* The rest of the fields differs in placement between 32-bit and 64-bit. */
     1041
     1042    if (   (f32Bit ? pHdrs32->OptionalHeader.NumberOfRvaAndSizes : pHdrs64->OptionalHeader.NumberOfRvaAndSizes)
     1043        != IMAGE_NUMBEROF_DIRECTORY_ENTRIES)
     1044        return false;
     1045
     1046    /* No imports: */
     1047    IMAGE_DATA_DIRECTORY const * const paDataDirs = f32Bit
     1048                                                  ? pHdrs32->OptionalHeader.DataDirectory : pHdrs64->OptionalHeader.DataDirectory;
     1049    if (   paDataDirs[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0
     1050        || paDataDirs[IMAGE_DIRECTORY_ENTRY_IAT].Size    != 0)
     1051        return false;
     1052    /* Has a bunch of exports ('winload.sys'), for win11/amd64 it's 11734 bytes: */
     1053    IMAGE_DATA_DIRECTORY const ExpRvaSize = paDataDirs[IMAGE_DIRECTORY_ENTRY_EXPORT]; /* cache for later */
     1054    if (ExpRvaSize.Size < 1024)
     1055        return false;
     1056    if ((uint64_t)ExpRvaSize.VirtualAddress + ExpRvaSize.Size > pHdrs32->OptionalHeader.SizeOfImage)
     1057        return false;
     1058
     1059    /*
     1060     * Final check is that export directory name is 'winload.sys'.
     1061     */
     1062    static char const       s_szWinLoadSys[] = "winload.sys";
     1063    DBGFADDRESS             Addr2;
     1064    IMAGE_EXPORT_DIRECTORY  ExpDir;
     1065    int rc = pVMM->pfnDBGFR3MemRead(pUVM, 0,
     1066                                    pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr2, pAddr->FlatPtr + ExpRvaSize.VirtualAddress),
     1067                                    &ExpDir, sizeof(ExpDir));
     1068    if (RT_FAILURE(rc))
     1069        return false;
     1070    /* There ought to be a few named exports here (win11 has 373): */
     1071    if (ExpDir.NumberOfNames < 128 || ExpDir.NumberOfNames > _4K)
     1072        return false;
     1073
     1074    if (   ExpDir.Name < pMzHdr->e_lfanew + pHdrs32->OptionalHeader.SizeOfHeaders
     1075        || (uint64_t)ExpDir.Name + sizeof(s_szWinLoadSys) > pHdrs32->OptionalHeader.SizeOfImage)
     1076        return false;
     1077
     1078    char szActualName[sizeof(s_szWinLoadSys)];
     1079    rc = pVMM->pfnDBGFR3MemRead(pUVM, 0, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr2, pAddr->FlatPtr + ExpDir.Name),
     1080                                &szActualName, sizeof(szActualName));
     1081    if (RT_FAILURE(rc))
     1082        return false;
     1083    if (szActualName[sizeof(s_szWinLoadSys) - 1] != '\0')
     1084        return false;
     1085    if (RTStrICmpAscii(szActualName, s_szWinLoadSys) != 0)
     1086        return false;
     1087
     1088    if (pf32Bit)
     1089        *pf32Bit  = f32Bit;
     1090    if (pcbImage)
     1091        *pcbImage = pHdrs32->OptionalHeader.SizeOfImage;
     1092    /* Note! We could get more accurate version info from the resource section if we wanted to... */
     1093    if (puNtMajorVersion)
     1094        *puNtMajorVersion = pHdrs32->OptionalHeader.MajorSubsystemVersion;
     1095    if (puNtMinorVersion)
     1096        *puNtMinorVersion = pHdrs32->OptionalHeader.MinorSubsystemVersion;
     1097
     1098    return true;
     1099}
     1100
     1101
     1102/**
    8521103 * Process a PE image found in guest memory.
    8531104 *
     
    8591110 * @param   pImageAddr      The image address.
    8601111 * @param   cbImage         The size of the image.
     1112 * @param   enmArch         Module architecture override.  Default is determined
     1113 *                          by DBGDIGGERWINNT::f32Bit.
    8611114 */
    8621115static void dbgDiggerWinNtProcessImage(PDBGDIGGERWINNT pThis, PUVM pUVM, PCVMMR3VTABLE pVMM, const char *pszName,
    863                                        const char *pszFilename, PCDBGFADDRESS pImageAddr, uint32_t cbImage)
     1116                                       const char *pszFilename, PCDBGFADDRESS pImageAddr, uint32_t cbImage,
     1117                                       RTLDRARCH enmArch = RTLDRARCH_WHATEVER)
    8641118{
    8651119    LogFlow(("DigWinNt: %RGp %#x %s\n", pImageAddr->FlatPtr, cbImage, pszName));
     
    8781132     * Use the common in-memory module reader to create a debug module.
    8791133     */
     1134    if (enmArch == RTLDRARCH_WHATEVER)
     1135        enmArch = pThis->f32Bit ? RTLDRARCH_X86_32 : RTLDRARCH_AMD64;
    8801136    RTERRINFOSTATIC ErrInfo;
    8811137    RTDBGMOD        hDbgMod = NIL_RTDBGMOD;
    8821138    int rc = pVMM->pfnDBGFR3ModInMem(pUVM, pImageAddr, pThis->fNt31 ? DBGFMODINMEM_F_PE_NT31 : 0, pszName, pszFilename,
    883                                      pThis->f32Bit ? RTLDRARCH_X86_32 : RTLDRARCH_AMD64, cbImage,
    884                                      &hDbgMod, RTErrInfoInitStatic(&ErrInfo));
     1139                                     enmArch, cbImage, &hDbgMod, RTErrInfoInitStatic(&ErrInfo));
    8851140    if (RT_SUCCESS(rc))
    8861141    {
     
    13111566
    13121567    /*
    1313      * Figure the NT version.
     1568     * Load the bootmgr module if it was detected and is still present.
     1569     * The boot manager is always 32-bit on x86.
     1570     */
     1571    if (DBGFADDRESS_IS_VALID(&pThis->BootMgrAddr))
     1572    {
     1573        rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->BootMgrAddr, &u, sizeof(u));
     1574        if (RT_SUCCESS(rc))
     1575        {
     1576            uint32_t cbImage = 0;
     1577            if (dbgDiggerWinNtIsBootMgr(pUVM, pVMM, &pThis->BootMgrAddr, &u.au8[0], sizeof(u), &cbImage))
     1578                dbgDiggerWinNtProcessImage(pThis, pUVM, pVMM, "BootMgr", "BootMgr.exe",
     1579                                           &pThis->BootMgrAddr, cbImage, RTLDRARCH_X86_32);
     1580        }
     1581    }
     1582
     1583    /*
     1584     * Load the winload module if it was detected and still present.
     1585     */
     1586    if (DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1587    {
     1588        rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, &pThis->WinLoadAddr, &u, sizeof(u));
     1589        if (RT_SUCCESS(rc))
     1590        {
     1591            uint32_t cbImage         = 0;
     1592            uint32_t uNtMajorVersion = 0;
     1593            uint32_t uNtMinorVersion = 0;
     1594            if (dbgDiggerWinNtIsWinLoad(pUVM, pVMM, &pThis->WinLoadAddr, &u.au8[0], sizeof(u),
     1595                                        NULL /*pf32Bit*/, &cbImage, &uNtMajorVersion, &uNtMinorVersion))
     1596            {
     1597                dbgDiggerWinNtProcessImage(pThis, pUVM, pVMM, "WinLoad", "WinLoad.exe", &pThis->WinLoadAddr, cbImage);
     1598                pThis->NtMajorVersion = uNtMajorVersion;
     1599                pThis->NtMinorVersion = uNtMinorVersion;
     1600            }
     1601        }
     1602    }
     1603
     1604    /*
     1605     * Try figure the NT version.
    13141606     */
    13151607    pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pThis->f32Bit ? NTKUSERSHAREDDATA_WINNT32 : NTKUSERSHAREDDATA_WINNT64);
     
    13341626    {
    13351627        Log(("DigWinNt: Error reading KUSER_SHARED_DATA: %Rrc\n", rc));
    1336         return rc;
     1628        if (   !DBGFADDRESS_IS_VALID(&pThis->KernelAddr)
     1629            || !DBGFADDRESS_IS_VALID(&pThis->KernelMteAddr)
     1630            || !DBGFADDRESS_IS_VALID(&pThis->PsLoadedModuleListAddr))
     1631            return DBGFADDRESS_IS_VALID(&pThis->BootMgrAddr) || DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr) ? VINF_SUCCESS : rc;
    13371632    }
    13381633
     
    14461741{
    14471742    PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;
     1743    bool            fRet  = false;
    14481744    DBGFADDRESS     Addr;
    14491745    union
     
    14651761
    14661762    /*
     1763     * Reset the state (paranoia)
     1764     */
     1765    RT_ZERO(pThis->BootMgrAddr);
     1766    RT_ZERO(pThis->WinLoadAddr);
     1767    RT_ZERO(pThis->KernelAddr);
     1768    RT_ZERO(pThis->KernelMteAddr);
     1769    RT_ZERO(pThis->PsLoadedModuleListAddr);
     1770    pThis->f32Bit = false;
     1771    pThis->fNt31  = false;
     1772
     1773    /*
     1774     * Look for the BootMgr/BootLib.dll module at 0x400000.
     1775     * This is only relevant when booting via BIOS.
     1776     */
     1777    if (1/** @todo BIOS + x86/amd64 only */)
     1778    {
     1779        int rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/,
     1780                                        pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, UINT32_C(0x400000)),
     1781                                        &u.au8[0], sizeof(u));
     1782        if (RT_SUCCESS(rc) && dbgDiggerWinNtIsBootMgr(pUVM, pVMM, &Addr, &u.au8[0], sizeof(u), NULL))
     1783        {
     1784            pThis->BootMgrAddr = Addr;
     1785            fRet = true;
     1786        }
     1787    }
     1788
     1789    /*
     1790     * Look for the winload.exe/winload.sys module that's, from the looks of it,
     1791     * responsible for loading the kernel and boot drivers.
     1792     */
     1793    if (DBGFADDRESS_IS_VALID(&pThis->BootMgrAddr))
     1794    {
     1795        static const char s_szNeedle[] = "PAGER32C"; /* Section name. No terminator. */
     1796        uint32_t const    uEndAddr     = _16M + _1M;
     1797        pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, pThis->BootMgrAddr.FlatPtr + _64K);
     1798        do
     1799        {
     1800            int rc = pVMM->pfnDBGFR3MemScan(pUVM, 0 /*idCpu*/, &Addr, uEndAddr - Addr.FlatPtr,
     1801                                            8 /*uAlign*/, s_szNeedle, sizeof(s_szNeedle) - 1, &Addr);
     1802            if (RT_FAILURE(rc))
     1803                break;
     1804
     1805            DBGFADDRESS AddrMz;
     1806            rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/,
     1807                                        pVMM->pfnDBGFR3AddrFromFlat(pUVM, &AddrMz,
     1808                                                                    Addr.FlatPtr & ~(RTGCUINTPTR)GUEST_PAGE_OFFSET_MASK),
     1809                                        &u.au8[0], sizeof(u));
     1810            bool f32Bit = false;
     1811            if (RT_SUCCESS(rc) && dbgDiggerWinNtIsWinLoad(pUVM, pVMM, &AddrMz, &u.au8[0], sizeof(u), &f32Bit, NULL, NULL, NULL))
     1812            {
     1813                pThis->WinLoadAddr = AddrMz;
     1814                pThis->f32Bit      = f32Bit;
     1815                fRet = true;
     1816                break;
     1817            }
     1818            pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, AddrMz.FlatPtr + GUEST_PAGE_SIZE);
     1819        } while (Addr.FlatPtr + _64K < uEndAddr);
     1820    }
     1821
     1822    /*
    14671823     * NT only runs in protected or long mode.
    14681824     */
    14691825    CPUMMODE const enmMode = pVMM->pfnDBGFR3CpuGetMode(pUVM, 0 /*idCpu*/);
    14701826    if (enmMode != CPUMMODE_PROTECTED && enmMode != CPUMMODE_LONG)
    1471         return false;
    1472     bool const      f64Bit = enmMode == CPUMMODE_LONG;
    1473     uint64_t const  uStart = f64Bit ? UINT64_C(0xffff080000000000) : UINT32_C(0x80001000);
     1827        return fRet;
     1828    bool const      f64Bit = enmMode == CPUMMODE_LONG
     1829                          || (DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr) && !pThis->f32Bit);
     1830    uint64_t const  uStart = f64Bit ? UINT64_C(0xffff800000000000) : UINT32_C(0x80001000);
    14741831    uint64_t const  uEnd   = f64Bit ? UINT64_C(0xffffffffffff0000) : UINT32_C(0xffff0000);
    14751832
     
    14831840    uint16_t uIdtrLimit = 0;
    14841841    int rc = pVMM->pfnDBGFR3RegCpuQueryXdtr(pUVM, 0, DBGFREG_IDTR, &uIdtrBase, &uIdtrLimit);
    1485     AssertRCReturn(rc, false);
     1842    AssertRCReturn(rc, fRet);
    14861843
    14871844    const uint16_t cbMinIdtr = (X86_XCPT_PF + 1) * (f64Bit ? sizeof(X86DESC64GATE) : sizeof(X86DESCGATE));
    14881845    if (uIdtrLimit < cbMinIdtr)
    1489         return false;
     1846        return fRet;
    14901847
    14911848    rc = pVMM->pfnDBGFR3MemRead(pUVM, 0 /*idCpu*/, pVMM->pfnDBGFR3AddrFromFlat(pUVM, &Addr, uIdtrBase), &u, cbMinIdtr);
    14921849    if (RT_FAILURE(rc))
    1493         return false;
    1494 
    1495     uint64_t uKrnlStart;
    1496     uint64_t uKrnlEnd;
     1850        return fRet;
     1851
     1852    uint64_t uKrnlStart = uStart;
     1853    uint64_t uKrnlEnd   = uEnd;
    14971854    if (f64Bit)
    14981855    {
     
    15001857                          | ((uint32_t)u.a64Gates[X86_XCPT_PF].u16OffsetHigh << 16)
    15011858                          | ((uint64_t)u.a64Gates[X86_XCPT_PF].u32OffsetTop  << 32);
    1502         if (uHandler < uStart || uHandler > uEnd)
    1503             return false;
    1504         uKrnlStart = (uHandler & ~(uint64_t)_4M) - _512M;
    1505         uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
     1859        if (uHandler >= uStart && uHandler <= uEnd)
     1860        {
     1861            uKrnlStart = (uHandler & ~(uint64_t)_4M) - _512M;
     1862            uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
     1863        }
     1864        else if (!DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1865            return fRet;
    15061866    }
    15071867    else
    15081868    {
    15091869        uint32_t uHandler = RT_MAKE_U32(u.a32Gates[X86_XCPT_PF].u16OffsetLow, u.a32Gates[X86_XCPT_PF].u16OffsetHigh);
    1510         if (uHandler < uStart || uHandler > uEnd)
    1511             return false;
    1512         uKrnlStart = (uHandler & ~(uint64_t)_4M) - _64M;
    1513         uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
     1870        if (uHandler >= uStart && uHandler <= uEnd)
     1871        {
     1872            uKrnlStart = (uHandler & ~(uint64_t)_4M) - _64M;
     1873            uKrnlEnd   = (uHandler + (uint64_t)_4M) & ~(uint64_t)_4M;
     1874        }
     1875        else if (!DBGFADDRESS_IS_VALID(&pThis->WinLoadAddr))
     1876            return fRet;
    15141877    }
    15151878
     
    15321895                                    8, "PAGELK\0", sizeof("PAGELK\0"), &KernelAddr);
    15331896        if (   rc == VERR_DBGF_MEM_NOT_FOUND
    1534             && enmMode != CPUMMODE_LONG)
     1897            && !f64Bit)
    15351898        {
    15361899            /* NT3.1 didn't have a PAGELK section, so look for _TEXT instead.  The
     
    15521915            &&  u.MzHdr.e_lfanew <= 0x400) /* W8 is at 0x288*/
    15531916        {
    1554             if (enmMode != CPUMMODE_LONG)
     1917            if (!f64Bit)
    15551918            {
    15561919                IMAGE_NT_HEADERS32 const *pHdrs = (IMAGE_NT_HEADERS32 const *)&u.au8[u.MzHdr.e_lfanew];
     
    17272090        }
    17282091    }
    1729     return false;
     2092
     2093    return fRet;
    17302094}
    17312095
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