public VirtualToPhysical ( |
||
eptp | ||
aCR3 | ||
Addr | long | |
Résultat |
/// <summary> /// /// </summary> /// <param name="Start"></param> /// <param name="Stop">We just truncate VA's at 48 bit's</param> /// <returns>count of new detections since last Run</returns> public long Run(long Start = 0, long Stop = 0xFFFFffffFFFF) { DetectedFragments = new ConcurrentDictionary <long, VAScanType>(); // convert index to an address // then add start to it long i = Start; var block = new long[0x200]; // 0x200 * 8 = 4k while (i < Stop) { foreach (var scanner in CheckMethods) { HARDWARE_ADDRESS_ENTRY locPhys = HARDWARE_ADDRESS_ENTRY.MinAddr; if (DPContext.vmcs != null) { //locPhys = MemoryBank[j].VirtualToPhysical(DPContext.vmcs.EPTP, DPContext.CR3Value, i); locPhys = BackingBlocks.VirtualToPhysical(DPContext.vmcs.EPTP, DPContext.CR3Value, i); } else { //locPhys = MemoryBank[j].VirtualToPhysical(DPContext.CR3Value, i); locPhys = BackingBlocks.VirtualToPhysical(DPContext.CR3Value, i); } var Curr = i; i += 0x1000; if (HARDWARE_ADDRESS_ENTRY.IsBadEntry(locPhys)) { continue; } bool GotData = false; BackingBlocks.GetPageForPhysAddr(locPhys, ref block, ref GotData, false); if (!GotData) { continue; } var scan_detect = scanner(Curr, block); if (scan_detect != VAScanType.UNDETERMINED) { DetectedFragments.TryAdd(Curr, scan_detect); if (Vtero.VerboseOutput) { Console.WriteLine($"Detected PE @ VA {Curr:X}"); } } } } return(DetectedFragments.Count()); }
public override long Seek(long offset, SeekOrigin origin) { HARDWARE_ADDRESS_ENTRY PhysAddr = HARDWARE_ADDRESS_ENTRY.MaxAddr; long DestAddr = long.MaxValue; switch (origin) { default: case SeekOrigin.Begin: DestAddr = offset; break; case SeekOrigin.End: DestAddr = Length - offset; break; case SeekOrigin.Current: DestAddr = position; DestAddr += offset; break; } PhysAddr = MemBlockStorage.VirtualToPhysical(Proc.vmcs.EPTP, Proc.CR3Value, DestAddr); if (PhysAddr == HARDWARE_ADDRESS_ENTRY.MinAddr || PhysAddr == HARDWARE_ADDRESS_ENTRY.MaxAddr || PhysAddr == HARDWARE_ADDRESS_ENTRY.MaxAddr - 1) { throw new PageNotFoundException($"unable to locate the physical page for the supplied virtual address {DestAddr}", PhysAddr, null, null); } position = DestAddr; CurrPage = PhysAddr; return(DestAddr); }
/// <summary> /// An Inline extraction for the page table hierarchy. /// Why not let the compiler do it? I have code clones here? /// /// I guess so, but we can see/deal with the subtle differences at each level here as we implement them. /// e.g. some levels have LargePage bits and we may also lay over other CPU modes here like 32 in 64 etc.. /// </summary> /// <param name="top"></param> /// <param name="Level"></param> /// <returns></returns> long InlineExtract(PFN top, int Level) { if (Level == 0) { return(0); } var entries = 0L; var VA = new VIRTUAL_ADDRESS(top.VA); //WriteLine($"4: Scanning {top.PageTable:X16}"); var hPA = HARDWARE_ADDRESS_ENTRY.MinAddr; var SLAT = top.SLAT; var CR3 = top.PageTable; // pull level 4 entries attach level 3 foreach (var top_sub in top.SubTables) { // scan each page for the level 4 entry var PTE = top_sub.Value.PTE; // we don't need to | in the PML4 AO (address offset) since were pulling down the whole page not just the one value // and were going to brute force our way through the entire table so this was just confusing things. var l3HW_Addr = PTE.NextTableAddress; // | top_sub.Key.PML4; // if we have an EPTP use it and request resolution of the HW_Addr if (SLAT != 0) { var hl3HW_Addr = HARDWARE_ADDRESS_ENTRY.MaxAddr; try { hl3HW_Addr = mem.VirtualToPhysical(SLAT, l3HW_Addr); } catch (Exception) { if (Vtero.DiagOutput) { WriteLine($"level3: Failed lookup {l3HW_Addr:X16}"); } } l3HW_Addr = hl3HW_Addr; } if (SLAT != 0 && (l3HW_Addr == long.MaxValue || l3HW_Addr == long.MaxValue - 1)) { continue; } // copy VA since were going to be making changes var s3va = new VIRTUAL_ADDRESS(top_sub.Key.Address); //WriteLine($"3: Scanning {s3va.Address:X16}"); top_sub.Value.hostPTE = l3HW_Addr; // cache translated value var lvl3_page = new long[512]; // extract the l3 page for each PTEEntry we had in l4 try { mem.GetPageForPhysAddr(l3HW_Addr, ref lvl3_page); } catch (Exception) { if (Vtero.DiagOutput) { WriteLine($"level3: Failed lookup {l3HW_Addr:X16}"); } } if (lvl3_page == null) { continue; } for (uint i3 = 0; i3 < 512; i3++) { if (lvl3_page[i3] == 0) { continue; } var l3PTE = new HARDWARE_ADDRESS_ENTRY(lvl3_page[i3]); // adjust VA to match extracted page entries s3va.DirectoryPointerOffset = i3; // save 'PFN' entry into sub-table I should really revisit all these names var l3PFN = new PFN(l3PTE, s3va.Address, CR3, SLAT); top_sub.Value.SubTables.Add(s3va, l3PFN); entries++; /// TODO: Double check if this is a real bit... /// I added it to help weed out some failure cases if (!l3PTE.LargePage) { // get the page that the current l3PFN describes var l2HW_Addr = l3PTE.NextTableAddress; if (SLAT != 0) { var hl2HW_Addr = HARDWARE_ADDRESS_ENTRY.MaxAddr; try { hl2HW_Addr = mem.VirtualToPhysical(SLAT, l2HW_Addr); } catch (Exception ex) { if (Vtero.DiagOutput) { WriteLine($"level2: Unable to V2P {l3PTE}"); } } l2HW_Addr = hl2HW_Addr; } // TODO: more error handling of exceptions & bad returns // TODO: support software PTE types if (l2HW_Addr == HARDWARE_ADDRESS_ENTRY.MaxAddr) { continue; } l3PFN.hostPTE = l2HW_Addr; var lvl2_page = new long[512]; try { mem.GetPageForPhysAddr(l2HW_Addr, ref lvl2_page); } catch (Exception ex) { if (Vtero.DiagOutput) { WriteLine($"level2: Failed lookup {l2HW_Addr:X16}"); } } if (lvl2_page == null) { continue; } // copy VA var s2va = new VIRTUAL_ADDRESS(s3va.Address); //WriteLine($"2: Scanning {s2va.Address:X16}"); // extract PTE's for each set entry for (uint i2 = 0; i2 < 512; i2++) { if (lvl2_page[i2] == 0) { continue; } var l2PTE = new HARDWARE_ADDRESS_ENTRY(lvl2_page[i2]); s2va.DirectoryOffset = i2; var l2PFN = new PFN(l2PTE, s2va.Address, CR3, SLAT) { Type = PFNType.Data }; l3PFN.SubTables.Add(s2va, l2PFN); entries++; if (!l2PTE.LargePage) { var l1HW_Addr = l2PTE.NextTableAddress; if (SLAT != 0) { var hl1HW_Addr = HARDWARE_ADDRESS_ENTRY.MaxAddr; try { hl1HW_Addr = mem.VirtualToPhysical(SLAT, l1HW_Addr); } catch (Exception ex) { if (Vtero.DiagOutput) { WriteLine($"level1: Unable to V2P {l2PTE}"); } } l1HW_Addr = hl1HW_Addr; } if (l1HW_Addr == HARDWARE_ADDRESS_ENTRY.MaxAddr) { continue; } l2PFN.hostPTE = l1HW_Addr; var lvl1_page = new long[512]; try { mem.GetPageForPhysAddr(l1HW_Addr, ref lvl1_page); } catch (Exception ex) { if (Vtero.DiagOutput) { WriteLine($"level1: Failed lookup {l1HW_Addr:X16}"); } } if (lvl1_page == null) { continue; } var s1va = new VIRTUAL_ADDRESS(s2va.Address); //WriteLine($"1: Scanning {s1va.Address:X16}"); for (uint i1 = 0; i1 < 512; i1++) { if (lvl1_page[i1] == 0) { continue; } var l1PTE = new HARDWARE_ADDRESS_ENTRY(lvl1_page[i1]); s1va.TableOffset = i1; var l1PFN = new PFN(l1PTE, s1va.Address, CR3, SLAT) { Type = PFNType.Data }; l2PFN.SubTables.Add(s1va, l1PFN); entries++; } } } } } } //top.PFNCount += entries; return(entries); }