Ejemplo n.º 1
0
        /// <summary>
        ///
        /// Pretty much not used any more, but I guess I can leave it in for a bit.  Trying to decide
        /// if I should focus on the core and release a bunch of .csx scripts seems everybody likes scripts these days
        ///
        /// Or maybe write a UI.... hmmmm
        ///
        ///
        /// 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>
        ///
        // TODO: RE-RE-Write this into an on-demand evaluated set of delegates to ease memory load
        // some testing on Windows 10: Virtualized Process PT Entries [1625181] Type [Windows] PID [97C0301E:1AB000]
        // that's over _1.6 Million_ page table entries, wow!!!
        long InlineExtract(PageTableRoot Root, int Depth = 4)
        {
            VIRTUAL_ADDRESS VAddr;

            var entries = 0L;

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

            // pull level 4 entries attach level 3
            foreach (var top_sub in top.SubTables)
            {
                //WriteLine($"4: Scanning {top_sub.Value.PTE:X16}");
                // 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;

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

                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;

                    //WriteLine($"3: Scanning VA {s3va.Address:X16}");

                    // save 'PFN' entry into sub-table I should really revisit all these names
                    VAddr = new VIRTUAL_ADDRESS(s3va.Address);
                    var l3PFN = new PFN()
                    {
                        PTE = l3PTE, VA = VAddr
                    };

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

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

                        // 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;
                            ///WriteLine($"2: Scanning VA {s2va.Address:X16}");
                            VAddr = new VIRTUAL_ADDRESS(s2va.Address);
                            var l2PFN = new PFN()
                            {
                                PTE = l2PTE, VA = VAddr
                            };

                            l3PFN.SubTables.Add(s2va, l2PFN);
                            entries++;


                            if (!l2PTE.LargePage && !KernelSpace)
                            {
                                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;
                                }

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

                                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;

                                    //WriteLine($"1: Scanning VA {s1va.Address:X16}");
                                    // copy this since were in a loop scanning and it (VA) changes every time
                                    VAddr = new VIRTUAL_ADDRESS(s1va.Address);
                                    var l1PFN = new PFN()
                                    {
                                        PTE = l1PTE, VA = VAddr
                                    };

                                    l2PFN.SubTables.Add(s1va, l1PFN);
                                    entries++;
                                }
                            }
                        }
                    }
                }
            }
            //top.PFNCount += entries;
            return(entries);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 
        /// Pretty much not used any more, but I guess I can leave it in for a bit.  Trying to decide 
        /// if I should focus on the core and release a bunch of .csx scripts seems everybody likes scripts these days
        /// 
        /// Or maybe write a UI.... hmmmm
        /// 
        /// 
        /// 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>
        /// 
        // TODO: RE-RE-Write this into an on-demand evaluated set of delegates to ease memory load
        // some testing on Windows 10: Virtualized Process PT Entries [1625181] Type [Windows] PID [97C0301E:1AB000]
        // that's over _1.6 Million_ page table entries, wow!!!
        long InlineExtract(PageTableRoot Root, int Depth = 4)
        {
            VIRTUAL_ADDRESS VAddr;

            var entries = 0L;

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

            // pull level 4 entries attach level 3
            foreach (var top_sub in top.SubTables)
            {
                //WriteLine($"4: Scanning {top_sub.Value.PTE:X16}");
                // 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;

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

                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;

                    //WriteLine($"3: Scanning VA {s3va.Address:X16}");

                    // save 'PFN' entry into sub-table I should really revisit all these names
                    VAddr = new VIRTUAL_ADDRESS(s3va.Address);
                    var l3PFN = new PFN() { PTE = l3PTE, VA = VAddr };

                    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;

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

                        // 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;
                            ///WriteLine($"2: Scanning VA {s2va.Address:X16}");
                            VAddr = new VIRTUAL_ADDRESS(s2va.Address);
                            var l2PFN = new PFN() { PTE = l2PTE, VA = VAddr };

                            l3PFN.SubTables.Add(s2va, l2PFN);
                            entries++;


                            if (!l2PTE.LargePage && !KernelSpace)
                            {
                                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;

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

                                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;

                                    //WriteLine($"1: Scanning VA {s1va.Address:X16}");
                                    // copy this since were in a loop scanning and it (VA) changes every time
                                    VAddr = new VIRTUAL_ADDRESS(s1va.Address);
                                    var l1PFN = new PFN() { PTE = l1PTE, VA = VAddr };

                                    l2PFN.SubTables.Add(s1va, l1PFN);
                                    entries++;
                                }
                            }
                        }
                    }
                }
            }
            //top.PFNCount += entries;
            return entries;
        }