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);
                    }
            }
        }
        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);
        }
Example #3
0
        internal static NtfsFileEntry CreateEntry(NTFSWrapper ntfsWrapper, uint fileId, AttributeFileName fileName = null)
        {
            if (fileName == null)
            {
                // Dig up a preferred name
                FileRecord tmpRecord = ntfsWrapper.ReadMFTRecord(fileId);
                fileName = NtfsUtils.GetPreferredDisplayName(tmpRecord);
            }

            NtfsFileEntry entry = ntfsWrapper.FileCache.Get(fileId, fileName.FileName.GetHashCode());

            if (entry != null)
            {
                Debug.WriteLine("Got from cache: " + fileId + ":" + fileName.Id);
                return(entry);
            }

            // Create it
            FileRecord record = ntfsWrapper.ReadMFTRecord(fileId);

            if (record.Flags.HasFlag(FileEntryFlags.Directory))
            {
                entry = new NtfsDirectory(ntfsWrapper, record, fileName);
            }
            else
            {
                entry = new NtfsFile(ntfsWrapper, record, fileName);
            }

            ntfsWrapper.FileCache.Set(fileId, fileName.Id, entry);

            return(entry);
        }
Example #4
0
        internal NtfsDirectory(NTFSWrapper ntfsWrapper, FileRecord record, AttributeFileName fileName)
            : base(ntfsWrapper, record, fileName)
        {
            Debug.Assert(record.Flags.HasFlag(FileEntryFlags.Directory));

            PrepRecord();
        }
Example #5
0
 protected NtfsFileEntry(NTFSWrapper ntfsWrapper, FileRecord record, AttributeFileName fileName)
 {
     NTFSWrapper = ntfsWrapper;
     MFTRecord   = record;
     FileName    = fileName;
     Init();
 }
        /* 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();
            }
        }
Example #7
0
        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);
                        }
                }
            }
        }
Example #8
0
        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 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);
                    }
            }
        }
Example #10
0
        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);
                    }
            }
        }
        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;
        }
        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);
            }
        }
Example #14
0
        private void PrepRecord()
        {
            // Ensure we have all INDEX attributes at hand
            bool parseLists = false;

            foreach (AttributeList list in MFTRecord.Attributes.OfType <AttributeList>())
            {
                foreach (AttributeListItem item in list.Items)
                {
                    if (item.BaseFile != MFTRecord.FileReference &&
                        (item.Type == AttributeType.INDEX_ROOT || item.Type == AttributeType.INDEX_ALLOCATION))
                    {
                        // We need to parse lists
                        parseLists = true;
                    }
                }
            }

            if (parseLists)
            {
                NTFSWrapper.ParseAttributeLists(MFTRecord);
            }

            // Get root
            _indexRoot = MFTRecord.Attributes.OfType <AttributeIndexRoot>().Single(s => s.AttributeName == DirlistAttribName);

            // Get allocations
            _indexes = MFTRecord.Attributes.OfType <AttributeIndexAllocation>().Where(s => s.AttributeName == DirlistAttribName).ToArray();

            foreach (AttributeIndexAllocation index in _indexes)
            {
                NTFSWrapper.ParseNonResidentAttribute(index);
            }

            // Get bitmap of allocations
            // var bitmap = MFTRecord.Attributes.OfType<AttributeBitmap>().Single(s => s.AttributeName == DirlistAttribName);
        }
        static void Main(string[] args)
        {
            const char driveLetter = 'E';
            RawDisk    disk        = new RawDisk(driveLetter);

            using (Stream stream = disk.CreateDiskStream())
                using (Stream streama = disk.CreateDiskStream())
                {
                    NTFSParser parser  = new NTFSParser(stream);
                    NTFSParser parsera = new NTFSParser(streama);

                    int longest = 0;
                    foreach (FileRecord record in parser.GetRecords(true))
                    {
                        int count = record.Attributes.Count;

                        if (count > longest)
                        {
                            longest = count;
                            Console.WriteLine(record.FileReference + " - " + count);
                        }
                    }
                }

            NTFSDiskProvider provider = new NTFSDiskProvider(disk);

            NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 524288);

            ntfsWrapper.InitializeCommon();

            Console.WriteLine("Read NTFS. Version: " + ntfsWrapper.NTFSVersion);

            // Filerecord bitmap
            ntfsWrapper.ParseNonResidentAttribute(ntfsWrapper.FileMFT.Attributes.OfType <AttributeBitmap>().Single());
            BitArray bitmapData = ntfsWrapper.FileMFT.Attributes.OfType <AttributeBitmap>().Single().Bitfield;

            HashSet <AttributeType> types = new HashSet <AttributeType>();

            // Read fragmented file
            for (uint i = 0; i < ntfsWrapper.FileRecordCount; i++)
            {
                if (!ntfsWrapper.InRawDiskCache(i))
                {
                    ntfsWrapper.PrepRawDiskCache(i);
                }

                if (!bitmapData[(int)i])
                {
                    continue;
                }

                FileRecord record = ntfsWrapper.ReadMFTRecord(i);

                if (record.Flags.HasFlag(FileEntryFlags.FileInUse))
                {
                    ntfsWrapper.ParseNonResidentAttributes(record);
                }

                Console.Write("Read {0:N0} of {1:N0} - ({2:N0} bytes {3:N0} allocated)", i, ntfsWrapper.FileRecordCount, record.SizeOfFileRecord, record.SizeOfFileRecordAllocated);

                if (record.Flags.HasFlag(FileEntryFlags.FileInUse))
                {
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.Write(" (InUse)");
                    Console.ForegroundColor = ConsoleColor.Gray;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.DarkMagenta;
                    Console.Write(" (Not InUse)");
                    Console.ForegroundColor = ConsoleColor.Gray;
                }

                if (bitmapData[(int)i])
                {
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.Write(" (Bitmap:InUse)");
                    Console.ForegroundColor = ConsoleColor.Gray;
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.DarkMagenta;
                    Console.Write(" (Bitmap:Not InUse)");
                    Console.ForegroundColor = ConsoleColor.Gray;
                }

                if (record.Flags.HasFlag(FileEntryFlags.Directory))
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write(" (dir)");
                    Console.ForegroundColor = ConsoleColor.Gray;
                }

                if (record.BaseFile.FileId != 0)
                {
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write(" (base: {0})", record.BaseFile);
                    Console.ForegroundColor = ConsoleColor.Gray;
                }

                if (Enum.IsDefined(typeof(SpecialMFTFiles), record.FileReference.FileId))
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.Write(" ({0})", (SpecialMFTFiles)record.FileReference.FileId);
                    Console.ForegroundColor = ConsoleColor.Gray;
                }

                Console.WriteLine();

                foreach (Attribute attribute in record.Attributes.Concat(record.ExternalAttributes).OrderBy(s => s.Id))
                {
                    bool wasNew = types.Add(attribute.Type);
                    if (wasNew)
                    {
                        File.AppendAllLines("out.txt", new[] { record.FileReference + ": " + attribute.Type });
                        Debugger.Break();
                    }

                    string name = string.IsNullOrWhiteSpace(attribute.AttributeName) ? string.Empty : " '" + attribute.AttributeName + "'";

                    Console.Write("  " + attribute.Id + " (" + attribute.Type);

                    if (name != string.Empty)
                    {
                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.Write(name);
                        Console.ForegroundColor = ConsoleColor.Gray;
                    }

                    Console.Write(")");

                    AttributeFileName attributeFileName = attribute as AttributeFileName;
                    if (attributeFileName != null)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write(" '{0}'", attributeFileName.FileName);
                        Console.ForegroundColor = ConsoleColor.Gray;
                    }

                    AttributeData attributeData = attribute as AttributeData;
                    if (attributeData != null)
                    {
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.Write(" {0}", attributeData.NonResidentFlag);

                        Console.ForegroundColor = ConsoleColor.Green;
                        Console.Write(" ({0:N0} bytes)", attributeData.NonResidentFlag == ResidentFlag.NonResident ? attributeData.NonResidentHeader.ContentSize : (ulong)attributeData.DataBytes.Length);

                        if (attributeData.NonResidentFlag == ResidentFlag.Resident)
                        {
                            Console.ForegroundColor = ConsoleColor.Red;
                            Console.Write(" ('{0}')", Encoding.ASCII.GetString(attributeData.DataBytes, 0, Math.Min(attributeData.DataBytes.Length, 30)));
                        }
                        else
                        {
                            Console.ForegroundColor = ConsoleColor.Cyan;
                            Console.WriteLine();

                            foreach (DataFragment fragment in attributeData.DataFragments)
                            {
                                Console.Write("    LCN: {0:N0} ({1:N0} clusters) ", fragment.LCN, fragment.Clusters);

                                if (fragment.IsCompressed)
                                {
                                    Console.ForegroundColor = ConsoleColor.Blue;
                                    Console.Write(" (Compressed)");
                                    Console.ForegroundColor = ConsoleColor.Cyan;
                                }

                                if (fragment.IsSparseFragment)
                                {
                                    Console.ForegroundColor = ConsoleColor.Blue;
                                    Console.Write(" (Sparse)");
                                    Console.ForegroundColor = ConsoleColor.Cyan;
                                }

                                Console.WriteLine();
                            }
                        }

                        Console.ForegroundColor = ConsoleColor.Gray;
                    }

                    Console.WriteLine();
                }

                Console.WriteLine();
            }

            Console.WriteLine("Done.");
            Console.ReadLine();
        }
        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
        }
Example #17
0
        private void PrepRecord()
        {
            // Ensure we have all INDEX attributes at hand
            bool parseLists = false;

            foreach (AttributeList list in MFTRecord.Attributes.OfType <AttributeList>())
            {
                foreach (AttributeListItem item in list.Items)
                {
                    if (item.BaseFile != MFTRecord.FileReference &&
                        (item.Type == AttributeType.INDEX_ROOT || item.Type == AttributeType.INDEX_ALLOCATION))
                    {
                        // We need to parse lists
                        parseLists = true;
                    }
                }
            }

            if (parseLists)
            {
                NTFSWrapper.ParseAttributeLists(MFTRecord);
            }

            bool containsItem = MFTRecord.Attributes.Any(s => s.AttributeName == DirlistAttribName);

            if (containsItem)
            {
                IEnumerable <AttributeIndexRoot> matches = MFTRecord.Attributes.OfType <AttributeIndexRoot>().Where(s => s.AttributeName == DirlistAttribName);
                if (!matches.Any())             // Does list contain any items?
                {
                    return;                     // Bail if no IndexRoot Attributes where AttributeName == DirlistAttribName
                }

                // IEnumerable.Single(predicate) returns the single item that matches the predicate,
                // and throws if the number of matches are not exactly one. That is, if it matches zero items or many items.
                // In our case, the exception message was "Sequence contains no matching element", so it was empty.
                //_indexRoot = MFTRecord.Attributes.OfType<AttributeIndexRoot>().Single(s => s.AttributeName == DirlistAttribName);


                // First will return the first item in the list, ignoring the rest.
                // It will throw if there is no items in the list, but wont if there are many.
                _indexRoot = matches.First();
            }
            else
            {
                // No point in continuing in this case, as it will just waste time parsing IndexAllocations below,
                // but never iterate them because _indexRoot == null
                return;

                //using (System.IO.StreamWriter w = System.IO.File.AppendText("D:\\Log\\faillog.txt"))
                //{
                //    w.WriteLine("failed to get indexroot for mft number " + MFTRecord.MFTNumber.ToString());
                //}
            }


            // Get allocations
            _indexes = MFTRecord.Attributes.OfType <AttributeIndexAllocation>().Where(s => s.AttributeName == DirlistAttribName).ToArray();

            foreach (AttributeIndexAllocation index in _indexes)
            {
                NTFSWrapper.ParseNonResidentAttribute(index);
            }

            // Get bitmap of allocations
            // var bitmap = MFTRecord.Attributes.OfType<AttributeBitmap>().Single(s => s.AttributeName == DirlistAttribName);
        }
        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();
                }
            }
        }
Example #19
0
        private static void PerformCopy(NTFSWrapper wrapper, Options opts, uint mftId)
        {
            // Fetch record
            FileRecord record = wrapper.ReadMFTRecord(mftId);

            // Find attribute(s)
            List <Attribute> attribs = record.Attributes.Concat(record.ExternalAttributes).Where(s => s.Type == opts.SourceAttribute && s.AttributeName == opts.SourceName).ToList();

            if (!attribs.Any())
            {
                PrintError("Unable to find any attribute named \"" + opts.SourceName + "\" of type " + opts.SourceAttribute);
                AwesomeConsole.WriteLine();
                return;
            }

            // Determine resident or non-resident data
            Stream fileStream = null;

            if (attribs.All(x => x.NonResidentFlag == ResidentFlag.NonResident))
            {
                // Fetch fragments
                DataFragment[] fragments = attribs.SelectMany(s => s.NonResidentHeader.Fragments).OrderBy(s => s.StartingVCN).ToArray();

                ushort compressionUnitSize     = attribs[0].NonResidentHeader.CompressionUnitSize;
                ushort compressionClusterCount = (ushort)(compressionUnitSize == 0 ? 0 : Math.Pow(2, compressionUnitSize));

                fileStream = new NtfsDiskStream(wrapper.GetDiskStream(), true, fragments, wrapper.BytesPrCluster, compressionClusterCount, (long)attribs.First().NonResidentHeader.ContentSize);
            }
            else
            {
                // Fetch data
                if (attribs.Count != 1)
                {
                    PrintError("There were multiple attributes for this single file that matched, yet they were all Resident. This is an error.");
                    AwesomeConsole.WriteLine();
                    return;
                }

                Attribute attrib = attribs.First();

                if (attrib is AttributeGeneric)
                {
                    AttributeGeneric generic = (AttributeGeneric)attrib;

                    fileStream = new MemoryStream(generic.Data);
                }
                else if (attrib is AttributeData)
                {
                    AttributeData data = (AttributeData)attrib;

                    fileStream = new MemoryStream(data.DataBytes);
                }
                else
                {
                    PrintError("Only certain resident attributes are supported, like $DATA");
                    AwesomeConsole.WriteLine();
                    return;
                }
            }

            // Perform copy
            using (AwesomeConsole.BeginSequentialWrite())
            {
                AwesomeConsole.Write("Found data, copying ");
                AwesomeConsole.Write(fileStream.Length.ToString("N0"), ConsoleColor.Green);
                AwesomeConsole.Write(" bytes to ");
                AwesomeConsole.WriteLine(opts.Destination, ConsoleColor.Green);
            }

            using (FileStream fs = File.OpenWrite(opts.Destination))
            {
                if (fs.CanSeek && fs.CanWrite)
                {
                    // Pre-expand the destination, to help filesystems allocate files
                    fs.SetLength(fileStream.Length);
                }

                byte[] buff           = new byte[65535];
                int    lastProgressed = -1;
                for (long offset = 0; offset < fileStream.Length; offset += buff.Length)
                {
                    int read = fileStream.Read(buff, 0, buff.Length);

                    if (read == 0)
                    {
                        // Finished
                        break;
                    }

                    fs.Write(buff, 0, read);

                    int progressed = (int)((offset * 1f / fileStream.Length) * 20);
                    if (read != buff.Length)
                    {
                        // Finished
                        progressed = 20;
                    }

                    if (lastProgressed != progressed)
                    {
                        AwesomeConsole.Write("[");
                        for (int i = 0; i < 20; i++)
                        {
                            if (i < progressed)
                            {
                                AwesomeConsole.Write("=");
                            }
                            else if (i == progressed)
                            {
                                AwesomeConsole.Write(">");
                            }
                            else
                            {
                                AwesomeConsole.Write(" ");
                            }
                        }
                        AwesomeConsole.Write("]");
                        Console.CursorLeft = 0;

                        lastProgressed = progressed;
                    }
                }
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine("Done.", ConsoleColor.Green);
            }
        }
Example #20
0
        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;
            }

            uint mftId = 0;

            if (opts.SourceType == PathType.File)
            {
                mftId = FindPathMftId(opts);
            }
            else if (opts.SourceType == PathType.MftId)
            {
                mftId = opts.MftId;
            }

            using (RawDisk disk = new RawDisk(opts.Drive))
            {
                NTFSWrapper wrapper = new NTFSWrapper(new NTFSDiskProvider(disk), 1);

                if (wrapper.FileRecordCount < mftId)
                {
                    PrintError("The given path or MftID didn't exist");
                    AwesomeConsole.WriteLine();

                    switch (opts.SourceType)
                    {
                    case PathType.File:
                        PrintError("Specified " + opts.SourceType + ": " + opts.Source);
                        break;

                    case PathType.MftId:
                        PrintError("Specified type: MftId, id: " + opts.MftId);
                        break;
                    }

                    AwesomeConsole.WriteLine();

                    return;
                }

                PerformCopy(wrapper, opts, mftId);
            }

            if (Debugger.IsAttached)
            {
                Console.ReadLine();
            }
        }