Beispiel #1
0
        private IRawFileSystem GetSystem(string path)
        {
            IRawFileSystem system;
            var            driveLetter = path[0];

            if (!char.IsLetter(driveLetter))
            {
                throw new ArgumentException($"Path '{path}' did not have a drive letter!");
            }

            if (systems.TryGetValue(driveLetter, out system))
            {
                return(system);
            }

            try
            {
                var disk          = new RawDisk(driveLetter);
                var rawDiskStream = disk.CreateDiskStream();
                system = new NtfsFileSystem(rawDiskStream);
                systems.Add(driveLetter, system);
            }
            catch (Exception)
            {
                Console.WriteLine("Failed to create a filesystem for drive '{0}'", driveLetter);
                throw;
            }
            return(system);
        }
Beispiel #2
0
        public override void Execute()
        {
            IEnumerable <char> volumeDrives = Utils.GetAllAvailableVolumes();

            foreach (char device in volumeDrives)
            {
                Console.WriteLine("Trying volume, " + device + ": .. ");

                try
                {
                    using (RawDisk disk = new RawDisk(device))
                    {
                        ExampleUtilities.PresentResult(disk);
                    }
                }
                catch (Win32Exception exception)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Error: " + new Win32Exception(exception.NativeErrorCode).Message);
                    Console.ForegroundColor = ExampleUtilities.DefaultColor;
                }

                Console.WriteLine();
            }
        }
        public override void Execute()
        {
            IEnumerable <int> physicalDrives = Utils.GetAllAvailableDrives(DiskNumberType.PhysicalDisk);

            foreach (int device in physicalDrives)
            {
                Console.WriteLine("Trying PhysicalDrive" + device + ": .. ");

                try
                {
                    using (RawDisk disk = new RawDisk(DiskNumberType.PhysicalDisk, device))
                    {
                        ExampleUtilities.PresentResult(disk);
                    }
                }
                catch (Win32Exception exception)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Error: " + new Win32Exception(exception.NativeErrorCode).Message);
                    Console.ForegroundColor = ExampleUtilities.DefaultColor;
                }

                Console.WriteLine();
            }
        }
        public void SimpleFile()
        {
            byte[] randomData = new byte[65 * 4096];
            _random.NextBytes(randomData);

            using (TempFile tmpFile = new TempFile())
            {
                // Create a file
                File.WriteAllBytes(tmpFile.File.FullName, randomData);

                // Discover it via the NTFS lib
                char    driveLetter = tmpFile.File.FullName[0];
                RawDisk disk        = new RawDisk(driveLetter);

                NTFSDiskProvider provider = new NTFSDiskProvider(disk);

                NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0);

                NtfsDirectory ntfsDir  = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName);
                NtfsFile      ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name);

                Assert.IsNotNull(ntfsFile);

                // Read it
                using (Stream actualStream = File.OpenRead(tmpFile.File.FullName))
                    using (Stream ntfsStream = ntfsFile.OpenRead())
                    {
                        bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream);

                        Assert.IsTrue(equal);
                    }
            }
        }
Beispiel #5
0
 public Stream OpenRawDiskStream(string diskPath)
 {
     using (RawDisk rawDisk = new RawDisk(diskPath))
     {
         return(rawDisk.CreateDiskStream());
     }
 }
Beispiel #6
0
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            string  devid          = (string)e.Argument;
            string  devnum         = new String(devid.Where(Char.IsDigit).ToArray());
            RawDisk disk           = new RawDisk(DiskNumberType.PhysicalDisk, Convert.ToInt32(devnum), FileAccess.Read);
            long    diskReadLength = disk.SizeBytes;
            long    totalRead      = 0;
            int     increment      = (int)(((16f * 1024f * 1024f) / disk.SectorSize) * disk.SectorSize);

            byte[]    input = new byte[increment];
            Stopwatch sw    = new Stopwatch();

            FileStream fs = new FileStream(textBox1.Text, FileMode.Create);

            using (RawDiskStream diskFs = disk.CreateDiskStream())
            {
                sw.Start();
                while (true)
                {
                    if (backgroundWorker1.CancellationPending)
                    {
                        e.Cancel = true;
                        diskFs.Close();
                        fs.Close();
                        break;
                    }
                    int read       = (int)Math.Min(increment, disk.SizeBytes - totalRead);
                    int actualRead = diskFs.Read(input, 0, read);

                    if (actualRead == 0)
                    {
                        diskFs.Close();
                        fs.Close();

                        if (totalRead == diskReadLength)
                        {
                            readCompleteOK = true;
                        }
                        else
                        {
                            readCompleteOK = false;
                        }

                        break;
                    }

                    totalRead += actualRead;
                    fs.Write(input, 0, input.Length);
                    imageState imst = new imageState();
                    imst.progress = fsToHuman(Convert.ToUInt64(totalRead)) + " / " + fsToHuman(Convert.ToUInt64(diskReadLength));
                    int perc = (int)(0.5f + ((100f * totalRead) / disk.SizeBytes));
                    //imst.disksize = disk.SizeBytes;
                    //imst.diskposition = totalRead;
                    imst.percent = perc.ToString() + "% complete";
                    imst.speed   = Math.Round(((diskFs.Position / 1048576f) / sw.Elapsed.TotalSeconds), 2).ToString() + "MB/s";
                    backgroundWorker1.ReportProgress(perc, imst);
                }
            }
        }
Beispiel #7
0
        public static IFileSystem GetFileSystem(char driveLetter, FileAccess fileAccess)
        {
            var disk          = new RawDisk(driveLetter, fileAccess);
            var rawDiskStream = disk.CreateDiskStream();
            var system        = new NtfsFileSystem(rawDiskStream);

            return(system);
        }
        static void Main(string[] args)
        {
            char driveLetter = 'C';

            if (args.Length == 1)
            {
                driveLetter = args[0][0];
            }

            using (RawDisk disk = new RawDisk(driveLetter))
            {
                MftDiskExtents res = new MftDiskExtents();

                byte[]     ntfsBoot = disk.ReadSectors(0, 1);
                BootSector boot     = BootSector.ParseData(ntfsBoot, ntfsBoot.Length, 0);
                Console.WriteLine("MFT is at LCN " + boot.MFTCluster);

                MftDetails mft = GetMftDetails(disk, boot);
                Console.WriteLine("MFT is in " + mft.MftExtents.Length + " extents");

                res.Extents.AddRange(mft.MftExtents);

                using (RawDiskStream diskStream = disk.CreateDiskStream())
                    using (NtfsDiskStream mftStream = new NtfsDiskStream(diskStream, false, mft.MftExtents, (uint)disk.ClusterSize, 0, (long)mft.MftSize))
                    {
                        uint   sectorsPrRecord = (uint)(boot.MFTRecordSizeBytes / disk.SectorSize);
                        ushort bytesPrSector   = (ushort)disk.SectorSize;

                        int records = (int)(mftStream.Length / boot.MFTRecordSizeBytes);

                        byte[] tmp = new byte[boot.MFTRecordSizeBytes];
                        while (true)
                        {
                            int read = mftStream.Read(tmp, 0, tmp.Length);
                            if (read < boot.MFTRecordSizeBytes)
                            {
                                Console.WriteLine("Stopped reading as we got " + read + " bytes instead of " + tmp.Length + " bytes");
                                break;
                            }

                            FileRecord rec = FileRecord.Parse(tmp, 0, bytesPrSector, sectorsPrRecord);

                            // Keep track of all external extents to the MFT
                            RecordExternalDiskExtents(rec, res);

                            //// Special case for LIST attributes, since they can further reference more extents outside the MFT
                            //ProcessNonResidentListAttributes(disk, rec);
                        }
                    }

                long clustersTotal = res.Extents.Sum(x => x.Clusters);

                Console.WriteLine("To copy: {0:N0} extents", res.Extents.Count);
                Console.WriteLine("{0:N0} clusters, {1:N0} bytes", clustersTotal, clustersTotal * disk.ClusterSize);
            }

            Console.ReadLine();
        }
        /* TODO:
         * List streams ($DATA, $BITMAP ..)
         * List alternate namings (Win32, DOS, POSIX)
         * Toggle FileID's
         * List matching attributes
         * Recursive
         * Deleted records
         */

        static void Main(string[] args)
        {
            Options opts = new Options();

            bool success = opts.Parse(args);

            if (!success)
            {
                AwesomeConsole.WriteLine("Unable to parse the commandline:");
                PrintError(opts.ErrorDetails);
                AwesomeConsole.WriteLine();
                AwesomeConsole.WriteLine("Try --help for more informations");
                return;
            }

            if (opts.ActionType == ActionType.ShowHelp)
            {
                opts.DisplayHelp();
                return;
            }

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

                NtfsDirectory dir = null;

                if (opts.PathType == PathType.Directory)
                {
                    dir = FindDir(wrapper, opts);
                }

                if (dir == null)
                {
                    PrintError("The given path didn't exist");
                    AwesomeConsole.WriteLine();

                    switch (opts.PathType)
                    {
                    case PathType.Directory:
                        PrintError("Specified " + opts.PathType + ": " + opts.PathArgument);
                        break;
                    }

                    AwesomeConsole.WriteLine();
                    return;
                }

                // Display
                DisplayDetails(wrapper, opts, dir);
            }

            if (Debugger.IsAttached)
            {
                Console.ReadLine();
            }
        }
        public static void PresentResult(RawDisk disk)
        {
            byte[] data = disk.ReadClusters(0, (int)Math.Min(disk.ClusterCount, ClustersToRead));

            string fatType = Encoding.ASCII.GetString(data, 82, 8);     // Extended FAT parameters have a display name here.
            bool   isFat   = fatType.StartsWith("FAT");
            bool   isNTFS  = Encoding.ASCII.GetString(data, 3, 4) == "NTFS";

            // Optimization, if it's a known FS, we know it's not all zeroes.
            bool allZero = (!isNTFS || !isFat) && data.All(s => s == 0);

            Console.WriteLine("Size in bytes : {0:N0}", disk.SizeBytes);
            Console.WriteLine("Sectors       : {0:N0}", disk.ClusterCount);
            Console.WriteLine("SectorSize    : {0:N0}", disk.SectorSize);
            Console.WriteLine("ClusterCount  : {0:N0}", disk.ClusterCount);
            Console.WriteLine("ClusterSize   : {0:N0}", disk.ClusterSize);

            if (!isFat && !isNTFS)
            {
                Console.ForegroundColor = ConsoleColor.Red;
            }

            if (isNTFS)
            {
                Console.ForegroundColor = ConsoleColor.Green;
            }

            Console.WriteLine("Is NTFS       : {0}", isNTFS);
            Console.ForegroundColor = DefaultColor;

            if (!isFat && !isNTFS)
            {
                Console.ForegroundColor = ConsoleColor.Red;
            }

            if (isFat)
            {
                Console.ForegroundColor = ConsoleColor.Green;
            }

            Console.WriteLine("Is FAT        : {0}", isFat ? fatType : "False");
            Console.ForegroundColor = DefaultColor;

            if (!allZero)
            {
                Console.ForegroundColor = ConsoleColor.Green;
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Red;
            }

            Console.WriteLine("All bytes zero: {0}", allZero);
            Console.ForegroundColor = DefaultColor;
        }
Beispiel #11
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);
                        }
                }
            }
        }
Beispiel #12
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));
                }
            }
        }
Beispiel #13
0
        internal override void ParseAttributeNonResidentBody(RawDisk disk)
        {
            base.ParseAttributeNonResidentBody(disk);

            // Read clusters from disk
            Data = new byte[NonResidentHeader.ContentSize];

            using (RawDiskStream diskStream = disk.CreateDiskStream())
                using (NtfsDiskStream attribStream = new NtfsDiskStream(diskStream, false, NonResidentHeader.Fragments, (uint)disk.ClusterSize, 0, Data.LongLength))
                    attribStream.Read(Data, 0, Data.Length);
        }
        public void SparseFile()
        {
            byte[] randomData = new byte[35 * 4096];
            _random.NextBytes(randomData);

            // Clear the 16 * 4096 -> 32 * 4096 range
            Array.Clear(randomData, 16 * 4096, 16 * 4096);

            using (TempFile tmpFile = new TempFile())
            {
                // Create a file
                File.WriteAllBytes(tmpFile.File.FullName, randomData);

                using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName))
                {
                    wrapper.FileSystemSetSparseFile(true);
                    wrapper.FileSystemSetZeroData(16 * 4096, 16 * 4096);

                    FILE_ALLOCATED_RANGE_BUFFER[] rangesData = wrapper.FileSystemQueryAllocatedRanges(0, randomData.Length);

                    // We should have 2 ranges on non-zero data
                    Assert.AreEqual(2, rangesData.Length);
                }

                // Discover it via the NTFS lib
                char    driveLetter = tmpFile.File.FullName[0];
                RawDisk disk        = new RawDisk(driveLetter);

                NTFSDiskProvider provider = new NTFSDiskProvider(disk);

                NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0);

                NtfsDirectory ntfsDir  = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName);
                NtfsFile      ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name);

                Assert.IsNotNull(ntfsFile);
                Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.SparseFile));
                AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single();
                Assert.IsTrue(attributeData.DataFragments.Length > 1);
                Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsSparseFragment));

                // Read it
                using (Stream actualStream = File.OpenRead(tmpFile.File.FullName))
                    using (Stream ntfsStream = ntfsFile.OpenRead())
                    {
                        bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream);

                        Assert.IsTrue(equal);
                    }
            }
        }
Beispiel #15
0
        private void FillInStorageDeviceDirectoryType(TreeNode parentNode, RawDisk disk)
        {
            if (disk.DiskInfo.MediaType != MEDIA_TYPE.FixedMedia)
            {
                return;
            }

            TreeNode thisNode = new TreeNode
            {
                Text = disk.DosDeviceName,
                Tag  = new DiskExGet(disk.DiskHandle)
            };

            parentNode.Nodes.Add(thisNode);
        }
Beispiel #16
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());
            }
        }
        private static void ProcessNonResidentListAttributes(RawDisk disk, FileRecord rec)
        {
            // First, take all LIST attributes
            foreach (Attribute attrib in rec.Attributes)
            {
                if (attrib.Type != AttributeType.ATTRIBUTE_LIST || attrib.NonResidentFlag != ResidentFlag.NonResident)
                {
                    continue;
                }

                AttributeList list = (AttributeList)attrib;

                // Parse attributes from elsewhere on disk
                list.ParseAttributeNonResidentBody(disk);
            }
        }
        public void CompressedFile()
        {
            using (TempFile tmpFile = new TempFile())
            {
                // Create a file
                // Write file data
                using (FileStream fs = File.OpenWrite(tmpFile.File.FullName))
                {
                    byte[] data = Encoding.ASCII.GetBytes("The white bunny jumps over the brown dog in a carparking lot");

                    for (int i = 0; i < 20000; i++)
                    {
                        fs.Write(data, 0, data.Length);
                    }
                }

                using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName))
                {
                    wrapper.FileSystemSetCompression(COMPRESSION_FORMAT.LZNT1);
                }

                // Discover it via the NTFS lib
                char    driveLetter = tmpFile.File.FullName[0];
                RawDisk disk        = new RawDisk(driveLetter);

                NTFSDiskProvider provider = new NTFSDiskProvider(disk);

                NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0);

                NtfsDirectory ntfsDir  = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName);
                NtfsFile      ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name);

                Assert.IsNotNull(ntfsFile);
                Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.Compressed));
                AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single();
                Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsCompressed));

                // Read it
                using (Stream actualStream = File.OpenRead(tmpFile.File.FullName))
                    using (Stream ntfsStream = ntfsFile.OpenRead())
                    {
                        bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream);

                        Assert.IsTrue(equal);
                    }
            }
        }
Beispiel #19
0
        private static SparseStream OpenFile(string path)
        {
            var rawPath = path.Substring(3);

            if (_fileSystem != null)
            {
                return(_fileSystem.OpenFile(rawPath, FileMode.Open, FileAccess.Read));
            }

            var disk          = new RawDisk(path.ToLowerInvariant().First());
            var rawDiskStream = disk.CreateDiskStream();

            _fileSystem = new NtfsFileSystem(rawDiskStream);



            return(_fileSystem.OpenFile(rawPath, FileMode.Open, FileAccess.Read));
        }
Beispiel #20
0
        private void ProcessDrive(RawDisk disk)
        {
            switch (scanType)
            {
            case ScanType.Unknown:
                break;

            case ScanType.Read:
                PerformRead(disk);
                break;

            case ScanType.Write:
                if (PerformWrite(disk))
                {
                    PerformRead(disk);
                }
                break;

            case ScanType.Verify:
                if (PerformWrite(disk, 0xAA))
                {
                    PerformRead(disk, 0xAA);
                }
                break;

            case ScanType.Pass2:
                if (PerformWrite(disk, 0xAA))
                {
                    if (PerformRead(disk, 0xAA))
                    {
                        if (PerformWrite(disk, 0x55))
                        {
                            PerformRead(disk, 0x55);
                        }
                    }
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
            cancelTokenSrc.Cancel();
        }
        private static MftDetails GetMftDetails(RawDisk disk, BootSector boot)
        {
            byte[]     mftFirst = disk.ReadClusters((long)boot.MFTCluster, 1);
            FileRecord rec      = FileRecord.Parse(mftFirst, 0, (ushort)disk.SectorSize, (uint)(boot.MFTRecordSizeBytes / disk.SectorSize));

            // Get DATA attrib
            // TODO: Handle multiple DATA attributes
            AttributeGeneric dataAttrib = null;

            foreach (Attribute attribute in rec.Attributes)
            {
                if (attribute.Type == AttributeType.DATA && attribute.AttributeName.Length == 0)
                {
                    // Got it!
                    dataAttrib = attribute as AttributeGeneric;
                    break;
                }
            }

            Debug.Assert(dataAttrib != null);

            MftDetails res = new MftDetails();

            // Get attribute data
            // Parse out extents
            if (dataAttrib.NonResidentFlag == ResidentFlag.Resident)
            {
                byte[] dataAttribData = dataAttrib.Data;

                res.MftSize    = dataAttrib.ResidentHeader.ContentLength;
                res.MftExtents = DataFragment.ParseFragments(dataAttribData, dataAttribData.Length, 0, 0, 0);
            }
            else
            {
                res.MftSize    = dataAttrib.NonResidentHeader.ContentSize;
                res.MftExtents = dataAttrib.NonResidentHeader.Fragments;
            }

            Debug.Assert(res.MftExtents != null);

            return(res);
        }
Beispiel #22
0
 public void Start()
 {
     try
     {
         Phase = @"Initialising";
         Log.Debug(@"Creating Disk interface");
         var disk = new RawDisk(deviceId, FileAccess.ReadWrite);
         Log.Info(@"Setting [{0}] offline", deviceId);
         if (!DiskExSet.SetOnline(disk.DiskHandle, false, false))
         {
             Log.Warn(@"Unable to take disk offline");
         }
         Task.Run(() => ProcessDrive(disk));
     }
     catch (Exception e)
     {
         Log.Error(e);
         Cancel();
     }
 }
        public static byte[] ReadFragments(RawDisk disk, DataFragment[] fragments)
        {
            int totalLength = 0;

            foreach (DataFragment fragment in fragments)
            {
                totalLength += (int)(fragment.Clusters * disk.ClusterSize);
            }

            byte[] data = new byte[totalLength];

            using (Stream diskStream = disk.CreateDiskStream())
                using (NtfsDiskStream stream = new NtfsDiskStream(diskStream, false, fragments, (uint)disk.ClusterSize, 0, totalLength))
                {
                    stream.Read(data, 0, data.Length);
                }

            // Return the data
            return(data);
        }
        private static uint FindPathMftId(Options opts)
        {
            string[] pathParts   = opts.PathArgument.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
            string[] pathParents = pathParts.Skip(1).Take(pathParts.Length - 2).ToArray();

            if (pathParts.Length == 1)
            {
                // Chosen path is root
                return((uint)SpecialMFTFiles.RootDir);
            }

            using (RawDisk disk = new RawDisk(opts.Drive))
            {
                NTFSWrapper ntfs = new NTFSWrapper(new NTFSDiskProvider(disk), 4);

                // Navigate to parent directory
                NtfsDirectory parentDir = ntfs.GetRootDirectory();

                for (int i = 0; i < pathParents.Length; i++)
                {
                    parentDir = parentDir.ListDirectories(false).FirstOrDefault(s => s.Name.Equals(pathParents[i], StringComparison.InvariantCultureIgnoreCase));

                    if (parentDir == null)
                    {
                        return(uint.MaxValue);
                    }
                }

                // Select the correct child
                IEnumerable <NtfsFileEntry> childs = opts.PathType == PathType.File ? (IEnumerable <NtfsFileEntry>)parentDir.ListFiles(false) : parentDir.ListDirectories(false);
                NtfsFileEntry child = childs.FirstOrDefault(s => s.Name.Equals(pathParts.Last(), StringComparison.InvariantCultureIgnoreCase));

                if (child == null)
                {
                    return(uint.MaxValue);
                }

                // Return the childs id
                return(child.MFTRecord.MFTNumber);
            }
        }
        public static void CopyFile(string sourceFile, string dstFile)
        {
            // FileAttributes 0x20000000L = FILE_FLAG_NO_BUFFERING
            SafeFileHandle fileHandle = Win32Helper.CreateFile(sourceFile, (FileAccess)Program.FILE_READ_ATTRIBUTES, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, FileAttributes.Normal | (FileAttributes)0x20000000L, IntPtr.Zero);

            if (fileHandle.IsInvalid)
            {
                throw new ArgumentException("Invalid file: " + sourceFile);
            }

            //var driveWrapper = new DeviceIOControlWrapper(driveHandle);
            FilesystemDeviceWrapper fileWrapper = new FilesystemDeviceWrapper(fileHandle);

            FileExtentInfo[] extents     = fileWrapper.FileSystemGetRetrievalPointers();
            decimal          totalSize   = extents.Sum(s => (decimal)s.Size);
            decimal          copiedBytes = 0;

            using (RawDisk disk = new RawDisk(char.ToUpper(sourceFile[0])))
            {
                // Write to the source file
                using (FileStream fs = new FileStream(dstFile, FileMode.Create))
                {
                    // Copy all extents
                    foreach (FileExtentInfo fileExtentInfo in extents)
                    {
                        // Copy chunks of data
                        for (ulong offset = 0; offset < fileExtentInfo.Size; offset += 10000)
                        {
                            int    currentSizeBytes = (int)Math.Min(10000, fileExtentInfo.Size - offset);
                            byte[] data             = disk.ReadClusters((long)(fileExtentInfo.Lcn + offset), currentSizeBytes);
                            fs.Write(data, 0, data.Length);

                            copiedBytes += currentSizeBytes;
                        }
                    }
                }
            }

            Debug.Assert(copiedBytes == totalSize);
        }
Beispiel #26
0
        IRawFileSystem GetSystem(string path)
        {
            IRawFileSystem system;
            var            driveLetter = path[0];

            if (!char.IsLetter(driveLetter))
            {
                throw new ArgumentException($"Path '{path}' did not have a drive letter!");
            }

            if (systems.TryGetValue(driveLetter, out system))
            {
                return(system);
            }

            var disk          = new RawDisk(driveLetter);
            var rawDiskStream = disk.CreateDiskStream();

            system = new NtfsFileSystem(rawDiskStream);
            systems.Add(driveLetter, system);
            return(system);
        }
        internal override void ParseAttributeNonResidentBody(RawDisk disk)
        {
            base.ParseAttributeNonResidentBody(disk);

            // Get all chunks
            byte[] data = NtfsUtils.ReadFragments(disk, NonResidentHeader.Fragments);

            // Parse
            List <AttributeListItem> results = new List <AttributeListItem>();

            int pointer     = 0;
            int contentSize = (int)NonResidentHeader.ContentSize;

            while (pointer + 26 <= contentSize)     // 26 is the smallest possible MFTAttributeListItem
            {
                AttributeListItem item = AttributeListItem.ParseListItem(data, data.Length - pointer, pointer);

                if (item.Type == AttributeType.EndOfAttributes)
                {
                    break;
                }

                if (item.Length == 0)
                {
                    break;
                }

                results.Add(item);

                pointer += item.Length;
            }

            Debug.Assert(pointer == contentSize);

            Items = results.ToArray();
        }
Beispiel #28
0
        private void FillInStorageDeviceDirectoryType(TreeNode parentNode, Win32DiskDrive win32Disk)
        {
            TreeNode thisNode = new TreeNode
            {
                Text = win32Disk.Caption,
                Tag  = win32Disk
            };

            parentNode.Nodes.Add(thisNode);

            using RawDisk disk = new RawDisk(win32Disk.DeviceId);
            FillInStorageDeviceDirectoryType(thisNode, disk);

            var partitionQueryText =
                $"associators of {{{win32Disk.RelativePath}}} where AssocClass = Win32_DiskDriveToDiskPartition";

            var partitionQuery = new ManagementObjectSearcher(partitionQueryText);

            foreach (ManagementObject p in partitionQuery.Get())
            {
                var logicalDriveQueryText =
                    $"associators of {{{p.Path.RelativePath}}} where AssocClass = Win32_LogicalDiskToPartition";
                var logicalDriveQuery = new ManagementObjectSearcher(logicalDriveQueryText);
                foreach (ManagementObject ld in logicalDriveQuery.Get())
                {
                    Win32LogicalDisk ldp  = new Win32LogicalDisk(ld);
                    TreeNode         part = new TreeNode
                    {
                        Text = string.Concat(ldp.VolumeName, @" -> ", ldp.Caption),
                        Tag  = ldp
                    };

                    thisNode.Nodes.Add(part);
                }
            }
        }
        static void Main(string[] args)
        {
            Options opts = new Options();

            bool success = opts.Parse(args);

            if (!success)
            {
                AwesomeConsole.WriteLine("Unable to parse the commandline:");
                PrintError(opts.ErrorDetails);
                AwesomeConsole.WriteLine();
                AwesomeConsole.WriteLine("Try --help for more informations");
                return;
            }

            if (opts.ActionType == ActionType.ShowHelp)
            {
                opts.DisplayHelp();
                return;
            }

            // Work with the options
            if (opts.ActionType == ActionType.ShowFull || opts.ActionType == ActionType.ShowExtents)
            {
                uint mftId = 0;

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

                using (RawDisk disk = new RawDisk(opts.Drive))
                    using (Stream stream = disk.CreateDiskStream())
                    {
                        NTFSParser parser = new NTFSParser(stream);

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

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

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

                            AwesomeConsole.WriteLine();

                            return;
                        }

                        if (opts.ActionType == ActionType.ShowFull)
                        {
                            PrintFull(parser, opts, mftId);
                        }
                        else if (opts.ActionType == ActionType.ShowExtents)
                        {
                            PrintExtents(parser, opts, mftId);
                        }
                    }
            }
            else if (opts.ActionType == ActionType.Path)
            {
                using (RawDisk disk = new RawDisk(opts.Drive))
                {
                    PrintPaths(disk, opts);
                }
            }

            if (Debugger.IsAttached)
            {
                Console.ReadLine();
            }
        }
        private static void PrintPaths(RawDisk disk, Options options)
        {
            uint mftId = uint.MaxValue;

            if (options.PathType == PathType.MftId)
            {
                AwesomeConsole.WriteLine("Specified an Mft Id - skipping forward-only search", ConsoleColor.DarkGreen);

                mftId = options.MftId;
            }
            else if (options.PathType == PathType.File || options.PathType == PathType.Directory)
            {
                AwesomeConsole.WriteLine("Conducting forward-only path search", ConsoleColor.Green);

                string[] pathParts   = options.PathArgument.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
                string[] pathParents = pathParts.Skip(1).Take(pathParts.Length - 2).ToArray();

                NTFSWrapper ntfs = new NTFSWrapper(new NTFSDiskProvider(disk), 4);

                NtfsDirectory dir = ntfs.GetRootDirectory();
                PrintName(dir.Name);
                AwesomeConsole.Write(" ");
                PrintReference(dir.MFTRecord.FileReference);
                AwesomeConsole.WriteLine();

                string pathSoFar = options.Drive + ":\\";
                for (int i = 0; i < pathParents.Length; i++)
                {
                    AwesomeConsole.Write(pathSoFar, ConsoleColor.DarkYellow);

                    if (dir == null)
                    {
                        PrintName(pathParents[i]);
                        AwesomeConsole.Write(" ");
                        PrintError("(Unable to find parent)");
                        AwesomeConsole.WriteLine();
                    }
                    else
                    {
                        dir = dir.ListDirectories(false).FirstOrDefault(s => s.Name.Equals(pathParents[i], StringComparison.InvariantCultureIgnoreCase));

                        if (dir == null)
                        {
                            PrintName(pathParents[i]);
                            AwesomeConsole.Write(" ");
                            PrintError("(Unable to find this)");
                            AwesomeConsole.WriteLine();
                        }
                        else
                        {
                            PrintName(dir.Name);
                            AwesomeConsole.Write(" ");
                            PrintReference(dir.MFTRecord.FileReference);
                            AwesomeConsole.WriteLine();
                        }
                    }

                    pathSoFar = Path.Combine(pathSoFar, pathParents[i] + "\\");
                }

                AwesomeConsole.Write(pathSoFar, ConsoleColor.DarkYellow);

                if (dir == null)
                {
                    PrintName(pathParts.Last());
                    AwesomeConsole.Write(" ");
                    PrintError("(Unable to find parent)");
                    AwesomeConsole.WriteLine();
                }
                else
                {
                    IEnumerable <NtfsFileEntry> childs = options.PathType == PathType.File ? (IEnumerable <NtfsFileEntry>)dir.ListFiles(false) : dir.ListDirectories(false);
                    NtfsFileEntry child = childs.FirstOrDefault(s => s.Name.Equals(pathParts.Last(), StringComparison.InvariantCultureIgnoreCase));

                    if (child == null)
                    {
                        PrintName(pathParts.Last());
                        AwesomeConsole.Write(" ");
                        PrintError("(Unable to find this)");
                        AwesomeConsole.WriteLine();
                    }
                    else
                    {
                        PrintName(child.Name);
                        AwesomeConsole.Write(" ");
                        PrintReference(child.MFTRecord.FileReference);
                        AwesomeConsole.WriteLine();

                        mftId = child.MFTRecord.MFTNumber;

                        AwesomeConsole.WriteLine("Search completed, found MftId: " + mftId);
                    }
                }
            }

            AwesomeConsole.WriteLine();

            {
                NTFSWrapper wrapper = new NTFSWrapper(new NTFSDiskProvider(disk), 4);

                if (wrapper.FileRecordCount < mftId)
                {
                    PrintError("Unable to locate the specified file, aborting.");
                    AwesomeConsole.WriteLine();
                    return;
                }

                AwesomeConsole.WriteLine("Conducting backwards-only path search", ConsoleColor.Green);

                Dictionary <uint, List <string> > paths = new Dictionary <uint, List <string> >();
                List <string> finalPaths = new List <string>();

                FileRecord baseRecord = wrapper.ReadMFTRecord(mftId);

                foreach (AttributeFileName fileName in baseRecord.Attributes.OfType <AttributeFileName>().Concat(baseRecord.ExternalAttributes.OfType <AttributeFileName>()))
                {
                    uint parentId = fileName.ParentDirectory.FileId;
                    if (paths.ContainsKey(parentId))
                    {
                        paths[parentId].Add(fileName.FileName);
                    }
                    else
                    {
                        paths[parentId] = new List <string> {
                            fileName.FileName
                        }
                    };
                }

                do
                {
                    Dictionary <uint, List <string> > newPaths = new Dictionary <uint, List <string> >();

                    foreach (KeyValuePair <uint, List <string> > keyValuePair in paths)
                    {
                        if (keyValuePair.Key == (uint)SpecialMFTFiles.RootDir)
                        {
                            finalPaths.AddRange(keyValuePair.Value.Select(s => Path.Combine(options.Drive + ":\\", s)));
                        }
                        else
                        {
                            FileRecord record = wrapper.ReadMFTRecord(keyValuePair.Key);

                            foreach (AttributeFileName fileName in record.Attributes.OfType <AttributeFileName>().Concat(record.ExternalAttributes.OfType <AttributeFileName>()))
                            {
                                uint parentId = fileName.ParentDirectory.FileId;
                                if (newPaths.ContainsKey(parentId))
                                {
                                    newPaths[parentId].AddRange(keyValuePair.Value.Select(s => Path.Combine(fileName.FileName, s)));
                                }
                                else
                                {
                                    newPaths[parentId] = new List <string>(keyValuePair.Value.Select(s => Path.Combine(fileName.FileName, s)));
                                }
                            }
                        }
                    }

                    paths = newPaths;
                } while (paths.Any());

                AwesomeConsole.WriteLine("Got " + finalPaths.Count + " paths");

                foreach (string finalPath in finalPaths)
                {
                    PrintName(finalPath);
                    AwesomeConsole.WriteLine();
                }
            }
        }