Beispiel #1
0
        static void LowerBoundOutput()
        {
            const int BarHeight = 5;

            var MaxText = (WindowTop + WindowHeight - 1) - BarHeight;

            if (CursorTop >= MaxText)
            {
                BackgroundColor = ConsoleColor.Black;
                var newlines = CursorTop % MaxText;

                for (int i = 0; i < newlines; i++)
                {
                    WriteLine(" ".PadRight(WindowWidth));
                }

                CursorTop = MaxText - 1;
            }
            ProgressBarz.RenderConsoleProgress(ProgressBarz.Progress);
        }
Beispiel #2
0
        /// <summary>
        /// A simple memory mapped scan over the input provided in the constructor
        /// </summary>
        /// <param name="ExitAfter">Optionally stop checking or exit early after this many candidates.  0 does not exit early.</param>
        /// <returns></returns>
        public int Analyze(int ExitAfter = 0)
        {
            CurrWindowBase = 0;
            mapSize        = (64 * 1024 * 1024);

            if (File.Exists(Filename))
            {
                using (var fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    var mapName = Path.GetFileNameWithoutExtension(Filename) + DateTime.Now.ToBinary().ToString("X16");
                    using (var mmap =
                               MemoryMappedFile.CreateFromFile(fs,
                                                               mapName,
                                                               0,
                                                               MemoryMappedFileAccess.Read,
                                                               null,
                                                               HandleInheritability.Inheritable,
                                                               false))
                    {
                        if (FileSize == 0)
                        {
                            FileSize = new FileInfo(Filename).Length;
                        }

                        while (CurrWindowBase < FileSize)
                        {
                            using (var reader = mmap.CreateViewAccessor(CurrWindowBase, mapSize, MemoryMappedFileAccess.Read))
                            {
                                CurrMapBase = 0;
                                reader.ReadArray(CurrMapBase, buffers[filled], 0, 512);

                                while (CurrMapBase < mapSize)
                                {
                                    var offset = CurrWindowBase + CurrMapBase;

                                    // next page, may be faster with larger chunks but it's simple to view 1 page at a time
                                    CurrMapBase += 4096;

                                    block   = buffers[filled];
                                    filled ^= 1;

#pragma warning disable HeapAnalyzerImplicitParamsRule // Array allocation for params parameter
                                    Parallel.Invoke(() =>
                                                    Parallel.ForEach <Func <long, bool> >(CheckMethods, (check) => {
                                        check(offset);
                                    }), () => {
                                        if (CurrMapBase < mapSize)
                                        {
                                            UnsafeHelp.ReadBytes(reader, CurrMapBase, ref buffers[filled]);
                                        }
                                    }
                                                    );
                                    if (ExitAfter > 0 && ExitAfter == DetectedProcesses.Count())
                                    {
                                        return(DetectedProcesses.Count());
                                    }

                                    var progress = Convert.ToInt32((Convert.ToDouble(CurrWindowBase) / Convert.ToDouble(FileSize) * 100.0) + 0.5);
                                    if (progress != ProgressBarz.Progress)
                                    {
                                        ProgressBarz.RenderConsoleProgress(progress);
                                    }
                                }
                            } // close current window

                            CurrWindowBase += CurrMapBase;

                            if (CurrWindowBase + mapSize > FileSize)
                            {
                                mapSize = FileSize - CurrWindowBase;
                            }
                        }
                    }
                } // close map
            }     // close stream
            return(DetectedProcesses.Count());
        }
Beispiel #3
0
        /// <summary>
        /// A simple memory mapped scan over the input provided in the constructor
        /// </summary>
        /// <param name="ExitAfter">Optionally stop checking or exit early after this many candidates.  0 does not exit early.</param>
        /// <returns></returns>
        public int Analyze(int ExitAfter = 0)
        {
            CurrWindowBase = 0;
            mapSize        = init_map_size;
            long RunShift = 0;

            if (File.Exists(Filename))
            {
                using (var fs = new FileStream(Filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                {
                    var mapName = Path.GetFileNameWithoutExtension(Filename) + DateTime.Now.ToBinary().ToString("X16");
                    using (var mmap =
                               MemoryMappedFile.CreateFromFile(fs,
                                                               mapName,
                                                               0,
                                                               MemoryMappedFileAccess.Read,
                                                               null,
                                                               HandleInheritability.Inheritable,
                                                               false))
                    {
                        if (FileSize == 0)
                        {
                            FileSize = new FileInfo(Filename).Length;
                        }

                        // TODO: Clean up all the shifts
                        while (CurrWindowBase < FileSize)
                        {
                            using (var reader = mmap.CreateViewAccessor(CurrWindowBase, mapSize, MemoryMappedFileAccess.Read))
                            {
                                CurrMapBase = 0;
                                //reader.ReadArray(CurrMapBase, buffers[filled], 0, block_count);
                                UnsafeHelp.ReadBytes(reader, CurrMapBase, ref buffers[filled], block_count);

                                while (CurrMapBase < mapSize)
                                {
                                    // setup buffers for parallel load/read
                                    block   = buffers[filled];
                                    filled ^= 1;
                                    var CURR_BASES = CurrWindowBase + CurrMapBase;
                                    CurrMapBase += block_size;

#pragma warning disable HeapAnalyzerImplicitParamsRule // Array allocation for params parameter
                                    Parallel.Invoke(() =>
                                                    Parallel.ForEach <Func <int, long, bool> >(CheckMethods, (check) =>
                                    {
                                        for (int bo = 0; bo < block_count; bo += 512)
                                        {
                                            // Adjust for known memory run / extents mappings.
                                            // Adjust TrueOffset is actually possibly used by check fn (TODO: CLEAN UP THE GLOBALS)
                                            var offset = TrueOffset = CURR_BASES + (bo * 8);

                                            var offset_pfn = offset >> MagicNumbers.PAGE_SHIFT;
                                            // next page, may be faster with larger chunks but it's simple to view 1 page at a time
                                            long IndexedOffset_pfn = 0;
                                            do
                                            {
                                                IndexedOffset_pfn = vtero.MemAccess.OffsetToMemIndex(offset_pfn + RunShift);
                                                if (IndexedOffset_pfn == -1)
                                                {
                                                    RunShift++;
                                                    continue;
                                                }
                                                if (IndexedOffset_pfn == -2)
                                                {
                                                    break;
                                                }
                                            } while (IndexedOffset_pfn < 0);

                                            // found shift, accumulate indexes
                                            offset_pfn       += RunShift;
                                            IndexedOffset_pfn = IndexedOffset_pfn >> MagicNumbers.PAGE_SHIFT;

                                            // Calculate DIFF
                                            var diff_off_pfn = offset < IndexedOffset_pfn ? IndexedOffset_pfn - offset_pfn : offset_pfn - IndexedOffset_pfn;

                                            // Skew Offset
                                            offset += (diff_off_pfn << MagicNumbers.PAGE_SHIFT);


                                            ///// !!! DO CHECK !!!
                                            check(bo, offset);
                                        }
                                    }), () =>
                                    {
                                        if (CurrMapBase < mapSize)
                                        {
                                            var total_count_remain = ((mapSize - CurrMapBase) / 8);
                                            var read_in_count      = total_count_remain > block_count ? block_count : total_count_remain;
                                            UnsafeHelp.ReadBytes(reader, CurrMapBase, ref buffers[filled], (int)read_in_count);
                                        }
                                    }
                                                    );
                                    if (ExitAfter > 0 && (ExitAfter == DetectedProcesses.Count())) // || FoundValueOffsets.Count() >= ExitAfter))
                                    {
                                        return(DetectedProcesses.Count());
                                    }
                                }
                            } // close current window

                            CurrWindowBase += CurrMapBase;

                            if (CurrWindowBase + mapSize > FileSize)
                            {
                                mapSize = FileSize - CurrWindowBase;
                            }

                            var progress = Convert.ToInt32(Convert.ToDouble(CurrWindowBase) / Convert.ToDouble(FileSize) * 100.0);
                            if (progress != ProgressBarz.Progress)
                            {
                                ProgressBarz.RenderConsoleProgress(progress);
                            }
                        }
                    }
                } // close map
            }     // close stream
            return(DetectedProcesses.Count());
        }
Beispiel #4
0
        /// <summary>
        /// Scan for a class configured variable "HexScanDword"
        /// This is a specialized thing we are trying to avoid over scanning
        /// Turns out the physical memory run data maintained by the OS is typically very deep physically
        /// So in start-up we may use this depending on input file
        /// </summary>
        /// <param name="ExitAfter"></param>
        /// <returns></returns>
        public static IEnumerable <long> BackwardsValueScan(String Filename, int ScanFor, int ExitAfter = 0)
        {
            List <long> FoundValueOffsets = new List <long>();
            var         FileSize          = new FileInfo(Filename).Length;

            long ReadSize       = 1024 * 1024 * 8;
            var  ValueReadCount = (int)ReadSize / 4;
            var  RevMapSize     = ReadSize;

            var ShortFirstChunkSize = (int)(FileSize & (ReadSize - 1));
            var ShortFirstChunkBase = FileSize - ShortFirstChunkSize;

            if (ShortFirstChunkSize != 0)
            {
                var found = MapScanFile(Filename, ShortFirstChunkBase, ScanFor, ShortFirstChunkSize / 4);
                foreach (var offset in found)
                {
                    yield return(offset);
                }

                if (ShortFirstChunkBase == 0)
                {
                    yield break;
                }
            }

            var RevCurrWindowBase = FileSize - ShortFirstChunkSize;

            RevCurrWindowBase -= RevMapSize;
            var ChunkCount = (FileSize / RevMapSize) + 1;

            bool StopRunning = false;

            long localOffset = ShortFirstChunkBase - ReadSize;

            for (long i = ChunkCount; i > 0; i--)
            {
                if (!StopRunning)
                {
                    if (Vtero.VerboseLevel > 1)
                    {
                        WriteColor($"Scanning From {localOffset:X} To {(localOffset + ReadSize):X} bytes");
                    }

                    var results = MapScanFile(Filename, localOffset, ScanFor, ValueReadCount);

                    foreach (var offset in results)
                    {
                        yield return(offset);
                    }

                    CurrWindowBase += (1 * ReadSize);
                    CurrWindowBase  = CurrWindowBase > FileSize ? FileSize : CurrWindowBase;
                    var progress = Convert.ToInt32(Convert.ToDouble(CurrWindowBase) / Convert.ToDouble(FileSize) * 100.0);
                    if (progress != ProgressBarz.Progress)
                    {
                        ProgressBarz.RenderConsoleProgress(progress);
                    }

                    localOffset -= RevMapSize;
                    if (localOffset < 0 && !StopRunning)
                    {
                        localOffset = 0;
                        StopRunning = true;
                    }
                }
            }
            yield break;
        }
Beispiel #5
0
        /// <summary>
        /// This routine is fairly expensive, maybe unnecessary as well but it demo's walking the page table + EPT.
        /// You can connect an address space dumper really easily
        /// </summary>
        /// <param name="MemSpace">The list of VMCS/EPTP configurations which will alter the page table use</param>
        /// <param name="Procs">Detected procs to query</param>
        /// <param name="pTypes">Type bitmas to interpreate</param>
        public List <DetectedProc> ExtrtactAddressSpaces(IOrderedEnumerable <VMCS> MemSpace = null, ConcurrentBag <DetectedProc> Procs = null, PTType pTypes = PTType.UNCONFIGURED)
        {
            List <DetectedProc> rvList = new List <DetectedProc>();

            var PT2Scan  = pTypes == PTType.UNCONFIGURED ? (PTType.Windows | PTType.HyperV | PTType.GENERIC) : pTypes;
            var procList = Procs == null ? Processes : Procs;
            //var memSpace = MemSpace == null ? VMCSs.First() : MemSpace.First();

            var memSpace = MemSpace == null?VMCSs.GroupBy(x => x.EPTP).Select(xg => xg.First()) : MemSpace;

            var p = from proc in Processes
                    where (((proc.PageTableType & PT2Scan) == proc.PageTableType))
                    orderby proc.CR3Value ascending
                    select proc;

            int pcnt  = Processes.Count();
            int vmcnt = memSpace.Count();
            var tot   = pcnt * vmcnt;
            var curr  = 0;

            var AlikelyKernelSet = from ptes in p.First().TopPageTablePage
                                   where ptes.Key > 255 && MagicNumbers.Each.All(ppx => ppx != ptes.Key)
                                   select ptes.Value;

            Console.ForegroundColor = ConsoleColor.Yellow;
            WriteLine($"assessing {tot} address spaces");
            ProgressBarz.Progress = 0;

            var VMCSTriage = new Dictionary <VMCS, int>();

            //Parallel.ForEach(memSpace, (space) =>
            foreach (var space in memSpace)
            {
                // we do it this way so that parallelized tasks do not interfere with each other
                // overall it may blow the cache hit ratio but will tune a single task to see the larger/better cache
                // versus multicore, my suspicion is that multi-core is better
                using (var memAxs = new Mem(MemFile, null, DetectedDesc))
                {
                    var sx = 0;
                    foreach (var px in p)
                    //Parallel.ForEach(p, (proc) =>
                    {
                        try
                        {
                            var proc = px.Clone <DetectedProc>();
                            proc.vmcs = space;

                            var pt = PageTable.AddProcess(proc, memAxs, false);
                            if (pt != null && VerboseOutput)
                            {
                                // If we used group detection correlation a valid EPTP should work for every process

                                if (proc.vmcs != null && proc.PT.RootPageTable.PFNCount > proc.TopPageTablePage.Count())
                                {
                                    WriteLine($"Virtualized Process PT Entries [{proc.PT.RootPageTable.PFNCount}] Type [{proc.PageTableType}] PID [{proc.vmcs.EPTP:X}:{proc.CR3Value:X}]");
                                    rvList.Add(proc);
                                }
                                else
                                {
                                    WriteLine($"canceling evaluation of bad EPTP for this group");
                                    foreach (var pxc in Processes)
                                    {
                                        pxc.vmcs = null;
                                    }
                                    break;
                                }

                                sx++;
                                curr++;
                                var progress = Convert.ToInt32((Convert.ToDouble(curr) / Convert.ToDouble(tot) * 100.0) + 0.5);
                                ProgressBarz.RenderConsoleProgress(progress);
                            }
                        }
                        catch (ExtendedPageNotFoundException eptpX)
                        {
                            WriteLine($"Bad EPTP selection;{Environment.NewLine}\tEPTP:{eptpX.RequestedEPTP}{Environment.NewLine}\t CR3:{eptpX.RequestedCR3}{Environment.NewLine} Attempting to skip to next proc.");

                            memAxs.DumpPFNIndex();
                        }
                        catch (MemoryRunMismatchException mrun)
                        {
                            WriteLine($"Error in accessing memory for PFN {mrun.PageRunNumber:X16}");

                            memAxs.DumpPFNIndex();
                        }
                        catch (PageNotFoundException pnf)
                        {
                            WriteLine($"Error in selecting page, see {pnf}");

                            memAxs.DumpPFNIndex();
                        }
                        catch (Exception ex)
                        {
                            WriteLine($"Error in memspace extraction: {ex.ToString()}");

                            memAxs.DumpPFNIndex();
                        }
                        WriteLine($"{sx} VMCS dominated process address spaces and were decoded succsessfully.");
                        //});
                    }
                }
            }
            //});


            using (var memAxs = new Mem(MemFile, null, DetectedDesc))
            {
                var nonVMCSprocs = from px in Processes
                                   where px.vmcs == null
                                   select px;

                foreach (var px in nonVMCSprocs)
                {
                    var pmetal = px.Clone <DetectedProc>();

                    // this is a process on the bare metal
                    var pt = PageTable.AddProcess(pmetal, memAxs, false);
                    WriteLine($"Process {pmetal.CR3Value:X16} Physical walk w/o SLAT yielded {pmetal.PT.RootPageTable.PFNCount} entries");

                    rvList.Add(pmetal);
                }
            }
            return(rvList);
        }