/// <summary> /// Gradually gathers pointers in the running process. /// </summary> private void GatherPointers() { Boolean isOpenedProcess32Bit = EngineCore.GetInstance().Processes.IsOpenedProcess32Bit(); dynamic invalidPointerMin = isOpenedProcess32Bit ? (UInt32)UInt16.MaxValue : (UInt64)UInt16.MaxValue; dynamic invalidPointerMax = isOpenedProcess32Bit ? Int32.MaxValue : Int64.MaxValue; ConcurrentHashSet <IntPtr> foundPointers = new ConcurrentHashSet <IntPtr>(); // Test for conditions where we set the final found set and take a new snapshot to parse if (this.CurrentSnapshot == null || this.CurrentSnapshot.GetRegionCount() <= 0 || this.processedCount >= this.CurrentSnapshot.GetRegionCount()) { this.processedCount = 0; this.CurrentSnapshot = SnapshotManager.GetInstance().CollectSnapshot(useSettings: true, usePrefilter: false).Clone(); this.FoundPointers = this.ConstructingSet; this.ConstructingSet = new HashSet <IntPtr>(); } List <SnapshotRegion> sortedRegions = new List <SnapshotRegion>(this.CurrentSnapshot.GetSnapshotRegions().OrderBy(x => x.GetTimeSinceLastRead())); // Process the allowed amount of chunks from the priority queue Parallel.For( 0, Math.Min(sortedRegions.Count, PointerCollector.RegionLimit), SettingsViewModel.GetInstance().ParallelSettings, (index) => { Interlocked.Increment(ref this.processedCount); SnapshotRegion region = sortedRegions[index]; Boolean success; // Set to type of a pointer region.ElementType = EngineCore.GetInstance().Processes.IsOpenedProcess32Bit() ? typeof(UInt32) : typeof(UInt64); // Enforce 4-byte alignment of pointers region.Alignment = sizeof(Int32); // Read current page data for chunk region.ReadAllRegionMemory(out success); // Read failed; Deallocated page if (!success) { return; } if (region.GetCurrentValues() == null || region.GetCurrentValues().Length <= 0) { return; } foreach (SnapshotElementRef element in region) { // Enforce user mode memory pointers if (element.LessThanValue(invalidPointerMin) || element.GreaterThanValue(invalidPointerMax)) { continue; } // Enforce 4-byte alignment of destination if (element.GetCurrentValue() % 4 != 0) { continue; } IntPtr Value = new IntPtr(element.GetCurrentValue()); // Check if it is possible that this pointer is valid, if so keep it if (this.CurrentSnapshot.ContainsAddress(Value)) { foundPointers.Add(Value); } } // Clear the saved values, we do not need them now region.SetCurrentValues(null); }); IEnumerable <IntPtr> pointers = foundPointers.ToList(); this.ConstructingSet.UnionWith(pointers); this.FoundPointers.UnionWith(pointers); }
/// <summary> /// Called when the scan updates. /// </summary> protected override void OnUpdate() { Int32 processedPages = 0; // Read memory to get current values Parallel.ForEach( this.Snapshot.Cast <Object>(), SettingsViewModel.GetInstance().ParallelSettings, (regionObject) => { SnapshotRegion region = regionObject as SnapshotRegion; Boolean readSuccess; region.ReadAllRegionMemory(out readSuccess, keepValues: true); if (!readSuccess) { region.SetAllValidBits(false); return; } // Ignore region if it requires current & previous values, but we cannot find them if (this.ScanConstraintManager.HasRelativeConstraint() && !region.CanCompare()) { region.SetAllValidBits(false); return; } foreach (SnapshotElementRef element in region) { // Enforce each value constraint on the element foreach (ScanConstraint scanConstraint in this.ScanConstraintManager) { switch (scanConstraint.Constraint) { case ConstraintsEnum.Unchanged: if (!element.Unchanged()) { element.SetValid(false); } break; case ConstraintsEnum.Changed: if (!element.Changed()) { element.SetValid(false); } break; case ConstraintsEnum.Increased: if (!element.Increased()) { element.SetValid(false); } break; case ConstraintsEnum.Decreased: if (!element.Decreased()) { element.SetValid(false); } break; case ConstraintsEnum.IncreasedByX: if (!element.IncreasedByValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.DecreasedByX: if (!element.DecreasedByValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.Equal: if (!element.EqualToValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.NotEqual: if (!element.NotEqualToValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.GreaterThan: if (!element.GreaterThanValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.GreaterThanOrEqual: if (!element.GreaterThanOrEqualToValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.LessThan: if (!element.LessThanValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.LessThanOrEqual: if (!element.LessThanOrEqualToValue(scanConstraint.ConstraintValue)) { element.SetValid(false); } break; case ConstraintsEnum.NotScientificNotation: if (element.IsScientificNotation()) { element.SetValid(false); } break; } } //// End foreach Constraint } //// End foreach Element lock (this.ProgressLock) { processedPages++; this.UpdateProgress(processedPages, this.Snapshot.GetRegionCount()); } }); //// End foreach Region base.OnUpdate(); }