/// <summary>
        /// Initializes a new instance of the <see cref="SnapshotElementVectorComparer" /> class.
        /// </summary>
        /// <param name="region">The parent region that contains this element.</param>
        /// <param name="constraints">The set of constraints to use for the element comparisons.</param>
        public SnapshotElementVectorComparer(SnapshotRegion region, ScanConstraints constraints)
        {
            this.Region          = region;
            this.VectorSize      = Vectors.VectorSize;
            this.VectorReadBase  = this.Region.ReadGroupOffset - this.Region.ReadGroupOffset % this.VectorSize;
            this.VectorReadIndex = 0;
            this.DataType        = constraints.ElementType;
            this.DataTypeSize    = constraints.ElementType.Size;
            this.ResultRegions   = new List <SnapshotRegion>();

            this.SetConstraintFunctions();
            this.VectorCompare = this.BuildCompareActions(constraints?.RootConstraint);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Starts the scan using the current constraints.
        /// </summary>
        private void StartScan()
        {
            // Create a constraint manager that includes the current active constraint
            DataTypeBase    dataType        = ScanResultsViewModel.GetInstance().ActiveType;
            ScanConstraints scanConstraints = new ScanConstraints(dataType, this.ActiveConstraint?.Clone());

            if (!scanConstraints.IsValid())
            {
                Logger.Log(LogLevel.Warn, "Unable to start scan with given constraints");
                return;
            }

            try
            {
                // Collect values
                TrackableTask <Snapshot> valueCollectorTask = ValueCollector.CollectValues(
                    SessionManager.Session.OpenedProcess,
                    SessionManager.Session.SnapshotManager.GetActiveSnapshotCreateIfNone(SessionManager.Session.OpenedProcess),
                    TrackableTask.UniversalIdentifier
                    );

                TaskTrackerViewModel.GetInstance().TrackTask(valueCollectorTask);

                // Perform manual scan on value collection complete
                valueCollectorTask.OnCompletedEvent += ((completedValueCollectionTask) =>
                {
                    Snapshot snapshot = valueCollectorTask.Result;
                    TrackableTask <Snapshot> scanTask = ManualScanner.Scan(
                        snapshot,
                        scanConstraints,
                        TrackableTask.UniversalIdentifier);

                    TaskTrackerViewModel.GetInstance().TrackTask(scanTask);
                    SessionManager.Session.SnapshotManager.SaveSnapshot(scanTask.Result);
                });
            }
            catch (TaskConflictException)
            {
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Filters the given snapshot to find all values that are valid pointers.
        /// </summary>
        /// <param name="snapshot">The snapshot on which to perfrom the scan.</param>
        /// <returns></returns>
        public static TrackableTask <Snapshot> Filter(TrackableTask parentTask, Snapshot snapshot, IVectorSearchKernel searchKernel, PointerSize pointerSize, Snapshot DEBUG, UInt32 RADIUS_DEBUG)
        {
            return(TrackableTask <Snapshot>
                   .Create(PointerFilter.Name, out UpdateProgress updateProgress, out CancellationToken cancellationToken)
                   .With(Task <Snapshot> .Run(() =>
            {
                try
                {
                    parentTask.CancellationToken.ThrowIfCancellationRequested();

                    ConcurrentBag <IList <SnapshotRegion> > regions = new ConcurrentBag <IList <SnapshotRegion> >();

                    ParallelOptions options = ParallelSettings.ParallelSettingsFastest.Clone();
                    options.CancellationToken = parentTask.CancellationToken;

                    // ISearchKernel DEBUG_KERNEL = new SpanSearchKernel(DEBUG, RADIUS_DEBUG);

                    Parallel.ForEach(
                        snapshot.OptimizedSnapshotRegions,
                        options,
                        (region) =>
                    {
                        // Check for canceled scan
                        parentTask.CancellationToken.ThrowIfCancellationRequested();

                        if (!region.ReadGroup.CanCompare(null))
                        {
                            return;
                        }

                        ScanConstraints constraints = new ScanConstraints(pointerSize.ToDataType(), null);
                        SnapshotElementVectorComparer vectorComparer = new SnapshotElementVectorComparer(region: region, constraints: constraints);
                        vectorComparer.SetCustomCompareAction(searchKernel.GetSearchKernel(vectorComparer));

                        // SnapshotElementVectorComparer DEBUG_COMPARER = new SnapshotElementVectorComparer(region: region);
                        // DEBUG_COMPARER.SetCustomCompareAction(DEBUG_KERNEL.GetSearchKernel(DEBUG_COMPARER));

                        IList <SnapshotRegion> results = vectorComparer.Compare();

                        // When debugging, these results should be the same as the results above
                        // IList<SnapshotRegion> DEBUG_RESULTS = vectorComparer.Compare();

                        if (!results.IsNullOrEmpty())
                        {
                            regions.Add(results);
                        }
                    });

                    // Exit if canceled
                    parentTask.CancellationToken.ThrowIfCancellationRequested();

                    snapshot = new Snapshot(PointerFilter.Name, regions.SelectMany(region => region));
                }
                catch (OperationCanceledException ex)
                {
                    Logger.Log(LogLevel.Warn, "Pointer filtering canceled", ex);
                    throw ex;
                }
                catch (Exception ex)
                {
                    Logger.Log(LogLevel.Error, "Error performing pointer filtering", ex);
                    return null;
                }

                return snapshot;
            }, parentTask.CancellationToken)));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Performs a pointer scan for a given address.
        /// </summary>
        /// <param name="address">The address for which to perform a pointer scan.</param>
        /// <param name="maxOffset">The maximum pointer offset.</param>
        /// <param name="depth">The maximum pointer search depth.</param>
        /// <param name="alignment">The pointer scan alignment.</param>
        /// <param name="taskIdentifier">The unique identifier to prevent duplicate tasks.</param>
        /// <returns>Atrackable task that returns the scan results.</returns>
        public static TrackableTask <PointerBag> Scan(Process process, PointerBag previousPointerBag, Boolean readMemory, Boolean performUnchangedScan, String taskIdentifier = null)
        {
            try
            {
                TrackableTask <PointerBag> pointerScanTask = TrackableTask <PointerBag> .Create(PointerRebase.Name, taskIdentifier, out UpdateProgress updateProgress, out CancellationToken cancellationToken);

                return(pointerScanTask.With(Task <PointerBag> .Run(() =>
                {
                    try
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        Stopwatch stopwatch = new Stopwatch();
                        stopwatch.Start();

                        DataTypeBase pointerDataType = previousPointerBag.PointerSize.ToDataType();
                        ScanConstraint scanConstraint = new ScanConstraint(ScanConstraint.ConstraintType.Unchanged);
                        ScanConstraints scanConstraints = new ScanConstraints(pointerDataType, scanConstraint);

                        IList <Level> oldLevels = previousPointerBag.Levels;
                        IList <Level> newLevels = new List <Level>();

                        for (Int32 levelIndex = 0; levelIndex < oldLevels.Count; levelIndex++)
                        {
                            Snapshot updatedStaticPointers = oldLevels[levelIndex].StaticPointers;
                            Snapshot updatedHeapPointers = oldLevels[levelIndex].HeapPointers;

                            // Step 1) Re-read values of all pointers
                            if (readMemory)
                            {
                                TrackableTask <Snapshot> staticValueCollector = ValueCollector.CollectValues(process, updatedStaticPointers);

                                // Does not apply to target address
                                if (levelIndex > 0)
                                {
                                    TrackableTask <Snapshot> heapValueCollector = ValueCollector.CollectValues(process, updatedHeapPointers);
                                    updatedHeapPointers = heapValueCollector.Result;
                                }

                                updatedStaticPointers = staticValueCollector.Result;
                            }

                            // Step 2) A neat (optional) trick: Scan for unchanged values to filter out dynamic pointers
                            if (performUnchangedScan)
                            {
                                TrackableTask <Snapshot> staticValueScanner = ManualScanner.Scan(updatedStaticPointers, scanConstraints);

                                // Does not apply to target address
                                if (levelIndex > 0)
                                {
                                    TrackableTask <Snapshot> heapValueScanner = ManualScanner.Scan(updatedHeapPointers, scanConstraints);
                                    updatedHeapPointers = heapValueScanner.Result;
                                }

                                updatedStaticPointers = staticValueScanner.Result;
                            }

                            Stopwatch levelStopwatch = new Stopwatch();
                            levelStopwatch.Start();

                            // Step 3) Rebase heap onto new previous heap
                            if (levelIndex > 0)
                            {
                                IVectorSearchKernel heapSearchKernel = SearchKernelFactory.GetSearchKernel(newLevels.Last().HeapPointers, previousPointerBag.MaxOffset, previousPointerBag.PointerSize);
                                TrackableTask <Snapshot> heapFilterTask = PointerFilter.Filter(pointerScanTask, updatedHeapPointers, heapSearchKernel, previousPointerBag.PointerSize, newLevels.Last().HeapPointers, previousPointerBag.MaxOffset);

                                updatedHeapPointers = heapFilterTask.Result;
                            }

                            // Step 4) Filter static pointers that still point into the updated heap
                            IVectorSearchKernel staticSearchKernel = SearchKernelFactory.GetSearchKernel(updatedHeapPointers, previousPointerBag.MaxOffset, previousPointerBag.PointerSize);
                            TrackableTask <Snapshot> staticFilterTask = PointerFilter.Filter(pointerScanTask, updatedStaticPointers, staticSearchKernel, previousPointerBag.PointerSize, updatedHeapPointers, previousPointerBag.MaxOffset);

                            updatedStaticPointers = staticFilterTask.Result;

                            levelStopwatch.Stop();
                            Logger.Log(LogLevel.Info, "Pointer rebase from level " + (levelIndex) + " => " + (levelIndex + 1) + " completed in: " + levelStopwatch.Elapsed);

                            newLevels.Add(new Level(updatedHeapPointers, updatedStaticPointers));
                        }

                        // Exit if canceled
                        cancellationToken.ThrowIfCancellationRequested();

                        PointerBag pointerBag = new PointerBag(newLevels, previousPointerBag.MaxOffset, previousPointerBag.PointerSize);

                        stopwatch.Stop();
                        Logger.Log(LogLevel.Info, "Pointer rebase complete in: " + stopwatch.Elapsed);

                        return pointerBag;
                    }
                    catch (OperationCanceledException ex)
                    {
                        Logger.Log(LogLevel.Warn, "Pointer rebase canceled", ex);
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(LogLevel.Error, "Error performing pointer rebase", ex);
                    }

                    return null;
                }, cancellationToken)));
            }
            catch (TaskConflictException ex)
            {
                Logger.Log(LogLevel.Warn, "A pointer scan is already scheduled.");
                throw ex;
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Begins the manual scan based on the provided snapshot and parameters.
        /// </summary>
        /// <param name="snapshot">The snapshot on which to perfrom the scan.</param>
        /// <param name="constraints">The collection of scan constraints to use in the manual scan.</param>
        /// <param name="taskIdentifier">The unique identifier to prevent duplicate tasks.</param>
        /// <returns></returns>
        public static TrackableTask <Snapshot> Scan(Snapshot snapshot, ScanConstraints constraints, String taskIdentifier = null)
        {
            try
            {
                return(TrackableTask <Snapshot>
                       .Create(ManualScanner.Name, taskIdentifier, out UpdateProgress updateProgress, out CancellationToken cancellationToken)
                       .With(Task <Snapshot> .Run(() =>
                {
                    Snapshot result = null;

                    try
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        Stopwatch stopwatch = new Stopwatch();
                        stopwatch.Start();

                        Int32 processedPages = 0;
                        ConcurrentBag <IList <SnapshotRegion> > regions = new ConcurrentBag <IList <SnapshotRegion> >();

                        ParallelOptions options = ParallelSettings.ParallelSettingsFastest.Clone();
                        options.CancellationToken = cancellationToken;

                        Parallel.ForEach(
                            snapshot.OptimizedSnapshotRegions,
                            options,
                            (region) =>
                        {
                            // Check for canceled scan
                            cancellationToken.ThrowIfCancellationRequested();

                            if (!region.ReadGroup.CanCompare(constraints: constraints))
                            {
                                return;
                            }

                            SnapshotElementVectorComparer vectorComparer = new SnapshotElementVectorComparer(region: region, constraints: constraints);
                            IList <SnapshotRegion> results = vectorComparer.Compare();

                            if (!results.IsNullOrEmpty())
                            {
                                regions.Add(results);
                            }

                            // Update progress every N regions
                            if (Interlocked.Increment(ref processedPages) % 32 == 0)
                            {
                                updateProgress((float)processedPages / (float)snapshot.RegionCount * 100.0f);
                            }
                        });
                        //// End foreach Region

                        // Exit if canceled
                        cancellationToken.ThrowIfCancellationRequested();

                        result = new Snapshot(ManualScanner.Name, regions.SelectMany(region => region));
                        stopwatch.Stop();
                        result.LoadMetaData(constraints.ElementType.Size);

                        Logger.Log(LogLevel.Info, "Scan complete in: " + stopwatch.Elapsed);
                        Logger.Log(LogLevel.Info, "Results: " + result.ElementCount + " (" + Conversions.ValueToMetricSize(result.ByteCount) + ")");
                    }
                    catch (OperationCanceledException ex)
                    {
                        Logger.Log(LogLevel.Warn, "Scan canceled", ex);
                    }
                    catch (Exception ex)
                    {
                        Logger.Log(LogLevel.Error, "Error performing scan", ex);
                    }

                    return result;
                }, cancellationToken)));
            }
            catch (TaskConflictException ex)
            {
                Logger.Log(LogLevel.Warn, "Unable to start scan. Scan is already queued.");
                throw ex;
            }
        }