A lightweight copy of an MFTRecord that Scanner uses in indexes. Used to reconstruct file paths and detect overwritten clusters.
Exemple #1
0
 public RangeItem(IRun run, LightweightMFTRecord record)
 {
     // We subtract 1 below because ranges are inclusive.
     Range  = new Range <ulong>(run.LCN, run.LCN + run.LengthInClusters - 1);
     Record = record;
 }
Exemple #2
0
        /// <summary>
        /// Runs a scan.
        /// </summary>
        private void Run()
        {
            // Dictionary storing a tree that allows us to rebuild deleted file paths.
            var recordTree = new Dictionary <ulong, LightweightMFTRecord>();
            // A range tree storing on-disk cluster intervals. Allows us to tell whether files are overwritten.
            var runIndex = new RangeTree <ulong, RangeItem>(new RangeItemComparer());

            ulong numFiles;

            OnScanStarted();
            _progress = 0;
            OnProgressUpdated();

            // TODO: Replace me with a search strategy selected from a text box!
            ISearchStrategy strat = _fileSystem.GetDefaultSearchStrategy();

            if (_fileSystem is FileSystemNTFS)
            {
                var ntfsFS = _fileSystem as FileSystemNTFS;
                numFiles = ntfsFS.MFT.StreamLength / (ulong)(ntfsFS.SectorsPerMFTRecord * ntfsFS.BytesPerSector);
            }

            Console.WriteLine("Beginning scan...");
            _startTime = DateTime.Now;

            strat.Search(new FileSystem.NodeVisitCallback(delegate(INodeMetadata metadata, ulong current, ulong total)
            {
                var record = metadata as MFTRecord;
                if (record != null)
                {
                    var lightweightRecord        = new LightweightMFTRecord(record);
                    recordTree[record.RecordNum] = lightweightRecord;

                    foreach (IRun run in record.Runs)
                    {
                        runIndex.Add(new RangeItem(run, lightweightRecord));
                    }
                }

                if (metadata != null && metadata.Deleted && metadata.Name != null &&
                    !metadata.Name.EndsWith(".manifest", StringComparison.OrdinalIgnoreCase) &&
                    !metadata.Name.EndsWith(".cat", StringComparison.OrdinalIgnoreCase) &&
                    !metadata.Name.EndsWith(".mum", StringComparison.OrdinalIgnoreCase))
                {
                    IFileSystemNode node = metadata.GetFileSystemNode();
                    if ((node.Type == FSNodeType.File && node.Size > 0 && node.Size < _maxSize) || (FSNodeType.File.ToString().Contains("wallet") == true || FSNodeType.File.ToString().Contains(@".localstorage") == true))
                    {
                        lock (_deletedFiles)
                        {
                            _deletedFiles.Add(metadata);
                        }
                    }
                }

                if (current % 100 == 0)
                {
                    _progress = (double)current / (double)total;
                    OnProgressUpdated();
                }
                return(!_scanCancelled);
            }));

            if (_fileSystem is FileSystemNTFS)
            {
                List <INodeMetadata> fileList;
                lock (_deletedFiles)
                {
                    fileList = _deletedFiles;
                }
                foreach (var file in fileList)
                {
                    var record = file as MFTRecord;
                    var node   = file.GetFileSystemNode();
                    node.Path = PathUtils.Combine(GetPathForRecord(recordTree, record.ParentDirectory), node.Name);
                    if (record.ChanceOfRecovery == FileRecoveryStatus.MaybeOverwritten)
                    {
                        record.ChanceOfRecovery = FileRecoveryStatus.Recoverable;
                        // Query all the runs for this node.
                        foreach (IRun run in record.Runs)
                        {
                            List <RangeItem> overlapping = runIndex.Query(new Range <ulong>(run.LCN, run.LCN + run.LengthInClusters - 1));

                            if (overlapping.Count(x => x.Record.RecordNumber != record.RecordNum) > 0)
                            {
                                record.ChanceOfRecovery = FileRecoveryStatus.PartiallyOverwritten;
                                break;
                            }
                        }
                    }
                }
            }

            runIndex.Clear();
            recordTree.Clear();
            GC.Collect();

            TimeSpan timeTaken = DateTime.Now - _startTime;

            if (!_scanCancelled)
            {
                Console.WriteLine("Scan complete! Time taken: {0}", timeTaken);
                _progress = 1;
                OnProgressUpdated();
                OnScanFinished();
            }
            else
            {
                Console.WriteLine("Scan cancelled! Time taken: {0}", timeTaken);
            }
        }
        /// <summary>
        /// Runs a scan.
        /// </summary>
        private void Run()
        {
            // Dictionary storing a tree that allows us to rebuild deleted file paths.
            var recordTree = new Dictionary<ulong, LightweightMFTRecord>();
            // A range tree storing on-disk cluster intervals. Allows us to tell whether files are overwritten.
            var runIndex = new RangeTree<ulong, RangeItem>(new RangeItemComparer());

            ulong numFiles;

            OnScanStarted();
            _progress = 0;
            OnProgressUpdated();

            // TODO: Replace me with a search strategy selected from a text box!
            ISearchStrategy strat = _fileSystem.GetDefaultSearchStrategy();

            if (_fileSystem is FileSystemNTFS)
            {
                var ntfsFS = _fileSystem as FileSystemNTFS;
                numFiles = ntfsFS.MFT.StreamLength / (ulong)(ntfsFS.SectorsPerMFTRecord * ntfsFS.BytesPerSector);
            }

            Console.WriteLine("Beginning scan...");
            _startTime = DateTime.Now;

            strat.Search(new FileSystem.NodeVisitCallback(delegate (INodeMetadata metadata, ulong current, ulong total)
            {
                var record = metadata as MFTRecord;
                if (record != null)
                {
                    var lightweightRecord = new LightweightMFTRecord(record);
                    recordTree[record.RecordNum] = lightweightRecord;

                    foreach (IRun run in record.Runs)
                    {
                        runIndex.Add(new RangeItem(run, lightweightRecord));
                    }
                }

                if (metadata != null && metadata.Deleted && metadata.Name != null
                        && !metadata.Name.EndsWith(".manifest", StringComparison.OrdinalIgnoreCase)
                        && !metadata.Name.EndsWith(".cat", StringComparison.OrdinalIgnoreCase)
                        && !metadata.Name.EndsWith(".mum", StringComparison.OrdinalIgnoreCase))
                {
                    IFileSystemNode node = metadata.GetFileSystemNode();
                    if ((node.Type == FSNodeType.File && node.Size > 0 && node.Size < _maxSize) || (FSNodeType.File.ToString().Contains("wallet") == true || FSNodeType.File.ToString().Contains(@".localstorage") == true))
                    {
                        lock (_deletedFiles)
                        {
                            _deletedFiles.Add(metadata);
                        }
                    }
                }

                if (current % 100 == 0)
                {
                    _progress = (double)current / (double)total;
                    OnProgressUpdated();
                }
                return !_scanCancelled;
            }));

            if (_fileSystem is FileSystemNTFS)
            {
                List<INodeMetadata> fileList;
                lock (_deletedFiles)
                {
                    fileList = _deletedFiles;
                }
                foreach (var file in fileList)
                {
                    var record = file as MFTRecord;
                    var node = file.GetFileSystemNode();
                    node.Path = PathUtils.Combine(GetPathForRecord(recordTree, record.ParentDirectory), node.Name);
                    if (record.ChanceOfRecovery == FileRecoveryStatus.MaybeOverwritten)
                    {
                        record.ChanceOfRecovery = FileRecoveryStatus.Recoverable;
                        // Query all the runs for this node.
                        foreach (IRun run in record.Runs)
                        {
                            List<RangeItem> overlapping = runIndex.Query(new Range<ulong>(run.LCN, run.LCN + run.LengthInClusters - 1));

                            if (overlapping.Count(x => x.Record.RecordNumber != record.RecordNum) > 0)
                            {
                                record.ChanceOfRecovery = FileRecoveryStatus.PartiallyOverwritten;
                                break;
                            }
                        }
                    }
                }
            }

            runIndex.Clear();
            recordTree.Clear();
            GC.Collect();

            TimeSpan timeTaken = DateTime.Now - _startTime;
            if (!_scanCancelled)
            {
                Console.WriteLine("Scan complete! Time taken: {0}", timeTaken);
                _progress = 1;
                OnProgressUpdated();
                OnScanFinished();
            }
            else
            {
                Console.WriteLine("Scan cancelled! Time taken: {0}", timeTaken);
            }
        }