VirtualBox

Changeset 70338 in vbox for trunk/src/VBox/Debugger


Ignore:
Timestamp:
Dec 25, 2017 5:38:40 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
119938
Message:

DBGPlugInWinNt.cpp: Detect NT 3.1. NTMTE32.SizeOfImage is used differently, VirtualSize absent, no KUSER_SHARED_DATA. Not perfect yet.

File:
1 edited

Legend:

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

    r69500 r70338  
    5454    uint32_t        DllBase;
    5555    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.  */
    5658    uint32_t        SizeOfImage;
    5759    struct
     
    195197    /** 32-bit (true) or 64-bit (false) */
    196198    bool                f32Bit;
     199    /** Set if NT 3.1 was detected.
     200     * This implies both Misc.VirtualSize and NTMTE32::SizeOfImage are zero. */
     201    bool                fNt31;
    197202
    198203    /** The NT version. */
     
    394399 * @param   cShs                Number of headers.
    395400 * @param   cbImage             The image size reported by NT.
     401 * @param   cbImageFromHdr      The image size by the linker in the header.
    396402 * @param   uRvaRsrc            The RVA of the resource directory. UINT32_MAX if
    397403 *                              no resource directory.
    398404 * @param   cbSectAlign         The section alignment specified in the header.
     405 * @param   fNt31               Set if NT 3.1.  Needed for chopped off HAL.
    399406 * @param   pcbImageCorrect     The corrected image size.  This is derived from
    400407 *                              cbImage and virtual range of the section tables.
     
    406413 */
    407414static 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)
    409417{
    410418    *pcbImageCorrect = cbImage;
     
    421429            continue;
    422430
     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
    423452        /* Check that sizes are within the same range and that both sizes and
    424453           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 >= _1G
    427             || paShs[i].SizeOfRawData    >= _1G)
    428         {
    429             Log(("DigWinNt: Section header #%u has a VirtualSize=%#x and 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));
    431460            return false;
    432461        }
    433         uint32_t uRvaEnd = paShs[i].VirtualAddress + paShs[i].Misc.VirtualSize;
     462        uint32_t uRvaEnd = paShs[i].VirtualAddress + cbVirtual;
    434463        if (uRvaEnd >= _1G || uRvaEnd < paShs[i].VirtualAddress)
    435464        {
    436             Log(("DigWinNt: Section header #%u has a VirtualSize=%#x and 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));
    438467            return false;
    439468        }
     
    445474
    446475        /* Check that the section is within the image. */
    447         if (uRvaEnd > cbImage)
     476        if (uRvaEnd > cbImage && fNt31)
    448477        {
    449478            Log(("DigWinNt: Section header #%u has a virtual address range beyond the image: %#x TO %#x cbImage=%#x\n",
     
    496525    PCIMAGE_SECTION_HEADER paShs = (PCIMAGE_SECTION_HEADER)(pbBuf + offShs);
    497526    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))
    501530    {
    502531        pRdr->cMappings = 0;
     
    594623
    595624    /*
     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    /*
    596631     * Do some basic validation first.
    597632     * This is the usual exteremely verbose and messy code...
    598633     */
    599634    Assert(cbBuf >= sizeof(IMAGE_NT_HEADERS64));
    600     if (   cbImage < sizeof(IMAGE_NT_HEADERS64)
     635    if (   (cbImage < sizeof(IMAGE_NT_HEADERS64) && !pThis->fNt31)
    601636        || cbImage >= _1M * 256)
    602637    {
     
    614649        pHdrs   = (PCNTHDRS)pbBuf;
    615650    }
    616     else if (   pMzHdr->e_lfanew >= cbImage
     651    else if (   pMzHdr->e_lfanew >= cbImageValidate
    617652             || pMzHdr->e_lfanew < sizeof(*pMzHdr)
    618              || pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) > cbImage)
     653             || pMzHdr->e_lfanew + sizeof(IMAGE_NT_HEADERS64) > cbImageValidate)
    619654    {
    620655        Log(("DigWinNt: %s: PE header to far into image: %#x  cbImage=%#x\n", pszName, pMzHdr->e_lfanew, cbImage));
     
    664699    }
    665700    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))
    667704    {
    668705        Log(("DigWinNt: %s: Invalid OH.SizeOfImage: %#x, expected %#x\n", pszName, cbImageFromHdr, cbImage));
     
    822859    DBGFR3AddrFromFlat(pUVM, &Addr, pThis->f32Bit ? NTKUSERSHAREDDATA_WINNT32 : NTKUSERSHAREDDATA_WINNT64);
    823860    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));
    825878        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    }
    831880
    832881    /*
     
    862911            break;
    863912        }
    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) )
    867923        {
    868924            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)));
    870926            break;
    871927        }
     
    898954                DBGFADDRESS ImageAddr;
    899955                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));
    901957                rc = DBGFR3MemRead(pUVM, 0 /*idCpu*/, &ImageAddr, &u, cbImageBuf);
    902958                if (RT_SUCCESS(rc))
     
    905961                                               pszName,
    906962                                               &ImageAddr,
    907                                                WINNT_UNION(pThis, &Mte, SizeOfImage),
     963                                               cbImageMte,
    908964                                               &u.au8[0],
    909965                                               sizeof(u));
     
    9501006     * in the PsLoadedModuleList we can easily validate the list head and report
    9511007     * success.
     1008     *
     1009     * Note! We ASSUME the section name is 8 byte aligned.
    9521010     */
    9531011    CPUMMODE        enmMode = DBGFR3CpuGetMode(pUVM, 0 /*idCpu*/);
     
    9591017         KernelAddr.FlatPtr += PAGE_SIZE)
    9601018    {
     1019        bool fNt31 = false;
     1020        DBGFADDRESS const RetryAddress = KernelAddr;
    9611021        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        }
    9631032        if (RT_FAILURE(rc))
    9641033            break;
     
    9891058                    uMte.v32.DllBase     = KernelAddr.FlatPtr;
    9901059                    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. */
    9921061                    DBGFADDRESS HitAddr;
    9931062                    rc = DBGFR3MemScan(pUVM, 0 /*idCpu*/, &KernelAddr, uEnd - KernelAddr.FlatPtr,
     
    10321101                                    pThis->PsLoadedModuleListAddr   = Addr;
    10331102                                    pThis->f32Bit                   = true;
     1103                                    pThis->fNt31                    = fNt31;
    10341104                                    return true;
    10351105                                }
     
    11171187                                    pThis->PsLoadedModuleListAddr   = Addr;
    11181188                                    pThis->f32Bit                   = false;
     1189                                    pThis->fNt31                    = false;
    11191190                                    return true;
    11201191                                }
Note: See TracChangeset for help on using the changeset viewer.

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