static IBuffer GetContent(MasterFileTableEntry entry) { foreach (var attr in entry.Attributes) { if (attr.AttributeType == AttributeType.Data) { return(attr.Content); } } return(null); }
static long GetSize(MasterFileTableEntry entry) { foreach (var attr in entry.Attributes) { FileNameAttribute fna = attr as FileNameAttribute; if (fna != null) { return(fna.RealSize); } } return(0); }
static string GetPath(MasterFileTable mft, MasterFileTableEntry entry) { if (entry.SequenceNumber == MasterFileTable.RootDirectoryIndex) { return("<root>"); } FileNameAttribute fna = null; foreach (var attr in entry.Attributes) { FileNameAttribute thisFna = attr as FileNameAttribute; if (thisFna != null) { if (fna == null || thisFna.FileNameNamespace == NtfsNamespace.Win32 || thisFna.FileNameNamespace == NtfsNamespace.Win32AndDos) { fna = thisFna; } } } if (fna == null) { return("<unknown>"); } string parentPath = "<unknown>"; MasterFileTableEntry parentEntry = mft[fna.ParentDirectory.RecordIndex]; if (parentEntry != null) { if (parentEntry.SequenceNumber == fna.ParentDirectory.RecordSequenceNumber || parentEntry.SequenceNumber == fna.ParentDirectory.RecordSequenceNumber + 1) { parentPath = GetPath(mft, parentEntry); } } return(parentPath + "\\" + fna.FileName); }
protected override void DoRun() { VolumeManager volMgr = new VolumeManager(); foreach (string disk in _diskFiles.Values) { volMgr.AddDisk(VirtualDisk.OpenDisk(disk, FileAccess.Read, UserName, Password)); } VolumeInfo volInfo = null; if (!string.IsNullOrEmpty(VolumeId)) { volInfo = volMgr.GetVolume(VolumeId); } else if (Partition >= 0) { volInfo = volMgr.GetPhysicalVolumes()[Partition]; } else { volInfo = volMgr.GetLogicalVolumes()[0]; } using (NtfsFileSystem fs = new NtfsFileSystem(volInfo.Open())) { MasterFileTable mft = fs.GetMasterFileTable(); if (_recoverFile.IsPresent) { MasterFileTableEntry entry = mft[long.Parse(_recoverFile.Value)]; IBuffer content = GetContent(entry); if (content == null) { Console.WriteLine("Sorry, unable to recover content"); Environment.Exit(1); } string outFile = _recoverFile.Value + "__recovered.bin"; if (File.Exists(outFile)) { Console.WriteLine("Sorry, the file already exists: " + outFile); Environment.Exit(1); } using (FileStream outFileStream = new FileStream(outFile, FileMode.CreateNew, FileAccess.Write)) { Pump(content, outFileStream); } Console.WriteLine("Possible file contents saved as: " + outFile); Console.WriteLine(); Console.WriteLine("Caution! It is rare for the file contents of deleted files to be intact - most"); Console.WriteLine("likely the contents recovered are corrupt as the space has been reused."); } else { foreach (var entry in mft.GetEntries(EntryStates.NotInUse)) { // Skip entries with no attributes, they've probably never been used. We're certainly // not going to manage to recover any useful data from them. if (entry.Attributes.Count == 0) { continue; } // Skip directories - any useful files inside will be found separately if ((entry.Flags & MasterFileTableEntryFlags.IsDirectory) != 0) { continue; } long size = GetSize(entry); string path = GetPath(mft, entry); if (!_showMeta.IsPresent && path.StartsWith(@"<root>\$Extend")) { continue; } if (!_showZeroSize.IsPresent && size == 0) { continue; } Console.WriteLine("Index: {0,-4} Size: {1,-8} Path: {2}", entry.Index, Utilities.ApproximateDiskSize(size), path); } } } }