GetPageForPhysAddr() public method

Extract a single page of data from a physical address in source dump accounts for memory gaps/run layout
public GetPageForPhysAddr ( HARDWARE_ADDRESS_ENTRY PAddr, long &block ) : long
PAddr HARDWARE_ADDRESS_ENTRY byte address an address contained in the block
block long array to be filled
return long
Exemplo n.º 1
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());
        }
Exemplo n.º 2
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            int CurrOff = 0;
            // figure out how many pages we need
            int PageCount = count / 4096;

            if ((count & 0xfff) != 0)
            {
                PageCount++;
            }

            int rv = PageCount;

            if (offset != 0)
            {
                throw new NotImplementedException("Sub-Page reads not supported, use BufferedStream to even out your access pattern.");
            }

            while (PageCount > 0)
            {
                // block may be set to null by the GetPageForPhysAddr call, so we need to remake it every time through...
                var lblock = new long[0x200]; // 0x200 * 8 = 4k
                PageCount--;

                //fixed (void* lp = lblock, bp = buffer)
                //{
                try {
                    if (MemBlockStorage.GetPageForPhysAddr(CurrPage.PTE, ref lblock) == MagicNumbers.BAD_VALUE_READ)
                    {
                        continue;
                    }

                    Buffer.BlockCopy(lblock, CurrOff / 4, buffer, CurrOff, 4096);
                    //Buffer.MemoryCopy((byte*)lp + CurrOff, (byte*)bp + CurrOff, 4096, 4096);
                } finally
                {
                    CurrOff += 0x1000;
                }

                //}
            }

            return((rv - PageCount) * 0x1000);
        }
Exemplo n.º 3
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            bool GoodRead = false;
            int  CurrOff  = 0;
            // figure out how many pages we need
            int PageCount = count / MagicNumbers.PAGE_SIZE;

            if ((count & 0xfff) != 0)
            {
                PageCount++;
            }

            int rv = PageCount;

            if (offset != 0)
            {
                throw new NotImplementedException("Sub-Page reads not supported, use BufferedStream to even out your access pattern.");
            }

            var lblock = new long[0x200]; // 0x200 * 8 = 4k

            while (PageCount > 0)
            {
                PageCount--;

                MemBlockStorage.GetPageForPhysAddr(CurrPage.PTE, ref lblock, ref GoodRead);
                if (!GoodRead)
                {
                    continue;
                }

                Buffer.BlockCopy(lblock, CurrOff / 4, buffer, CurrOff, MagicNumbers.PAGE_SIZE);
                CurrOff += MagicNumbers.PAGE_SIZE;
            }

            return((rv - PageCount) * MagicNumbers.PAGE_SIZE);
        }
Exemplo n.º 4
0
        public void DumpASToFile(List<DetectedProc> ToDump)
        {
            using (var memAxs = new Mem(MemFile, null, DetectedDesc))
            {
                // in all likelyhood this is the kernel
                var tdp = (from p in ToDump
                           where p.AddressSpaceID == 1
                           orderby p.CR3Value ascending
                           select p).Take(1).First();

                // as a test let's find the process with the most to dump
                /*var tdp = (from p in ToDump
                               where p.AddressSpaceID == 1
                               orderby p.PT.RootPageTable.PFNCount descending
                               select p).Take(1).First();
                               */

                var pml4 = tdp.PT.RootPageTable;

                WriteLine($"Test dumping {tdp}, {pml4.PFNCount} entries scanned.");

                var MemRanges = pml4.SubTables.SelectMany(x => x.Value.SubTables).SelectMany(y => y.Value.SubTables).SelectMany(z => z.Value.SubTables);

    //            WriteLine($"MemRanges = {MemRanges.Count()} available.");

                
                var saveLoc = Path.Combine(Path.GetDirectoryName(MemFile), Path.GetFileName(MemFile) + ".");

                long[] block = new long[0x200]; // 0x200 * 8 = 4k
                byte[] bpage = new byte[0x1000];

                unsafe
                {
                    fixed (void * lp = block, bp = bpage)
                    {
                        foreach (var pte in MemRanges)
                        {
                            if (VerboseOutput)
                                WriteLine($"VA: {pte.Key:X16}  \t PFN: {pte.Value.PTE}");

                            if (pte.Value.PTE.LargePage)
                            {
                                using (var lsavefile = File.OpenWrite(saveLoc + pte.Key.Address.ToString("X") + ".bin"))
                                    // 0x200 * 4kb = 2MB
                                    for (int i = 0; i < 0x200; i++)
                                    {
                                        try { memAxs.GetPageForPhysAddr(pte.Value.PTE, ref block); } catch (Exception ex) { }
                                        pte.Value.PTE.PTE += (i * 0x1000);
                                        if (block == null)
                                            continue;

                                        Buffer.MemoryCopy(lp, bp, 4096, 4096);
                                        lsavefile.Write(bpage, 0, 4096);
                                    }

                            }
                            else
                            {
                                try { memAxs.GetPageForPhysAddr(pte.Value.PTE, ref block); } catch (Exception ex) { }
                                if (block == null)
                                    continue;

                                using (var savefile = File.OpenWrite(saveLoc + pte.Key.Address.ToString("X") + ".bin"))
                                {
                                    Buffer.MemoryCopy(lp, bp, 4096, 4096);
                                    savefile.Write(bpage, 0, 4096);
                                }
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
0
        // TODO: Figure out if MemoryCopy or BlockCopy ...
         

        public string WriteRange(VIRTUAL_ADDRESS KEY, PFN VALUE, string BaseFileName, Mem PhysMemReader = null, bool SinglePFNStore = false, bool DumpNULL = false)
        {
            if (SinglePFNStore && SISmap == null)
                SISmap = new WAHBitArray();

            if(SinglePFNStore)
            {
                if (SISmap.Get((int)VALUE.PTE.PFN))
                    return string.Empty;

                SISmap.Set((int)VALUE.PTE.PFN, true);
            }

            bool canAppend = false;
            var saveLoc = BaseFileName + KEY.Address.ToString("X") + ".bin";
            var lastLoc = BaseFileName + (KEY.Address - ContigSize).ToString("X") + ".bin";

            if (File.Exists(lastLoc))
            {
                canAppend = true;
                ContigSize += 0x1000;
                saveLoc = lastLoc;
            }
            else
                ContigSize = 0x1000;

            //unsafe
            //{
                var block = new long[0x200]; // 0x200 * 8 = 4k
                var bpage = new byte[0x1000];

                //fixed (void* lp = block, bp = bpage)
                //{

                    if (DiagOutput)
                        WriteColor(VALUE.PTE.Valid ? ConsoleColor.Cyan : ConsoleColor.Red,  $"VA: {KEY:X12}  \t PFN: {VALUE.PTE}");

                    // if we have invalid (software managed) page table entries
                    // the data may be present, or a prototype or actually in swap.
                    // for the moment were only going to dump hardware managed data
                    // or feel free to patch this up ;)
                    if (!VALUE.PTE.Valid)
                        return string.Empty;

                    if (VALUE.PTE.LargePage)
                    {
                        bool GoodRead = false;
                        using (var lsavefile = File.OpenWrite(saveLoc))
                        {
                            // 0x200 * 4kb = 2MB
                            // TODO: Large pages properly?
                            // TODO: PageCache is still broken in some cases... disable for now here
                            for (int i = 0; i < 0x200; i++)
                            {
                                PhysMemReader.GetPageForPhysAddr(VALUE.PTE, ref block, ref GoodRead); 
                                VALUE.PTE.PTE += 0x1000;
                                if(!GoodRead)
                                    block = new long[0x200];

                                Buffer.BlockCopy(block, 0, bpage, 0, 4096);
                                //Buffer.MemoryCopy(lp, bp, 4096, 4096);
                                lsavefile.Write(bpage, 0, 4096);
                                //lsavefile.Write(bpage, 0, 4096);

                            }
                            return lastLoc;
                        }
                    }
                    else
                    {
                        try { PhysMemReader.GetPageForPhysAddr(VALUE.PTE, ref block); } catch (Exception ex) { }

                        if (block != null)
                        {
                            if (DumpNULL || !UnsafeHelp.IsZero(block))
                            {
                                Buffer.BlockCopy(block, 0, bpage, 0, 4096);
                               //Buffer.MemoryCopy(lp, bp, 4096, 4096);
                                
                                using (var savefile = (canAppend ? File.Open(lastLoc, FileMode.Append, FileAccess.Write, FileShare.ReadWrite) : File.OpenWrite(saveLoc)))
                                    savefile.Write(bpage, 0, 4096);

                                    //savefile.Write(bpage, 0, 4096);
                                return lastLoc;
                            }
                        }
                    }
                    ContigSize = 0;
                    return string.Empty;
                //}
            //}
        }
Exemplo n.º 7
0
        public void DumpASToFile(List <DetectedProc> ToDump)
        {
            using (var memAxs = new Mem(MemFile, null, DetectedDesc))
            {
                // in all likelyhood this is the kernel
                var tdp = (from p in ToDump
                           where p.AddressSpaceID == 1
                           orderby p.CR3Value ascending
                           select p).Take(1).First();

                // as a test let's find the process with the most to dump

                /*var tdp = (from p in ToDump
                 *             where p.AddressSpaceID == 1
                 *             orderby p.PT.RootPageTable.PFNCount descending
                 *             select p).Take(1).First();
                 */

                var pml4 = tdp.PT.RootPageTable;

                WriteLine($"Test dumping {tdp}, {pml4.PFNCount} entries scanned.");

                var MemRanges = pml4.SubTables.SelectMany(x => x.Value.SubTables).SelectMany(y => y.Value.SubTables).SelectMany(z => z.Value.SubTables);

                //            WriteLine($"MemRanges = {MemRanges.Count()} available.");


                var saveLoc = Path.Combine(Path.GetDirectoryName(MemFile), Path.GetFileName(MemFile) + ".");

                long[] block = new long[0x200]; // 0x200 * 8 = 4k
                byte[] bpage = new byte[0x1000];

                unsafe
                {
                    fixed(void *lp = block, bp = bpage)
                    {
                        foreach (var pte in MemRanges)
                        {
                            if (VerboseOutput)
                            {
                                WriteLine($"VA: {pte.Key:X16}  \t PFN: {pte.Value.PTE}");
                            }

                            if (pte.Value.PTE.LargePage)
                            {
                                using (var lsavefile = File.OpenWrite(saveLoc + pte.Key.Address.ToString("X") + ".bin"))
                                    // 0x200 * 4kb = 2MB
                                    for (int i = 0; i < 0x200; i++)
                                    {
                                        try { memAxs.GetPageForPhysAddr(pte.Value.PTE, ref block); } catch (Exception ex) { }
                                        pte.Value.PTE.PTE += (i * 0x1000);
                                        if (block == null)
                                        {
                                            continue;
                                        }

                                        Buffer.MemoryCopy(lp, bp, 4096, 4096);
                                        lsavefile.Write(bpage, 0, 4096);
                                    }
                            }
                            else
                            {
                                try { memAxs.GetPageForPhysAddr(pte.Value.PTE, ref block); } catch (Exception ex) { }
                                if (block == null)
                                {
                                    continue;
                                }

                                using (var savefile = File.OpenWrite(saveLoc + pte.Key.Address.ToString("X") + ".bin"))
                                {
                                    Buffer.MemoryCopy(lp, bp, 4096, 4096);
                                    savefile.Write(bpage, 0, 4096);
                                }
                            }
                        }
                    }
                }
            }
        }