Moving things around to support save state If it turns out that we are to parse the input aggressivly, it may make sence to not have to waste time doing the same analysis over again Rooting everything off of a main class helps the structure a bit
Пример #1
0
        public static void DumpDetected(Vtero vtero, DetectedProc p, long VAStart = 0, long VAEnd = 0xffffffff0000)
        {
            var mods = vtero.ModuleScan(p, 3, VAStart, VAEnd);

            //Parallel.ForEach(mods, (detected) =>
            //{
            foreach (var detected in p.Sections)
            {
                var cv_data = vtero.ExtractCVDebug(p, detected.Value);

                if (cv_data != null)
                {
                    var sympath = Environment.GetEnvironmentVariable("_NT_SYMBOL_PATH");
                    if (string.IsNullOrWhiteSpace(sympath))
                    {
                        sympath = "SRV*http://msdl.microsoft.com/download/symbols";
                    }

                    // TODO: fix this or not?
                    //if(Vtero.TryLoadSymbols(p.ID.GetHashCode(), cv_data, detected.Key))
                    //    vtero.KernelProc = p;
                }
            }
            //});
        }
Пример #2
0
        /// <summary>
        /// Initial testing/prototype
        /// Detect/download all binaries in all AS
        /// </summary>
        /// <param name="ops"></param>
        /// <param name="vtero"></param>
        public void StartAnalyze(AnalyzeOptions ops, Vtero vtero)
        {
            long VAStart = 0;
            long VAEnd = VAStart + (0x8000000000 - 0x1000);
            string input = string.Empty;
            var GloalView = new ConcurrentDictionary<DetectedProc, ConcurrentDictionary<long, Extract>>();

            vtero.MemAccess = Mem.InitMem(vtero.MemFile, vtero.MRD);

            if (vtero.VMCSs.Count < 1)
            {
                foreach (var p in vtero.FlattenASGroups)
                {
                    DumpDetected(vtero, p);
                }
                // scan bare metal
                // Parallel.ForEach(vtero.Processes, (p) =>
                //{
                //    WriteColor(ConsoleColor.Cyan, $"Scanning for modules addressable by: {p}");
                //    DumpDetected(vtero, p);
                //});
            }
            else
            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)
                    {
                        DumpDetected(vtero, p);
                    }
                }
            }
        }
Пример #3
0
        public dynamic xStructInfo(string Struct, long[] memRead = null, string Module = "ntkrnlmp")
        {
            MemSection pdb = null;

            if (Module == "ntkrnlmp" && KernelSection != null)
            {
                pdb = KernelSection;
            }
            else
            {
                var pdbPaths = from files in Sections.Values
                               where files.DebugDetails != null &&
                               !string.IsNullOrWhiteSpace(files.DebugDetails.PDBFullPath) &&
                               files.DebugDetails.PDBFullPath.ToLower().Contains(Module.ToLower())
                               select files;

                pdb           = pdbPaths.FirstOrDefault();
                KernelSection = pdb;
            }
            if (sym == null)
            {
                sym = Vtero.TryLoadSymbols(ID.GetHashCode(), pdb.DebugDetails, pdb.VA.Address);
            }
            return(sym.xStructInfo(pdb.DebugDetails.PDBFullPath, Struct, memRead, GetVirtualByte, GetVirtualLong));
        }
Пример #4
0
        public void LoadModulesInRange(long VA, long length, string OnlyModule = null)
        {
            var KVS = new VirtualScanner(this, new Mem(MemAccess));

            foreach (var artifact in KVS.Run(VA, VA + length))
            {
                var ms = new MemSection()
                {
                    IsExec = true, Module = artifact, VA = new VIRTUAL_ADDRESS(artifact.VA)
                };
                var extracted = ExtractCVDebug(ms);
                if (extracted == null)
                {
                    continue;
                }

                if (!string.IsNullOrWhiteSpace(OnlyModule) && OnlyModule != ms.Name)
                {
                    continue;
                }

                if (!Sections.ContainsKey(artifact.VA))
                {
                    Sections.TryAdd(artifact.VA, ms);
                }

                // we can clobber this guy all the time I guess since everything is stateless in Sym and managed
                // entirely by the handle ID really which is local to our GUID so....
                sym = Vtero.TryLoadSymbols(ID.GetHashCode(), ms.DebugDetails, ms.VA.Address);
                if (Vtero.VerboseOutput)
                {
                    WriteColor(ConsoleColor.Green, $"symbol loaded [{sym != null}] from file [{ms.DebugDetails.PDBFullPath}]");
                }
            }
        }
Пример #5
0
        public void DumpProc(string Folder, bool IncludeData = false, bool KernelSpace = true, bool OnlyExec = true)
        {
            //// TODO: BOILER PLATE check perf of using callbacks
            PageTable.AddProcess(this, new Mem(MemAccess));
            var cnt = PT.FillPageQueue(false, KernelSpace);

            Folder = Folder + Path.DirectorySeparatorChar.ToString();
            Directory.CreateDirectory(Folder);

            long ContigSizeState = 0, curr = 0;

            // single threaded worked best so far
            //Parallel.For(0, cnt, (i, loopState) => x
            foreach (var range in PT.FillPageQueue(false, KernelSpace))
            {
                curr++;
                if (Vtero.VerboseLevel > 1)
                {
                    //var curr = cnt - PT.PageQueue.Count;
                    //var done = Convert.ToDouble(curr) / Convert.ToDouble(cnt) * 100.0;
                    Console.CursorLeft = 0;
                    Console.Write($"{curr} scanned");
                }
                if (range.PTE.Valid)
                {
                    // skip data as requested
                    if (!IncludeData && range.PTE.NoExecute)
                    {
                        continue;
                    }

                    Vtero.WriteRange(range.VA, range, Folder, ref ContigSizeState, MemAccess);
                }
            }
        }
Пример #6
0
        public static void DumpDetected(Vtero vtero, DetectedProc p, long VAStart = 0, long VAEnd = 0xffffffff0000)
        {
            var mods = vtero.ModuleScan(p, VAStart, VAEnd);

            // BUGBUG: TODO: Refactor the threadlocal stuff seems were re-entrant unsafe :(
            //Parallel.ForEach(mods, (detected) =>
            //{
            foreach (var detected in mods)
            {
                var cv_data = vtero.ExtractCVDebug(p, 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(p, detected.Value, cv_data, detected.Key, sympath))
                    {
                        vtero.GetKernelDebuggerData(p, detected.Value, cv_data, sympath);
                    }
                }
            }
            //});
        }
Пример #7
0
        public Dumper(Vtero vtero, string outDir, DetectedProc dp, MemRangeArgs args)
        {
            Vtero = vtero;
            DP = dp;
            OutDir = outDir;

            SelectedRegions = args.Regions;
        }
Пример #8
0
        public static Vtero CheckpointRestoreState(string SaveFile)
        {
            Vtero ThisInstance = null;

            using (var SerData = File.OpenRead(SaveFile))
                ThisInstance = Serializer.Deserialize <inVtero.net.Vtero>(SerData);

            return(ThisInstance);
        }
Пример #9
0
 public void LoadSymbols(MemSection OnlyMS = null)
 {
     foreach (var ms in Sections)
     {
         if (OnlyMS == null || (OnlyMS != null && OnlyMS.VA.Address == ms.Key))
         {
             sym = Vtero.TryLoadSymbols(ID.GetHashCode(), ms.Value.DebugDetails, ms.Value.VA.Address);
             if (Vtero.VerboseOutput)
             {
                 WriteColor(ConsoleColor.Green, $"symbol loaded [{sym != null}] from file [{ms.Value.DebugDetails.PDBFullPath}]");
             }
         }
     }
 }
Пример #10
0
        public static void DumpDetected(Vtero vtero, DetectedProc p, long VAStart = 0, long VAEnd = 0xffffffff0000)
        {
            var mods = vtero.ModuleScan(p, VAStart, VAEnd);

            //Parallel.ForEach(mods, (detected) =>
            //{
            foreach (var detected in p.Sections)
            {
                var cv_data = vtero.ExtractCVDebug(p, detected);

                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.VA.Address, sympath))
                        vtero.KernelProc = p;
                }
            }
            //});
        }
Пример #11
0
        public void dump(DumpOptions argz)
        {

            DumpOptions dOptions = argz;

            if(argz == null)
            {
                ArgUsage.GetStyledUsage<DumpOptions>().Write();
                return;
            }

            if (option.IgnoreSaveData)
            {
                ConsoleString.WriteLine("No save state available or requested to ignore, scan first before dumping.", ConsoleColor.Yellow, ConsoleColor.Black);
                return;
            }

            if(vtero == null)
                vtero = Scan.Scanit(option);
          
             Dump.DumpIt(vtero, option, dOptions);
        }
Пример #12
0
        /// <summary>
        /// Initial testing/prototype
        /// Detect/download all binaries in all AS
        /// </summary>
        /// <param name="ops"></param>
        /// <param name="vtero"></param>
        public void StartAnalyze(AnalyzeOptions ops, Vtero vtero)
        {
            long   VAStart   = 0;
            long   VAEnd     = VAStart + (0x8000000000 - 0x1000);
            string input     = string.Empty;
            var    GloalView = new ConcurrentDictionary <DetectedProc, ConcurrentDictionary <long, Extract> >();

            vtero.MemAccess = Mem.InitMem(vtero.MemFile, vtero.MRD);

            if (vtero.VMCSs.Count < 1)
            {
                foreach (var p in vtero.FlattenASGroups)
                {
                    DumpDetected(vtero, p);
                }
                // scan bare metal
                // Parallel.ForEach(vtero.Processes, (p) =>
                //{
                //    WriteColor(ConsoleColor.Cyan, $"Scanning for modules addressable by: {p}");
                //    DumpDetected(vtero, p);
                //});
            }
            else
            {
                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)
                        {
                            DumpDetected(vtero, p);
                        }
                    }
                }
            }
        }
Пример #13
0
        /// <summary>
        /// Currently we scan hard for only kernel regions (2MB pages + ExEC)
        /// If there are kernel modules named the OnlyModule it may cause us to ignore the real one in   that case
        /// you can still scan for * by passing null or empty string
        /// </summary>
        /// <param name="OnlyModule">Stop when the first module named this is found</param>
        public VirtualScanner ScanAndLoadModules(string OnlyModule = "ntkrnlmp.pdb", bool OnlyLarge = true, bool IncludeKernelSpace = true, bool OnlyValid = true, bool IncludeData = false, bool DoExtraHeaderScan = true)
        {
            const int LARGE_PAGE_SIZE = 1024 * 1024 * 2;
            var       curr            = 0;

            PageTable.AddProcess(this, new Mem(MemAccess));
            //var cnt = PT.FillPageQueue(OnlyLarge, IncludeKernelSpace);

            var KVS = new VirtualScanner(this, new Mem(MemAccess), DoExtraHeaderScan);

            // single threaded worked best so far
            //Parallel.For(0, cnt, (i, loopState) => x
            foreach (var range in PT.FillPageQueue(OnlyLarge, IncludeKernelSpace, OnlyValid, IncludeData))
            //for (int i = 0; i < cnt; i++)
            {
                curr++;
                bool stop = false;
                if (Vtero.VerboseLevel > 1)
                {
                    //var curr = cnt - PT.PageQueue.Count;
                    //var done = Convert.ToDouble(curr) / Convert.ToDouble(cnt) * 100.0;
                    Console.CursorLeft = 0;
                    Console.Write($"{curr} scanned");
                }
                if (range.PTE.Valid && !range.PTE.NoExecute)
                {
                    foreach (var artifact in KVS.Run(range.VA.Address, range.VA.Address + (range.PTE.LargePage ? LARGE_PAGE_SIZE : MagicNumbers.PAGE_SIZE), range))
                    {
                        var ms = new MemSection()
                        {
                            IsExec = true, Module = artifact, VA = new VIRTUAL_ADDRESS(artifact.VA), Source = range
                        };
                        var extracted = ExtractCVDebug(ms);
                        if (extracted == null)
                        {
                            if (Vtero.VerboseLevel > 1)
                            {
                                WriteColor(ConsoleColor.Yellow, $"failed debug info for PE @address {range.VA.Address:X}, extracted headers: {artifact}");
                            }
                            continue;
                        }

                        if (!string.IsNullOrWhiteSpace(OnlyModule) && OnlyModule != ms.Name)
                        {
                            continue;
                        }

                        if (!Sections.ContainsKey(artifact.VA))
                        {
                            Sections.TryAdd(artifact.VA, ms);
                        }

                        // we can clobber this guy all the time I guess since everything is stateless in Sym and managed
                        // entirely by the handle ID really which is local to our GUID so....
                        sym = Vtero.TryLoadSymbols(ID.GetHashCode(), ms.DebugDetails, ms.VA.Address);
                        if (Vtero.VerboseOutput)
                        {
                            WriteColor((sym != null) ? ConsoleColor.Green : ConsoleColor.Yellow, $" symbol loaded = [{sym != null}] PDB [{ms.DebugDetails.PDBFullPath}] @ {range.VA.Address:X}, {ms.Name}");
                            if (Vtero.VerboseLevel > 1)
                            {
                                WriteColor((sym != null) ? ConsoleColor.Green : ConsoleColor.Yellow, $"headers: { artifact} ");
                            }
                        }

                        if (!string.IsNullOrWhiteSpace(OnlyModule))
                        {
                            if (!string.IsNullOrWhiteSpace(ms.Name) && ms.Name == OnlyModule)
                            {
                                stop = true;
                                //loopState.Stop();
                                break;
                            }
                        }
                        //if (loopState.IsStopped)
                        //return;
                        if (stop)
                        {
                            break;
                        }
                    }
                }

                //if (loopState.IsStopped)
                //    return;e
                //});
                if (stop)
                {
                    break;
                }
            }
            return(KVS);
        }
Пример #14
0
        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;
        }
Пример #15
0
        public override bool IsSupportedFormat(Vtero vtero)
        {
            bool rv = false;
            if (!File.Exists(DumpFile))
                return rv;

            // use abstract implementation & scan for internal 
            LogicalPhysMemDesc = ExtractMemDesc(vtero);

            using (var dstream = File.OpenRead(DumpFile))
            {
                MemSize = dstream.Length;

                using (var dbin = new BinaryReader(dstream))
                {
                    // start with a easy to handle format of DMP
                    if (ASCIIEncoding.ASCII.GetString(dbin.ReadBytes(8)) != "PAGEDU64")
                        return rv;

                    dbin.BaseStream.Position = 0x2020;
                    StartOfMem = dbin.ReadUInt32();

                    // Find the RUN info
                    dbin.BaseStream.Position = 0x88;

                    var MemRunDescriptor = new MemoryDescriptor();
                    MemRunDescriptor.StartOfMemmory = StartOfMem;
                    MemRunDescriptor.NumberOfRuns = dbin.ReadInt64();
                    MemRunDescriptor.NumberOfPages = dbin.ReadInt64();

                    // this struct has to fit in the header which is only 0x2000 in total size
                    if (MemRunDescriptor.NumberOfRuns > 32 || MemRunDescriptor.NumberOfRuns < 0)
                    {
                        // TODO: in this case we have to de-patchguard the KDDEBUGGER_DATA block
                        // before resulting to that... implemented a memory scanning mode to extract the runs out via struct detection
                        PhysMemDesc = LogicalPhysMemDesc;
                        PhysMemDesc.StartOfMemmory = StartOfMem;
                        // physmem is preferred place to load from so if we have only 1 run move it to phys.
                        LogicalPhysMemDesc = null;
                    }
                    else
                    {
                        // in this case StartOfMem is 0x2000
                        MemRunDescriptor.StartOfMemmory = 0x2000;

                        // we have an embedded RUN in the DMP file that appears to conform to the rules we know
                        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 });
                        }
                        PhysMemDesc = MemRunDescriptor;
                    } 
                    rv = true;
                }
            }

#if OLD_CODE
            long aSkipCount = 0;

            for (int i = 0; i < PhysMemDesc.NumberOfRuns; i++)
            {
                var RunSkip = PhysMemDesc.Run[i].BasePage - aSkipCount;
                PhysMemDesc.Run[i].SkipCount = RunSkip;
                aSkipCount = PhysMemDesc.Run[i].BasePage + PhysMemDesc.Run[i].PageCount;
            }
#endif
            return rv;
        }
Пример #16
0
        public Vtero CheckpointRestoreState(string SaveFile)
        {
            Vtero ThisInstance = new Vtero();

            var siz = new FileInfo(SaveFile).Length;
            if (siz == 0)
                return null;

            using (var SerData = File.OpenRead(SaveFile))
                ThisInstance = Serializer.Deserialize<inVtero.net.Vtero>(SerData);

            return ThisInstance;
        }
Пример #17
0
 public Scanner(string InputFile, Vtero vTero) : this()
 {
     Filename = InputFile;
     vtero = vTero;
 }
Пример #18
0
        public Vtero Scanit(ScanOptions op)
        {
            bool SkipVMCS = false;

#if TESTING
            foreach (var sx in op.DisabledScans)
            {
                var spec = sx.ToLower();

                if (spec.Contains("vmcs"))
                {
                    SkipVMCS = true;
                }
                if (spec.Contains("obsd"))
                {
                    Version = Version & ~PTType.OpenBSD;
                }
                if (spec.Contains("nbsd"))
                {
                    Version = Version & ~PTType.NetBSD;
                }
                if (spec.Contains("fbsd"))
                {
                    Version = Version & ~PTType.FreeBSD;
                }
                if (spec.Contains("lin"))
                {
                    Version = Version & ~PTType.LinuxS;
                }
                if (spec.Contains("hv"))
                {
                    Version = Version & ~PTType.HyperV;
                }
                if (spec.Contains("gen"))
                {
                    Version = Version & ~PTType.GENERIC;
                }
                if (spec.Contains("win"))
                {
                    Version = Version & ~PTType.Windows;
                }
            }
            if ((Version & PTType.VALUE) == PTType.VALUE)
            {
                bool Parsed = false;
                do
                {
                    if (args.Length < 2)
                    {
                        WriteLine($"Specify value");
                        return;
                    }

                    Parsed = uint.TryParse(args[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuI);
                    if (!Parsed)
                    {
                        Parsed = ulong.TryParse(args[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuL);
                        if (Parsed)
                        {
                            Is64Scan = true;
                        }
                        else
                        {
                            WriteLine($"Unable to parse input {args[2]}");
                            return;
                        }
                    }
                    else
                    {
                        valuL = (ulong)valuI;
                    }
                } while (!Parsed);
            }
#endif
            string Filename = null;
            Vtero  vtero    = null;
            PTType Version  = PTType.Windows;

            // 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 (todo.Key != ConsoleKey.D)
                {
                    vtero = vtero.CheckpointRestoreState(saveStateFile);
                    vtero.OverRidePhase = true;
                }
                else
                {
                    File.Delete(saveStateFile);
                }
            }

            if (vtero.Phase < 2)
            {
                vtero = new Vtero(Filename);
            }

            //Mem.InitMem(parsed.FileName, null, vtero.DetectedDesc);
            ProgressBarz.Bar.Message = "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(Version);

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

            //BackgroundColor = ConsoleColor.Black;
            //ForegroundColor = ConsoleColor.Cyan;

            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)
            {
                return(vtero);
            }

            ProgressBarz.Bar.Message = "Second pass, correlating for VMCS pages";

            var VMCSCount = vtero.VMCSScan();
            //Timer.Stop();

            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);
            }
            return(vtero);
        }
Пример #19
0
        public static void Main(string[] args)
        {
            #region fluff
            var Version = PTType.UNCONFIGURED;
            string Filename = null;

            if (args.Length == 0 || args.Length > 2)
            {
                WriteLine("inVtero FileName [win|fbsd|obsd|nbsd|!]");
                WriteLine("\"inVtero FileName winfbsd\"  (e.g. Run FreeBSD and Windows together)");
                return;
            }
            try {
                Filename = args[0];

                if (args.Length > 1)
                {
                    var spec = args[1].ToLower();

                    if (spec.Contains("gen"))
                        Version |= PTType.GENERIC;
                    if (spec.Contains("win"))
                        Version |= PTType.Windows;
                    if (spec.Contains("fbsd"))
                        Version |= PTType.FreeBSD;
                    if (spec.Contains("obsd"))
                        Version |= PTType.OpenBSD;
                    if (spec.Contains("nbsd"))
                        Version |= PTType.NetBSD;
                    if (spec.Contains("!"))
                        Version |= PTType.ALL;
                }
                else
                    Version = PTType.ALL;

                var vtero = new Vtero(Filename);

                Vtero.VerboseOutput = true;
                
                CancelKeyPress += Console_CancelKeyPress;
                AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
                ForegroundColor = ConsoleColor.Cyan;

                #endregion

                // basic perf checking
                Timer = Stopwatch.StartNew();

                var procCount = vtero.ProcDetectScan(Version);

                #region page table/CR3 progress report
                ForegroundColor = ConsoleColor.Blue;
                BackgroundColor = ConsoleColor.Yellow;

                var msg = $"{procCount} candiate process page tables. Time so far: {Timer.Elapsed}, second pass starting.";

                Write(msg);

                WriteLine(PrintRate(vtero.FileSize, Timer.Elapsed));
                BackgroundColor = ConsoleColor.Black;
                ForegroundColor = ConsoleColor.Cyan;
                if (procCount < 3)
                {
                    WriteLine("Seems like a fail.  See if this is Linux or something that a different detection technique is needed? :(");
                    return;
                }
                //BackgroundColor = ConsoleColor.White;
                #endregion
                #region blighering
                // second pass
                // with the page tables we aquired, 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
                #endregion

                var VMCSCount = vtero.VMCSScan();

                //Timer.Stop();

                #region VMCS page detection
                ForegroundColor = ConsoleColor.Blue;
                BackgroundColor = ConsoleColor.Yellow;


                WriteLine($"{VMCSCount} candiate VMCS pages. Time to process: {Timer.Elapsed}");
                Write($"Data scanned: {vtero.FileSize:N}");

                // second time 
                WriteLine("Second pass done. " + PrintRate(vtero.FileSize * 2, Timer.Elapsed));
                BackgroundColor = ConsoleColor.Black;
                ForegroundColor = ConsoleColor.Cyan;

                #region TEST
                WriteLine("grouping and joinging all memory");
                vtero.GroupAS();
                //vtero.ExtrtactAddressSpaces();
                vtero.DumpFailList();

                WriteLine($"Final analysis compleated, address spaces extracted. {Timer.Elapsed} {PrintRate(vtero.FileSize * 3, Timer.Elapsed)}");

                #endregion
                #endregion
            } catch (Exception ex)
            {
                Write("Error in processing, likely need to adjust run/gaps. ");
                Write(ex.ToString());
                WriteLine((ex.InnerException == null ? "." : ex.InnerException.ToString()));
            }
            finally {
                ResetColor();
            }
            return;
        }
Пример #20
0
        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;
        }
Пример #21
0
        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;
        }
Пример #22
0
 public void scan()
 {
     vtero = Scan.Scanit(option);
 }
Пример #23
0
        public static void Main(string[] args)
        {
            #region fluff
            var Version = PTType.UNCONFIGURED;
            var Filename = string.Empty;
            var SkipVMCS = false;

            if (args.Length < 1)
            {
                PrintHelp();
                return;
            }
            try {
                Filename = args[0];

                if (!File.Exists(Filename))
                {
                    PrintHelp();
                    return;
                }

                if (args.Length > 1)
                {
                    var spec = args[1].ToLower();

                    if (spec.Contains("win"))
                        Version |= PTType.Windows;
                    if (spec.Contains("lin"))
                        Version |= PTType.LinuxS;
                    if (spec.Contains("fbsd"))
                        Version |= PTType.FreeBSD;
                    if (spec.Contains("obsd"))
                        Version |= PTType.OpenBSD;
                    if (spec.Contains("nbsd"))
                        Version |= PTType.NetBSD;
                    if (spec.Contains("gen"))
                        Version |= PTType.GENERIC;

                    if (spec.Contains("!"))
                        Version |= PTType.ALL;

                    if (spec.Contains("-vmcs"))
                        SkipVMCS = true;

                    if (spec.Contains("-obsd"))
                        Version = Version & ~PTType.OpenBSD;
                    if (spec.Contains("-nbsd"))
                        Version = Version & ~PTType.NetBSD;
                    if (spec.Contains("-fbsd"))
                        Version = Version & ~PTType.FreeBSD;
                    if (spec.Contains("-lin"))
                        Version = Version & ~PTType.LinuxS;
                    if (spec.Contains("-win"))
                        Version = Version & ~PTType.Windows;
                }
                else
                    Version = PTType.ALL;

                Vtero vtero = null;

                var saveStateFile = $"{Filename}.inVtero.net";

                if (File.Exists(saveStateFile))
                {
                    WriteLine("Found save state, (l)oad or (d)iscard?");
                    var todo = ReadKey();
                    if (todo.Key == ConsoleKey.L)
                    {
                        vtero = Vtero.CheckpointRestoreState(saveStateFile);
                        vtero.OverRidePhase = true;
                    }
                    else
                        File.Delete(saveStateFile);
                }

                if(vtero == null)
                    vtero = new Vtero(Filename);

                Vtero.VerboseOutput = true;
                
                CancelKeyPress += Console_CancelKeyPress;
                AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
                ForegroundColor = ConsoleColor.Cyan;

                #endregion

                // basic perf checking
                Timer = Stopwatch.StartNew();

                var procCount = vtero.ProcDetectScan(Version);

                #region page table/CR3 progress report
                ForegroundColor = ConsoleColor.Blue;
                BackgroundColor = ConsoleColor.Yellow;

                var msg = $"{procCount} candiate process page tables. Time so far: {Timer.Elapsed}, second pass starting.";

                Write(msg);

                WriteLine(FormatRate(vtero.FileSize, Timer.Elapsed));
                BackgroundColor = ConsoleColor.Black;
                ForegroundColor = ConsoleColor.Cyan;
                if (procCount < 3)
                {
                    WriteLine("Seems like a fail. Try generic scanning or implement a state scan like LinuxS");
                    return;
                }
                //BackgroundColor = ConsoleColor.White;
                #endregion
                #region blighering
                // 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
                #endregion

                if (!SkipVMCS)
                {
                    var VMCSCount = vtero.VMCSScan();

                    //Timer.Stop();

                    #region VMCS page detection
                    ForegroundColor = ConsoleColor.Blue;
                    BackgroundColor = ConsoleColor.Yellow;


                    WriteLine($"{VMCSCount} candiate VMCS pages. Time to process: {Timer.Elapsed}");
                    Write($"Data scanned: {vtero.FileSize:N}");

                    // second time 
                    WriteLine($"Second pass done. {FormatRate(vtero.FileSize * 2, Timer.Elapsed)}");
                    BackgroundColor = ConsoleColor.Black;
                    ForegroundColor = ConsoleColor.Cyan;
                    
                    #region TEST
                    // each of these depends on a VMCS scan/pass having been done at the moment
                    WriteLine("grouping and joining all memory");

                    vtero.GroupAS();

                    // sync-save state so restarting is faster
                    if (!File.Exists(saveStateFile))
                    {
                        Write($"Saving checkpoint... ");
                        saveStateFile = vtero.CheckpointSaveState();
                        WriteLine(saveStateFile);
                    }

                    // Extract Address Spaces verifies the linkages between
                    // process<->CR3<->EPTP(if there is one)
                    // and that they are functional
                    var vetted = vtero.ExtrtactAddressSpaces();
                    
                    // do a test dump
                    // extract & dump could be done at the same time
                    vtero.DumpASToFile(vetted);

                    if (Vtero.VerboseOutput)
                        vtero.DumpFailList();

                    WriteLine($"Final analysis compleated, address spaces extracted. {Timer.Elapsed} {FormatRate(vtero.FileSize * 3, Timer.Elapsed)}");
                }
                #endregion
                #endregion
            } catch (Exception ex)
            {
                Write("Error in processing, likely need to adjust run/gaps. ");
                Write(ex.ToString());
                WriteLine((ex.InnerException == null ? "." : ex.InnerException.ToString()));
            }
            finally {
                ResetColor();
            }
            return;
        }
Пример #24
0
 public Scanner(string InputFile, Vtero vTero) : this()
 {
     Filename = InputFile;
     vtero    = vTero;
 }
Пример #25
0
        public Vtero Scanit(ScanOptions op)
        {
            bool SkipVMCS = false;
            
#if TESTING

            foreach (var sx in op.DisabledScans)
            {
                var spec = sx.ToLower();

                if (spec.Contains("vmcs"))
                    SkipVMCS = true;
                if (spec.Contains("obsd"))
                    Version = Version & ~PTType.OpenBSD;
                if (spec.Contains("nbsd"))
                    Version = Version & ~PTType.NetBSD;
                if (spec.Contains("fbsd"))
                    Version = Version & ~PTType.FreeBSD;
                if (spec.Contains("lin"))
                    Version = Version & ~PTType.LinuxS;
                if (spec.Contains("hv"))
                    Version = Version & ~PTType.HyperV;
                if (spec.Contains("gen"))
                    Version = Version & ~PTType.GENERIC;
                if (spec.Contains("win"))
                    Version = Version & ~PTType.Windows;

            }
                if((Version & PTType.VALUE) == PTType.VALUE)
                {
                    bool Parsed = false;
                    do
                    {
                        if(args.Length < 2)
                        {
                            WriteLine($"Specify value");
                            return;
                        }

                        Parsed = uint.TryParse(args[2],NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuI);
                        if (!Parsed)
                        {
                            Parsed = ulong.TryParse(args[2], NumberStyles.HexNumber, CultureInfo.CurrentCulture, out valuL);
                            if (Parsed)
                                Is64Scan = true;
                            else {
                                WriteLine($"Unable to parse input {args[2]}");
                                return;
                            }
                        }
                        else
                            valuL = (ulong)valuI;

                    } while (!Parsed);
                }
#endif
            string Filename = null;
            Vtero vtero = null;
            PTType Version = PTType.Windows;
            
            // 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 (todo.Key != ConsoleKey.D )
                {
                    vtero = vtero.CheckpointRestoreState(saveStateFile);
                    vtero.OverRidePhase = true;
                }
                else
                    File.Delete(saveStateFile);
            }

            if (vtero.Phase < 2)
                vtero = new Vtero(Filename);

            //Mem.InitMem(parsed.FileName, null, vtero.DetectedDesc);
            ProgressBarz.Bar.Message = "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(Version);

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

            //BackgroundColor = ConsoleColor.Black;
            //ForegroundColor = ConsoleColor.Cyan;

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

            ProgressBarz.Bar.Message = "Second pass, correlating for VMCS pages";

            var VMCSCount = vtero.VMCSScan();
            //Timer.Stop();

            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);
            }
            return vtero;
        }
Пример #26
0
        /// <summary>
        /// Currently we scan hard for only kernel regions (2MB pages + ExEC)
        /// If there are kernel modules named the OnlyModule it may cause us to ignore the real one in that case
        /// you can still scan for * by passing null or empty string
        /// </summary>
        /// <param name="OnlyModule">Stop when the first module named this is found</param>
        public VirtualScanner ScanAndLoadModules(string OnlyModule = "ntkrnlmp")
        {
            PageTable.AddProcess(this, new Mem(MemAccess));
            var cnt = PT.FillPageQueue(true);

            var KVS = new VirtualScanner(this, new Mem(MemAccess));

            KVS.ScanMode = VAScanType.PE_FAST;

            Parallel.For(0, cnt, (i, loopState) =>
            {
                PFN range;



                var curr = cnt - PT.PageQueue.Count;
                var done = (int)(Convert.ToDouble(curr) / Convert.ToDouble(cnt) * 100.0) + 0.5;

                if (PT.PageQueue.TryDequeue(out range) && range.PTE.Valid)
                {
                    var found = KVS.Run(range.VA.Address, range.VA.Address + (range.PTE.LargePage ? (1024 * 1024 * 2) : 0x1000), loopState);
                    // Attempt load
                    foreach (var artifact in found)
                    {
                        var ms = new MemSection()
                        {
                            IsExec = true, Module = artifact.Value, VA = new VIRTUAL_ADDRESS(artifact.Key)
                        };
                        var extracted = ExtractCVDebug(ms);
                        if (extracted == null)
                        {
                            continue;
                        }

                        if (!string.IsNullOrWhiteSpace(OnlyModule) && OnlyModule != ms.Name)
                        {
                            continue;
                        }

                        if (!Sections.ContainsKey(artifact.Key))
                        {
                            Sections.TryAdd(artifact.Key, ms);
                        }

                        // we can clobber this guy all the time I guess since everything is stateless in Sym and managed
                        // entirely by the handle ID really which is local to our GUID so....
                        sym = Vtero.TryLoadSymbols(ID.GetHashCode(), ms.DebugDetails, ms.VA.Address);
                        if (Vtero.VerboseOutput)
                        {
                            WriteColor(ConsoleColor.Green, $"symbol loaded [{sym != null}] from file [{ms.DebugDetails.PDBFullPath}]");
                        }

                        if (!string.IsNullOrWhiteSpace(OnlyModule))
                        {
                            if (!string.IsNullOrWhiteSpace(ms.Name) && ms.Name == OnlyModule)
                            {
                                loopState.Stop();
                                return;
                            }
                        }
                        if (loopState.IsStopped)
                        {
                            return;
                        }
                    }
                }

                if (loopState.IsStopped)
                {
                    return;
                }
            });
            return(KVS);
        }