/// <summary> /// Gets a random pointer from the pointer collection. /// </summary> /// <returns>A random discovered pointer, or null if unable to find one.</returns> public Pointer GetRandomPointer(Int32 levelIndex) { if (levelIndex >= this.Levels.Count || this.Levels[levelIndex].StaticPointers == null) { return(null); } Snapshot currentSnapshot = this.Levels[levelIndex].StaticPointers; ExtractedPointer pointer = this.ExtractRandomPointer(currentSnapshot); UInt64 pointerBase = pointer.BaseAddress; List <Int32> offsets = new List <Int32>(); foreach (Level level in this.Levels.Take(levelIndex + 1).Reverse()) { IEnumerable <Int32> shuffledOffsets = Enumerable.Range(-(Int32)this.MaxOffset, (Int32)(this.MaxOffset * 2) + 1).Shuffle(); Boolean found = false; // Brute force all possible offsets in a random order to find the next path (this guarantees uniform path probabilities) foreach (Int32 nextRandomOffset in shuffledOffsets) { UInt64 newDestination = nextRandomOffset < 0 ? pointer.Destination.Subtract(-nextRandomOffset, wrapAround: false) : pointer.Destination.Add(nextRandomOffset, wrapAround: false); SnapshotRegion snapshotRegion = level.HeapPointers.SnapshotRegions.Select(x => x).Where(y => newDestination >= y.BaseAddress && newDestination <= y.EndAddress).FirstOrDefault(); if (snapshotRegion != null) { // We may have sampled an offset that results in a mis-aligned index, so just randomly take an element from this snapshot rather than using the random offset SnapshotElementIndexer randomElement = snapshotRegion[Random.Next(0, snapshotRegion.GetElementCount(PointerSize.ToSize()))]; UInt64 baseAddress = randomElement.GetBaseAddress(PointerSize.ToSize()); Int32 alignedOffset = pointer.Destination >= baseAddress ? -((Int32)(pointer.Destination - baseAddress)) : ((Int32)(baseAddress - pointer.Destination)); pointer = this.ExtractPointerFromElement(randomElement); offsets.Add(alignedOffset); found = true; break; } } if (!found) { Logger.Log(LogLevel.Error, "Unable to collect a pointer, encountered dead end path"); return(null); } } return(new Pointer(pointerBase, this.PointerSize, offsets.ToArray())); }
/// <summary> /// Starts the pointer value rescan. /// </summary> private void StartPointerRetargetScan() { try { PointerSize pointerSize = SessionManager.Session.OpenedProcess.Is32Bit() ? PointerSize.Byte4 : PointerSize.Byte8; TrackableTask <PointerBag> pointerRetargetScanTask = PointerRetargetScan.Scan( SessionManager.Session.OpenedProcess, this.RetargetAddress, pointerSize.ToSize(), PointerScanResultsViewModel.GetInstance().DiscoveredPointers, PointerScannerViewModel.PointerScanTaskIdentifier ); TaskTrackerViewModel.GetInstance().TrackTask(pointerRetargetScanTask); PointerScanResultsViewModel.GetInstance().DiscoveredPointers = pointerRetargetScanTask.Result; } catch (TaskConflictException) { } }
/// <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> /// <returns>Atrackable task that returns the scan results.</returns> public static TrackableTask <PointerBag> Scan(UInt64 address, UInt32 maxOffset, Int32 depth, Int32 alignment) { TrackableTask <PointerBag> pointerScanTask = TrackableTask <PointerBag> .Create(PointerScan.Name, out UpdateProgress updateProgress, out CancellationToken cancellationToken); return(pointerScanTask.With(Task.Factory.StartNew <PointerBag>(() => { try { cancellationToken.ThrowIfCancellationRequested(); PointerSize pointerSize = Processes.Default.IsOpenedProcess32Bit() ? PointerSize.Byte4 : PointerSize.Byte8; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // Step 1) Create a snapshot of the target address Snapshot targetAddress = new Snapshot(new SnapshotRegion[] { new SnapshotRegion(new ReadGroup(address, pointerSize.ToSize(), pointerSize.ToDataType(), alignment), 0, pointerSize.ToSize()) }); // Step 2) Collect static pointers Snapshot staticPointers = SnapshotManager.GetSnapshot(Snapshot.SnapshotRetrievalMode.FromModules, pointerSize.ToDataType()); TrackableTask <Snapshot> valueCollector = ValueCollector.CollectValues(staticPointers); staticPointers = valueCollector.Result; // Step 3) Collect heap pointers Snapshot heapPointers = SnapshotManager.GetSnapshot(Snapshot.SnapshotRetrievalMode.FromHeaps, pointerSize.ToDataType()); TrackableTask <Snapshot> heapValueCollector = ValueCollector.CollectValues(heapPointers); heapPointers = heapValueCollector.Result; // Step 3) Build levels IList <Level> levels = new List <Level>(); if (depth > 0) { // Create 1st level with target address and static pointers levels.Add(new Level(targetAddress, staticPointers)); // Initialize each level with all static addresses and all heap addresses for (Int32 index = 0; index < depth - 1; index++) { levels.Add(new Level(heapPointers, staticPointers)); } } // Exit if canceled cancellationToken.ThrowIfCancellationRequested(); // Step 4) Rebase to filter out unwanted pointers PointerBag newPointerBag = new PointerBag(levels, maxOffset, pointerSize); TrackableTask <PointerBag> pointerRebaseTask = PointerRebase.Scan(newPointerBag, readMemory: false, performUnchangedScan: false); PointerBag rebasedPointerBag = pointerRebaseTask.Result; // Exit if canceled cancellationToken.ThrowIfCancellationRequested(); stopwatch.Stop(); Logger.Log(LogLevel.Info, "Pointer scan complete in: " + stopwatch.Elapsed); return rebasedPointerBag; } catch (OperationCanceledException ex) { Logger.Log(LogLevel.Warn, "Pointer scan canceled", ex); } catch (Exception ex) { Logger.Log(LogLevel.Error, "Error performing pointer scan", ex); } return null; }, cancellationToken))); }
/// <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, UInt64 address, UInt32 maxOffset, Int32 depth, Int32 alignment, PointerSize pointerSize, String taskIdentifier = null) { try { return(TrackableTask <PointerBag> .Create(PointerScan.Name, taskIdentifier, out UpdateProgress updateProgress, out CancellationToken cancellationToken) .With(Task <PointerBag> .Run(() => { try { cancellationToken.ThrowIfCancellationRequested(); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // Step 1) Create a snapshot of the target address Snapshot targetAddress = new Snapshot(new SnapshotRegion[] { new SnapshotRegion(new ReadGroup(address, pointerSize.ToSize()), 0, pointerSize.ToSize()) }); // Step 2) Collect static pointers Snapshot staticPointers = SnapshotQuery.GetSnapshot(process, SnapshotQuery.SnapshotRetrievalMode.FromModules); TrackableTask <Snapshot> valueCollector = ValueCollector.CollectValues(process, staticPointers); staticPointers = valueCollector.Result; // Step 3) Collect heap pointers Snapshot heapPointers = SnapshotQuery.GetSnapshot(process, SnapshotQuery.SnapshotRetrievalMode.FromHeaps); TrackableTask <Snapshot> heapValueCollector = ValueCollector.CollectValues(process, heapPointers); heapPointers = heapValueCollector.Result; // Step 4) Build levels IList <Level> levels = new List <Level>(); if (depth > 0) { // Create 1st level with target address and static pointers levels.Add(new Level(targetAddress, staticPointers)); // Initialize each level with all static addresses and all heap addresses for (Int32 index = 0; index < depth - 1; index++) { levels.Add(new Level(heapPointers, staticPointers)); } } // Exit if canceled cancellationToken.ThrowIfCancellationRequested(); // Step 4) Rebase to filter out unwanted pointers PointerBag newPointerBag = new PointerBag(levels, maxOffset, pointerSize); TrackableTask <PointerBag> pointerRebaseTask = PointerRebase.Scan(process, newPointerBag, readMemory: false, performUnchangedScan: false); PointerBag rebasedPointerBag = pointerRebaseTask.Result; // Exit if canceled cancellationToken.ThrowIfCancellationRequested(); stopwatch.Stop(); Logger.Log(LogLevel.Info, "Pointer scan complete in: " + stopwatch.Elapsed); return rebasedPointerBag; } catch (OperationCanceledException ex) { Logger.Log(LogLevel.Warn, "Pointer scan canceled", ex); } catch (Exception ex) { Logger.Log(LogLevel.Error, "Error performing pointer scan", ex); } return null; }, cancellationToken))); } catch (TaskConflictException ex) { Logger.Log(LogLevel.Warn, "A pointer scan is already scheduled."); throw ex; } }
private ExtractedPointer ExtractPointerFromElement(SnapshotElementIndexer element) { return(new ExtractedPointer(element.GetBaseAddress(PointerSize.ToSize()), element.HasCurrentValue() ? (this.PointerSize == PointerSize.Byte4 ? (UInt32)element.LoadCurrentValue(PointerSize.ToDataType()) : (UInt64)element.LoadCurrentValue(PointerSize.ToDataType())) : 0)); }
private ExtractedPointer ExtractRandomPointer(Snapshot snapshot) { SnapshotRegion extractedRegion = snapshot.SnapshotRegions[Random.Next(0, snapshot.SnapshotRegions.Length)]; SnapshotElementIndexer extractedElement = extractedRegion[Random.Next(0, extractedRegion.GetElementCount(PointerSize.ToSize()))]; return(this.ExtractPointerFromElement(extractedElement)); }