Ejemplo n.º 1
0
        private static void PrintName(string name, bool enclose = false, bool writeUnamed = false)
        {
            using (AwesomeConsole.BeginSequentialWrite())
            {
                if (string.IsNullOrEmpty(name) && writeUnamed)
                {
                    if (enclose)
                    {
                        AwesomeConsole.Write("(unamed)", ConsoleColor.DarkGray);
                    }
                    else
                    {
                        AwesomeConsole.Write("unamed", ConsoleColor.DarkGray);
                    }

                    return;
                }

                // Write name
                if (enclose)
                {
                    AwesomeConsole.Write("(", ConsoleColor.Yellow);
                }

                AwesomeConsole.Write("\"", ConsoleColor.Yellow);
                AwesomeConsole.Write(name, ConsoleColor.Yellow);
                AwesomeConsole.Write("\"", ConsoleColor.Yellow);

                if (enclose)
                {
                    AwesomeConsole.Write(")", ConsoleColor.Yellow);
                }
            }
        }
Ejemplo n.º 2
0
 private static void PrintEnums(Enum value)
 {
     Enum[] enumFlags = GetEnumFlags(value);
     if (enumFlags.Any())
     {
         AwesomeConsole.Write("(" + string.Join(", ", enumFlags.Select(s => s.ToString())) + ")", ConsoleColor.Magenta);
     }
 }
Ejemplo n.º 3
0
 private static void PrintGUID(Guid guid)
 {
     if (guid == Guid.Empty)
     {
         AwesomeConsole.Write("unset", ConsoleColor.DarkGray);
     }
     else
     {
         AwesomeConsole.Write(guid);
     }
 }
Ejemplo n.º 4
0
        private static void PrintSID(SecurityIdentifier sid)
        {
            AwesomeConsole.Write(sid, ConsoleColor.DarkCyan);

            foreach (WellKnownSidType wellKnownSidType in Enum.GetValues(typeof(WellKnownSidType)).OfType <WellKnownSidType>())
            {
                if (sid.IsWellKnown(wellKnownSidType))
                {
                    AwesomeConsole.Write(" (" + wellKnownSidType + ")", ConsoleColor.Yellow);
                    break;
                }
            }
        }
Ejemplo n.º 5
0
        private static void PrintACE(string indent, ACE ace)
        {
            AwesomeConsole.Write(indent + SingleIndent + "SID: ");
            PrintSID(ace.SID);
            AwesomeConsole.WriteLine();

            AwesomeConsole.Write(indent + SingleIndent + SingleIndent + "Access: ");
            PrintEnums(ace.AccessMask);
            AwesomeConsole.WriteLine();

            AwesomeConsole.WriteLine(indent + SingleIndent + SingleIndent + "Type  : " + ace.Type);

            AwesomeConsole.Write(indent + SingleIndent + SingleIndent + "Flags : ");
            PrintEnums(ace.Flags);
            AwesomeConsole.WriteLine();
        }
Ejemplo n.º 6
0
        private static void PrintRange(INTFSInfo ntfs, Options opts, long start, long count)
        {
            switch (opts.SizeUnit)
            {
            case SizeUnit.Bytes:
                AwesomeConsole.Write("{0:N0} -> {1:N0}", start * ntfs.BytesPrCluster, (start + count) * ntfs.BytesPrCluster);
                break;

            case SizeUnit.Sectors:
                AwesomeConsole.Write("{0:N0} -> {1:N0}", start * ntfs.SectorsPrCluster, (start + count) * ntfs.SectorsPrCluster);
                break;

            default:
                AwesomeConsole.Write("{0:N0} -> {1:N0}", start, start + count);
                break;
            }
        }
Ejemplo n.º 7
0
        private static void PrintSize(INTFSInfo ntfs, Options opts, long clusters)
        {
            switch (opts.SizeUnit)
            {
            case SizeUnit.Bytes:
                AwesomeConsole.Write("({0:N0} bytes)", ConsoleColor.DarkGreen, clusters * ntfs.BytesPrCluster);
                break;

            case SizeUnit.Sectors:
                AwesomeConsole.Write("({0:N0} sectors)", ConsoleColor.DarkGreen, clusters * ntfs.SectorsPrCluster);
                break;

            default:
                AwesomeConsole.Write("({0:N0} clusters)", ConsoleColor.DarkGreen, clusters);
                break;
            }
        }
Ejemplo n.º 8
0
 private static void PrintError(string error)
 {
     AwesomeConsole.Write(error, ConsoleColor.Red);
 }
Ejemplo n.º 9
0
 private static void PrintType(AttributeType type)
 {
     AwesomeConsole.Write(type, ConsoleColor.Green);
 }
Ejemplo n.º 10
0
 private static void PrintReference(FileReference reference)
 {
     AwesomeConsole.Write(reference, ConsoleColor.Cyan);
 }
Ejemplo n.º 11
0
        private static void PrettyPrintAttribute(NTFSParser parser, Options options, FileRecord record, Attribute attrib, int indentCount)
        {
            string indent = "";

            for (int i = 0; i < indentCount; i++)
            {
                indent += SingleIndent;
            }

            AwesomeConsole.Write(indent + attrib.Id + ": ");
            PrintType(attrib.Type);

            AwesomeConsole.Write(" ");
            PrintName(attrib.AttributeName, true, true);

            if (attrib.NonResidentFlag == ResidentFlag.NonResident)
            {
                AwesomeConsole.Write(" (NonResident)", ConsoleColor.Red);
            }

            AwesomeConsole.WriteLine();

            indent += SingleIndent;

            switch (attrib.Type)
            {
            case AttributeType.STANDARD_INFORMATION:
                AttributeStandardInformation standardInformation = (AttributeStandardInformation)attrib;

                AwesomeConsole.WriteLine(indent + "Creation Time: " + standardInformation.TimeCreated + " " + standardInformation.TimeCreated.Kind);
                AwesomeConsole.WriteLine(indent + "Modified Time: " + standardInformation.TimeModified + " " + standardInformation.TimeModified.Kind);
                AwesomeConsole.WriteLine(indent + "Accessed Time: " + standardInformation.TimeAccessed + " " + standardInformation.TimeAccessed.Kind);
                AwesomeConsole.WriteLine(indent + "Mft Modified : " + standardInformation.TimeMftModified + " " + standardInformation.TimeMftModified.Kind);

                break;

            case AttributeType.ATTRIBUTE_LIST:
                AttributeList list = (AttributeList)attrib;

                foreach (AttributeListItem listItem in list.Items)
                {
                    AwesomeConsole.Write(indent + listItem.AttributeId + ": ");
                    PrintType(listItem.Type);
                    AwesomeConsole.Write(" ");

                    PrintName(listItem.Name, true, true);
                    AwesomeConsole.Write(" ");

                    if (record.FileReference == listItem.BaseFile)
                    {
                        AwesomeConsole.Write("(this record)", ConsoleColor.DarkGray);
                    }
                    else
                    {
                        PrintReference(listItem.BaseFile);
                    }

                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.FILE_NAME:
                AttributeFileName fileName = (AttributeFileName)attrib;

                using (AwesomeConsole.BeginSequentialWrite())
                {
                    AwesomeConsole.Write(indent + "Parent dir: ");
                    AwesomeConsole.WriteLine(fileName.ParentDirectory, ConsoleColor.Cyan);
                }

                AwesomeConsole.WriteLine(indent + "Namespace: " + fileName.FilenameNamespace);

                AwesomeConsole.Write(indent + "Flags: ");
                PrintEnums(fileName.FileFlags);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "Name: ");
                PrintName(fileName.FileName, false, true);
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine(indent + "C Time: " + fileName.CTime + " " + fileName.CTime.Kind);
                AwesomeConsole.WriteLine(indent + "M Time: " + fileName.MTime + " " + fileName.MTime.Kind);
                AwesomeConsole.WriteLine(indent + "A Time: " + fileName.ATime + " " + fileName.ATime.Kind);
                AwesomeConsole.WriteLine(indent + "R Time: " + fileName.RTime + " " + fileName.RTime.Kind);

                break;

            case AttributeType.DATA:
                AttributeData data = (AttributeData)attrib;

                if (data.NonResidentFlag == ResidentFlag.Resident)
                {
                    AwesomeConsole.WriteLine(indent + "Data length: {0:N0} Bytes", data.ResidentHeader.ContentLength);
                }
                else
                {
                    AwesomeConsole.WriteLine(indent + "Data length: {0:N0} Bytes", data.NonResidentHeader.ContentSize);

                    AwesomeConsole.Write(indent + "VCN: ");
                    PrintRange(parser, options, data.NonResidentHeader.StartingVCN, data.NonResidentHeader.EndingVCN - data.NonResidentHeader.StartingVCN);
                    AwesomeConsole.WriteLine();

                    AwesomeConsole.WriteLine(indent + "Fragments: {0:N0}", data.NonResidentHeader.Fragments.Length);

                    AwesomeConsole.WriteLine(indent + SingleIndent + "LCN-range, cluster count, VCN-range", ConsoleColor.DarkGray);

                    foreach (DataFragment fragment in data.NonResidentHeader.Fragments)
                    {
                        AwesomeConsole.Write(indent + SingleIndent);
                        PrintRange(parser, options, fragment.LCN, fragment.Clusters);
                        AwesomeConsole.Write(SingleIndent);
                        PrintSize(parser, options, fragment.Clusters);
                        AwesomeConsole.Write(SingleIndent);
                        PrintRange(parser, options, fragment.StartingVCN, fragment.Clusters);

                        if (fragment.IsCompressed)
                        {
                            AwesomeConsole.Write(" (Compressed)");
                        }
                        if (fragment.IsSparseFragment)
                        {
                            AwesomeConsole.Write(" (Sparse)");
                        }

                        AwesomeConsole.WriteLine();
                    }
                }

                break;

            case AttributeType.OBJECT_ID:
                AttributeObjectId objectId = (AttributeObjectId)attrib;

                AwesomeConsole.Write(indent + "ObjectId    : ");
                PrintGUID(objectId.ObjectId);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "BithVolumeId: ");
                PrintGUID(objectId.BithVolumeId);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "BithObjectId: ");
                PrintGUID(objectId.BithObjectId);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "DomainId    : ");
                PrintGUID(objectId.DomainId);
                AwesomeConsole.WriteLine();

                break;

            case AttributeType.SECURITY_DESCRIPTOR:
                AttributeSecurityDescriptor securityDescriptor = (AttributeSecurityDescriptor)attrib;

                AwesomeConsole.Write(indent + "SID: ");
                PrintSID(securityDescriptor.UserSID);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "GID: ");
                PrintSID(securityDescriptor.GroupSID);
                AwesomeConsole.WriteLine();

                AwesomeConsole.Write(indent + "Flags: ");
                PrintEnums(securityDescriptor.ControlFlags);
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine(indent + "SACL: " + (securityDescriptor.SACL == null ? 0 : securityDescriptor.SACL.ACECount));
                if (securityDescriptor.SACL == null)
                {
                    AwesomeConsole.WriteLine(indent + SingleIndent + "Not present", ConsoleColor.Red);
                }
                else
                {
                    foreach (ACE ace in securityDescriptor.SACL.ACEs)
                    {
                        PrintACE(indent, ace);
                    }
                }

                AwesomeConsole.WriteLine(indent + "DACL: " + (securityDescriptor.DACL == null ? 0 : securityDescriptor.DACL.ACECount));
                if (securityDescriptor.DACL == null)
                {
                    AwesomeConsole.WriteLine(indent + SingleIndent + "Not present", ConsoleColor.Red);
                }
                else
                {
                    foreach (ACE ace in securityDescriptor.DACL.ACEs)
                    {
                        PrintACE(indent, ace);
                    }
                }

                break;

            case AttributeType.VOLUME_NAME:
                AttributeVolumeName volumeName = (AttributeVolumeName)attrib;

                AwesomeConsole.Write(indent + "Name: ");
                PrintName(volumeName.VolumeName);
                AwesomeConsole.WriteLine();

                break;

            case AttributeType.VOLUME_INFORMATION:
                AttributeVolumeInformation volumeInformation = (AttributeVolumeInformation)attrib;

                AwesomeConsole.WriteLine(indent + "Reserved: " + volumeInformation.Reserved);
                AwesomeConsole.WriteLine(indent + "MajorVersion: " + volumeInformation.MajorVersion + "." + volumeInformation.MinorVersion);

                AwesomeConsole.Write(indent + "VolumeInformationFlag: ");
                PrintEnums(volumeInformation.VolumeInformationFlag);
                AwesomeConsole.WriteLine();

                break;

            case AttributeType.INDEX_ROOT:
                AttributeIndexRoot indexRoot = (AttributeIndexRoot)attrib;

                AwesomeConsole.WriteLine(indent + "IndexType: " + indexRoot.IndexType);
                AwesomeConsole.WriteLine(indent + "CollationRule: " + indexRoot.CollationRule);
                AwesomeConsole.WriteLine(indent + "IndexAllocationSize: " + indexRoot.IndexAllocationSize);
                AwesomeConsole.WriteLine(indent + "ClustersPrIndexRecord: " + indexRoot.ClustersPrIndexRecord);
                AwesomeConsole.WriteLine();

                AwesomeConsole.WriteLine(indent + "SizeOfIndexTotal: " + indexRoot.SizeOfIndexTotal);
                AwesomeConsole.WriteLine(indent + "IndexFlags: " + indexRoot.IndexFlags);
                AwesomeConsole.WriteLine(indent + "Entries: " + indexRoot.Entries.Length);

                foreach (IndexEntry entry in indexRoot.Entries)
                {
                    AwesomeConsole.Write(indent + SingleIndent);
                    PrintReference(entry.FileRefence);

                    if (entry.ChildFileName != null)
                    {
                        AwesomeConsole.Write(" ");
                        PrintName(entry.ChildFileName.FileName, true);
                        AwesomeConsole.Write(" ");
                        PrintEnums(entry.ChildFileName.FileFlags);
                    }

                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.INDEX_ALLOCATION:
                AttributeIndexAllocation indexAllocation = (AttributeIndexAllocation)attrib;

                AwesomeConsole.WriteLine(indent + "Chunks: " + indexAllocation.Indexes.Length);

                for (int i = 0; i < indexAllocation.Indexes.Length; i++)
                {
                    IndexAllocationChunk chunk = indexAllocation.Indexes[i];
                    AwesomeConsole.WriteLine(indent + SingleIndent + string.Format("{0:N0}: {1:N0} of {2:N0} Bytes used", i, chunk.SizeOfIndexTotal, chunk.SizeOfIndexAllocated));
                }

                AwesomeConsole.WriteLine(indent + "Entries: " + indexAllocation.Entries.Length);

                foreach (IndexEntry entry in indexAllocation.Entries)
                {
                    AwesomeConsole.Write(indent + SingleIndent);
                    PrintReference(entry.FileRefence);

                    if (entry.ChildFileName != null)
                    {
                        AwesomeConsole.Write(" ");
                        PrintName(entry.ChildFileName.FileName, true);
                        AwesomeConsole.Write(" ");
                        PrintEnums(entry.ChildFileName.FileFlags);
                    }

                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.BITMAP:
                AttributeBitmap bitmap = (AttributeBitmap)attrib;

                AwesomeConsole.WriteLine(indent + "Bitfield Size: {0:N0} ({1:N0} bytes)", bitmap.Bitfield.Length, bitmap.Bitfield.Length / 8);

                // Print out 4 lines of 64 bits
                const int bitsPrLine = 64;

                for (int line = 0; line < 4; line++)
                {
                    if (bitmap.Bitfield.Length <= line * bitsPrLine)
                    {
                        break;
                    }

                    AwesomeConsole.Write(indent + "{0,-6}", (line * bitsPrLine) + ":");

                    for (int offset = line * bitsPrLine; offset < line * bitsPrLine + bitsPrLine; offset += 8)
                    {
                        if (bitmap.Bitfield.Length <= offset)
                        {
                            break;
                        }

                        for (int j = offset; j < offset + 8; j++)
                        {
                            if (bitmap.Bitfield.Length <= j)
                            {
                                break;
                            }

                            AwesomeConsole.Write(bitmap.Bitfield[j] ? "1" : "0");
                        }

                        AwesomeConsole.Write(" ");
                    }

                    AwesomeConsole.WriteLine();
                }

                if (bitmap.Bitfield.Length > 256)
                {
                    PrintError(indent + "Bitfield was longer than 256 bits, so the rest wasn't printed.");
                    AwesomeConsole.WriteLine();
                }

                break;

            case AttributeType.LOGGED_UTILITY_STREAM:
                AttributeLoggedUtilityStream loggedUtilityStream = (AttributeLoggedUtilityStream)attrib;

                AwesomeConsole.WriteLine(indent + "Data: {0:N0} Bytes", loggedUtilityStream.Data.Length);

                break;

            default:
                if (Debugger.IsAttached)
                {
                    Debugger.Break();
                }
                PrintError(attrib.Type + " not supported");
                break;
            }
        }
Ejemplo n.º 12
0
        private static void PrintFull(NTFSParser parser, Options options, uint mftnumber)
        {
            HashSet <FileReference> otherRecords = new HashSet <FileReference>();

            parser.CurrentMftRecordNumber = mftnumber;
            FileRecord record = parser.ParseNextRecord();

            using (AwesomeConsole.BeginSequentialWrite())
            {
                AwesomeConsole.Write("Record Id: ");
                PrintReference(record.FileReference);
                AwesomeConsole.Write(" Attributes: ");
                AwesomeConsole.Write(record.Attributes.Count.ToString("N0"));

                if (record.Flags.HasFlag(FileEntryFlags.FileInUse))
                {
                    AwesomeConsole.Write(" (InUse)", ConsoleColor.Magenta);
                }
                else
                {
                    AwesomeConsole.Write(" (Not InUse)", ConsoleColor.Red);
                }

                if (record.Flags.HasFlag(FileEntryFlags.Directory))
                {
                    AwesomeConsole.Write(" (Directory)", ConsoleColor.Yellow);
                }

                if (Enum.IsDefined(typeof(SpecialMFTFiles), record.MFTNumber))
                {
                    AwesomeConsole.Write(" (Special MFT Record: " + (SpecialMFTFiles)record.MFTNumber + ")", ConsoleColor.White);
                }
            }

            if (record.BaseFile.FileId != 0)
            {
                AwesomeConsole.Write(" (BaseFile: ", ConsoleColor.Cyan);
                PrintReference(record.BaseFile);
                AwesomeConsole.Write(")", ConsoleColor.Cyan);
            }

            AwesomeConsole.WriteLine();

            foreach (Attribute attribute in record.Attributes)
            {
                if (attribute.NonResidentFlag == ResidentFlag.NonResident &&
                    (attribute.Type == AttributeType.ATTRIBUTE_LIST || attribute.Type == AttributeType.INDEX_ALLOCATION || attribute.Type == AttributeType.SECURITY_DESCRIPTOR || attribute.Type == AttributeType.BITMAP))
                {
                    parser.ParseNonResidentAttribute(attribute);
                }

                PrettyPrintAttribute(parser, options, record, attribute, 1);

                if (attribute.Type == AttributeType.ATTRIBUTE_LIST)
                {
                    foreach (FileReference otherFile in ((AttributeList)attribute).Items.Select(s => s.BaseFile))
                    {
                        otherRecords.Add(otherFile);
                    }
                }

                AwesomeConsole.WriteLine();
            }

            // Don't go into infinite loops
            otherRecords.RemoveWhere(s => s.FileId == record.MFTNumber);

            foreach (FileReference fileReference in otherRecords)
            {
                AwesomeConsole.WriteLine();
                PrintFull(parser, options, fileReference.FileId);
            }
        }
Ejemplo n.º 13
0
        private static void PrintExtents(NTFSParser parser, Options options, uint mftnumber)
        {
            // Read record
            List <FileRecord> records = new List <FileRecord>();

            parser.CurrentMftRecordNumber = mftnumber;
            records.Add(parser.ParseNextRecord());

            // Parse all references
            for (int i = 0; i < records.Count; i++)
            {
                List <AttributeList> lists = records[i].Attributes.OfType <AttributeList>().ToList();

                foreach (AttributeList attr in lists)
                {
                    if (attr.NonResidentFlag == ResidentFlag.NonResident)
                    {
                        parser.ParseNonResidentAttribute(attr);
                    }

                    foreach (AttributeListItem attributeListItem in attr.Items)
                    {
                        uint otherRecId = attributeListItem.BaseFile.FileId;

                        // Is new?
                        if (records.All(s => s.MFTNumber != otherRecId))
                        {
                            parser.CurrentMftRecordNumber = otherRecId;
                            records.Add(parser.ParseNextRecord());
                        }
                    }
                }
            }

            // Combine all streams
            List <Attribute> attributes = records.SelectMany(x => x.Attributes.Where(s => s.NonResidentFlag == ResidentFlag.NonResident)).ToList();

            var groups = attributes.GroupBy(s => new { s.Type, s.AttributeName }).OrderBy(s => s.Key.Type).ThenBy(s => s.Key.AttributeName).ToList();

            foreach (var @group in groups)
            {
                List <DataFragment> fragments = @group.SelectMany(s => s.NonResidentHeader.Fragments).OrderBy(s => s.StartingVCN).ToList();

                PrintType(group.Key.Type);
                AwesomeConsole.Write(" ");
                PrintName(group.Key.AttributeName, true, true);
                AwesomeConsole.Write(" ");
                AwesomeConsole.Write("{0:N0} fragments", fragments.Count);
                AwesomeConsole.WriteLine();

                foreach (DataFragment fragment in fragments)
                {
                    AwesomeConsole.Write(SingleIndent);
                    PrintRange(parser, options, fragment.LCN, fragment.Clusters);
                    AwesomeConsole.Write(" ");
                    PrintSize(parser, options, fragment.Clusters);
                    AwesomeConsole.WriteLine();
                }

                AwesomeConsole.WriteLine();
            }
        }
Ejemplo n.º 14
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;
            }

            // 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();
            }
        }
Ejemplo n.º 15
0
        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();
                }
            }
        }