EPTP for SLAT configuration hypervisors 64-ia-32-architectures-software-developer-system-programming-manual-325384.pdf Section 24.6.11
Пример #1
1
        /// <summary>
        /// The VMCS scan is based on the LINK pointer, abort code and CR3 register
        /// We  later isolate the EPTP based on constraints for that pointer
        /// </summary>
        /// <param name="xoffset"></param>
        /// <returns>true if the page being scanned is a candidate</returns>
        public bool VMCS(long xoffset)
        {
            var RevID = (REVISION_ID)(block[0] & 0xffffffff);
            var Acode = (VMCS_ABORT)((block[0] >> 32) & 0x7fffffff);

            var KnownAbortCode = false;
            var KnownRevision = false;
            var Candidate = false;
            var LinkCount = 0;
            var Neg1 = -1;

            if (ScanForVMCSset == null)
                throw new NullReferenceException("Entered VMCS callback w/o having found any VMCS, this is a second pass Func");

            // this might be a bit micro-opt-pointless ;)
            KnownRevision = typeof(REVISION_ID).GetEnumValues().Cast<REVISION_ID>().Any(x => x == RevID);
            KnownAbortCode = typeof(VMCS_ABORT).GetEnumValues().Cast<VMCS_ABORT>().Any(x => x == Acode);

            // TODO: Relax link pointer check. Possible when VMCS is shadow, then the link pointer is configured, retest this detection/nesting etc..
            // Find a 64bit value for link ptr
            for (int l = 0; l < block.Length; l++)
            {
                if (block[l] == Neg1)
                    LinkCount++;

                // too many
                if (LinkCount > 32)
                    return false;
            }
            // Currently, we expect to have 1 Link pointer at least
            if (LinkCount == 0 || !KnownAbortCode)
                return false;

            // curr width of line to screen
            Candidate = false;
            Parallel.For(0, ScanForVMCSset.Length, (v) =>
            {
                var ScanFor = ScanForVMCSset[v];

                for (int check = 1; check < block.Length; check++)
                {
                    if (block[check] == ScanFor.CR3Value && Candidate == false)
                    {
                        var OutputList = new List<long>();
                        StringBuilder sb = null, sbRED = null;
                        byte[] shorted = null;
                        var curr_width = 0;

                        if (Vtero.VerboseOutput)
                        {
                            sb = new StringBuilder();
                            // reverse endianness for easy reading in hex dumps/editors
                            shorted = BitConverter.GetBytes(block[check]);
                            Array.Reverse(shorted, 0, 8);
                            var Converted = BitConverter.ToUInt64(shorted, 0);

                            sbRED = new StringBuilder();
                            sbRED.Append($"Hypervisor: VMCS revision field: {RevID} [{((uint)RevID):X8}] abort indicator: {Acode} [{((int)Acode):X8}]{Environment.NewLine}");
                            sbRED.Append($"Hypervisor: {ScanFor.PageTableType} CR3 found [{ScanFor.CR3Value:X16})] byte-swapped: [{Converted:X16}] @ PAGE/File Offset = [{xoffset:X16}]");
                        }

                        for (int i = 0; i < block.Length; i++)
                        {
                            var value = block[i];

                            var eptp = new EPTP(value);

                            // any good minimum size? 64kb?
                            if (block[i] > 0
                            && block[i] < FileSize
                            && eptp.IsFullyValidated()
                   //         && EPTP.IsValid(eptp.aEPTP) && EPTP.IsValid2(eptp.aEPTP) && EPTP.IsValidEntry(eptp.aEPTP)
                            && !OutputList.Contains(block[i]))
                            {
                                Candidate = true;
                                OutputList.Add(block[i]);

                                if (Vtero.VerboseOutput)
                                {
                                    var linefrag = $"[{i}][{block[i]:X16}] ";

                                    if (curr_width + linefrag.Length > MAX_LINE_WIDTH)
                                    {
                                        sb.Append(Environment.NewLine);
                                        curr_width = 0;
                                    }
                                    sb.Append(linefrag);
                                    curr_width += linefrag.Length;
                                }

                            }
                        }
                        if (Candidate && Vtero.VerboseOutput)
                        {
                            WColor(ConsoleColor.Red, ConsoleColor.Black, sbRED.ToString().PadRight(WindowWidth));
                            WColor(ConsoleColor.DarkGreen, ConsoleColor.Black, sb.ToString().PadRight(WindowWidth));
                        }

                        // most VMWare I've scanned comes are using this layout
                        // we know VMWare well so ignore any other potential candidates // TODO: Constantly Verify assumption's 
                        if (RevID == REVISION_ID.VMWARE_NESTED && OutputList.Contains(block[14]))
                        {
                            var vmcsFound = new VMCS { dp = ScanFor, EPTP = block[14], gCR3 = ScanFor.CR3Value, Offset = xoffset };
                            HVLayer.Add(vmcsFound);
                        }
                        else
                            foreach (var entry in OutputList)
                                HVLayer.Add(new VMCS { dp = ScanFor, EPTP = entry, gCR3 = ScanFor.CR3Value, Offset = xoffset });
                    }
                }
            });
            return Candidate;
        }
Пример #2
1
        /// <summary>
        /// The VMCS scan is based on the LINK pointer, abort code and CR3 register
        /// We  later isolate the EPTP based on constraints for that pointer
        /// </summary>
        /// <param name="xoffset"></param>
        /// <returns>true if the page being scanned is a candidate</returns>
        public bool VMCS(long xoffset)
        {
            var RevID = (REVISION_ID)(block[0] & 0xffffffff);
            var Acode = (VMCS_ABORT)((block[0] >> 32) & 0x7fffffff);

            var KnownAbortCode = false;
            var KnownRevision = false;
            var Candidate = false;
            var LinkCount = 0;
            var Neg1 = -1;

            if(VMCSScanSet == null)
                throw new NullReferenceException("Entered VMCS callback w/o having found any VMCS, this is a second pass Func") ;

            // this might be a bit micro-opt-pointless ;)
            //Parallel.Invoke(() =>
            //{
            KnownRevision = typeof(REVISION_ID).GetEnumValues().Cast<REVISION_ID>().Any(x => x == RevID);
            //}, () =>
            //{
            KnownAbortCode = typeof(VMCS_ABORT).GetEnumValues().Cast<VMCS_ABORT>().Any(x => x == Acode);
            //});



            // TODO: Link pointer may not always be needed, evaluate removing this constraint
            // Find a 64bit value for link ptr
            for (int l = 0; l < block.Length; l++)
            {
                if (block[l] == Neg1)
                    LinkCount++;

                // too many
                if (LinkCount > 32)
                    return false;
            }
            // Currently, we expect to have 1 Link pointer at least
            if (LinkCount == 0 || !KnownAbortCode)
                return false;

            // curr width of line to screen
            Candidate = false;
            Parallel.For(0, VMCSScanSet.Length, (v) =>
            {
                var vmcs_entry = VMCSScanSet[v];

                for (int check = 1; check < block.Length; check++)
                {
                    if (block[check] == vmcs_entry.CR3Value && Candidate == false)
                    {
                        var OutputList = new List<long>();
                        StringBuilder sb = null, sbRED = null;
                        byte[] shorted = null;
                        var curr_width = 0;

                        if (Vtero.VerboseOutput)
                        {
                            sb = new StringBuilder();
                            // reverse endianess for easy reading in hex dumps/editors
                            shorted = BitConverter.GetBytes(block[check]);
                            Array.Reverse(shorted, 0, 8);
                            var Converted = BitConverter.ToUInt64(shorted, 0);

                            sbRED = new StringBuilder();
                            sbRED.Append($"Hypervisor: VMCS revision field: {RevID} [{((uint)RevID):X8}] abort indicator: {Acode} [{((int)Acode):X8}]{Environment.NewLine}");
                            sbRED.Append($"Hypervisor: {vmcs_entry.PageTableType} CR3 found [{vmcs_entry.CR3Value:X16})] byte-swapped: [{Converted:X16}] @ PAGE/File Offset = [{xoffset:X16}]");
                        }

                        for (int i = 0; i < block.Length; i++)
                        {
                            var eptp = new EPTP(block[i]);

                            // any good minimum size? 64kb?
                            if (block[i] > 0
                            && block[i] < FileSize
                            && eptp.IsFullyValidated()
                            && !OutputList.Contains(block[i]))
                            {
                                Candidate = true;
                                OutputList.Add(block[i]);

                                if (Vtero.VerboseOutput)
                                {
                                    var linefrag = $"[{i}][{block[i]:X16}] ";

                                    if (curr_width + linefrag.Length > MAX_LINE_WIDTH)
                                    {
                                        sb.Append(Environment.NewLine);
                                        curr_width = 0;
                                    }
                                    sb.Append(linefrag);
                                    curr_width += linefrag.Length;
                                }

                            }
                        }
                        if (Candidate && Vtero.VerboseOutput)
                        {
                            ForegroundColor = ConsoleColor.Red;
                            WriteLine(sbRED.ToString());
                            ForegroundColor = ConsoleColor.DarkGreen;
                            WriteLine(sb.ToString());
                        }

                        VMCS vmcsFound = null;
                        // most VMWare I've scanned comes are using this layout
                        if (RevID == REVISION_ID.VMWARE_NESTED && OutputList.Contains(block[14]))
                            vmcsFound = new VMCS { dp = vmcs_entry, EPTP = block[14], gCR3 = vmcs_entry.CR3Value };
                        else if (OutputList.Count() == 1)
                            vmcsFound = new net.VMCS { dp = vmcs_entry, EPTP = OutputList[0], gCR3 = vmcs_entry.CR3Value };

                        if (vmcsFound != null)
                            HVLayer.Add(vmcsFound);
                    }
                }
            });
            return Candidate;
        }
Пример #3
0
        /// <summary>
        /// The VMCS scan is based on the LINK pointer, abort code and CR3 register
        /// We  later isolate the EPTP based on constraints for that pointer
        /// </summary>
        /// <param name="xoffset"></param>
        /// <returns>true if the page being scanned is a candidate</returns>
        public bool VMCS(long xoffset)
        {
            var RevID = (REVISION_ID)(block[0] & 0xffffffff);
            var Acode = (VMCS_ABORT)((block[0] >> 32) & 0x7fffffff);

            var KnownAbortCode = false;
            var KnownRevision  = false;
            var Candidate      = false;
            var LinkCount      = 0;
            var Neg1           = -1;

            if (VMCSScanSet == null)
            {
                throw new NullReferenceException("Entered VMCS callback w/o having found any VMCS, this is a second pass Func");
            }

            // this might be a bit micro-opt-pointless ;)
            //Parallel.Invoke(() =>
            //{
            KnownRevision = typeof(REVISION_ID).GetEnumValues().Cast <REVISION_ID>().Any(x => x == RevID);
            //}, () =>
            //{
            KnownAbortCode = typeof(VMCS_ABORT).GetEnumValues().Cast <VMCS_ABORT>().Any(x => x == Acode);
            //});



            // TODO: Link pointer may not always be needed, evaluate removing this constraint
            // Find a 64bit value for link ptr
            for (int l = 0; l < block.Length; l++)
            {
                if (block[l] == Neg1)
                {
                    LinkCount++;
                }

                // too many
                if (LinkCount > 32)
                {
                    return(false);
                }
            }
            // Currently, we expect to have 1 Link pointer at least
            if (LinkCount == 0 || !KnownAbortCode)
            {
                return(false);
            }

            // curr width of line to screen
            Candidate = false;
            Parallel.For(0, VMCSScanSet.Length, (v) =>
            {
                var vmcs_entry = VMCSScanSet[v];

                for (int check = 1; check < block.Length; check++)
                {
                    if (block[check] == vmcs_entry.CR3Value && Candidate == false)
                    {
                        var OutputList   = new List <long>();
                        StringBuilder sb = null, sbRED = null;
                        byte[] shorted   = null;
                        var curr_width   = 0;

                        if (Vtero.VerboseOutput)
                        {
                            sb = new StringBuilder();
                            // reverse endianess for easy reading in hex dumps/editors
                            shorted = BitConverter.GetBytes(block[check]);
                            Array.Reverse(shorted, 0, 8);
                            var Converted = BitConverter.ToUInt64(shorted, 0);

                            sbRED = new StringBuilder();
                            sbRED.Append($"Hypervisor: VMCS revision field: {RevID} [{((uint)RevID):X8}] abort indicator: {Acode} [{((int)Acode):X8}]{Environment.NewLine}");
                            sbRED.Append($"Hypervisor: {vmcs_entry.PageTableType} CR3 found [{vmcs_entry.CR3Value:X16})] byte-swapped: [{Converted:X16}] @ PAGE/File Offset = [{xoffset:X16}]");
                        }

                        for (int i = 0; i < block.Length; i++)
                        {
                            var eptp = new EPTP(block[i]);

                            // any good minimum size? 64kb?
                            if (block[i] > 0 &&
                                block[i] < FileSize &&
                                eptp.IsFullyValidated() &&
                                !OutputList.Contains(block[i]))
                            {
                                Candidate = true;
                                OutputList.Add(block[i]);

                                if (Vtero.VerboseOutput)
                                {
                                    var linefrag = $"[{i}][{block[i]:X16}] ";

                                    if (curr_width + linefrag.Length > MAX_LINE_WIDTH)
                                    {
                                        sb.Append(Environment.NewLine);
                                        curr_width = 0;
                                    }
                                    sb.Append(linefrag);
                                    curr_width += linefrag.Length;
                                }
                            }
                        }
                        if (Candidate && Vtero.VerboseOutput)
                        {
                            ForegroundColor = ConsoleColor.Red;
                            WriteLine(sbRED.ToString());
                            ForegroundColor = ConsoleColor.DarkGreen;
                            WriteLine(sb.ToString());
                        }

                        VMCS vmcsFound = null;
                        // most VMWare I've scanned comes are using this layout
                        if (RevID == REVISION_ID.VMWARE_NESTED && OutputList.Contains(block[14]))
                        {
                            vmcsFound = new VMCS {
                                dp = vmcs_entry, EPTP = block[14], gCR3 = vmcs_entry.CR3Value
                            }
                        }
                        ;
                        else if (OutputList.Count() == 1)
                        {
                            vmcsFound = new net.VMCS {
                                dp = vmcs_entry, EPTP = OutputList[0], gCR3 = vmcs_entry.CR3Value
                            }
                        }
                        ;

                        if (vmcsFound != null)
                        {
                            HVLayer.Add(vmcsFound);
                        }
                    }
                }
            });
            return(Candidate);
        }
Пример #4
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);
        }
Пример #5
0
        /// <summary>
        /// The VMCS scan is based on the LINK pointer, abort code and CR3 register
        /// We  later isolate the EPTP based on constraints for that pointer
        /// </summary>
        /// <param name="xoffset"></param>
        /// <returns>true if the page being scanned is a candidate</returns>
        public bool VMCS(int bo, long xoffset)
        {
            var RevID = (REVISION_ID)(block[bo + 0] & 0xffffffff);
            var Acode = (VMCS_ABORT)((block[bo + 0] >> 32) & 0x7fffffff);

            var KnownAbortCode = false;
            var KnownRevision  = false;
            var Candidate      = false;
            var LinkCount      = 0;
            var Neg1           = -1;

            if (ScanForVMCSset == null)
            {
                throw new NullReferenceException("Entered VMCS callback w/o having found any VMCS, this is a second pass Func");
            }

            // this might be a bit micro-opt-pointless ;)
            KnownRevision  = typeof(REVISION_ID).GetEnumValues().Cast <REVISION_ID>().Any(x => x == RevID);
            KnownAbortCode = typeof(VMCS_ABORT).GetEnumValues().Cast <VMCS_ABORT>().Any(x => x == Acode);

            // TODO: Relax link pointer check. Possible when VMCS is shadow, then the link pointer is configured, retest this detection/nesting etc..
            // Find a 64bit value for link ptr
            for (int l = 0; l < block.Length; l++)
            {
                if (block[bo + l] == Neg1)
                {
                    LinkCount++;
                }

                // too many
                if (LinkCount > 32)
                {
                    return(false);
                }
            }
            // Currently, we expect to have 1 Link pointer at least
            if (LinkCount == 0 || !KnownAbortCode)
            {
                return(false);
            }

            // curr width of line to screen
            Candidate = false;
            Parallel.For(0, ScanForVMCSset.Length, (v) =>
            {
                var ScanFor = ScanForVMCSset[v];

                for (int check = 1; check < block.Length; check++)
                {
                    if (block[bo + check] == ScanFor.CR3Value && Candidate == false)
                    {
                        var OutputList   = new List <long>();
                        StringBuilder sb = null, sbRED = null;
                        byte[] shorted   = null;
                        var curr_width   = 0;

                        if (Vtero.VerboseOutput)
                        {
                            sb = new StringBuilder();
                            // reverse endianness for easy reading in hex dumps/editors
                            shorted = BitConverter.GetBytes(block[bo + check]);
                            Array.Reverse(shorted, 0, 8);
                            var Converted = BitConverter.ToUInt64(shorted, 0);

                            sbRED = new StringBuilder();
                            sbRED.Append($"Hypervisor: VMCS revision field: {RevID} [{((uint)RevID):X8}] abort indicator: {Acode} [{((int)Acode):X8}]{Environment.NewLine}");
                            sbRED.Append($"Hypervisor: {ScanFor.PageTableType} CR3 found [{ScanFor.CR3Value:X16})] byte-swapped: [{Converted:X16}] @ PAGE/File Offset = [{xoffset:X16}]");
                        }

                        for (int i = 0; i < block.Length; i++)
                        {
                            var value = block[bo + i];

                            var eptp = new EPTP(value);

                            // any good minimum size? 64kb?
                            if (block[bo + i] > 0 &&
                                block[bo + i] < FileSize &&
                                eptp.IsFullyValidated()
                                //         && EPTP.IsValid(eptp.aEPTP) && EPTP.IsValid2(eptp.aEPTP) && EPTP.IsValidEntry(eptp.aEPTP)
                                && !OutputList.Contains(block[bo + i]))
                            {
                                Candidate = true;
                                OutputList.Add(block[bo + i]);

                                if (Vtero.VerboseOutput)
                                {
                                    var linefrag = $"[{i}][{block[bo + i]:X16}] ";

                                    if (curr_width + linefrag.Length > MAX_LINE_WIDTH)
                                    {
                                        sb.Append(Environment.NewLine);
                                        curr_width = 0;
                                    }
                                    sb.Append(linefrag);
                                    curr_width += linefrag.Length;
                                }
                            }
                        }
                        if (Candidate && Vtero.VerboseOutput)
                        {
                            WColor(ConsoleColor.Red, ConsoleColor.Black, sbRED.ToString().PadRight(WindowWidth));
                            WColor(ConsoleColor.DarkGreen, ConsoleColor.Black, sb.ToString().PadRight(WindowWidth));
                        }

                        // most VMWare I've scanned comes are using this layout
                        // we know VMWare well so ignore any other potential candidates // TODO: Constantly Verify assumption's
                        if (RevID == REVISION_ID.VMWARE_NESTED && OutputList.Contains(block[bo + 14]))
                        {
                            var vmcsFound = new VMCS {
                                dp = ScanFor, EPTP = block[bo + 14], gCR3 = ScanFor.CR3Value, Offset = xoffset
                            };
                            HVLayer.Add(vmcsFound);
                        }
                        else
                        {
                            foreach (var entry in OutputList)
                            {
                                HVLayer.Add(new VMCS {
                                    dp = ScanFor, EPTP = entry, gCR3 = ScanFor.CR3Value, Offset = xoffset
                                });
                            }
                        }
                    }
                }
            });
            return(Candidate);
        }