public static Vtero Scanit(ConfigOptions co) { bool SkipVMCS = (co.VersionsToEnable & PTType.VMCS) != PTType.VMCS; var Filename = co.FileName; co.VersionsToEnable = co.VersionsToEnable & ~PTType.VMCS; // allocate now so that we can un-serialize or keep an instance Vtero vtero = new Vtero(); // this instance is temporally used for loading state // i.e. don't set properties or fields here var saveStateFile = $"{Filename}.inVtero.net"; if (File.Exists(saveStateFile)) { if (!co.IgnoreSaveData) { vtero = vtero.CheckpointRestoreState(saveStateFile); if(vtero == null) { WriteColor(ConsoleColor.Red, "ERROR IN SERIALIZER"); return null; } vtero.OverRidePhase = true; } else File.Delete(saveStateFile); } if (vtero.Phase < 2) vtero = new Vtero(Filename); if (!vtero.OverRidePhase) { Mem.InitMem(co.FileName, vtero.MRD); ProgressBarz.BaseMessage = new ConsoleString("First pass, looking for processes"); ForegroundColor = ConsoleColor.Cyan; #if TESTING Timer = Stopwatch.StartNew(); if ((Version & PTType.VALUE) == PTType.VALUE) { var off = vtero.ScanValue(Is64Scan, valuL, 0); WriteLine(FormatRate(vtero.FileSize, Timer.Elapsed)); using (var dstream = File.OpenRead(vtero.MemFile)) { using (var dbin = new BinaryReader(dstream)) { foreach (var xoff in off) { WriteLine($"Checking Memory Descriptor @{(xoff + 28):X}"); if (xoff > vtero.FileSize) { WriteLine($"offset {xoff:X} > FileSize {vtero.FileSize:X}"); continue; } dstream.Position = xoff + 28; var MemRunDescriptor = new MemoryDescriptor(); MemRunDescriptor.NumberOfRuns = dbin.ReadInt64(); MemRunDescriptor.NumberOfPages = dbin.ReadInt64(); Console.WriteLine($"Runs: {MemRunDescriptor.NumberOfRuns}, Pages: {MemRunDescriptor.NumberOfPages} "); if (MemRunDescriptor.NumberOfRuns < 0 || MemRunDescriptor.NumberOfRuns > 32) { continue; } for (int i = 0; i < MemRunDescriptor.NumberOfRuns; i++) { var basePage = dbin.ReadInt64(); var pageCount = dbin.ReadInt64(); MemRunDescriptor.Run.Add(new MemoryRun() { BasePage = basePage, PageCount = pageCount }); } WriteLine($"MemoryDescriptor {MemRunDescriptor}"); } } } WriteLine("Finished VALUE scan."); return; } if ((Version & PTType.VALUE) == PTType.VALUE) return; #endif } // basic perf checking QuickOptions.Timer = Stopwatch.StartNew(); var procCount = vtero.ProcDetectScan(co.VersionsToEnable); if (!vtero.OverRidePhase) { WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{procCount} candidate process page tables. Time so far: {QuickOptions.Timer.Elapsed}, second pass starting. {QuickOptions.FormatRate(vtero.FileSize, QuickOptions.Timer.Elapsed)}"); if (procCount < 3) { WriteColor(ConsoleColor.Red, "Seems like a fail. Try generic scanning or implement a state scan like LinuxS"); return null; } } // second pass // with the page tables we acquired, locate candidate VMCS pages in the format // [31-bit revision id][abort indicator] // the page must also have at least 1 64bit value which is all set (-1) // Root-HOST CR3 will have uniform diff // unless an extent based dump image is input, some .DMP variations // TODO: Add support for extent based inputs // Guest VMCS will contain host CR3 & guest CR3 (hCR3 & gCR3) // sometimes CR3 will be found in multiple page tables, e.g. system process or SMP // if I have more than 1 CR3 from different file_offset, just trim them out for now // future may have a reason to isolate based on original locationAG if (SkipVMCS) { if (!vtero.OverRidePhase) vtero.GroupAS(); if (co.VerboseLevel > 1) WriteColor(ConsoleColor.Yellow, "Skipping VMCS scan (as requested)."); } else { ProgressBarz.BaseMessage = new ConsoleString("Second pass, correlating for VMCS pages"); var VMCSCount = vtero.VMCSScan(); //Timer.Stop(); if (!vtero.OverRidePhase) { WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"{VMCSCount} candidate VMCS pages. Time to process: {QuickOptions.Timer.Elapsed}, Data scanned: {vtero.FileSize:N}"); // second time WriteColor(ConsoleColor.Blue, ConsoleColor.Yellow, $"Second pass done. {QuickOptions.FormatRate(vtero.FileSize * 2, QuickOptions.Timer.Elapsed)}"); // each of these depends on a VMCS scan/pass having been done at the moment WriteColor(ConsoleColor.Cyan, ConsoleColor.Black, "grouping and joining all memory"); } // After this point were fairly functional vtero.GroupAS(); } // sync-save state so restarting is faster if (!File.Exists(saveStateFile)) { Write($"Saving checkpoint... "); saveStateFile = vtero.CheckpointSaveState(); WriteColor(ConsoleColor.White, saveStateFile); } Console.CursorVisible = true; return vtero; }
public static void DumpIt(Vtero vtero, ConfigOptions co, DumpOptions dmpo) { var Version = vtero.Version; Mem.InitMem(co.FileName, vtero.MRD); // Extract Address Spaces verifies the linkages between // process<->CR3<->EPTP(if there is one) // and that they are functional var vetted = vtero.ExtrtactAddressSpaces(null, null, Version); // leaving this in as an example maybe? ;) //WriteLine("enter a group ID: "); //input = ReadLine(); //int Grp = int.Parse(input); //WriteLine("enter a process ID: "); //input = ReadLine(); //long procID = long.Parse(input, NumberStyles.HexNumber); //var proc = (from procz in vtero.ASGroups[Grp] // where procz.CR3Value == procID // select procz).First(); //int i = 1; //DetectedProc dp = proc; //while(dp == null) // dp = vtero.GetKernelRangeFromGroup(i++); // Scan for kernel // NT kernel may be in 0xFFFFF80000000 to 0xFFFFF8800000 range long KernVAStart = 0xF80000000000; long KernVAEnd = KernVAStart + (0x8000000000 - 0x1000); string input = string.Empty; var Detections = new Dictionary <long, Extract>(); DetectedProc LikelyKernel = null; bool Decoded = false; // were doing this in nested loops to brute force our way past any errors // but only need the first set of detections per group foreach (var grpz in vtero.ASGroups) { foreach (var vm in vtero.VMCSs.Values) { WriteColor(ConsoleColor.White, $"Group ID: {grpz.Key}"); foreach (var p in grpz.Value) { WriteLine($"Proc: {p.CR3Value:X}"); Detections = Detections.Concat( vtero.ModuleScan(p, 3, KernVAStart, KernVAEnd).Where(x => !Detections.ContainsKey(x.Key))) .ToDictionary(x => x.Key, x => x.Value); if (Detections.Count() > 0) { LikelyKernel = p; if (vm.EPTP == 0) { p.vmcs = null; } else { p.vmcs = vm; } // scan for kernel foreach (var detected in Detections) { WriteColor(ConsoleColor.Green, $"Attempting to parse detected PE module loaded @ {detected.Key:X}"); WriteColor(ConsoleColor.Cyan, detected.Value.ToString()); if (detected.Value.ToString().Contains("POOLCODE")) { WriteColor(ConsoleColor.White, "Likely Kernel analyzing for CV data"); /* * var cv_data = vtero.ExtractCVDebug(LikelyKernel, detected.Value, detected.Key); * * if (cv_data != null) * { * var sympath = Environment.GetEnvironmentVariable("_NT_SYMBOL_PATH"); * if (string.IsNullOrWhiteSpace(sympath)) * sympath = "SRV*http://msdl.microsoft.com/download/symbols"; * * if (Vtero.TryLoadSymbols(cv_data, detected.Key, sympath)) * Decoded = vtero.GetKernelDebuggerData(LikelyKernel, detected.Value, cv_data, sympath); * } */ } } } if (Decoded) { break; } } if (Decoded) { break; } } if (Decoded) { break; } } ForegroundColor = ConsoleColor.Green; WriteLine($"{Environment.NewLine}Final analysis completed, address spaces extracted. {QuickOptions.Timer.Elapsed} {QuickOptions.FormatRate(vtero.FileSize * 3, QuickOptions.Timer.Elapsed)}"); // do a test dump // extract & dump could be done at the same time if (!dmpo.ListOnly) { vtero.DumpASToFile(); } //if (Vtero.VerboseOutput) //vtero.DumpFailList(); return; }
public void config([DefaultValue(""), ArgDescription("set true to ")] string reset, [DefaultValue(""), ArgDescription("will dump history or clear")] string history) { // dump info if (reset.StartsWith("his") || string.IsNullOrWhiteSpace(reset)) { ConsoleString.WriteLine(option, ConsoleColor.White); var tc = (typeof(CLI).GetCustomAttributes(typeof(TabCompletion), true)[0] as TabCompletion); if(!File.Exists(tc.HistoryFileNameInternal) || new FileInfo(tc.HistoryFileNameInternal).Length <= 1) ConsoleString.WriteLine($"History file {tc.HistoryFileNameInternal} contains no data. (check permissions)", ConsoleColor.Yellow); if(!string.IsNullOrWhiteSpace(history) || reset.StartsWith("his")) foreach (var line in File.ReadAllLines(tc.HistoryFileNameInternal)) ConsoleString.WriteLine(line, ConsoleColor.White); } else if(reset.Equals("reset")) { option = null; if(history.StartsWith("hist")) (typeof(CLI).GetCustomAttributes(typeof(TabCompletion), true)[0] as TabCompletion).ClearHistory(); option = new ConfigOptions(); MemoryDump = null; ConsoleString.WriteLine("done clearing data"); } }
public static void DumpIt(Vtero vtero, ConfigOptions co, DumpOptions dmpo) { var Version = vtero.Version; Mem.InitMem(co.FileName, vtero.MRD); // Extract Address Spaces verifies the linkages between // process<->CR3<->EPTP(if there is one) // and that they are functional var vetted = vtero.ExtrtactAddressSpaces(null, null, Version); // leaving this in as an example maybe? ;) //WriteLine("enter a group ID: "); //input = ReadLine(); //int Grp = int.Parse(input); //WriteLine("enter a process ID: "); //input = ReadLine(); //long procID = long.Parse(input, NumberStyles.HexNumber); //var proc = (from procz in vtero.ASGroups[Grp] // where procz.CR3Value == procID // select procz).First(); //int i = 1; //DetectedProc dp = proc; //while(dp == null) // dp = vtero.GetKernelRangeFromGroup(i++); // Scan for kernel // NT kernel may be in 0xFFFFF80000000 to 0xFFFFF8800000 range long KernVAStart = 0xF80000000000; long KernVAEnd = KernVAStart + (0x8000000000 - 0x1000); string input = string.Empty; var Detections = new Dictionary<long, Extract>(); DetectedProc LikelyKernel = null; bool Decoded = false; // were doing this in nested loops to brute force our way past any errors // but only need the first set of detections per group foreach (var grpz in vtero.ASGroups) { foreach (var vm in vtero.VMCSs.Values) { WriteColor(ConsoleColor.White, $"Group ID: {grpz.Key}"); foreach (var p in grpz.Value) { WriteLine($"Proc: {p.CR3Value:X}"); Detections = Detections.Concat( vtero.ModuleScan(p, KernVAStart, KernVAEnd).Where(x => !Detections.ContainsKey(x.Key))) .ToDictionary(x => x.Key, x => x.Value); if (Detections.Count() > 0) { LikelyKernel = p; if (vm.EPTP == 0) p.vmcs = null; else p.vmcs = vm; // scan for kernel foreach (var detected in Detections) { WriteColor(ConsoleColor.Green, $"Attempting to parse detected PE module loaded @ {detected.Key:X}"); WriteColor(ConsoleColor.Cyan, detected.Value.ToString()); if (detected.Value.ToString().Contains("POOLCODE")) { WriteColor(ConsoleColor.White, "Likely Kernel analyzing for CV data"); /* * var cv_data = vtero.ExtractCVDebug(LikelyKernel, detected.Value, detected.Key); if (cv_data != null) { var sympath = Environment.GetEnvironmentVariable("_NT_SYMBOL_PATH"); if (string.IsNullOrWhiteSpace(sympath)) sympath = "SRV*http://msdl.microsoft.com/download/symbols"; if (vtero.TryLoadSymbols(cv_data, detected.Key, sympath)) Decoded = vtero.GetKernelDebuggerData(LikelyKernel, detected.Value, cv_data, sympath); } */ } } } if (Decoded) break; } if (Decoded) break; } if (Decoded) break; } ForegroundColor = ConsoleColor.Green; WriteLine($"{Environment.NewLine}Final analysis completed, address spaces extracted. {QuickOptions.Timer.Elapsed} {QuickOptions.FormatRate(vtero.FileSize * 3, QuickOptions.Timer.Elapsed)}"); // do a test dump // extract & dump could be done at the same time if(!dmpo.ListOnly) vtero.DumpASToFile(); //if (Vtero.VerboseOutput) //vtero.DumpFailList(); return; }
public CLI() { if (option == null) option = new ConfigOptions(); option.VersionsToEnable = PTType.Windows | PTType.FreeBSD | PTType.VMCS | PTType.HyperV; }