Пример #1
0
        public long GetValueAtPhysicalAddr(HARDWARE_ADDRESS_ENTRY PAddr)
        {
            long[] block = null;
            return(GetPageForPhysAddr(PAddr, ref block));

            //return pageData[PAddr.AddressOffset >> 3];
        }
Пример #2
0
        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);
        }
Пример #3
0
        public long GetPageForPhysAddr <T>(HARDWARE_ADDRESS_ENTRY PAddr, ref T[] block, ref bool GotData)
        {
            long rv = 0;
            // convert PAddr to PFN
            var aPFN = PAddr.NextTable_PFN;

            GotData = false;

            // should return with - error_value
            // This happens quite a bit and is a good boost
            // I guess were constrained by int.MaxValue pages here.
            // so that is about 8TB
            // TODO: explore 5 level page tables and larger than 8TB inputs :)
            if (aPFN > int.MaxValue || aPFN < 0)
            {
                return(0);
            }

            // paranoid android setting

            var FileOffset = OffsetToMemIndex(aPFN);

            if (FileOffset >= 0)
            {
                rv = GetPageFromFileOffset(FileOffset + PAddr.AddressOffset, ref block, ref GotData);
            }

            if (!GotData)
            {
                rv = MagicNumbers.BAD_VALUE_READ;
            }

            return(rv);
        }
Пример #4
0
        /// <summary>
        /// Get a long back for the address specified
        /// </summary>
        /// <param name="PAddr">physical address (byte address)</param>
        /// <returns>value</returns>
        public long GetValueAtPhysicalAddr(HARDWARE_ADDRESS_ENTRY PAddr)
        {
            bool Ignored = false;

            long[] block = new long[512];

            return(GetPageForPhysAddr(PAddr, ref block, ref Ignored));
        }
Пример #5
0
 public ExtendedPageNotFoundException(string message, HARDWARE_ADDRESS_ENTRY eptpUsed, HARDWARE_ADDRESS_ENTRY cr3Used, HARDWARE_ADDRESS_ENTRY lastEPAttempted, List <HARDWARE_ADDRESS_ENTRY> ePFound, PageNotFoundException ex)
     : base(message, ex)
 {
     EPFound         = ePFound;
     LastEPAttempted = lastEPAttempted;
     RequestedCR3    = cr3Used;
     RequestedEPTP   = eptpUsed;
 }
Пример #6
0
        /// <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);
        }
Пример #7
0
        public static bool IsBadEntry(HARDWARE_ADDRESS_ENTRY entry)
        {
            if (entry <= HARDWARE_ADDRESS_ENTRY.MinAddr + 2L || entry >= HARDWARE_ADDRESS_ENTRY.MaxAddr - 2L)
            {
                return(true);
            }

            return(false);
        }
Пример #8
0
        public long GetPageForPhysAddr(HARDWARE_ADDRESS_ENTRY PAddr, ref long[] block, ref bool GotData, bool NoCache = true)
        {
            long rv = 0;
            // convert PAddr to PFN
            var aPFN = PAddr.NextTable_PFN;

            GotData = false;
            //NoCache = true;

            if (!NoCache && PageCache.ContainsKey(aPFN))
            {
                do
                {
                    PageCache.TryGetValue(aPFN, out block);
                }while (block == null);
                // shift down since were loading a long[]
                GotData = true;
                return(block[(PAddr >> 3) & 0x1ff]);
            }

            // should return with - error_value
            if (aPFN > int.MaxValue || aPFN < 0)
            {
                return(0);
            }
#if USE_BITMAP
            if (pfnTableIdx != null)
            {
                pfnTableIdx.Set((int)PFN, true);
            }
#endif
            // paranoid android setting

            var FileOffset = OffsetToMemIndex(aPFN);
            if (FileOffset < 0)
            {
                rv = MagicNumbers.BAD_RUN_CONFIG_READ;
            }
            else
            {
                // add back in the file offset for possible exact byte lookup
                rv = GetPageFromFileOffset(FileOffset + PAddr.AddressOffset, ref block, ref GotData);
            }

            if (!GotData)
            {
                rv = MagicNumbers.BAD_VALUE_READ;
            }

            if (!NoCache && GotData)
            {
                PageCache.TryAdd(aPFN, block);
            }

            return(rv);
        }
Пример #9
0
        /// <summary>
        /// Get a long back for the address specified
        /// </summary>
        /// <param name="PAddr">physical address (byte address)</param>
        /// <returns>value</returns>
        public long GetValueAtPhysicalAddr(HARDWARE_ADDRESS_ENTRY PAddr)
        {
            bool Ignored = false;

            long[] block = new long[512];

            return(GetPageForPhysAddr(PAddr, ref block, ref Ignored));

            //return pageData[PAddr.AddressOffset >> 3];
        }
Пример #10
0
        // Extract a single page of data from a physical address in source dump
        // account for memory gaps/run layout
        // TODO: Add windowing currently uses naive single-page-at-a-time view
        public long GetPageForPhysAddr(HARDWARE_ADDRESS_ENTRY PAddr, ref long[] block)
        {
            // convert PAddr to PFN
            var PFN = PAddr.NextTable_PFN;

            if (PageCache.ContainsKey(PFN))
            {
                if (PageCache.TryGetValue(PAddr, out block))
                {
                    return(block[PAddr & 0x1ff]);
                }
            }

            // record our access attempt to the pfnIndex
            if (PFN > int.MaxValue || PFN > MD.MaxAddressablePageNumber)
            {
                return(0);
            }

            pfnTableIdx.Set((int)PFN, true);

            // paranoid android setting
            var Fail = true;

            long IndexedPFN = 0;

            for (int i = 0; i < MD.NumberOfRuns; i++)
            {
                if (PFN >= MD.Run[i].BasePage && PFN < (MD.Run[i].BasePage + MD.Run[i].PageCount))
                {
                    var currBaseOffset = PFN - MD.Run[i].BasePage;
                    IndexedPFN += currBaseOffset;
                    Fail        = false;
                    break;
                }
                IndexedPFN += MD.Run[i].PageCount;
            }
            if (Fail)
            {
                throw new MemoryRunMismatchException(PAddr.PTE);
            }

            // Determine file offset based on indexed/gap adjusted PFN and page size
            var FileOffset = StartOfMemory + (IndexedPFN * PAGE_SIZE);

            // add back in the file offset for possible exact byte lookup
            var rv = GetPageFromFileOffset(FileOffset + PAddr.AddressOffset, ref block);

            if (block != null)
            {
                PageCache.TryAdd(PFN, block);
            }

            return(rv);
        }
Пример #11
0
        /// <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());
        }
Пример #12
0
        /// <summary>
        /// These properties combine together to formulate our database/cross reference between physical to virtual addresses 
        /// </summary>
        /// <param name="RawEntry">PTE</param>
        /// <param name="va">Virtual Address</param>
        /// <param name="pageTable">CR3 address</param>
        /// <param name="sLAT">EPTP</param>
        public PFN(long RawEntry, long va, long pageTable, long sLAT)
        {
            PTE = new HARDWARE_ADDRESS_ENTRY(RawEntry);

            // this is the key into bitmap, since were never going to get past 32bit PFN
            // figures to make it only uint
            VA = va;

            PageTable.PTE = pageTable;
            SLAT.PTE = sLAT;
            SubTables = new Dictionary<VIRTUAL_ADDRESS, PFN>();
        }
Пример #13
0
        /// <summary>
        /// These properties combine together to formulate our database/cross reference between physical to virtual addresses
        /// </summary>
        /// <param name="RawEntry">PTE</param>
        /// <param name="va">Virtual Address</param>
        /// <param name="pageTable">CR3 address</param>
        /// <param name="sLAT">EPTP</param>
        public PFN(long RawEntry, long va, long pageTable, long sLAT)
        {
            PTE = new HARDWARE_ADDRESS_ENTRY(RawEntry);

            // this is the key into bitmap, since were never going to get past 32bit PFN
            // figures to make it only uint
            VA = va;

            PageTable.PTE = pageTable;
            SLAT.PTE      = sLAT;
            SubTables     = new Dictionary <VIRTUAL_ADDRESS, PFN>();
        }
Пример #14
0
        public bool IsDumpedPFN(HARDWARE_ADDRESS_ENTRY PTE)
        {
            if (PTE.PFN == 0xffffffffff)
            {
                return(true);
            }

            if (PTE.LargePage)
            {
                return(false);
            }

            return(DumpedPFNBitmap.GetBit((ulong)PTE.PFN));
        }
Пример #15
0
        // Extract a single page of data from a physical address in source dump
        // accout for memory gaps/run layout
        // TODO: Add windowing currently uses naieve single-page-at-a-time view
        public long GetPageForPhysAddr(HARDWARE_ADDRESS_ENTRY PAddr, ref long[] block) 
        {
            // convert PAddr to PFN
            var PFN = PAddr.NextTable_PFN;

            // paranoid android setting
            var Fail = true;

            long IndexedPFN = 0;
            for (int i = 0; i < MD.NumberOfRuns; i++)
            {
                if (PFN >= MD.Run[i].BasePage && PFN < (MD.Run[i].BasePage + MD.Run[i].PageCount))
                {
                    var currBaseOffset = PFN - MD.Run[i].BasePage;
                    IndexedPFN += currBaseOffset;
                    Fail = false;
                    break;
                }
                IndexedPFN += MD.Run[i].PageCount;
            }
            if (Fail)
                throw new MemoryRunMismatchException(PAddr.PTE);

            // Determine file offset based on indexed/gap adjusted PFN and page size
            var FileOffset = StartOfMemory + (IndexedPFN * PAGE_SIZE);

            // add back in the file offset for possiable exact byte lookup
            return GetPageFromFileOffset(FileOffset + PAddr.AddressOffset, ref block);
        }
Пример #16
0
        /// <summary>
        /// Extract a single page of data from a physical address in source dump
        /// accounts for memory gaps/run layout
        /// </summary>
        /// <param name="PAddr">byte address an address contained in the block</param>
        /// <param name="block">array to be filled</param>
        /// <returns>specific return value for long value at </returns>
        public long GetPageForPhysAddr(HARDWARE_ADDRESS_ENTRY PAddr, ref long[] block)
        {
            bool GoodRead = false;

            return(GetPageForPhysAddr(PAddr, ref block, ref GoodRead));
        }
Пример #17
0
        public long hostPTE;  // if we have SLAT and had the chance to de-virtualize, place the translated entry here

        public PFN() { PTE = long.MaxValue; }
Пример #18
0
        /// <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);
        }
Пример #19
0
        // Translates virtual address to physical address  (normal CR3 path)
        // Since Valid & Read access overlap each other for EPT and normal PT go through this path for both
        public HARDWARE_ADDRESS_ENTRY VirtualToPhysical(HARDWARE_ADDRESS_ENTRY aCR3, long Addr)
        {
            var rv           = HARDWARE_ADDRESS_ENTRY.MaxAddr;
            var va           = new VIRTUAL_ADDRESS(Addr);
            var ConvertedV2P = new List <HARDWARE_ADDRESS_ENTRY>();
            var Attempted    = HARDWARE_ADDRESS_ENTRY.MinAddr;

            //Console.WriteLine($"V2P CR3 = {aCR3.PTE:X16}  VA = {va}");
            // PML4E
            try
            {
                Attempted = (HARDWARE_ADDRESS_ENTRY)aCR3.NextTableAddress | (va.PML4 << 3);

                var PML4E = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted);
                //Console.WriteLine($"PML4E = {PML4E.PTE:X16}");
                ConvertedV2P.Add(PML4E);
                if (PML4E.Valid)
                {
                    Attempted = PML4E.NextTableAddress | (va.DirectoryPointerOffset << 3);
                    var PDPTE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted);
                    ConvertedV2P.Add(PDPTE);
                    //Console.WriteLine($"PDPTE = {PDPTE.PTE:X16}");

                    if (PDPTE.Valid)
                    {
                        if (!PDPTE.LargePage)
                        {
                            Attempted = PDPTE.NextTableAddress | (va.DirectoryOffset << 3);
                            var PDE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted);
                            ConvertedV2P.Add(PDE);
                            //Console.WriteLine($"PDE = {PDE.PTE:X16}");

                            if (PDE.Valid)
                            {
                                if (!PDE.LargePage)
                                {
                                    Attempted = PDE.NextTableAddress | (va.TableOffset << 3);
                                    var PTE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted);
                                    ConvertedV2P.Add(PTE);
                                    //Console.WriteLine($"PTE = {PTE.PTE:X16}");
                                    //rv = PTE;
                                    // page is normal 4kb
                                    if (PTE.Valid)
                                    {
                                        rv = PTE.PTE | (PTE.NextTableAddress | va.Offset);
                                    }
                                    else
                                    {
                                        rv.Valid = false;
                                    }
                                }
                                else
                                {   // we have a 2MB page
                                    rv = PDE.PTE | ((PDE.PTE & 0xFFFFFFE00000) | va.TableOffset << 12);
                                }
                            }
                            else
                            {
                                rv.Valid = false;
                            }
                        }
                        else
                        {   // we have a 1GB page
                            rv = PDPTE.PTE | ((PDPTE.PTE & 0xFFFFC0000000) | va.DirectoryOffset << 12 << 9);
                            //rv = PDPTE;
                        }
                    }
                    else
                    {
                        rv.Valid = false;
                    }
                }
                else
                {
                    rv.Valid = false;
                }
            }
            catch (Exception ex)
            {
                rv.Valid = false;
            }
            finally
            {
                //foreach(var paddr in ConvertedV2P)
                //{
                //}
            }
            //Console.WriteLine($"return from V2P {rv:X16}");
            // serialize the dictionary out
            return(rv);
        }
Пример #20
0
        public long GetValueAtPhysicalAddr(HARDWARE_ADDRESS_ENTRY PAddr)
        {
            long[] block = null;
            return GetPageForPhysAddr(PAddr, ref block);

            //return pageData[PAddr.AddressOffset >> 3];
        }
Пример #21
0
        // Extract a single page of data from a physical address in source dump
        // account for memory gaps/run layout
        // TODO: Add windowing currently uses naive single-page-at-a-time view
        public long GetPageForPhysAddr(HARDWARE_ADDRESS_ENTRY PAddr, ref long[] block) 
        {
            // convert PAddr to PFN
            var PFN = PAddr.NextTable_PFN;

            if (PageCache.ContainsKey(PFN))
            {
                if (PageCache.TryGetValue(PAddr, out block))
                    return block[PAddr & 0x1ff];
            }

            // record our access attempt to the pfnIndex
            if (PFN > int.MaxValue || PFN > MD.MaxAddressablePageNumber)
                return 0;

            pfnTableIdx.Set((int)PFN, true);

            // paranoid android setting
            var Fail = true;

            long IndexedPFN = 0;
            for (int i = 0; i < MD.NumberOfRuns; i++)
            {
                if (PFN >= MD.Run[i].BasePage && PFN < (MD.Run[i].BasePage + MD.Run[i].PageCount))
                {
                    var currBaseOffset = PFN - MD.Run[i].BasePage;
                    IndexedPFN += currBaseOffset;
                    Fail = false;
                    break;
                }
                IndexedPFN += MD.Run[i].PageCount;
            }
            if (Fail)
                throw new MemoryRunMismatchException(PAddr.PTE);

            // Determine file offset based on indexed/gap adjusted PFN and page size
            var FileOffset = StartOfMemory + (IndexedPFN * PAGE_SIZE);

            // add back in the file offset for possible exact byte lookup
            var rv = GetPageFromFileOffset(FileOffset + PAddr.AddressOffset, ref block);

            if(block != null)
                PageCache.TryAdd(PFN, block);

            return rv;
        }
Пример #22
0
        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;

        }
Пример #23
0
        public IEnumerable <PFN> ExtractNextLevel(PFN PageContext, int Level = 4, bool RedundantKernelSpaces = false)
        {
            if (PageContext == null)
            {
                yield break;
            }

            var SLAT = Root.SLAT;
            var CR3  = Root.CR3;
            var top  = Root.Entries;

            VIRTUAL_ADDRESS        SubVA = PageContext.VA;
            HARDWARE_ADDRESS_ENTRY PA    = PageContext.PTE;

            // get the page that the current PFN describes
            var HW_Addr = PA.NextTableAddress;

            if (SLAT != 0)
            {
                var hHW_Addr = HARDWARE_ADDRESS_ENTRY.MaxAddr;
                try { hHW_Addr = mem.VirtualToPhysical(SLAT, HW_Addr); } catch (Exception ex) { if (Vtero.DiagOutput)
                                                                                                {
                                                                                                    WriteLine($"level{Level}: Unable to V2P {HW_Addr}");
                                                                                                }
                }
                HW_Addr = hHW_Addr;

                if (HW_Addr == long.MaxValue || HW_Addr == long.MaxValue - 1)
                {
                    yield break;
                }
            }

            if (PageContext.PTE.LargePage && Level <= 1)
            {
                // cyclic
                if (MemorizeTables)
                {
                    PageContext.SubTables.Add(PageContext.VA, PageContext);
                }
                yield break;
            }

            long[] page     = new long[512];
            bool   ReadData = false;
            // copy VA since were going to be making changes

            var valueRead = mem.GetPageForPhysAddr(HW_Addr, ref page, ref ReadData);

            if (!ReadData || page == null)
            {
                yield break;
            }

            // if every entry is exactially the same bail out
            var check1 = page[0];

            if (Array.TrueForAll <long>(page, (entry) => entry == check1))
            {
                yield break;
            }

            var dupVA = new VIRTUAL_ADDRESS(SubVA.Address);

            for (int i = 0; i < 512; i++)
            {
                // kernel indexes are only relevant on the top level
                if (Level == 4 && (!RedundantKernelSpaces && i >= MagicNumbers.KERNEL_PT_INDEX_START_USUALLY))
                {
                    continue;
                }

                if (page[i] == 0)
                {
                    continue;
                }

                switch (Level)
                {
                case 4:
                    dupVA.PML4 = i;
                    break;

                case 3:
                    dupVA.DirectoryPointerOffset = i;
                    break;

                case 2:
                    dupVA.DirectoryOffset = i;
                    break;

                case 1:
                    dupVA.TableOffset = i;
                    break;

                default:
                    break;
                }

                var pfn = new PFN
                {
                    VA  = new VIRTUAL_ADDRESS(dupVA.Address),
                    PTE = new HARDWARE_ADDRESS_ENTRY(page[i])
                };

                if (MemorizeTables)
                {
                    PageContext.SubTables.Add(
                        pfn.VA,
                        pfn);
                }

                EntriesParsed++;
                yield return(pfn);
            }
            yield break;
        }
Пример #24
0
 public PageNotFoundException(string message, HARDWARE_ADDRESS_ENTRY lastPageAttempted, List <HARDWARE_ADDRESS_ENTRY> pagesFound, Exception ex)
     : base(message, ex)
 {
     PagesFound        = pagesFound;
     LastPageAttempted = lastPageAttempted;
 }
Пример #25
0
        /// <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;
        }
Пример #26
0
 public PFN()
 {
     PTE = long.MaxValue;
 }
Пример #27
0
        /// <summary>
        /// Get a long back for the address specified
        /// </summary>
        /// <param name="PAddr">physical address (byte address)</param>
        /// <returns>value</returns>
        public long GetValueAtPhysicalAddr(HARDWARE_ADDRESS_ENTRY PAddr)
        {

            bool Ignored = false;
            long[] block = new long[512];

            return GetPageForPhysAddr(PAddr, ref block, ref Ignored);

            //return pageData[PAddr.AddressOffset >> 3];
        }
Пример #28
0
        public static bool IsBadEntry(HARDWARE_ADDRESS_ENTRY entry)
        {
            if (entry <= HARDWARE_ADDRESS_ENTRY.MinAddr + 2L || entry >= HARDWARE_ADDRESS_ENTRY.MaxAddr - 2L)
                return true;

            return false;
        }
Пример #29
0
        /// <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);
        }
Пример #30
0
 /// <summary>
 /// Extract a single page of data from a physical address in source dump
 /// accounts for memory gaps/run layout
 /// </summary>
 /// <param name="PAddr">byte address an address contained in the block</param>
 /// <param name="block">array to be filled</param>
 /// <returns>specific return value for long value at </returns>
 public long GetPageForPhysAddr(HARDWARE_ADDRESS_ENTRY PAddr, ref long[] block) 
 {
     bool GoodRead = false;
     return GetPageForPhysAddr(PAddr, ref block, ref GoodRead);
 }
Пример #31
0
        // Translates virtual address to physical address  (normal CR3 path)
        // Since Valid & Read access overlap each other for EPT and normal PT go through this path for both
        public HARDWARE_ADDRESS_ENTRY VirtualToPhysical(HARDWARE_ADDRESS_ENTRY aCR3, long Addr)
        {
            var rv = HARDWARE_ADDRESS_ENTRY.MaxAddr;
            var va = new VIRTUAL_ADDRESS(Addr);
            var ConvertedV2P = new List<HARDWARE_ADDRESS_ENTRY>();
            var Attempted = HARDWARE_ADDRESS_ENTRY.MinAddr;

            //Console.WriteLine($"V2P CR3 = {aCR3.PTE:X16}  VA = {va}");
            // PML4E
            try
            {
                Attempted = (HARDWARE_ADDRESS_ENTRY) aCR3.NextTableAddress | (va.PML4 << 3);
                var PML4E = (HARDWARE_ADDRESS_ENTRY) GetValueAtPhysicalAddr(Attempted);
                //Console.WriteLine($"PML4E = {PML4E.PTE:X16}");
                ConvertedV2P.Add(PML4E);
                if (PML4E.Valid)
                {
                    Attempted = PML4E.NextTableAddress | (va.DirectoryPointerOffset << 3);
                    var PDPTE = (HARDWARE_ADDRESS_ENTRY) GetValueAtPhysicalAddr(Attempted);
                    ConvertedV2P.Add(PDPTE);
                    //Console.WriteLine($"PDPTE = {PDPTE.PTE:X16}");

                    if (PDPTE.Valid)
                    {
                        if (!PDPTE.LargePage)
                        {
                            Attempted = PDPTE.NextTableAddress | (va.DirectoryOffset << 3);
                            var PDE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted);
                            ConvertedV2P.Add(PDE);
                            //Console.WriteLine($"PDE = {PDE.PTE:X16}");

                            if (PDE.Valid)
                            {
                                if (!PDE.LargePage)
                                {
                                    Attempted = PDE.NextTableAddress | (va.TableOffset << 3);
                                    var PTE = (HARDWARE_ADDRESS_ENTRY)GetValueAtPhysicalAddr(Attempted);
                                    ConvertedV2P.Add(PTE);
                                    //Console.WriteLine($"PTE = {PTE.PTE:X16}");

                                    // page is normal 4kb
                                    if (PTE.Valid)
                                        rv = PTE.NextTableAddress | va.Offset;
                                    else
                                        rv.Valid = false;
                                }
                                else
                                {   // we have a 2MB page
                                    rv = (PDE.PTE & 0xFFFFFFE00000) | (Addr & 0x1FFFFF);
                                }
                            }
                            else
                                rv.Valid = false;
                        }
                        else
                        {   // we have a 1GB page
                            rv = (PDPTE.PTE & 0xFFFFC0000000) | (Addr & 0x3FFFFFFF);
                        }
                    }
                    else
                        rv.Valid = false;
                }
                else
                    rv.Valid = false;
            }
            catch (Exception ex)
            {
                throw new PageNotFoundException("V2P conversion error page not found", Attempted, ConvertedV2P, ex);
            }
            finally
            {
                foreach(var paddr in ConvertedV2P)
                {

                }
            }
            //Console.WriteLine($"return from V2P {rv:X16}");
            // serialize the dictionary out
            return rv;
        }
Пример #32
0
 public void SetDumpedPFN(HARDWARE_ADDRESS_ENTRY PTE)
 {
     DumpedPFNBitmap.SetBit((ulong)PTE.PFN);
 }
Пример #33
0
        // 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);
        }
Пример #34
0
        // 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);

                // Validate page table. Possibly adjust for run gaps
                //var GapSize = ValidateAndGetGap(gpaCR3, aCR3);
                // let's just ignore failures for now
                //if (GapSize == long.MaxValue)
                //Debug.Print("Table verification error.  YMMV.");
                long GapSize = 0;
                //}

                //Console.WriteLine($"In V2P2P, using CR3 {aCR3.PTE:X16}, found guest phys CR3 {gpaCR3.PTE:X16}, attemptng load of PML4E from {(gpaCR3 | va.PML4):X16}");
                // gPML4E - as we go were getting gPA's which need to pPA

                Attempted = (gpaCR3.NextTableAddress - GapSize) | (va.PML4 << 3);

                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))
                { 
                    Attempted = (hPML4E.NextTableAddress - GapSize) | (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 - GapSize) | (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 - GapSize) | (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 - GapSize) | va.Offset;
                                        }
                                    }
                                    else
                                        rv = (hPDE.PTE & 0xFFFFFFE00000) | (Addr & 0x1FFFFF);
                                }
                            }
                        }
                        else
                            rv = (hPDPTE.PTE & 0xFFFFC0000000) | (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;
        }
Пример #35
0
 public PageNotFoundException(string message, HARDWARE_ADDRESS_ENTRY lastPageAttempted, List<HARDWARE_ADDRESS_ENTRY> pagesFound, Exception ex)
     : base(message, ex)
 {
     PagesFound = pagesFound;
     LastPageAttempted = lastPageAttempted;
 }
Пример #36
0
        public ExtendedPageNotFoundException(string message, HARDWARE_ADDRESS_ENTRY eptpUsed, HARDWARE_ADDRESS_ENTRY cr3Used, HARDWARE_ADDRESS_ENTRY lastEPAttempted, List<HARDWARE_ADDRESS_ENTRY> ePFound, PageNotFoundException ex)
            : base(message, ex)
        {

            EPFound = ePFound;
            LastEPAttempted = lastEPAttempted;
            RequestedCR3 = cr3Used;
            RequestedEPTP = eptpUsed;
        }
Пример #37
0
 public SLAT_ENTRY(HARDWARE_ADDRESS_ENTRY slat)
 {
     SLATEntry = slat.PTE;
 }
Пример #38
0
        long InlineExtract(PFN top, int Level)
        {
            if (Level == 0)
                return 0;

            var entries = 0L;

            var VA = new VIRTUAL_ADDRESS(top.VA);
            var hPA = HARDWARE_ADDRESS_ENTRY.MinAddr;

            var CR3 = top.PageTable;
            var SLAT = top.SLAT;

            // 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;

                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;
                    hl3HW_Addr = mem.VirtualToPhysical(SLAT, l3HW_Addr);
                    l3HW_Addr = hl3HW_Addr;
                }
                if (l3HW_Addr == long.MaxValue)
                    continue;

                // copy VA since were going to be making changes
                var s3va = new VIRTUAL_ADDRESS(top_sub.Key.Address);

                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) { 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++;

                    // 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) { WriteLine($"level2: Unable to V2P {l3PTE}"); }
                        l2HW_Addr = hl2HW_Addr;
                    }
                    // TODO: more error handlng of exceptions & bad return's
                    // 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) { WriteLine($"level2: Failed lookup {l2HW_Addr:X16}"); }

                    if (lvl2_page == null)
                        continue;

                    // copy VA 
                    var s2va = new VIRTUAL_ADDRESS(s3va.Address);
                    // 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);
                        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) { 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) { WriteLine($"level1: Failed lookup {l1HW_Addr:X16}"); }

                            if (lvl1_page == null)
                                continue;

                            var s1va = new VIRTUAL_ADDRESS(s2va.Address);

                            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);
                                l2PFN.SubTables.Add(s1va, l1PFN);
                                entries++;
                            }
                        }
                    }
                }
            }
            top.PFNCount += entries;
            return entries;
        }
Пример #39
0
 public SLAT_ENTRY(HARDWARE_ADDRESS_ENTRY slat) { SLATEntry = slat.PTE; }
Пример #40
0
        public long GetPageForPhysAddr(HARDWARE_ADDRESS_ENTRY PAddr, ref long[] block, ref bool GotData)
        {
            long rv = 0;
            // convert PAddr to PFN
            var aPFN = PAddr.NextTable_PFN;
            GotData = false;

            // should return with - error_value
            // This happens quite a bit and is a good boost
            // I guess were constrained by int.MaxValue pages here. 
            // so that is about 8TB
            // TODO: explore 5 level page tables and larger than 8TB inputs :)
            if (aPFN > int.MaxValue || aPFN < 0)
                return 0;
#if USE_BITMAP
            if(pfnTableIdx != null)
                pfnTableIdx.Set((int)PFN, true);
#endif
            // paranoid android setting

            var FileOffset = OffsetToMemIndex(aPFN);
            if (FileOffset >= 0)
                rv = GetPageFromFileOffset(FileOffset + PAddr.AddressOffset, ref block, ref GotData);

            if (!GotData)
                rv = MagicNumbers.BAD_VALUE_READ;

            return rv;

        }