private IRawFileSystem GetSystem(string path) { IRawFileSystem system; var driveLetter = path[0]; if (!char.IsLetter(driveLetter)) { throw new ArgumentException($"Path '{path}' did not have a drive letter!"); } if (systems.TryGetValue(driveLetter, out system)) { return(system); } try { var disk = new RawDisk(driveLetter); var rawDiskStream = disk.CreateDiskStream(); system = new NtfsFileSystem(rawDiskStream); systems.Add(driveLetter, system); } catch (Exception) { Console.WriteLine("Failed to create a filesystem for drive '{0}'", driveLetter); throw; } return(system); }
public override void Execute() { IEnumerable <char> volumeDrives = Utils.GetAllAvailableVolumes(); foreach (char device in volumeDrives) { Console.WriteLine("Trying volume, " + device + ": .. "); try { using (RawDisk disk = new RawDisk(device)) { ExampleUtilities.PresentResult(disk); } } catch (Win32Exception exception) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error: " + new Win32Exception(exception.NativeErrorCode).Message); Console.ForegroundColor = ExampleUtilities.DefaultColor; } Console.WriteLine(); } }
public override void Execute() { IEnumerable <int> physicalDrives = Utils.GetAllAvailableDrives(DiskNumberType.PhysicalDisk); foreach (int device in physicalDrives) { Console.WriteLine("Trying PhysicalDrive" + device + ": .. "); try { using (RawDisk disk = new RawDisk(DiskNumberType.PhysicalDisk, device)) { ExampleUtilities.PresentResult(disk); } } catch (Win32Exception exception) { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Error: " + new Win32Exception(exception.NativeErrorCode).Message); Console.ForegroundColor = ExampleUtilities.DefaultColor; } Console.WriteLine(); } }
public void SimpleFile() { byte[] randomData = new byte[65 * 4096]; _random.NextBytes(randomData); using (TempFile tmpFile = new TempFile()) { // Create a file File.WriteAllBytes(tmpFile.File.FullName, randomData); // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
public Stream OpenRawDiskStream(string diskPath) { using (RawDisk rawDisk = new RawDisk(diskPath)) { return(rawDisk.CreateDiskStream()); } }
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { string devid = (string)e.Argument; string devnum = new String(devid.Where(Char.IsDigit).ToArray()); RawDisk disk = new RawDisk(DiskNumberType.PhysicalDisk, Convert.ToInt32(devnum), FileAccess.Read); long diskReadLength = disk.SizeBytes; long totalRead = 0; int increment = (int)(((16f * 1024f * 1024f) / disk.SectorSize) * disk.SectorSize); byte[] input = new byte[increment]; Stopwatch sw = new Stopwatch(); FileStream fs = new FileStream(textBox1.Text, FileMode.Create); using (RawDiskStream diskFs = disk.CreateDiskStream()) { sw.Start(); while (true) { if (backgroundWorker1.CancellationPending) { e.Cancel = true; diskFs.Close(); fs.Close(); break; } int read = (int)Math.Min(increment, disk.SizeBytes - totalRead); int actualRead = diskFs.Read(input, 0, read); if (actualRead == 0) { diskFs.Close(); fs.Close(); if (totalRead == diskReadLength) { readCompleteOK = true; } else { readCompleteOK = false; } break; } totalRead += actualRead; fs.Write(input, 0, input.Length); imageState imst = new imageState(); imst.progress = fsToHuman(Convert.ToUInt64(totalRead)) + " / " + fsToHuman(Convert.ToUInt64(diskReadLength)); int perc = (int)(0.5f + ((100f * totalRead) / disk.SizeBytes)); //imst.disksize = disk.SizeBytes; //imst.diskposition = totalRead; imst.percent = perc.ToString() + "% complete"; imst.speed = Math.Round(((diskFs.Position / 1048576f) / sw.Elapsed.TotalSeconds), 2).ToString() + "MB/s"; backgroundWorker1.ReportProgress(perc, imst); } } }
public static IFileSystem GetFileSystem(char driveLetter, FileAccess fileAccess) { var disk = new RawDisk(driveLetter, fileAccess); var rawDiskStream = disk.CreateDiskStream(); var system = new NtfsFileSystem(rawDiskStream); return(system); }
static void Main(string[] args) { char driveLetter = 'C'; if (args.Length == 1) { driveLetter = args[0][0]; } using (RawDisk disk = new RawDisk(driveLetter)) { MftDiskExtents res = new MftDiskExtents(); byte[] ntfsBoot = disk.ReadSectors(0, 1); BootSector boot = BootSector.ParseData(ntfsBoot, ntfsBoot.Length, 0); Console.WriteLine("MFT is at LCN " + boot.MFTCluster); MftDetails mft = GetMftDetails(disk, boot); Console.WriteLine("MFT is in " + mft.MftExtents.Length + " extents"); res.Extents.AddRange(mft.MftExtents); using (RawDiskStream diskStream = disk.CreateDiskStream()) using (NtfsDiskStream mftStream = new NtfsDiskStream(diskStream, false, mft.MftExtents, (uint)disk.ClusterSize, 0, (long)mft.MftSize)) { uint sectorsPrRecord = (uint)(boot.MFTRecordSizeBytes / disk.SectorSize); ushort bytesPrSector = (ushort)disk.SectorSize; int records = (int)(mftStream.Length / boot.MFTRecordSizeBytes); byte[] tmp = new byte[boot.MFTRecordSizeBytes]; while (true) { int read = mftStream.Read(tmp, 0, tmp.Length); if (read < boot.MFTRecordSizeBytes) { Console.WriteLine("Stopped reading as we got " + read + " bytes instead of " + tmp.Length + " bytes"); break; } FileRecord rec = FileRecord.Parse(tmp, 0, bytesPrSector, sectorsPrRecord); // Keep track of all external extents to the MFT RecordExternalDiskExtents(rec, res); //// Special case for LIST attributes, since they can further reference more extents outside the MFT //ProcessNonResidentListAttributes(disk, rec); } } long clustersTotal = res.Extents.Sum(x => x.Clusters); Console.WriteLine("To copy: {0:N0} extents", res.Extents.Count); Console.WriteLine("{0:N0} clusters, {1:N0} bytes", clustersTotal, clustersTotal * disk.ClusterSize); } Console.ReadLine(); }
/* TODO: * List streams ($DATA, $BITMAP ..) * List alternate namings (Win32, DOS, POSIX) * Toggle FileID's * List matching attributes * Recursive * Deleted records */ static void Main(string[] args) { Options opts = new Options(); bool success = opts.Parse(args); if (!success) { AwesomeConsole.WriteLine("Unable to parse the commandline:"); PrintError(opts.ErrorDetails); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine("Try --help for more informations"); return; } if (opts.ActionType == ActionType.ShowHelp) { opts.DisplayHelp(); return; } using (RawDisk disk = new RawDisk(opts.Drive)) { NTFSWrapper wrapper = new NTFSWrapper(new NTFSDiskProvider(disk), 1); NtfsDirectory dir = null; if (opts.PathType == PathType.Directory) { dir = FindDir(wrapper, opts); } if (dir == null) { PrintError("The given path didn't exist"); AwesomeConsole.WriteLine(); switch (opts.PathType) { case PathType.Directory: PrintError("Specified " + opts.PathType + ": " + opts.PathArgument); break; } AwesomeConsole.WriteLine(); return; } // Display DisplayDetails(wrapper, opts, dir); } if (Debugger.IsAttached) { Console.ReadLine(); } }
public static void PresentResult(RawDisk disk) { byte[] data = disk.ReadClusters(0, (int)Math.Min(disk.ClusterCount, ClustersToRead)); string fatType = Encoding.ASCII.GetString(data, 82, 8); // Extended FAT parameters have a display name here. bool isFat = fatType.StartsWith("FAT"); bool isNTFS = Encoding.ASCII.GetString(data, 3, 4) == "NTFS"; // Optimization, if it's a known FS, we know it's not all zeroes. bool allZero = (!isNTFS || !isFat) && data.All(s => s == 0); Console.WriteLine("Size in bytes : {0:N0}", disk.SizeBytes); Console.WriteLine("Sectors : {0:N0}", disk.ClusterCount); Console.WriteLine("SectorSize : {0:N0}", disk.SectorSize); Console.WriteLine("ClusterCount : {0:N0}", disk.ClusterCount); Console.WriteLine("ClusterSize : {0:N0}", disk.ClusterSize); if (!isFat && !isNTFS) { Console.ForegroundColor = ConsoleColor.Red; } if (isNTFS) { Console.ForegroundColor = ConsoleColor.Green; } Console.WriteLine("Is NTFS : {0}", isNTFS); Console.ForegroundColor = DefaultColor; if (!isFat && !isNTFS) { Console.ForegroundColor = ConsoleColor.Red; } if (isFat) { Console.ForegroundColor = ConsoleColor.Green; } Console.WriteLine("Is FAT : {0}", isFat ? fatType : "False"); Console.ForegroundColor = DefaultColor; if (!allZero) { Console.ForegroundColor = ConsoleColor.Green; } else { Console.ForegroundColor = ConsoleColor.Red; } Console.WriteLine("All bytes zero: {0}", allZero); Console.ForegroundColor = DefaultColor; }
public void AlternateDatastreamDirectory() { Random rand = new Random(); byte[][] data = new byte[10][]; for (int i = 0; i < 10; i++) { data[i] = new byte[1024 * 1024]; rand.NextBytes(data[i]); } using (TempDir tmpDir = new TempDir()) { // Make file for (int i = 0; i < 10; i++) { using (SafeFileHandle fileHandle = Win32.CreateFile(tmpDir.Directory.FullName + ":alternate" + i + ":$DATA")) using (FileStream fs = new FileStream(fileHandle, FileAccess.ReadWrite)) { fs.Write(data[i], 0, data[i].Length); } } // Discover dir in NTFSLib char driveLetter = tmpDir.Directory.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpDir.Directory.FullName); // Check streams string[] streams = ntfsWrapper.ListDatastreams(ntfsDir.MFTRecord); Assert.AreEqual(10, streams.Length); for (int i = 0; i < 10; i++) { Assert.AreEqual(1, streams.Count(s => s == "alternate" + i)); } // Check data for (int i = 0; i < 10; i++) { using (Stream memStream = new MemoryStream(data[i])) using (Stream fileStream = ntfsWrapper.OpenFileRecord(ntfsDir.MFTRecord, "alternate" + i)) { StreamUtils.CompareStreams(memStream, fileStream); } } } }
public void EnumerateChilds() { Random rand = new Random(); using (TempDir tmpDir = new TempDir()) { // Make files byte[] data = new byte[1024 * 1024]; for (int i = 0; i < 10; i++) { rand.NextBytes(data); File.WriteAllBytes(Path.Combine(tmpDir.Directory.FullName, i + ".bin"), data); } // Make dirs for (int i = 0; i < 10; i++) { rand.NextBytes(data); tmpDir.Directory.CreateSubdirectory("dir" + i); } // Discover dir in NTFSLib char driveLetter = tmpDir.Directory.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpDir.Directory.FullName); // Enumerate files List <NtfsFile> ntfsFiles = ntfsDir.ListFiles().ToList(); Assert.AreEqual(10, ntfsFiles.Count); for (int i = 0; i < 10; i++) { Assert.AreEqual(1, ntfsFiles.Count(s => s.Name == i + ".bin")); } // Enumerate dirs List <NtfsDirectory> ntfsDirs = ntfsDir.ListDirectories().ToList(); Assert.AreEqual(10, ntfsDirs.Count); for (int i = 0; i < 10; i++) { Assert.AreEqual(1, ntfsDirs.Count(s => s.Name == "dir" + i)); } } }
internal override void ParseAttributeNonResidentBody(RawDisk disk) { base.ParseAttributeNonResidentBody(disk); // Read clusters from disk Data = new byte[NonResidentHeader.ContentSize]; using (RawDiskStream diskStream = disk.CreateDiskStream()) using (NtfsDiskStream attribStream = new NtfsDiskStream(diskStream, false, NonResidentHeader.Fragments, (uint)disk.ClusterSize, 0, Data.LongLength)) attribStream.Read(Data, 0, Data.Length); }
public void SparseFile() { byte[] randomData = new byte[35 * 4096]; _random.NextBytes(randomData); // Clear the 16 * 4096 -> 32 * 4096 range Array.Clear(randomData, 16 * 4096, 16 * 4096); using (TempFile tmpFile = new TempFile()) { // Create a file File.WriteAllBytes(tmpFile.File.FullName, randomData); using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName)) { wrapper.FileSystemSetSparseFile(true); wrapper.FileSystemSetZeroData(16 * 4096, 16 * 4096); FILE_ALLOCATED_RANGE_BUFFER[] rangesData = wrapper.FileSystemQueryAllocatedRanges(0, randomData.Length); // We should have 2 ranges on non-zero data Assert.AreEqual(2, rangesData.Length); } // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.SparseFile)); AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single(); Assert.IsTrue(attributeData.DataFragments.Length > 1); Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsSparseFragment)); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
private void FillInStorageDeviceDirectoryType(TreeNode parentNode, RawDisk disk) { if (disk.DiskInfo.MediaType != MEDIA_TYPE.FixedMedia) { return; } TreeNode thisNode = new TreeNode { Text = disk.DosDeviceName, Tag = new DiskExGet(disk.DiskHandle) }; parentNode.Nodes.Add(thisNode); }
public static IEnumerable <NtfsDirectory> GetDirectories(char driveLetter, string directory) { if (string.IsNullOrWhiteSpace(directory)) { throw new ArgumentException("String cannot be null, empty or whitespace.", nameof(directory)); } using (RawDisk disk = new RawDisk(driveLetter, FileAccess.Read)) { NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, rawDiskCacheRecordSize); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, directory); return(ntfsDir.ListDirectories()); } }
private static void ProcessNonResidentListAttributes(RawDisk disk, FileRecord rec) { // First, take all LIST attributes foreach (Attribute attrib in rec.Attributes) { if (attrib.Type != AttributeType.ATTRIBUTE_LIST || attrib.NonResidentFlag != ResidentFlag.NonResident) { continue; } AttributeList list = (AttributeList)attrib; // Parse attributes from elsewhere on disk list.ParseAttributeNonResidentBody(disk); } }
public void CompressedFile() { using (TempFile tmpFile = new TempFile()) { // Create a file // Write file data using (FileStream fs = File.OpenWrite(tmpFile.File.FullName)) { byte[] data = Encoding.ASCII.GetBytes("The white bunny jumps over the brown dog in a carparking lot"); for (int i = 0; i < 20000; i++) { fs.Write(data, 0, data.Length); } } using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName)) { wrapper.FileSystemSetCompression(COMPRESSION_FORMAT.LZNT1); } // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.Compressed)); AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single(); Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsCompressed)); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
private static SparseStream OpenFile(string path) { var rawPath = path.Substring(3); if (_fileSystem != null) { return(_fileSystem.OpenFile(rawPath, FileMode.Open, FileAccess.Read)); } var disk = new RawDisk(path.ToLowerInvariant().First()); var rawDiskStream = disk.CreateDiskStream(); _fileSystem = new NtfsFileSystem(rawDiskStream); return(_fileSystem.OpenFile(rawPath, FileMode.Open, FileAccess.Read)); }
private void ProcessDrive(RawDisk disk) { switch (scanType) { case ScanType.Unknown: break; case ScanType.Read: PerformRead(disk); break; case ScanType.Write: if (PerformWrite(disk)) { PerformRead(disk); } break; case ScanType.Verify: if (PerformWrite(disk, 0xAA)) { PerformRead(disk, 0xAA); } break; case ScanType.Pass2: if (PerformWrite(disk, 0xAA)) { if (PerformRead(disk, 0xAA)) { if (PerformWrite(disk, 0x55)) { PerformRead(disk, 0x55); } } } break; default: throw new ArgumentOutOfRangeException(); } cancelTokenSrc.Cancel(); }
private static MftDetails GetMftDetails(RawDisk disk, BootSector boot) { byte[] mftFirst = disk.ReadClusters((long)boot.MFTCluster, 1); FileRecord rec = FileRecord.Parse(mftFirst, 0, (ushort)disk.SectorSize, (uint)(boot.MFTRecordSizeBytes / disk.SectorSize)); // Get DATA attrib // TODO: Handle multiple DATA attributes AttributeGeneric dataAttrib = null; foreach (Attribute attribute in rec.Attributes) { if (attribute.Type == AttributeType.DATA && attribute.AttributeName.Length == 0) { // Got it! dataAttrib = attribute as AttributeGeneric; break; } } Debug.Assert(dataAttrib != null); MftDetails res = new MftDetails(); // Get attribute data // Parse out extents if (dataAttrib.NonResidentFlag == ResidentFlag.Resident) { byte[] dataAttribData = dataAttrib.Data; res.MftSize = dataAttrib.ResidentHeader.ContentLength; res.MftExtents = DataFragment.ParseFragments(dataAttribData, dataAttribData.Length, 0, 0, 0); } else { res.MftSize = dataAttrib.NonResidentHeader.ContentSize; res.MftExtents = dataAttrib.NonResidentHeader.Fragments; } Debug.Assert(res.MftExtents != null); return(res); }
public void Start() { try { Phase = @"Initialising"; Log.Debug(@"Creating Disk interface"); var disk = new RawDisk(deviceId, FileAccess.ReadWrite); Log.Info(@"Setting [{0}] offline", deviceId); if (!DiskExSet.SetOnline(disk.DiskHandle, false, false)) { Log.Warn(@"Unable to take disk offline"); } Task.Run(() => ProcessDrive(disk)); } catch (Exception e) { Log.Error(e); Cancel(); } }
public static byte[] ReadFragments(RawDisk disk, DataFragment[] fragments) { int totalLength = 0; foreach (DataFragment fragment in fragments) { totalLength += (int)(fragment.Clusters * disk.ClusterSize); } byte[] data = new byte[totalLength]; using (Stream diskStream = disk.CreateDiskStream()) using (NtfsDiskStream stream = new NtfsDiskStream(diskStream, false, fragments, (uint)disk.ClusterSize, 0, totalLength)) { stream.Read(data, 0, data.Length); } // Return the data return(data); }
private static uint FindPathMftId(Options opts) { string[] pathParts = opts.PathArgument.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); string[] pathParents = pathParts.Skip(1).Take(pathParts.Length - 2).ToArray(); if (pathParts.Length == 1) { // Chosen path is root return((uint)SpecialMFTFiles.RootDir); } using (RawDisk disk = new RawDisk(opts.Drive)) { NTFSWrapper ntfs = new NTFSWrapper(new NTFSDiskProvider(disk), 4); // Navigate to parent directory NtfsDirectory parentDir = ntfs.GetRootDirectory(); for (int i = 0; i < pathParents.Length; i++) { parentDir = parentDir.ListDirectories(false).FirstOrDefault(s => s.Name.Equals(pathParents[i], StringComparison.InvariantCultureIgnoreCase)); if (parentDir == null) { return(uint.MaxValue); } } // Select the correct child IEnumerable <NtfsFileEntry> childs = opts.PathType == PathType.File ? (IEnumerable <NtfsFileEntry>)parentDir.ListFiles(false) : parentDir.ListDirectories(false); NtfsFileEntry child = childs.FirstOrDefault(s => s.Name.Equals(pathParts.Last(), StringComparison.InvariantCultureIgnoreCase)); if (child == null) { return(uint.MaxValue); } // Return the childs id return(child.MFTRecord.MFTNumber); } }
public static void CopyFile(string sourceFile, string dstFile) { // FileAttributes 0x20000000L = FILE_FLAG_NO_BUFFERING SafeFileHandle fileHandle = Win32Helper.CreateFile(sourceFile, (FileAccess)Program.FILE_READ_ATTRIBUTES, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal | (FileAttributes)0x20000000L, IntPtr.Zero); if (fileHandle.IsInvalid) { throw new ArgumentException("Invalid file: " + sourceFile); } //var driveWrapper = new DeviceIOControlWrapper(driveHandle); FilesystemDeviceWrapper fileWrapper = new FilesystemDeviceWrapper(fileHandle); FileExtentInfo[] extents = fileWrapper.FileSystemGetRetrievalPointers(); decimal totalSize = extents.Sum(s => (decimal)s.Size); decimal copiedBytes = 0; using (RawDisk disk = new RawDisk(char.ToUpper(sourceFile[0]))) { // Write to the source file using (FileStream fs = new FileStream(dstFile, FileMode.Create)) { // Copy all extents foreach (FileExtentInfo fileExtentInfo in extents) { // Copy chunks of data for (ulong offset = 0; offset < fileExtentInfo.Size; offset += 10000) { int currentSizeBytes = (int)Math.Min(10000, fileExtentInfo.Size - offset); byte[] data = disk.ReadClusters((long)(fileExtentInfo.Lcn + offset), currentSizeBytes); fs.Write(data, 0, data.Length); copiedBytes += currentSizeBytes; } } } } Debug.Assert(copiedBytes == totalSize); }
IRawFileSystem GetSystem(string path) { IRawFileSystem system; var driveLetter = path[0]; if (!char.IsLetter(driveLetter)) { throw new ArgumentException($"Path '{path}' did not have a drive letter!"); } if (systems.TryGetValue(driveLetter, out system)) { return(system); } var disk = new RawDisk(driveLetter); var rawDiskStream = disk.CreateDiskStream(); system = new NtfsFileSystem(rawDiskStream); systems.Add(driveLetter, system); return(system); }
internal override void ParseAttributeNonResidentBody(RawDisk disk) { base.ParseAttributeNonResidentBody(disk); // Get all chunks byte[] data = NtfsUtils.ReadFragments(disk, NonResidentHeader.Fragments); // Parse List <AttributeListItem> results = new List <AttributeListItem>(); int pointer = 0; int contentSize = (int)NonResidentHeader.ContentSize; while (pointer + 26 <= contentSize) // 26 is the smallest possible MFTAttributeListItem { AttributeListItem item = AttributeListItem.ParseListItem(data, data.Length - pointer, pointer); if (item.Type == AttributeType.EndOfAttributes) { break; } if (item.Length == 0) { break; } results.Add(item); pointer += item.Length; } Debug.Assert(pointer == contentSize); Items = results.ToArray(); }
private void FillInStorageDeviceDirectoryType(TreeNode parentNode, Win32DiskDrive win32Disk) { TreeNode thisNode = new TreeNode { Text = win32Disk.Caption, Tag = win32Disk }; parentNode.Nodes.Add(thisNode); using RawDisk disk = new RawDisk(win32Disk.DeviceId); FillInStorageDeviceDirectoryType(thisNode, disk); var partitionQueryText = $"associators of {{{win32Disk.RelativePath}}} where AssocClass = Win32_DiskDriveToDiskPartition"; var partitionQuery = new ManagementObjectSearcher(partitionQueryText); foreach (ManagementObject p in partitionQuery.Get()) { var logicalDriveQueryText = $"associators of {{{p.Path.RelativePath}}} where AssocClass = Win32_LogicalDiskToPartition"; var logicalDriveQuery = new ManagementObjectSearcher(logicalDriveQueryText); foreach (ManagementObject ld in logicalDriveQuery.Get()) { Win32LogicalDisk ldp = new Win32LogicalDisk(ld); TreeNode part = new TreeNode { Text = string.Concat(ldp.VolumeName, @" -> ", ldp.Caption), Tag = ldp }; thisNode.Nodes.Add(part); } } }
static void Main(string[] args) { Options opts = new Options(); bool success = opts.Parse(args); if (!success) { AwesomeConsole.WriteLine("Unable to parse the commandline:"); PrintError(opts.ErrorDetails); AwesomeConsole.WriteLine(); AwesomeConsole.WriteLine("Try --help for more informations"); return; } if (opts.ActionType == ActionType.ShowHelp) { opts.DisplayHelp(); return; } // Work with the options if (opts.ActionType == ActionType.ShowFull || opts.ActionType == ActionType.ShowExtents) { uint mftId = 0; if (opts.PathType == PathType.File || opts.PathType == PathType.Directory) { mftId = FindPathMftId(opts); } else if (opts.PathType == PathType.MftId) { mftId = opts.MftId; } using (RawDisk disk = new RawDisk(opts.Drive)) using (Stream stream = disk.CreateDiskStream()) { NTFSParser parser = new NTFSParser(stream); if (parser.FileRecordCount < mftId) { PrintError("The given path or MftID didn't exist"); AwesomeConsole.WriteLine(); switch (opts.PathType) { case PathType.Directory: case PathType.File: PrintError("Specified " + opts.PathType + ": " + opts.PathArgument); break; case PathType.MftId: PrintError("Specified type: MftId, id: " + opts.MftId); break; } AwesomeConsole.WriteLine(); return; } if (opts.ActionType == ActionType.ShowFull) { PrintFull(parser, opts, mftId); } else if (opts.ActionType == ActionType.ShowExtents) { PrintExtents(parser, opts, mftId); } } } else if (opts.ActionType == ActionType.Path) { using (RawDisk disk = new RawDisk(opts.Drive)) { PrintPaths(disk, opts); } } if (Debugger.IsAttached) { Console.ReadLine(); } }
private static void PrintPaths(RawDisk disk, Options options) { uint mftId = uint.MaxValue; if (options.PathType == PathType.MftId) { AwesomeConsole.WriteLine("Specified an Mft Id - skipping forward-only search", ConsoleColor.DarkGreen); mftId = options.MftId; } else if (options.PathType == PathType.File || options.PathType == PathType.Directory) { AwesomeConsole.WriteLine("Conducting forward-only path search", ConsoleColor.Green); string[] pathParts = options.PathArgument.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); string[] pathParents = pathParts.Skip(1).Take(pathParts.Length - 2).ToArray(); NTFSWrapper ntfs = new NTFSWrapper(new NTFSDiskProvider(disk), 4); NtfsDirectory dir = ntfs.GetRootDirectory(); PrintName(dir.Name); AwesomeConsole.Write(" "); PrintReference(dir.MFTRecord.FileReference); AwesomeConsole.WriteLine(); string pathSoFar = options.Drive + ":\\"; for (int i = 0; i < pathParents.Length; i++) { AwesomeConsole.Write(pathSoFar, ConsoleColor.DarkYellow); if (dir == null) { PrintName(pathParents[i]); AwesomeConsole.Write(" "); PrintError("(Unable to find parent)"); AwesomeConsole.WriteLine(); } else { dir = dir.ListDirectories(false).FirstOrDefault(s => s.Name.Equals(pathParents[i], StringComparison.InvariantCultureIgnoreCase)); if (dir == null) { PrintName(pathParents[i]); AwesomeConsole.Write(" "); PrintError("(Unable to find this)"); AwesomeConsole.WriteLine(); } else { PrintName(dir.Name); AwesomeConsole.Write(" "); PrintReference(dir.MFTRecord.FileReference); AwesomeConsole.WriteLine(); } } pathSoFar = Path.Combine(pathSoFar, pathParents[i] + "\\"); } AwesomeConsole.Write(pathSoFar, ConsoleColor.DarkYellow); if (dir == null) { PrintName(pathParts.Last()); AwesomeConsole.Write(" "); PrintError("(Unable to find parent)"); AwesomeConsole.WriteLine(); } else { IEnumerable <NtfsFileEntry> childs = options.PathType == PathType.File ? (IEnumerable <NtfsFileEntry>)dir.ListFiles(false) : dir.ListDirectories(false); NtfsFileEntry child = childs.FirstOrDefault(s => s.Name.Equals(pathParts.Last(), StringComparison.InvariantCultureIgnoreCase)); if (child == null) { PrintName(pathParts.Last()); AwesomeConsole.Write(" "); PrintError("(Unable to find this)"); AwesomeConsole.WriteLine(); } else { PrintName(child.Name); AwesomeConsole.Write(" "); PrintReference(child.MFTRecord.FileReference); AwesomeConsole.WriteLine(); mftId = child.MFTRecord.MFTNumber; AwesomeConsole.WriteLine("Search completed, found MftId: " + mftId); } } } AwesomeConsole.WriteLine(); { NTFSWrapper wrapper = new NTFSWrapper(new NTFSDiskProvider(disk), 4); if (wrapper.FileRecordCount < mftId) { PrintError("Unable to locate the specified file, aborting."); AwesomeConsole.WriteLine(); return; } AwesomeConsole.WriteLine("Conducting backwards-only path search", ConsoleColor.Green); Dictionary <uint, List <string> > paths = new Dictionary <uint, List <string> >(); List <string> finalPaths = new List <string>(); FileRecord baseRecord = wrapper.ReadMFTRecord(mftId); foreach (AttributeFileName fileName in baseRecord.Attributes.OfType <AttributeFileName>().Concat(baseRecord.ExternalAttributes.OfType <AttributeFileName>())) { uint parentId = fileName.ParentDirectory.FileId; if (paths.ContainsKey(parentId)) { paths[parentId].Add(fileName.FileName); } else { paths[parentId] = new List <string> { fileName.FileName } }; } do { Dictionary <uint, List <string> > newPaths = new Dictionary <uint, List <string> >(); foreach (KeyValuePair <uint, List <string> > keyValuePair in paths) { if (keyValuePair.Key == (uint)SpecialMFTFiles.RootDir) { finalPaths.AddRange(keyValuePair.Value.Select(s => Path.Combine(options.Drive + ":\\", s))); } else { FileRecord record = wrapper.ReadMFTRecord(keyValuePair.Key); foreach (AttributeFileName fileName in record.Attributes.OfType <AttributeFileName>().Concat(record.ExternalAttributes.OfType <AttributeFileName>())) { uint parentId = fileName.ParentDirectory.FileId; if (newPaths.ContainsKey(parentId)) { newPaths[parentId].AddRange(keyValuePair.Value.Select(s => Path.Combine(fileName.FileName, s))); } else { newPaths[parentId] = new List <string>(keyValuePair.Value.Select(s => Path.Combine(fileName.FileName, s))); } } } } paths = newPaths; } while (paths.Any()); AwesomeConsole.WriteLine("Got " + finalPaths.Count + " paths"); foreach (string finalPath in finalPaths) { PrintName(finalPath); AwesomeConsole.WriteLine(); } } }