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