VirtualBox

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


Ignore:
Timestamp:
Sep 13, 2020 8:26:41 AM (4 years ago)
Author:
vboxsync
Message:

Debugger/DBGPlugInWinNt: Implement the OS WinNT interface

File:
1 edited

Legend:

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

    r82968 r86103  
    222222    /** The address of PsLoadedModuleList. */
    223223    DBGFADDRESS         PsLoadedModuleListAddr;
     224
     225    /** Array of detected KPCR addresses for each vCPU. */
     226    PDBGFADDRESS        paKpcrAddr;
     227    /** Array of detected KPCRB addresses for each vCPU. */
     228    PDBGFADDRESS        paKpcrbAddr;
     229
     230    /** The Windows NT specifics interface. */
     231    DBGFOSIWINNT        IWinNt;
    224232} DBGDIGGERWINNT;
    225233/** Pointer to the linux guest OS digger instance data. */
     
    299307
    300308/**
     309 * Tries to resolve the KPCR and KPCRB addresses for each vCPU.
     310 *
     311 * @returns nothing.
     312 * @param   pThis           The instance data.
     313 * @param   pUVM            The user mode VM handle.
     314 */
     315static void dbgDiggerWinNtResolveKpcr(PDBGDIGGERWINNT pThis, PUVM pUVM)
     316{
     317    if (pThis->f32Bit)
     318    { /** @todo */ }
     319    else
     320    {
     321        /*
     322         * Getting at the KPCR and KPCRB is explained here:
     323         *     https://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kprcb/amd64.htm
     324         * Together with the available offsets from:
     325         *     https://github.com/tpn/winsdk-10/blob/master/Include/10.0.16299.0/shared/ksamd64.inc#L883
     326         * we can verify that the found addresses are valid by cross checking that the GDTR and self reference
     327         * match what we expect.
     328         */
     329        VMCPUID cCpus = DBGFR3CpuGetCount(pUVM);
     330        pThis->paKpcrAddr = (PDBGFADDRESS)RTMemAllocZ(cCpus * 2 * sizeof(DBGFADDRESS));
     331        if (RT_LIKELY(pThis->paKpcrAddr))
     332        {
     333            pThis->paKpcrbAddr = &pThis->paKpcrAddr[cCpus];
     334
     335            /* Work each CPU, unexpected values in each CPU make the whole thing fail to play safe. */
     336            int rc = VINF_SUCCESS;
     337            for (VMCPUID idCpu = 0; (idCpu < cCpus) && RT_SUCCESS(rc); idCpu++)
     338            {
     339                PDBGFADDRESS pKpcrAddr = &pThis->paKpcrAddr[idCpu];
     340                PDBGFADDRESS pKpcrbAddr = &pThis->paKpcrbAddr[idCpu];
     341
     342                /* Read GS base which points to the base of the KPCR for each CPU. */
     343                RTGCUINTPTR GCPtrTmp = 0;
     344                rc = DBGFR3RegCpuQueryU64(pUVM, idCpu, DBGFREG_GS_BASE, &GCPtrTmp);
     345                if (RT_SUCCESS(rc))
     346                {
     347                    LogFlow(("DigWinNt/KPCR[%u]: GS Base %RGv\n", GCPtrTmp));
     348                    DBGFR3AddrFromFlat(pUVM, pKpcrAddr, GCPtrTmp);
     349
     350                    rc = DBGFR3RegCpuQueryU64(pUVM, idCpu, DBGFREG_GDTR_BASE, &GCPtrTmp);
     351                    if (RT_SUCCESS(rc))
     352                    {
     353                        /*
     354                         * Read the start of the KPCR (@todo Probably move this to a global header)
     355                         * and verify its content.
     356                         */
     357                        struct
     358                        {
     359                            RTGCUINTPTR GCPtrGdt;
     360                            RTGCUINTPTR GCPtrTss;
     361                            RTGCUINTPTR GCPtrUserRsp;
     362                            RTGCUINTPTR GCPtrSelf;
     363                            RTGCUINTPTR GCPtrCurrentPrcb;
     364                        } Kpcr;
     365
     366                        rc = DBGFR3MemRead(pUVM, idCpu, pKpcrAddr, &Kpcr, sizeof(Kpcr));
     367                        if (RT_SUCCESS(rc))
     368                        {
     369                            if (   Kpcr.GCPtrGdt == GCPtrTmp
     370                                && Kpcr.GCPtrSelf == pKpcrAddr->FlatPtr
     371                                /** @todo && TSS */ )
     372                            {
     373                                DBGFR3AddrFromFlat(pUVM, pKpcrbAddr, Kpcr.GCPtrCurrentPrcb);
     374                                LogRel(("DigWinNt/KPCR[%u]: KPCR=%RGv KPCRB=%RGv\n", idCpu, pKpcrAddr->FlatPtr, pKpcrbAddr->FlatPtr));
     375                            }
     376                            else
     377                                LogRel(("DigWinNt/KPCR[%u]: KPCR validation error GDT=(%RGv vs %RGv) KPCRB=(%RGv vs %RGv)\n", idCpu,
     378                                        Kpcr.GCPtrGdt, GCPtrTmp, Kpcr.GCPtrSelf, pKpcrAddr->FlatPtr));
     379                        }
     380                        else
     381                            LogRel(("DigWinNt/KPCR[%u]: Reading KPCR start at %RGv failed with %Rrc\n", idCpu, pKpcrAddr->FlatPtr, rc));
     382                    }
     383                    else
     384                        LogRel(("DigWinNt/KPCR[%u]: Getting GDT base register failed with %Rrc\n", idCpu, rc));
     385                }
     386                else
     387                    LogRel(("DigWinNt/KPCR[%u]: Getting GS base register failed with %Rrc\n", idCpu, rc));
     388            }
     389
     390            if (RT_FAILURE(rc))
     391            {
     392                LogRel(("DigWinNt/KPCR: Failed to detmine KPCR and KPCRB\n", rc));
     393                RTMemFree(pThis->paKpcrAddr);
     394                pThis->paKpcrAddr  = NULL;
     395                pThis->paKpcrbAddr = NULL;
     396            }
     397        }
     398        else
     399            LogRel(("DigWinNt/KPCR: Failed to allocate %u entries for the KPCR/KPCRB addresses\n", cCpus * 2));
     400    }
     401}
     402
     403
     404/**
    301405 * Process a PE image found in guest memory.
    302406 *
     
    399503    pszName[off] = '\0';
    400504    return pszName;
     505}
     506
     507
     508/**
     509 * @interface_method_impl{DBGFOSIWINNT,pfnQueryVersion}
     510 */
     511static DECLCALLBACK(int) dbgDiggerWinNtIWinNt_QueryVersion(struct DBGFOSIWINNT *pThis, PUVM pUVM,
     512                                                           uint32_t *puVersMajor, uint32_t *puVersMinor)
     513{
     514    RT_NOREF(pUVM);
     515    PDBGDIGGERWINNT pData = RT_FROM_MEMBER(pThis, DBGDIGGERWINNT, IWinNt);
     516
     517    *puVersMajor = pData->NtMajorVersion;
     518    *puVersMinor = pData->NtMinorVersion;
     519    return VINF_SUCCESS;
     520}
     521
     522
     523/**
     524 * @interface_method_impl{DBGFOSIWINNT,pfnQueryVersion}
     525 */
     526static DECLCALLBACK(int) dbgDiggerWinNtIWinNt_QueryKernelPtrs(struct DBGFOSIWINNT *pThis, PUVM pUVM,
     527                                                              PRTGCUINTPTR pGCPtrKernBase, PRTGCUINTPTR pGCPtrPsLoadedModuleList)
     528{
     529    RT_NOREF(pUVM);
     530    PDBGDIGGERWINNT pData = RT_FROM_MEMBER(pThis, DBGDIGGERWINNT, IWinNt);
     531
     532    *pGCPtrKernBase           = pData->KernelAddr.FlatPtr;
     533    *pGCPtrPsLoadedModuleList = pData->PsLoadedModuleListAddr.FlatPtr;
     534    return VINF_SUCCESS;
     535}
     536
     537
     538/**
     539 * @interface_method_impl{DBGFOSIWINNT,pfnQueryKpcrForVCpu}
     540 */
     541static DECLCALLBACK(int) dbgDiggerWinNtIWinNt_QueryKpcrForVCpu(struct DBGFOSIWINNT *pThis, PUVM pUVM, VMCPUID idCpu,
     542                                                               PRTGCUINTPTR pKpcr, PRTGCUINTPTR pKpcrb)
     543{
     544    PDBGDIGGERWINNT pData = RT_FROM_MEMBER(pThis, DBGDIGGERWINNT, IWinNt);
     545
     546    if (!pData->paKpcrAddr)
     547        return VERR_NOT_SUPPORTED;
     548
     549    AssertReturn(idCpu < DBGFR3CpuGetCount(pUVM), VERR_INVALID_PARAMETER);
     550
     551    if (pKpcr)
     552        *pKpcr = pData->paKpcrAddr[idCpu].FlatPtr;
     553    if (pKpcrb)
     554        *pKpcrb = pData->paKpcrbAddr[idCpu].FlatPtr;
     555    return VINF_SUCCESS;
     556}
     557
     558
     559/**
     560 * @interface_method_impl{DBGFOSIWINNT,pfnQueryCurThrdForVCpu}
     561 */
     562static DECLCALLBACK(int) dbgDiggerWinNtIWinNt_QueryCurThrdForVCpu(struct DBGFOSIWINNT *pThis, PUVM pUVM, VMCPUID idCpu,
     563                                                                  PRTGCUINTPTR pCurThrd)
     564{
     565    PDBGDIGGERWINNT pData = RT_FROM_MEMBER(pThis, DBGDIGGERWINNT, IWinNt);
     566
     567    if (!pData->paKpcrAddr)
     568        return VERR_NOT_SUPPORTED;
     569
     570    AssertReturn(idCpu < DBGFR3CpuGetCount(pUVM), VERR_INVALID_PARAMETER);
     571
     572    DBGFADDRESS AddrCurThrdPtr = pData->paKpcrbAddr[idCpu];
     573    DBGFR3AddrAdd(&AddrCurThrdPtr, 0x08); /** @todo Make this prettier. */
     574    return DBGFR3MemRead(pUVM, idCpu, &AddrCurThrdPtr, pCurThrd, sizeof(*pCurThrd));
    401575}
    402576
     
    546720static DECLCALLBACK(void *) dbgDiggerWinNtQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf)
    547721{
    548     RT_NOREF3(pUVM, pvData, enmIf);
    549     return NULL;
     722    RT_NOREF(pUVM);
     723    PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;
     724
     725    switch (enmIf)
     726    {
     727        case DBGFOSINTERFACE_WINNT:
     728            return &pThis->IWinNt;
     729        default:
     730            return NULL;
     731    }
    550732}
    551733
     
    605787        RTDbgAsRelease(hDbgAs);
    606788    }
     789
     790    if (pThis->paKpcrAddr)
     791        RTMemFree(pThis->paKpcrAddr);
     792    /* pThis->paKpcrbAddr comes from the same allocation as pThis->paKpcrAddr. */
     793
     794    pThis->paKpcrAddr  = NULL;
     795    pThis->paKpcrbAddr = NULL;
    607796
    608797    pThis->fValid = false;
     
    759948    } while (   Addr.FlatPtr != pThis->KernelMteAddr.FlatPtr
    760949             && Addr.FlatPtr != pThis->PsLoadedModuleListAddr.FlatPtr);
     950
     951    /* Try resolving the KPCR and KPCRB addresses for each vCPU. */
     952    dbgDiggerWinNtResolveKpcr(pThis, pUVM);
    761953
    762954    pThis->fValid = true;
     
    10661258    RT_NOREF1(pUVM);
    10671259    PDBGDIGGERWINNT pThis = (PDBGDIGGERWINNT)pvData;
    1068     pThis->fValid = false;
    1069     pThis->f32Bit = false;
    1070     pThis->enmVer = DBGDIGGERWINNTVER_UNKNOWN;
     1260    pThis->fValid      = false;
     1261    pThis->f32Bit      = false;
     1262    pThis->enmVer      = DBGDIGGERWINNTVER_UNKNOWN;
     1263
     1264    pThis->IWinNt.u32Magic               = DBGFOSIWINNT_MAGIC;
     1265    pThis->IWinNt.pfnQueryVersion        = dbgDiggerWinNtIWinNt_QueryVersion;
     1266    pThis->IWinNt.pfnQueryKernelPtrs     = dbgDiggerWinNtIWinNt_QueryKernelPtrs;
     1267    pThis->IWinNt.pfnQueryKpcrForVCpu    = dbgDiggerWinNtIWinNt_QueryKpcrForVCpu;
     1268    pThis->IWinNt.pfnQueryCurThrdForVCpu = dbgDiggerWinNtIWinNt_QueryCurThrdForVCpu;
     1269    pThis->IWinNt.u32EndMagic            = DBGFOSIWINNT_MAGIC;
     1270
    10711271    return VINF_SUCCESS;
    10721272}
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