/// <summary> /// Gets a snapshot based on the provided mode. Will not read any memory. /// </summary> /// <param name="snapshotCreationMode">The method of snapshot retrieval.</param> /// <returns>The collected snapshot.</returns> public static Snapshot GetSnapshot(Snapshot.SnapshotRetrievalMode snapshotCreationMode, DataType dataType) { switch (snapshotCreationMode) { case Snapshot.SnapshotRetrievalMode.FromActiveSnapshot: return(SnapshotManager.GetActiveSnapshot()); case Snapshot.SnapshotRetrievalMode.FromActiveSnapshotOrPrefilter: return(SnapshotManager.GetActiveSnapshotCreateIfNone(dataType)); case Snapshot.SnapshotRetrievalMode.FromSettings: return(SnapshotManager.CreateSnapshotFromSettings(dataType)); case Snapshot.SnapshotRetrievalMode.FromUserModeMemory: return(SnapshotManager.CreateSnapshotFromUsermodeMemory(dataType)); case Snapshot.SnapshotRetrievalMode.FromModules: return(SnapshotManager.CreateSnapshotFromModules(dataType)); case Snapshot.SnapshotRetrievalMode.FromHeaps: return(SnapshotManager.CreateSnapshotFromHeaps(dataType)); case Snapshot.SnapshotRetrievalMode.FromStack: throw new NotImplementedException(); default: Logger.Log(LogLevel.Error, "Unknown snapshot retrieval mode"); return(null); } }
/// <summary> /// Creates a snapshot from modules in the selected process. /// </summary> /// <returns>The created snapshot.</returns> private static Snapshot CreateSnapshotFromHeaps(DataType dataType) { // TODO: This currently grabs all usermode memory and excludes modules. A better implementation would involve actually grabbing heaps. Snapshot snapshot = SnapshotManager.CreateSnapshotFromUsermodeMemory(dataType); IEnumerable <NormalizedModule> modules = Query.Default.GetModules(); MemoryProtectionEnum requiredPageFlags = 0; MemoryProtectionEnum excludedPageFlags = 0; MemoryTypeEnum allowedTypeFlags = MemoryTypeEnum.None | MemoryTypeEnum.Private | MemoryTypeEnum.Image; UInt64 startAddress = 0; UInt64 endAddress = Query.Default.GetMaxUsermodeAddress(); List <ReadGroup> memoryRegions = new List <ReadGroup>(); IEnumerable <NormalizedRegion> virtualPages = Query.Default.GetVirtualPages( requiredPageFlags, excludedPageFlags, allowedTypeFlags, startAddress, endAddress); foreach (NormalizedRegion virtualPage in virtualPages) { if (modules.Any(x => x.BaseAddress == virtualPage.BaseAddress)) { continue; } memoryRegions.Add(new ReadGroup(virtualPage.BaseAddress, virtualPage.RegionSize, dataType, ScanSettings.Default.Alignment)); } return(new Snapshot(null, memoryRegions)); }
/// <summary> /// Subscribes the given object to changes in the active snapshot. /// </summary> /// <param name="snapshotObserver">The object to observe active snapshot changes.</param> public static void Subscribe(ISnapshotObserver snapshotObserver) { lock (SnapshotManager.ObserverLock) { if (!SnapshotManager.SnapshotObservers.Contains(snapshotObserver)) { SnapshotManager.SnapshotObservers.Add(snapshotObserver); snapshotObserver.Update(SnapshotManager.GetSnapshot(Snapshot.SnapshotRetrievalMode.FromActiveSnapshot, null)); } } }
/// <summary> /// Notify all observing objects of an active snapshot change. /// </summary> private static void NotifyObservers() { lock (SnapshotManager.ObserverLock) { Snapshot activeSnapshot = SnapshotManager.GetSnapshot(Snapshot.SnapshotRetrievalMode.FromActiveSnapshot, null); foreach (ISnapshotObserver observer in SnapshotManager.SnapshotObservers) { observer.Update(activeSnapshot); } } }
/// <summary> /// Clears all snapshot records. /// </summary> public static void ClearSnapshots() { lock (SnapshotManager.AccessLock) { SnapshotManager.Snapshots.Clear(); SnapshotManager.DeletedSnapshots.Clear(); SnapshotManager.NotifyObservers(); // There can be multiple GB of deleted snapshots, so run the garbage collector ASAP for a performance boost. Task.Run(() => GC.Collect()); } }
/// <summary> /// Reverses an undo action. /// </summary> public static void RedoSnapshot() { lock (SnapshotManager.AccessLock) { if (SnapshotManager.DeletedSnapshots.Count == 0) { return; } SnapshotManager.Snapshots.Push(SnapshotManager.DeletedSnapshots.Pop()); SnapshotManager.NotifyObservers(); } }
/// <summary> /// Saves a new snapshot, which will become the current active snapshot. /// </summary> /// <param name="snapshot">The snapshot to save.</param> public static void SaveSnapshot(Snapshot snapshot) { lock (SnapshotManager.AccessLock) { // Remove null snapshot if exists if (SnapshotManager.Snapshots.Count != 0 && SnapshotManager.Snapshots.Peek() == null) { SnapshotManager.Snapshots.Pop(); } // Do not keep large snapshots in the undo history if (SnapshotManager.Snapshots.Count != 0 && SnapshotManager.Snapshots.Peek() != null && SnapshotManager.Snapshots.Peek().ByteCount > SnapshotManager.SizeLimit) { SnapshotManager.Snapshots.Pop(); } SnapshotManager.Snapshots.Push(snapshot); SnapshotManager.DeletedSnapshots.Clear(); SnapshotManager.NotifyObservers(); } }
/// <summary> /// Creates a new snapshot of memory in the target process. Will not read any memory. /// </summary> /// <returns>The snapshot of memory taken in the target process.</returns> private static Snapshot CreateSnapshotFromSettings(DataType dataType) { MemoryProtectionEnum requiredPageFlags = SnapshotManager.GetRequiredProtectionSettings(); MemoryProtectionEnum excludedPageFlags = SnapshotManager.GetExcludedProtectionSettings(); MemoryTypeEnum allowedTypeFlags = SnapshotManager.GetAllowedTypeSettings(); UInt64 startAddress; UInt64 endAddress; if (ScanSettings.Default.IsUserMode) { startAddress = 0; endAddress = Query.Default.GetMaxUsermodeAddress(); } else { startAddress = ScanSettings.Default.StartAddress; endAddress = ScanSettings.Default.EndAddress; } List <ReadGroup> memoryRegions = new List <ReadGroup>(); IEnumerable <NormalizedRegion> virtualPages = Query.Default.GetVirtualPages( requiredPageFlags, excludedPageFlags, allowedTypeFlags, startAddress, endAddress); // Convert each virtual page to a snapshot region foreach (NormalizedRegion virtualPage in virtualPages) { memoryRegions.Add(new ReadGroup(virtualPage.BaseAddress, virtualPage.RegionSize, dataType, ScanSettings.Default.Alignment)); } return(new Snapshot(null, memoryRegions)); }