VirtualBox

Ignore:
Timestamp:
Dec 11, 2009 2:17:04 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55914
Message:

SUPDrv-win.cpp/supdrvOSLdrLoad: Ignore mistmatching OriginalFirstThunk tables (import / windows 2003 sp2 (x86)).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp

    r25308 r25331  
    3535#include "../SUPDrvInternal.h"
    3636#include <excpt.h>
     37#include <ntimage.h>
     38
    3739#include <iprt/assert.h>
    3840#include <iprt/initterm.h>
     
    732734
    733735
    734 int  VBOXCALL   supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits)
    735 {
    736     NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits);
    737     if (pImage->pvNtSectionObj)
    738     {
    739         if (!memcmp(pImage->pvImage, pbImageBits, pImage->cbImageBits))
    740             return VINF_SUCCESS;
    741 
    742         /* trac down the difference and log it. */
    743         uint32_t        cbLeft = pImage->cbImageBits;
     736/**
     737 * memcmp + log.
     738 * 
     739 * @returns Same as memcmp.
     740 * @param   pImage          The image.
     741 * @param   pbImageBits     The image bits ring-3 uploads.
     742 * @param   uRva            The RVA to start comparing at.
     743 * @param   cb              The number of bytes to compare.
     744 */
     745static int supdrvNtCompare(PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, uint32_t uRva, uint32_t cb)
     746{
     747    int iDiff = memcmp((uint8_t const *)pImage->pvImage + uRva, pbImageBits + uRva, cb);
     748    if (iDiff)
     749    {
     750        uint32_t        cbLeft = cb;
    744751        const uint8_t  *pbNativeBits = (const uint8_t *)pImage->pvImage;
    745         for (size_t off = 0; cbLeft > 0; off++, cbLeft--)
     752        for (size_t off = uRva; cbLeft > 0; off++, cbLeft--)
    746753            if (pbNativeBits[off] != pbImageBits[off])
    747754            {
     
    751758                            RT_MIN(12, cbLeft), &pbImageBits[off]);
    752759                SUPR0Printf("VBoxDrv: Mismatch at %#x of %s: %s\n", off, pImage->szName, szBytes);
    753                 return VERR_LDR_MISMATCH_NATIVE;
    754             }
     760                break;
     761            }
     762    }
     763    return iDiff;
     764}
     765
     766int  VBOXCALL   supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits)
     767{
     768    NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits);
     769    if (pImage->pvNtSectionObj)
     770    {
     771        /*
     772         * Usually, the entire image matches exactly.
     773         */
     774        if (!memcmp(pImage->pvImage, pbImageBits, pImage->cbImageBits))
     775            return VINF_SUCCESS;
     776
     777        /*
     778         * However, on Windows Server 2003 (sp2 x86) both import thunk tables
     779         * are fixed up and we typically get a mismatch in the INIT section.
     780         *
     781         * So, lets see if everything matches when excluding the
     782         * OriginalFirstThunk tables.  To make life simpler, set the max number
     783         * of imports to 16 and just record and sort the locations that needs
     784         * to be excluded from the comparison.
     785         */
     786        IMAGE_NT_HEADERS const *pNtHdrs;
     787        pNtHdrs = (IMAGE_NT_HEADERS const *)(pbImageBits
     788                                             + (  *(uint16_t *)pbImageBits == IMAGE_DOS_SIGNATURE
     789                                                ? ((IMAGE_DOS_HEADER const *)pbImageBits)->e_lfanew
     790                                                : 0));
     791        if (    pNtHdrs->Signature == IMAGE_NT_SIGNATURE
     792            &&  pNtHdrs->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR_MAGIC
     793            &&  pNtHdrs->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_IMPORT
     794            &&  pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size >= sizeof(IMAGE_IMPORT_DESCRIPTOR)
     795            &&  pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress > sizeof(IMAGE_NT_HEADERS)
     796            &&  pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress < pImage->cbImageBits
     797            )
     798        {
     799            struct MyRegion
     800            {
     801                uint32_t uRva;
     802                uint32_t cb;
     803            }           aExcludeRgns[16];
     804            unsigned    cExcludeRgns = 0;
     805            uint32_t    cImpsLeft    = pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
     806                                     / sizeof(IMAGE_IMPORT_DESCRIPTOR);
     807            IMAGE_IMPORT_DESCRIPTOR const *pImp;
     808            pImp = (IMAGE_IMPORT_DESCRIPTOR const *)(pbImageBits
     809                                                     + pNtHdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
     810            while (   cImpsLeft-- > 0
     811                   && cExcludeRgns < RT_ELEMENTS(aExcludeRgns))
     812            {
     813                uint32_t uRvaThunk = pImp->OriginalFirstThunk;
     814                if (    uRvaThunk >  sizeof(IMAGE_NT_HEADERS)
     815                    &&  uRvaThunk <= pImage->cbImageBits - sizeof(IMAGE_THUNK_DATA)
     816                    &&  uRvaThunk != pImp->FirstThunk)
     817                {
     818                    /* Find the size of the thunk table. */
     819                    IMAGE_THUNK_DATA const *paThunk    = (IMAGE_THUNK_DATA const *)(pbImageBits + uRvaThunk);
     820                    uint32_t                cMaxThunks = (pImage->cbImageBits - uRvaThunk) / sizeof(IMAGE_THUNK_DATA);
     821                    uint32_t                cThunks    = 0;
     822                    while (cThunks < cMaxThunks && paThunk[cThunks].u1.Function != 0)
     823                        cThunks++;
     824
     825                    /* Ordered table insert. */
     826                    unsigned i = 0;
     827                    for (; i < cExcludeRgns; i++)
     828                        if (uRvaThunk < aExcludeRgns[i].uRva)
     829                            break;
     830                    if (i != cExcludeRgns)
     831                        memmove(&aExcludeRgns[i + 1], &aExcludeRgns[i], (cExcludeRgns - i) * sizeof(aExcludeRgns[0]));
     832                    aExcludeRgns[i].uRva = uRvaThunk;
     833                    aExcludeRgns[i].cb   = cThunks * sizeof(IMAGE_THUNK_DATA);
     834                    cExcludeRgns++;
     835                }
     836
     837                /* advance */
     838                pImp++;
     839            }
     840
     841            /*
     842             * Ok, do the comparison.
     843             */
     844            int         iDiff    = 0;
     845            uint32_t    uRvaNext = 0;
     846            for (unsigned i = 0; !iDiff && i < cExcludeRgns; i++)
     847            {
     848                if (uRvaNext < aExcludeRgns[i].uRva)
     849                    iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, aExcludeRgns[i].uRva - uRvaNext);
     850                uRvaNext = aExcludeRgns[i].uRva + aExcludeRgns[i].cb;
     851            }
     852            if (!iDiff && uRvaNext < pImage->cbImageBits)
     853                iDiff = supdrvNtCompare(pImage, pbImageBits, uRvaNext, pImage->cbImageBits - uRvaNext);
     854            if (!iDiff)
     855                return VINF_SUCCESS;
     856        }
     857        else
     858            supdrvNtCompare(pImage, pbImageBits, 0, pImage->cbImageBits);
     859        return VERR_LDR_MISMATCH_NATIVE;
    755860    }
    756861    return VERR_INTERNAL_ERROR_4;
     
    768873        }
    769874
    770         NTSTATUS rc = ZwSetSystemInformation(MY_SystemUnloadGdiDriverInformation,
    771                                              &pImage->pvNtSectionObj, sizeof(pImage->pvNtSectionObj));
     875        NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemUnloadGdiDriverInformation,
     876                                               &pImage->pvNtSectionObj, sizeof(pImage->pvNtSectionObj));
     877        if (rcNt != STATUS_SUCCESS)
     878            SUPR0Printf("VBoxDrv: failed to unload '%s', rcNt=%#x\n", pImage->szName, rcNt);
    772879        pImage->pvNtSectionObj = NULL;
    773880    }
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