Changeset 86103 in vbox for trunk/src/VBox/Debugger
- Timestamp:
- Sep 13, 2020 8:26:41 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Debugger/DBGPlugInWinNt.cpp
r82968 r86103 222 222 /** The address of PsLoadedModuleList. */ 223 223 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; 224 232 } DBGDIGGERWINNT; 225 233 /** Pointer to the linux guest OS digger instance data. */ … … 299 307 300 308 /** 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 */ 315 static 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 /** 301 405 * Process a PE image found in guest memory. 302 406 * … … 399 503 pszName[off] = '\0'; 400 504 return pszName; 505 } 506 507 508 /** 509 * @interface_method_impl{DBGFOSIWINNT,pfnQueryVersion} 510 */ 511 static 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 */ 526 static 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 */ 541 static 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 */ 562 static 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)); 401 575 } 402 576 … … 546 720 static DECLCALLBACK(void *) dbgDiggerWinNtQueryInterface(PUVM pUVM, void *pvData, DBGFOSINTERFACE enmIf) 547 721 { 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 } 550 732 } 551 733 … … 605 787 RTDbgAsRelease(hDbgAs); 606 788 } 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; 607 796 608 797 pThis->fValid = false; … … 759 948 } while ( Addr.FlatPtr != pThis->KernelMteAddr.FlatPtr 760 949 && Addr.FlatPtr != pThis->PsLoadedModuleListAddr.FlatPtr); 950 951 /* Try resolving the KPCR and KPCRB addresses for each vCPU. */ 952 dbgDiggerWinNtResolveKpcr(pThis, pUVM); 761 953 762 954 pThis->fValid = true; … … 1066 1258 RT_NOREF1(pUVM); 1067 1259 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 1071 1271 return VINF_SUCCESS; 1072 1272 }
Note:
See TracChangeset
for help on using the changeset viewer.