/// <summary> /// Scan and return Extract objects which represent detected PE's /// </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 Dictionary <long, Extract> Run(long Start = 0, long Stop = 0xFFFFffffFFFF, ParallelLoopState pState = null, Mem Instance = null) { var memAxss = Instance == null ? BackingBlocks : Instance; var rv = new Dictionary <long, Extract>(); // convert index to an address // then add start to it long i = Start; var block = new long[0x200]; // 0x200 * 8 = 4k while (i < Stop) { if (pState != null && pState.IsStopped) { return(rv); } HARDWARE_ADDRESS_ENTRY locPhys = HARDWARE_ADDRESS_ENTRY.MinAddr; if (DPContext.vmcs != null) { locPhys = memAxss.VirtualToPhysical(DPContext.vmcs.EPTP, DPContext.CR3Value, i); } else { locPhys = memAxss.VirtualToPhysical(DPContext.CR3Value, i); } var Curr = i; i += 0x1000; if (HARDWARE_ADDRESS_ENTRY.IsBadEntry(locPhys)) { continue; } bool GotData = false; memAxss.GetPageForPhysAddr(locPhys, ref block, ref GotData); if (!GotData) { continue; } foreach (var scanner in CheckMethods) { var scan_detect = scanner(Curr, block); if (scan_detect != VAScanType.UNDETERMINED) { rv.Add(Curr, Artifacts[Curr]); if (Vtero.VerboseOutput) { Console.WriteLine($"Detected PE @ VA {Curr:X}"); } } } } return(rv); }
/// <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()); }
// Translates virtual address to physical address by way of CR3->EPTP double dereferencing (up to 24 loads) public HARDWARE_ADDRESS_ENTRY VirtualToPhysical(HARDWARE_ADDRESS_ENTRY eptp, HARDWARE_ADDRESS_ENTRY aCR3, long Addr) { var rv = HARDWARE_ADDRESS_ENTRY.MinAddr; var va = new VIRTUAL_ADDRESS(Addr); var gVa = new VIRTUAL_ADDRESS(aCR3.PTE); var Attempted = HARDWARE_ADDRESS_ENTRY.MinAddr; var ConvertedV2hP = new List <HARDWARE_ADDRESS_ENTRY>(); try { Attempted = gVa.Address; //convert Guest CR3 gPA into Host CR3 pPA var gpaCR3 = VirtualToPhysical(eptp, gVa.Address); //Console.WriteLine($"In V2P2P, using CR3 {aCR3.PTE:X16}, found guest phys CR3 {gpaCR3.PTE:X16}, attempting load of PML4E from {(gpaCR3 | va.PML4):X16}"); // gPML4E - as we go were getting gPA's which need to pPA Attempted = gpaCR3.NextTableAddress | va.PML4; var gPML4E = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted); ConvertedV2hP.Add(gPML4E); //Console.WriteLine($"guest PML4E = {gPML4E}"); // take CR3 and extract gPhys for VA we want to query var hPML4E = VirtualToPhysical(eptp, gPML4E.NextTableAddress); if (EPTP.IsValid(hPML4E.PTE) && EPTP.IsValid2(hPML4E.PTE) && HARDWARE_ADDRESS_ENTRY.IsBadEntry(hPML4E)) { Attempted = hPML4E.NextTableAddress | (va.DirectoryPointerOffset << 3); var gPDPTE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted); ConvertedV2hP.Add(gPDPTE); var hPDPTE = VirtualToPhysical(eptp, gPDPTE.NextTableAddress); if (EPTP.IsValid(hPDPTE.PTE)) { if (!EPTP.IsLargePDPTE(hPDPTE.PTE)) { if (EPTP.IsValid2(hPDPTE.PTE)) { Attempted = hPDPTE.NextTableAddress | (va.DirectoryOffset << 3); var gPDE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted); ConvertedV2hP.Add(gPDE); var hPDE = VirtualToPhysical(eptp, gPDE.NextTableAddress); if (EPTP.IsValid(hPDE.PTE)) { if (!EPTP.IsLargePDE(hPDE.PTE)) { if (EPTP.IsValid2(hPDE.PTE)) { Attempted = hPDE.NextTableAddress | (va.TableOffset << 3); var gPTE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted); ConvertedV2hP.Add(gPTE); var hPTE = VirtualToPhysical(eptp, gPTE.NextTableAddress); if (EPTP.IsValidEntry(hPTE.PTE)) { rv = hPTE.NextTableAddress | va.Offset; } } } else { rv = (hPDE.PTE & 0xFFFFFFE00000) | va.TableOffset; //(Addr & 0x1FFFFF); } } } } else { rv = (hPDPTE.PTE & 0xFFFFC0000000) | va.DirectoryOffset; //(Addr & 0x3FFFFFFF); } } } } catch (PageNotFoundException ex) { throw new ExtendedPageNotFoundException( $"V2gP2hP conversion error. EPTP:{eptp}, CR3:{aCR3}, Requesting:{Attempted} Step:{ConvertedV2hP.Count()}. Step of 0 may indicate invalid EPTP.{Environment.NewLine}" , eptp, aCR3, Attempted, ConvertedV2hP, ex); } return(rv); }
/// <summary> /// Scan and return Extract objects which represent detected PE's /// /// TODO:simplify/rewrite this /// </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 List <Extract> Run(long Start = 0, long Stop = 0xFFFFffffFFFF, PFN entry = null, ParallelLoopState pState = null, Mem Instance = null) { bool GotData = false; var memAxss = Instance == null ? BackingBlocks : Instance; long i = Start, Curr = 0; byte[] block; var rv = new List <Extract>(); // large page read if (entry != null && entry.PTE.LargePage) { block = new byte[MagicNumbers.LARGE_PAGE_SIZE]; memAxss.GetPageForPhysAddr(entry.PTE, ref block, ref GotData); if (GotData) { rv = FastPE(Start, block); } return(rv); } else // use supplied page sized physical entry if (entry != null && Stop - Start == MagicNumbers.PAGE_SIZE) { block = new byte[MagicNumbers.PAGE_SIZE]; memAxss.GetPageForPhysAddr(entry.PTE, ref block, ref GotData); if (GotData) { rv = FastPE(Start, block); } // we only header scan when asked and if the page read is 1 from an alignment if (!HeaderScan) { return(rv); } if ((Start & 0xF000) != MagicNumbers.PAGE_SIZE) { return(rv); } // if were doing a header scan back up i so we do the previous page i -= 0x1000; // back up Stop also so we just scan this current page one time Stop -= 0x1000; } // just use the virtual addresses and attempt to locate phys from page walk // this is a really slow way to enumerate memory // convert index to an address // then add start to it block = new byte[MagicNumbers.PAGE_SIZE]; // 0x200 * 8 = 4k while (i < Stop) { if (pState != null && pState.IsStopped) { return(rv); } HARDWARE_ADDRESS_ENTRY locPhys = HARDWARE_ADDRESS_ENTRY.MinAddr; if (DPContext.vmcs != null) { locPhys = memAxss.VirtualToPhysical(DPContext.vmcs.EPTP, DPContext.CR3Value, i); } else { locPhys = memAxss.VirtualToPhysical(DPContext.CR3Value, i); } Curr = i; i += MagicNumbers.PAGE_SIZE; if (HARDWARE_ADDRESS_ENTRY.IsBadEntry(locPhys) || !locPhys.Valid) { continue; } memAxss.GetPageForPhysAddr(locPhys, ref block, ref GotData); if (!GotData) { continue; } var new_pe = FastPE(Curr, block); rv.AddRange(new_pe); if (Vtero.VerboseOutput && new_pe.Count > 0) { Console.WriteLine($"Detected PE @ VA {Curr:X}"); } } return(rv); }