private static NtfsDirectory FindDir(NTFSWrapper wrapper, Options opts) { string[] pathParts = opts.PathArgument.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries).Skip(1).ToArray(); if (pathParts.Length == 0) { // Chosen path is root return(wrapper.GetRootDirectory()); } // Navigate to directory NtfsDirectory dir = wrapper.GetRootDirectory(); for (int i = 0; i < pathParts.Length; i++) { dir = dir.ListDirectories(false).FirstOrDefault(s => s.Name.Equals(pathParts[i], StringComparison.InvariantCultureIgnoreCase)); if (dir == null) { return(null); } } // Return the last directory return(dir); }
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 IActionResult Get([FromQuery] string id) { var req = id; if (Regex.IsMatch(id, @"^([a-zA-Z]\:)\/") || Regex.IsMatch(id, @"^([a-zA-Z]\:)\\") || Regex.IsMatch(id, @"^\\\\")) { id = id; } else { //id = @"\\" + (id.Replace("/", "\\")); id = @"\\" + (id.Replace(@"/", @"\")); } var folder = new NtfsDirectory(id); var result = new vmNtfsDirectory(folder, appConfiguration.ApiRootUrl, req); string json = JsonConvert.SerializeObject(result, Formatting.Indented); json = json.Replace(@"\\", @"\"); //return Ok(result); //return Ok(json); return(new ContentResult { Content = json, ContentType = "application/json", StatusCode = 200 }); }
public static NtfsFile OpenFile(NtfsDirectory dir, string file) { NtfsFile currFile = dir.ListFiles(false).SingleOrDefault(s => s.Name.Equals(file, StringComparison.InvariantCultureIgnoreCase)); Debug.Assert(currFile != null); return(currFile); }
/* 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 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)); } } }
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 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); } } }
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()); } }
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 string GetDirectory(NtfsFile file) { StringBuilder result = new StringBuilder(); result.Insert(0, "\\"); NtfsDirectory dir = file.Parent; while (dir.Name != ".") { result.Insert(0, $"{Path.DirectorySeparatorChar}{dir.Name}"); dir = dir.Parent; } result.Insert(0, ":"); return(result.ToString()); }
public static NtfsDirectory OpenDir(NTFSWrapper ntfsWrapper, string path) { Assert.IsTrue(Path.IsPathRooted(path)); string[] dirs = path.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); NtfsDirectory currDir = ntfsWrapper.GetRootDirectory(); foreach (string dir in dirs.Skip(1)) // Skip root (C:\) { IEnumerable<NtfsDirectory> subDirs = currDir.ListDirectories(false); NtfsDirectory subDir = subDirs.FirstOrDefault(s => s.Name.Equals(dir, StringComparison.InvariantCultureIgnoreCase)); Assert.IsNotNull(subDir); currDir = subDir; } return currDir; }
//CONSTRUCTOR public vmNtfsDirectory(NtfsDirectory dir, string apiRoot, string reqPath) { Name = dir.Name; FullPath = dir.FullPath; Exists = dir.Exists; Created = dir.Created; LastWrite = dir.LastWrite; TerminalLeaf = dir.TerminalLeaf; DirLink = new Uri(apiRoot + "Dir?id=" + reqPath.Replace(@"/", @"\")); ScanTime = DateTime.Now; //ScanUser = user; InheritanceEnabled = dir.InheritanceEnabled; Owner = dir.Owner; ChildFiles = new Dictionary <string, Uri>(); ChildDirectories = new Dictionary <string, Uri>(); AccessControl = new List <vmNtfsAccessRule>(); //foreach (var f in dir.ChildFiles) if (dir.ChildFiles.Any()) { for (int i = 0; i < dir.ChildFiles.Count; i++) { var uri = new Uri(apiRoot + "File?id=" + reqPath.Replace(@"/", @"\") + "\\" + dir.ChildFiles[i]); ChildFiles.Add(dir.ChildFiles[i], uri); } } if (dir.ChildDirectories.Any()) { for (int i = 0; i < dir.ChildDirectories.Count; i++) { var uri = new Uri(apiRoot + "Dir?id=" + reqPath.Replace(@"/", @"\") + "\\" + dir.ChildDirectories[i]); ChildDirectories.Add(dir.ChildDirectories[i], uri); } } foreach (var ar in dir.AccessControlList) { AccessControl.Add(new vmNtfsAccessRule(ar)); } }
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); } }
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(); } } }
private static void DisplayDetails(NTFSWrapper wrapper, Options opts, NtfsDirectory dir) { Console.WriteLine("Listing details for " + dir.Name); IEnumerable <NtfsFileEntry> subDirs = dir.ListDirectories(!opts.ShowAllNames); IEnumerable <NtfsFileEntry> subFiles = dir.ListFiles(!opts.ShowAllNames); foreach (NtfsFileEntry entry in subDirs.Concat(subFiles)) { if (opts.ShowAllStreams) { // Stream display var streams = entry.MFTRecord.Attributes.Concat(entry.MFTRecord.ExternalAttributes).GroupBy(s => new { s.AttributeName, s.Type }); foreach (var stream in streams) { AwesomeConsole.WriteLine(); } } else { // Simple file display AwesomeConsole.Write(entry.TimeModified.ToString("yyyy-MM-dd HH:mm")); AwesomeConsole.Write(" "); if (opts.ShowFileIds) { AwesomeConsole.Write(entry.MFTRecord.FileReference); AwesomeConsole.Write(" "); } if (entry is NtfsDirectory) { AwesomeConsole.Write("<DIR>"); } else { AttributeData dataAttrib = entry.MFTRecord.Attributes.OfType <AttributeData>().FirstOrDefault(s => s.NameLength == 0); long fileSize = -1; if (dataAttrib != null && dataAttrib.NonResidentFlag == ResidentFlag.Resident) { fileSize = dataAttrib.ResidentHeader.ContentLength; } else if (dataAttrib != null && dataAttrib.NonResidentFlag == ResidentFlag.NonResident) { fileSize = (long)dataAttrib.NonResidentHeader.ContentSize; } AwesomeConsole.Write(fileSize.ToString("N0")); } AwesomeConsole.Write(" "); AwesomeConsole.Write(entry.Name); AwesomeConsole.WriteLine(); } } // Volume in drive C has no label. // Volume Serial Number is 50C3-B38B // Directory of C:\ //23-08-2012 12:51 1.024 .rnd //12-05-2013 13:04 <DIR> AMD //03-03-2013 09:51 <SYMLINKD> Cygwin [C:\Program Files (x86)\Cygwin] //14-11-2012 23:24 <DIR> Intel //14-07-2009 05:20 <DIR> PerfLogs //20-05-2013 18:14 <DIR> Program Files //20-05-2013 18:20 <DIR> Program Files (x86) //12-05-2013 13:08 <DIR> ProgramData //11-05-2013 14:49 <DIR> Python27 //18-01-2013 02:13 <DIR> Temp //19-05-2013 18:21 378.273.792 test.bin //24-02-2013 02:32 <DIR> Users //21-05-2013 13:37 <DIR> Windows // 2 File(s) 378.274.816 bytes // 11 Dir(s) 21.434.728.448 bytes free }