Beispiel #1
0
        public void GetFileLength()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            ntfs.OpenFile(@"AFILE.TXT", FileMode.Create).Dispose();
            Assert.Equal(0, ntfs.GetFileLength("AFILE.TXT"));

            using (var stream = ntfs.OpenFile(@"AFILE.TXT", FileMode.Open))
            {
                stream.Write(new byte[14325], 0, 14325);
            }
            Assert.Equal(14325, ntfs.GetFileLength("AFILE.TXT"));

            using (var attrStream = ntfs.OpenFile(@"AFILE.TXT:altstream", FileMode.Create))
            {
                attrStream.Write(new byte[122], 0, 122);
            }
            Assert.Equal(122, ntfs.GetFileLength("AFILE.TXT:altstream"));


            // Test NTFS options for hardlink behaviour
            ntfs.CreateDirectory("Dir");
            ntfs.CreateHardLink("AFILE.TXT", @"Dir\OtherLink.txt");

            using (var stream = ntfs.OpenFile("AFILE.TXT", FileMode.Open, FileAccess.ReadWrite))
            {
                stream.SetLength(50);
            }
            Assert.Equal(50, ntfs.GetFileLength("AFILE.TXT"));
            Assert.Equal(14325, ntfs.GetFileLength(@"Dir\OtherLink.txt"));

            ntfs.NtfsOptions.FileLengthFromDirectoryEntries = false;

            Assert.Equal(50, ntfs.GetFileLength(@"Dir\OtherLink.txt"));
        }
Beispiel #2
0
        public void ShortNames()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            // Check we can find a short name in the same directory
            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) {}
            ntfs.SetShortName("ALongFileName.txt", "ALONG~01.TXT");
            Assert.Equal("ALONG~01.TXT", ntfs.GetShortName("ALongFileName.txt"));
            Assert.True(ntfs.FileExists("ALONG~01.TXT"));

            // Check path handling
            ntfs.CreateDirectory("DIR");
            using (Stream s = ntfs.OpenFile(@"DIR\ALongFileName2.txt", FileMode.CreateNew)) { }
            ntfs.SetShortName(@"DIR\ALongFileName2.txt", "ALONG~02.TXT");
            Assert.Equal("ALONG~02.TXT", ntfs.GetShortName(@"DIR\ALongFileName2.txt"));
            Assert.True(ntfs.FileExists(@"DIR\ALONG~02.TXT"));

            // Check we can open a file by the short name
            using (Stream s = ntfs.OpenFile("ALONG~01.TXT", FileMode.Open)) { }

            // Delete the long name, and make sure the file is gone
            ntfs.DeleteFile("ALONG~01.TXT");
            Assert.False(ntfs.FileExists("ALONG~01.TXT"));

            // Delete the short name, and make sure the file is gone
            ntfs.DeleteFile(@"DIR\ALONG~02.TXT");
            Assert.False(ntfs.FileExists(@"DIR\ALongFileName2.txt"));
        }
Beispiel #3
0
        public void Sparse()
        {
            int fileSize = 1 * 1024 * 1024;

            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            byte[] data = new byte[fileSize];
            for (int i = 0; i < fileSize; i++)
            {
                data[i] = (byte)i;
            }

            using (SparseStream s = ntfs.OpenFile("file.bin", FileMode.CreateNew))
            {
                s.Write(data, 0, fileSize);

                ntfs.SetAttributes("file.bin", ntfs.GetAttributes("file.bin") | FileAttributes.SparseFile);

                s.Position = 64 * 1024;
                s.Clear(128 * 1024);
                s.Position = fileSize - 64 * 1024;
                s.Clear(128 * 1024);
            }

            using (SparseStream s = ntfs.OpenFile("file.bin", FileMode.Open))
            {
                Assert.Equal(fileSize + 64 * 1024, s.Length);

                List <StreamExtent> extents = new List <StreamExtent>(s.Extents);

                Assert.Equal(2, extents.Count);
                Assert.Equal(0, extents[0].Start);
                Assert.Equal(64 * 1024, extents[0].Length);
                Assert.Equal((64 + 128) * 1024, extents[1].Start);
                Assert.Equal(fileSize - (64 * 1024) - ((64 + 128) * 1024), extents[1].Length);


                s.Position = 72 * 1024;
                s.WriteByte(99);

                byte[] readBuffer = new byte[fileSize];
                s.Position = 0;
                s.Read(readBuffer, 0, fileSize);

                for (int i = 64 * 1024; i < (128 + 64) * 1024; ++i)
                {
                    data[i] = 0;
                }
                for (int i = fileSize - (64 * 1024); i < fileSize; ++i)
                {
                    data[i] = 0;
                }
                data[72 * 1024] = 99;

                Assert.Equal(data, readBuffer);
            }
        }
Beispiel #4
0
        public void Fragmented()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            ntfs.CreateDirectory(@"DIR");

            byte[] buffer = new byte[4096];

            for (int i = 0; i < 2500; ++i)
            {
                using (var stream = ntfs.OpenFile(@"DIR\file" + i + ".bin", FileMode.Create, FileAccess.ReadWrite))
                {
                    stream.Write(buffer, 0, buffer.Length);
                }

                using (var stream = ntfs.OpenFile(@"DIR\" + i + ".bin", FileMode.Create, FileAccess.ReadWrite))
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }

            for (int i = 0; i < 2500; ++i)
            {
                ntfs.DeleteFile(@"DIR\file" + i + ".bin");
            }

            // Create fragmented file (lots of small writes)
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.Create, FileAccess.ReadWrite))
            {
                for (int i = 0; i < 2500; ++i)
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
            }

            // Try a large write
            byte[] largeWriteBuffer = new byte[200 * 1024];
            for (int i = 0; i < largeWriteBuffer.Length / 4096; ++i)
            {
                largeWriteBuffer[i * 4096] = (byte)i;
            }
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                stream.Position = stream.Length - largeWriteBuffer.Length;
                stream.Write(largeWriteBuffer, 0, largeWriteBuffer.Length);
            }

            // And a large read
            byte[] largeReadBuffer = new byte[largeWriteBuffer.Length];
            using (var stream = ntfs.OpenFile(@"DIR\fragmented.bin", FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                stream.Position = stream.Length - largeReadBuffer.Length;
                stream.Read(largeReadBuffer, 0, largeReadBuffer.Length);
            }

            Assert.Equal(largeWriteBuffer, largeReadBuffer);
        }
Beispiel #5
0
        public void GetAlternateDataStreams()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            ntfs.OpenFile("AFILE.TXT", FileMode.Create).Dispose();
            Assert.Equal(0, ntfs.GetAlternateDataStreams("AFILE.TXT").Length);

            ntfs.OpenFile("AFILE.TXT:ALTSTREAM", FileMode.Create).Dispose();
            Assert.Equal(1, ntfs.GetAlternateDataStreams("AFILE.TXT").Length);
            Assert.Equal("ALTSTREAM", ntfs.GetAlternateDataStreams("AFILE.TXT")[0]);
        }
Beispiel #6
0
        public void HasHardLink()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) { }
            Assert.False(ntfs.HasHardLinks("ALongFileName.txt"));

            ntfs.CreateHardLink("ALongFileName.txt", "AHardLink.TXT");
            Assert.True(ntfs.HasHardLinks("ALongFileName.txt"));

            using (Stream s = ntfs.OpenFile("ALongFileName2.txt", FileMode.CreateNew)) { }

            // If we enumerate short names, then the initial long name results in two 'hardlinks'
            ntfs.NtfsOptions.HideDosFileNames = false;
            Assert.True(ntfs.HasHardLinks("ALongFileName2.txt"));
        }
Beispiel #7
0
        public void ExtentInfo()
        {
            using (SparseMemoryStream ms = new SparseMemoryStream())
            {
                Geometry       diskGeometry = Geometry.FromCapacity(30 * 1024 * 1024);
                NtfsFileSystem ntfs         = NtfsFileSystem.Format(ms, "", diskGeometry, 0, diskGeometry.TotalSectorsLong);

                // Check non-resident attribute
                using (Stream s = ntfs.OpenFile(@"file", FileMode.Create, FileAccess.ReadWrite))
                {
                    byte[] data = new byte[(int)ntfs.ClusterSize];
                    data[0] = 0xAE;
                    data[1] = 0x3F;
                    data[2] = 0x8D;
                    s.Write(data, 0, (int)ntfs.ClusterSize);
                }

                var extents = ntfs.PathToExtents("file");
                Assert.Equal(1, extents.Length);
                Assert.Equal(ntfs.ClusterSize, extents[0].Length);

                ms.Position = extents[0].Start;
                Assert.Equal(0xAE, ms.ReadByte());
                Assert.Equal(0x3F, ms.ReadByte());
                Assert.Equal(0x8D, ms.ReadByte());


                // Check resident attribute
                using (Stream s = ntfs.OpenFile(@"file2", FileMode.Create, FileAccess.ReadWrite))
                {
                    s.WriteByte(0xBA);
                    s.WriteByte(0x82);
                    s.WriteByte(0x2C);
                }
                extents = ntfs.PathToExtents("file2");
                Assert.Equal(1, extents.Length);
                Assert.Equal(3, extents[0].Length);

                byte[] read = new byte[100];
                ms.Position = extents[0].Start;
                ms.Read(read, 0, 100);

                Assert.Equal(0xBA, read[0]);
                Assert.Equal(0x82, read[1]);
                Assert.Equal(0x2C, read[2]);
            }
        }
Beispiel #8
0
        public string ExpandFile(string Entry)
        {
            var tmp = Path.GetTempFileName();

            using (var srcstrm = _ntfs.OpenFile(Entry, FileMode.Open))
            {
                using var dststrm = new FileStream(tmp, FileMode.Append);
                srcstrm.CopyTo(dststrm);
            }

            return(tmp);
        }
Beispiel #9
0
        public void ManyAttributes()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            using (Stream s = ntfs.OpenFile(@"file", FileMode.Create, FileAccess.ReadWrite))
            {
                s.WriteByte(32);
            }

            for (int i = 0; i < 50; ++i)
            {
                ntfs.CreateHardLink("file", "hl" + i);
            }

            using (Stream s = ntfs.OpenFile("hl35", FileMode.Open, FileAccess.ReadWrite))
            {
                Assert.Equal(32, s.ReadByte());
                s.Position = 0;
                s.WriteByte(12);
            }

            using (Stream s = ntfs.OpenFile("hl5", FileMode.Open, FileAccess.ReadWrite))
            {
                Assert.Equal(12, s.ReadByte());
            }

            for (int i = 0; i < 50; ++i)
            {
                ntfs.DeleteFile("hl" + i);
            }

            Assert.Equal(1, ntfs.GetFiles(@"\").Length);

            ntfs.DeleteFile("file");

            Assert.Equal(0, ntfs.GetFiles(@"\").Length);
        }
Beispiel #10
0
        public void ClusterInfo()
        {
            // 'Big' files have clusters
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            using (Stream s = ntfs.OpenFile(@"file", FileMode.Create, FileAccess.ReadWrite))
            {
                s.Write(new byte[(int)ntfs.ClusterSize], 0, (int)ntfs.ClusterSize);
            }

            var ranges = ntfs.PathToClusters("file");

            Assert.Equal(1, ranges.Length);
            Assert.Equal(1, ranges[0].Count);


            // Short files have no clusters (stored in MFT)
            using (Stream s = ntfs.OpenFile(@"file2", FileMode.Create, FileAccess.ReadWrite))
            {
                s.WriteByte(1);
            }
            ranges = ntfs.PathToClusters("file2");
            Assert.Equal(0, ranges.Length);
        }
Beispiel #11
0
        public void HardLinkCount()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) { }
            Assert.Equal(1, ntfs.GetHardLinkCount("ALongFileName.txt"));

            ntfs.CreateHardLink("ALongFileName.txt", "AHardLink.TXT");
            Assert.Equal(2, ntfs.GetHardLinkCount("ALongFileName.txt"));

            ntfs.CreateDirectory("DIR");
            ntfs.CreateHardLink(@"ALongFileName.txt", @"DIR\SHORTLNK.TXT");
            Assert.Equal(3, ntfs.GetHardLinkCount("ALongFileName.txt"));

            // If we enumerate short names, then the initial long name results in two 'hardlinks'
            ntfs.NtfsOptions.HideDosFileNames = false;
            Assert.Equal(4, ntfs.GetHardLinkCount("ALongFileName.txt"));
        }
Beispiel #12
0
        public void AclInheritance()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            RawSecurityDescriptor sd = new RawSecurityDescriptor("O:BAG:BAD:(A;OICINP;GA;;;BA)");

            ntfs.CreateDirectory("dir");
            ntfs.SetSecurity("dir", sd);

            ntfs.CreateDirectory(@"dir\subdir");
            RawSecurityDescriptor inheritedSd = ntfs.GetSecurity(@"dir\subdir");

            Assert.NotNull(inheritedSd);
            Assert.Equal("O:BAG:BAD:(A;ID;GA;;;BA)", inheritedSd.GetSddlForm(AccessControlSections.All));

            using (ntfs.OpenFile(@"dir\subdir\file", FileMode.Create, FileAccess.ReadWrite)) { }
            inheritedSd = ntfs.GetSecurity(@"dir\subdir\file");
            Assert.NotNull(inheritedSd);
            Assert.Equal("O:BAG:BAD:", inheritedSd.GetSddlForm(AccessControlSections.All));
        }
Beispiel #13
0
        public void MoveLongName()
        {
            NtfsFileSystem ntfs = FileSystemSource.NtfsFileSystem();

            using (Stream s = ntfs.OpenFile("ALongFileName.txt", FileMode.CreateNew)) { }

            Assert.True(ntfs.FileExists("ALONGF~1.TXT"));

            ntfs.MoveFile("ALongFileName.txt", "ADifferentLongFileName.txt");

            Assert.False(ntfs.FileExists("ALONGF~1.TXT"));
            Assert.True(ntfs.FileExists("ADIFFE~1.TXT"));

            ntfs.CreateDirectory("ALongDirectoryName");
            Assert.True(ntfs.DirectoryExists("ALONGD~1"));

            ntfs.MoveDirectory("ALongDirectoryName", "ADifferentLongDirectoryName");
            Assert.False(ntfs.DirectoryExists("ALONGD~1"));
            Assert.True(ntfs.DirectoryExists("ADIFFE~1"));
        }
Beispiel #14
0
        private void CopyFile(NtfsFileSystem sourceNtfs, NtfsFileSystem destNtfs, string path)
        {
            if (IsExcluded(path))
            {
                return;
            }

            using (Stream s = sourceNtfs.OpenFile(path, FileMode.Open, FileAccess.Read))
                using (Stream d = destNtfs.OpenFile(path, FileMode.Create, FileAccess.ReadWrite))
                {
                    d.SetLength(s.Length);
                    int numRead = s.Read(_copyBuffer, 0, _copyBuffer.Length);
                    while (numRead > 0)
                    {
                        d.Write(_copyBuffer, 0, numRead);
                        numRead = s.Read(_copyBuffer, 0, _copyBuffer.Length);
                    }
                }

            destNtfs.SetSecurity(path, sourceNtfs.GetSecurity(path));
            destNtfs.SetFileStandardInformation(path, sourceNtfs.GetFileStandardInformation(path));
        }
Beispiel #15
0
        protected override void DoRun()
        {
            if (DiskSize <= 0)
            {
                DisplayHelp();
                return;
            }

            using (VirtualDisk sourceDisk = VirtualDisk.OpenDisk(_sourceFile.Value, FileAccess.Read, UserName, Password))
                using (VirtualDisk destDisk = VirtualDisk.CreateDisk(OutputDiskType, OutputDiskVariant, _destFile.Value, DiskParameters, UserName, Password))
                {
                    if (destDisk is DiscUtils.Vhd.Disk)
                    {
                        ((DiscUtils.Vhd.Disk)destDisk).AutoCommitFooter = false;
                    }

                    // Copy the MBR from the source disk, and invent a new signature for this new disk
                    destDisk.SetMasterBootRecord(sourceDisk.GetMasterBootRecord());
                    destDisk.Signature = new Random().Next();

                    SparseStream   sourcePartStream = SparseStream.FromStream(sourceDisk.Partitions[0].Open(), Ownership.None);
                    NtfsFileSystem sourceNtfs       = new NtfsFileSystem(sourcePartStream);

                    // Copy the OS boot code into memory, so we can apply it when formatting the new disk
                    byte[] bootCode;
                    using (Stream bootStream = sourceNtfs.OpenFile("$Boot", FileMode.Open, FileAccess.Read))
                    {
                        bootCode = new byte[bootStream.Length];
                        int totalRead = 0;
                        while (totalRead < bootCode.Length)
                        {
                            totalRead += bootStream.Read(bootCode, totalRead, bootCode.Length - totalRead);
                        }
                    }

                    // Partition the new disk with a single NTFS partition
                    BiosPartitionTable.Initialize(destDisk, WellKnownPartitionType.WindowsNtfs);
                    VolumeManager volMgr = new VolumeManager(destDisk);

                    string label = _labelSwitch.IsPresent ? _labelSwitch.Value : sourceNtfs.VolumeLabel;
                    using (NtfsFileSystem destNtfs = NtfsFileSystem.Format(volMgr.GetLogicalVolumes()[0], label, bootCode))
                    {
                        destNtfs.SetSecurity(@"\", sourceNtfs.GetSecurity(@"\"));
                        destNtfs.NtfsOptions.ShortNameCreation = ShortFileNameOption.Disabled;

                        sourceNtfs.NtfsOptions.HideHiddenFiles = false;
                        sourceNtfs.NtfsOptions.HideSystemFiles = false;
                        CopyFiles(sourceNtfs, destNtfs, @"\", true);

                        if (destNtfs.FileExists(@"\boot\BCD"))
                        {
                            // Force all boot entries in the BCD to point to the newly created NTFS partition - does _not_ cope with
                            // complex multi-volume / multi-boot scenarios at all.
                            using (Stream bcdStream = destNtfs.OpenFile(@"\boot\BCD", FileMode.Open, FileAccess.ReadWrite))
                            {
                                using (RegistryHive hive = new RegistryHive(bcdStream))
                                {
                                    Store store = new Store(hive.Root);
                                    foreach (var obj in store.Objects)
                                    {
                                        foreach (var elem in obj.Elements)
                                        {
                                            if (elem.Format == DiscUtils.BootConfig.ElementFormat.Device)
                                            {
                                                elem.Value = DiscUtils.BootConfig.ElementValue.ForDevice(elem.Value.ParentObject, volMgr.GetPhysicalVolumes()[0]);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
        }
Beispiel #16
0
        public static void GetFile(string VMDKpath, string filepath, string destinationfile)
        {
            if (File.Exists(VMDKpath) && Directory.Exists(Path.GetDirectoryName(destinationfile)))
            {
                try
                {
                    if (Path.GetFileName(destinationfile) == "")
                    {
                        destinationfile += Path.GetFileName(filepath);
                    }

                    using (VirtualDisk vhdx = VirtualDisk.OpenDisk(VMDKpath, FileAccess.Read))
                    {
                        if (vhdx.Partitions.Count > 1)
                        {
                            Console.WriteLine("Target has more than one partition");
                            for (var i = 0; i <= vhdx.Partitions.Count; i++)
                            {
                                try
                                {
                                    NtfsFileSystem vhdbNtfs = new NtfsFileSystem(vhdx.Partitions[i].Open());
                                    if (vhdbNtfs.FileExists("\\\\" + filepath))
                                    {
                                        long fileLength = vhdbNtfs.GetFileLength("\\\\" + filepath);
                                        using (Stream bootStream = vhdbNtfs.OpenFile("\\\\" + filepath, FileMode.Open, FileAccess.Read))
                                        {
                                            byte[] file      = new byte[bootStream.Length];
                                            int    totalRead = 0;
                                            while (totalRead < file.Length)
                                            {
                                                totalRead += bootStream.Read(file, totalRead, file.Length - totalRead);
                                                FileStream fileStream = File.Create(destinationfile, (int)bootStream.Length);
                                                bootStream.CopyTo(fileStream);
                                                fileStream.Write(file, 0, (int)bootStream.Length);
                                            }
                                        }
                                        long destinationLength = new FileInfo(destinationfile).Length;
                                        if (fileLength != destinationLength)
                                        {
                                            Console.WriteLine("[!] Something went wrong. Source file has size {0} and destination file has size {1}", fileLength, destinationLength);
                                        }
                                        else
                                        {
                                            Console.WriteLine("\r\n[*] File {0} was successfully copied to {1}", filepath, destinationfile);
                                        }
                                    }
                                    else
                                    {
                                        Console.WriteLine("\r\n [!] File {0} can not be found", filepath);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine("\r\n [!] An exception occured: {0}", ex);
                                    Environment.Exit(1);
                                    throw;
                                }
                            }
                        }
                        else
                        {
                            try
                            {
                                NtfsFileSystem vhdbNtfs = new NtfsFileSystem(vhdx.Partitions[0].Open());
                                if (vhdbNtfs.FileExists("\\\\" + filepath))
                                {
                                    //vhdbNtfs.CopyFile();
                                    long fileLength = vhdbNtfs.GetFileLength("\\\\" + filepath);
                                    using (Stream bootStream = vhdbNtfs.OpenFile("\\\\" + filepath, FileMode.Open, FileAccess.Read))
                                    {
                                        byte[] file      = new byte[bootStream.Length];
                                        int    totalRead = 0;
                                        while (totalRead < file.Length)
                                        {
                                            totalRead += bootStream.Read(file, totalRead, file.Length - totalRead);
                                            FileStream fileStream = File.Create(destinationfile, (int)bootStream.Length);
                                            bootStream.CopyTo(fileStream);
                                            fileStream.Write(file, 0, (int)bootStream.Length);
                                        }
                                    }
                                    long destinationLength = new FileInfo(destinationfile).Length;
                                    if (fileLength != destinationLength)
                                    {
                                        Console.WriteLine("[!] Something went wrong. Source file has size {0} and destination file has size {1}", fileLength, destinationLength);
                                    }
                                    else
                                    {
                                        Console.WriteLine("\r\n[*] File {0} was successfully copied to {1}", filepath, destinationfile);
                                    }
                                }
                                else
                                {
                                    Console.WriteLine("\r\n [!] File {0} can not be found", filepath);
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine("\r\n [!] An exception occured: {0}", ex);
                                Environment.Exit(1);
                                throw;
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("\r\n [!] An exception occured: {0}", ex);
                    Environment.Exit(1);
                    throw;
                }
            }
            else
            {
                Console.WriteLine("\r\n [!] The provided VMDK image does not exist / can not be accessed or the destination folder does not exist");
            }
        }
        protected override void DoRun()
        {
            if (!IsAdministrator())
            {
                Console.WriteLine("\nThis utility must be run as an administrator!\n");
                Environment.Exit(1);
            }

            DiskImageBuilder builder = DiskImageBuilder.GetBuilder(OutputDiskType, OutputDiskVariant);

            builder.GenericAdapterType = AdapterType;

            string[] sourceVolume = _volumes.Values;

            uint diskNumber;

            List <CloneVolume> cloneVolumes = GatherVolumes(sourceVolume, out diskNumber);


            if (!Quiet)
            {
                Console.WriteLine("Inspecting Disk...");
            }

            // Construct a stream representing the contents of the cloned disk.
            BiosPartitionedDiskBuilder contentBuilder;
            Geometry biosGeometry;
            Geometry ideGeometry;
            long     capacity;

            using (Disk disk = new Disk(diskNumber))
            {
                contentBuilder = new BiosPartitionedDiskBuilder(disk);
                biosGeometry   = disk.BiosGeometry;
                ideGeometry    = disk.Geometry;
                capacity       = disk.Capacity;
            }

            // Preserve the IDE (aka Physical) geometry
            builder.Geometry = ideGeometry;

            // Translate the BIOS (aka Logical) geometry
            GeometryTranslation translation = _translation.EnumValue;

            if (builder.PreservesBiosGeometry && translation == GeometryTranslation.Auto)
            {
                // If the new format preserves BIOS geometry, then take no action if asked for 'auto'
                builder.BiosGeometry = biosGeometry;
                translation          = GeometryTranslation.None;
            }
            else
            {
                builder.BiosGeometry = ideGeometry.TranslateToBios(0, translation);
            }

            if (translation != GeometryTranslation.None)
            {
                contentBuilder.UpdateBiosGeometry(builder.BiosGeometry);
            }


            IVssBackupComponents backupCmpnts;
            int status;

            if (Marshal.SizeOf(typeof(IntPtr)) == 4)
            {
                status = NativeMethods.CreateVssBackupComponents(out backupCmpnts);
            }
            else
            {
                status = NativeMethods.CreateVssBackupComponents64(out backupCmpnts);
            }


            Guid snapshotSetId = CreateSnapshotSet(cloneVolumes, backupCmpnts);

            if (!Quiet)
            {
                Console.Write("Copying Disk...");
            }


            foreach (var sv in cloneVolumes)
            {
                Volume sourceVol = new Volume(sv.SnapshotProperties.SnapshotDeviceObject, sv.SourceExtent.ExtentLength);

                SnapshotStream rawVolStream = new SnapshotStream(sourceVol.Content, Ownership.None);
                rawVolStream.Snapshot();

                byte[] volBitmap;
                int    clusterSize;
                using (NtfsFileSystem ntfs = new NtfsFileSystem(rawVolStream))
                {
                    ntfs.NtfsOptions.HideSystemFiles = false;
                    ntfs.NtfsOptions.HideHiddenFiles = false;
                    ntfs.NtfsOptions.HideMetafiles   = false;

                    // Remove VSS snapshot files (can be very large)
                    foreach (string filePath in ntfs.GetFiles(@"\System Volume Information", "*{3808876B-C176-4e48-B7AE-04046E6CC752}"))
                    {
                        ntfs.DeleteFile(filePath);
                    }

                    // Remove the page file
                    if (ntfs.FileExists(@"\Pagefile.sys"))
                    {
                        ntfs.DeleteFile(@"\Pagefile.sys");
                    }

                    // Remove the hibernation file
                    if (ntfs.FileExists(@"\hiberfil.sys"))
                    {
                        ntfs.DeleteFile(@"\hiberfil.sys");
                    }

                    using (Stream bitmapStream = ntfs.OpenFile(@"$Bitmap", FileMode.Open))
                    {
                        volBitmap = new byte[bitmapStream.Length];

                        int totalRead = 0;
                        int numRead   = bitmapStream.Read(volBitmap, 0, volBitmap.Length - totalRead);
                        while (numRead > 0)
                        {
                            totalRead += numRead;
                            numRead    = bitmapStream.Read(volBitmap, totalRead, volBitmap.Length - totalRead);
                        }
                    }

                    clusterSize = (int)ntfs.ClusterSize;

                    if (translation != GeometryTranslation.None)
                    {
                        ntfs.UpdateBiosGeometry(builder.BiosGeometry);
                    }
                }

                List <StreamExtent> extents          = new List <StreamExtent>(BitmapToRanges(volBitmap, clusterSize));
                SparseStream        partSourceStream = SparseStream.FromStream(rawVolStream, Ownership.None, extents);

                for (int i = 0; i < contentBuilder.PartitionTable.Partitions.Count; ++i)
                {
                    var part = contentBuilder.PartitionTable.Partitions[i];
                    if (part.FirstSector * 512 == sv.SourceExtent.StartingOffset)
                    {
                        contentBuilder.SetPartitionContent(i, partSourceStream);
                    }
                }
            }
            SparseStream contentStream = contentBuilder.Build();


            // Write out the disk images
            string dir  = Path.GetDirectoryName(_destDisk.Value);
            string file = Path.GetFileNameWithoutExtension(_destDisk.Value);

            builder.Content = contentStream;
            DiskImageFileSpecification[] fileSpecs = builder.Build(file);

            for (int i = 0; i < fileSpecs.Length; ++i)
            {
                // Construct the destination file path from the directory of the primary file.
                string outputPath = Path.Combine(dir, fileSpecs[i].Name);

                // Force the primary file to the be one from the command-line.
                if (i == 0)
                {
                    outputPath = _destDisk.Value;
                }

                using (SparseStream vhdStream = fileSpecs[i].OpenStream())
                    using (FileStream fs = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
                    {
                        StreamPump pump = new StreamPump()
                        {
                            InputStream  = vhdStream,
                            OutputStream = fs,
                        };

                        long totalBytes = 0;
                        foreach (var se in vhdStream.Extents)
                        {
                            totalBytes += se.Length;
                        }

                        if (!Quiet)
                        {
                            Console.WriteLine();
                            DateTime now = DateTime.Now;
                            pump.ProgressEvent += (o, e) => { ShowProgress(fileSpecs[i].Name, totalBytes, now, o, e); };
                        }

                        pump.Run();

                        if (!Quiet)
                        {
                            Console.WriteLine();
                        }
                    }
            }


            // Complete - tidy up
            CallAsyncMethod(backupCmpnts.BackupComplete);

            long numDeleteFailed;
            Guid deleteFailed;

            backupCmpnts.DeleteSnapshots(snapshotSetId, 2 /*VSS_OBJECT_SNAPSHOT_SET*/, true, out numDeleteFailed, out deleteFailed);

            Marshal.ReleaseComObject(backupCmpnts);
        }
Beispiel #18
0
        /// <summary>
        /// Clones file system sector by sector omiting the unused ones.
        /// Note: caller is responsible for disposing the streams used in parameters
        /// </summary>
        /// <param name="sourceFileSystemToClone"></param>
        /// <param name="destinationLocationStream"></param>
        public void CloneNtfsFileSystem(Stream sourceFileSystemToClone, Stream destinationLocationStream, ILogger logger)
        {
            if (sourceFileSystemToClone == null || destinationLocationStream == null)
            {
                throw new ArgumentNullException("Neither sourceFileSystemToClone nor destinationLocationStream can be null.");
            }
            if (destinationLocationStream.Length < sourceFileSystemToClone.Length)
            {
                throw new ArgumentException("Cloning NTFS file system to a smaller destination is not supported.");
            }

            byte[] volBitmap;
            int    clusterSize;

            using (NtfsFileSystem ntfs = new NtfsFileSystem(sourceFileSystemToClone))
            {
                ntfs.NtfsOptions.HideSystemFiles = false;
                ntfs.NtfsOptions.HideHiddenFiles = false;
                ntfs.NtfsOptions.HideMetafiles   = false;

                using (Stream bitmapStream = ntfs.OpenFile(@"$Bitmap", FileMode.Open))
                {
                    volBitmap = new byte[bitmapStream.Length];

                    int totalRead = 0;
                    int numRead   = bitmapStream.Read(volBitmap, 0, volBitmap.Length - totalRead);
                    while (numRead > 0)
                    {
                        totalRead += numRead;
                        numRead    = bitmapStream.Read(volBitmap, totalRead, volBitmap.Length - totalRead);
                    }
                }

                clusterSize = (int)ntfs.ClusterSize;
            }

            List <StreamExtent> extents = new List <StreamExtent>(ConvertBitmapToRanges(volBitmap, clusterSize));

            SparseStream contentStream = SparseStream.FromStream(sourceFileSystemToClone, Ownership.None, extents);
            {
                ImprovedStreamPump pump = new ImprovedStreamPump()
                {
                    InputStream  = contentStream,
                    OutputStream = destinationLocationStream,
                };

                long totalBytes = 0;
                foreach (var se in contentStream.Extents)
                {
                    totalBytes += se.Length;
                }

                long onePercentageBytesAmount = totalBytes / 100;
                int  currentPercentage        = 0;

                if (logger != null)
                {
                    pump.ProgressEvent += (o, e) =>
                    {
                        if (e.BytesWritten >= (currentPercentage + 1) * onePercentageBytesAmount)
                        {
                            currentPercentage++;
                            logger.LogInformation($"Copy ntfs file system: {currentPercentage}%");
                        }
                    };
                }

                pump.Run();
            }
        }
        public NtfsFileSystem Format(Stream stream)
        {
            _context                      = new NtfsContext();
            _context.Options              = new NtfsOptions();
            _context.RawStream            = stream;
            _context.AttributeDefinitions = new AttributeDefinitions();

            string localAdminString = (ComputerAccount == null)
                    ? "LA"
                    : new SecurityIdentifier(WellKnownSidType.AccountAdministratorSid, ComputerAccount).ToString();

            using (new NtfsTransaction())
            {
                _clusterSize     = 4096;
                _mftRecordSize   = 1024;
                _indexBufferSize = 4096;

                long totalClusters = ((SectorCount - 1) * Sizes.Sector) / _clusterSize;

                // Allocate a minimum of 8KB for the boot loader, but allow for more
                int numBootClusters = Utilities.Ceil(Math.Max((int)(8 * Sizes.OneKiB), BootCode == null ? 0 : BootCode.Length), _clusterSize);

                // Place MFT mirror in the middle of the volume
                _mftMirrorCluster = totalClusters / 2;
                uint numMftMirrorClusters = 1;

                // The bitmap is also near the middle
                _bitmapCluster = _mftMirrorCluster + 13;
                int numBitmapClusters = (int)Utilities.Ceil((totalClusters / 8), _clusterSize);

                // The MFT bitmap goes 'near' the start - approx 10% in - but ensure we avoid the bootloader
                long mftBitmapCluster     = Math.Max(3 + (totalClusters / 10), numBootClusters);
                int  numMftBitmapClusters = 1;

                // The MFT follows it's bitmap
                _mftCluster = mftBitmapCluster + numMftBitmapClusters;
                int numMftClusters = 8;

                if (_mftCluster + numMftClusters > _mftMirrorCluster ||
                    _bitmapCluster + numBitmapClusters >= totalClusters)
                {
                    throw new IOException("Unable to determine initial layout of NTFS metadata - disk may be too small");
                }

                CreateBiosParameterBlock(stream, numBootClusters * _clusterSize);

                _context.Mft = new MasterFileTable(_context);
                File mftFile = _context.Mft.InitializeNew(_context, mftBitmapCluster, (ulong)numMftBitmapClusters, (long)_mftCluster, (ulong)numMftClusters);

                File bitmapFile = CreateFixedSystemFile(MasterFileTable.BitmapIndex, _bitmapCluster, (ulong)numBitmapClusters, true);
                _context.ClusterBitmap = new ClusterBitmap(bitmapFile);
                _context.ClusterBitmap.MarkAllocated(0, numBootClusters);
                _context.ClusterBitmap.MarkAllocated(_bitmapCluster, numBitmapClusters);
                _context.ClusterBitmap.MarkAllocated(mftBitmapCluster, numMftBitmapClusters);
                _context.ClusterBitmap.MarkAllocated(_mftCluster, numMftClusters);
                _context.ClusterBitmap.SetTotalClusters(totalClusters);
                bitmapFile.UpdateRecordInMft();

                File mftMirrorFile = CreateFixedSystemFile(MasterFileTable.MftMirrorIndex, _mftMirrorCluster, numMftMirrorClusters, true);

                File logFile = CreateSystemFile(MasterFileTable.LogFileIndex);
                using (Stream s = logFile.OpenStream(AttributeType.Data, null, FileAccess.ReadWrite))
                {
                    s.SetLength(Math.Min(Math.Max(2 * Sizes.OneMiB, (totalClusters / 500) * (long)_clusterSize), 64 * Sizes.OneMiB));
                    byte[] buffer = new byte[1024 * 1024];
                    for (int i = 0; i < buffer.Length; ++i)
                    {
                        buffer[i] = 0xFF;
                    }

                    long totalWritten = 0;
                    while (totalWritten < s.Length)
                    {
                        int toWrite = (int)Math.Min(s.Length - totalWritten, buffer.Length);
                        s.Write(buffer, 0, toWrite);
                        totalWritten += toWrite;
                    }
                }

                File       volumeFile    = CreateSystemFile(MasterFileTable.VolumeIndex);
                NtfsStream volNameStream = volumeFile.CreateStream(AttributeType.VolumeName, null);
                volNameStream.SetContent(new VolumeName(Label ?? "New Volume"));
                NtfsStream volInfoStream = volumeFile.CreateStream(AttributeType.VolumeInformation, null);
                volInfoStream.SetContent(new VolumeInformation(3, 1, VolumeInformationFlags.None));
                SetSecurityAttribute(volumeFile, "O:" + localAdminString + "G:BAD:(A;;0x12019f;;;SY)(A;;0x12019f;;;BA)");
                volumeFile.UpdateRecordInMft();

                _context.GetFileByIndex = delegate(long index) { return(new File(_context, _context.Mft.GetRecord(index, false))); };
                _context.AllocateFile   = delegate(FileRecordFlags frf) { return(new File(_context, _context.Mft.AllocateRecord(frf, false))); };

                File attrDefFile = CreateSystemFile(MasterFileTable.AttrDefIndex);
                _context.AttributeDefinitions.WriteTo(attrDefFile);
                SetSecurityAttribute(attrDefFile, "O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)");
                attrDefFile.UpdateRecordInMft();

                File bootFile = CreateFixedSystemFile(MasterFileTable.BootIndex, 0, (uint)numBootClusters, false);
                SetSecurityAttribute(bootFile, "O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)");
                bootFile.UpdateRecordInMft();

                File badClusFile = CreateSystemFile(MasterFileTable.BadClusIndex);
                badClusFile.CreateStream(AttributeType.Data, "$Bad");
                badClusFile.UpdateRecordInMft();

                File secureFile = CreateSystemFile(MasterFileTable.SecureIndex, FileRecordFlags.HasViewIndex);
                secureFile.RemoveStream(secureFile.GetStream(AttributeType.Data, null));
                _context.SecurityDescriptors = SecurityDescriptors.Initialize(secureFile);
                secureFile.UpdateRecordInMft();

                File upcaseFile = CreateSystemFile(MasterFileTable.UpCaseIndex);
                _context.UpperCase = UpperCase.Initialize(upcaseFile);
                upcaseFile.UpdateRecordInMft();

                File objIdFile = File.CreateNew(_context, FileRecordFlags.IsMetaFile | FileRecordFlags.HasViewIndex, FileAttributeFlags.None);
                objIdFile.RemoveStream(objIdFile.GetStream(AttributeType.Data, null));
                objIdFile.CreateIndex("$O", (AttributeType)0, AttributeCollationRule.MultipleUnsignedLongs);
                objIdFile.UpdateRecordInMft();

                File reparseFile = File.CreateNew(_context, FileRecordFlags.IsMetaFile | FileRecordFlags.HasViewIndex, FileAttributeFlags.None);
                reparseFile.CreateIndex("$R", (AttributeType)0, AttributeCollationRule.MultipleUnsignedLongs);
                reparseFile.UpdateRecordInMft();

                File quotaFile = File.CreateNew(_context, FileRecordFlags.IsMetaFile | FileRecordFlags.HasViewIndex, FileAttributeFlags.None);
                Quotas.Initialize(quotaFile);

                Directory extendDir = CreateSystemDirectory(MasterFileTable.ExtendIndex);
                extendDir.AddEntry(objIdFile, "$ObjId", FileNameNamespace.Win32AndDos);
                extendDir.AddEntry(reparseFile, "$Reparse", FileNameNamespace.Win32AndDos);
                extendDir.AddEntry(quotaFile, "$Quota", FileNameNamespace.Win32AndDos);
                extendDir.UpdateRecordInMft();

                Directory rootDir = CreateSystemDirectory(MasterFileTable.RootDirIndex);
                rootDir.AddEntry(mftFile, "$MFT", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(mftMirrorFile, "$MFTMirr", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(logFile, "$LogFile", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(volumeFile, "$Volume", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(attrDefFile, "$AttrDef", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(rootDir, ".", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(bitmapFile, "$Bitmap", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(bootFile, "$Boot", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(badClusFile, "$BadClus", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(secureFile, "$Secure", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(upcaseFile, "$UpCase", FileNameNamespace.Win32AndDos);
                rootDir.AddEntry(extendDir, "$Extend", FileNameNamespace.Win32AndDos);
                SetSecurityAttribute(rootDir, "O:" + localAdminString + "G:BUD:(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)(A;OICIIO;GA;;;CO)(A;OICI;0x1200a9;;;BU)(A;CI;LC;;;BU)(A;CIIO;DC;;;BU)(A;;0x1200a9;;;WD)");
                rootDir.UpdateRecordInMft();

                // A number of records are effectively 'reserved'
                for (long i = MasterFileTable.ExtendIndex + 1; i <= 15; i++)
                {
                    File f = CreateSystemFile(i);
                    SetSecurityAttribute(f, "O:S-1-5-21-1708537768-746137067-1060284298-1003G:BAD:(A;;0x12019f;;;SY)(A;;0x12019f;;;BA)");
                    f.UpdateRecordInMft();
                }
            }

            // XP-style security permissions setup
            NtfsFileSystem ntfs = new NtfsFileSystem(stream);

            ntfs.SetSecurity(@"$MFT", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)"));
            ntfs.SetSecurity(@"$MFTMirr", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)"));
            ntfs.SetSecurity(@"$LogFile", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)"));
            ntfs.SetSecurity(@"$Bitmap", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)"));
            ntfs.SetSecurity(@"$BadClus", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)"));
            ntfs.SetSecurity(@"$UpCase", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;FR;;;SY)(A;;FR;;;BA)"));
            ntfs.SetSecurity(@"$Secure", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;0x12019f;;;SY)(A;;0x12019f;;;BA)"));
            ntfs.SetSecurity(@"$Extend", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;0x12019f;;;SY)(A;;0x12019f;;;BA)"));
            ntfs.SetSecurity(@"$Extend\$Quota", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;0x12019f;;;SY)(A;;0x12019f;;;BA)"));
            ntfs.SetSecurity(@"$Extend\$ObjId", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;0x12019f;;;SY)(A;;0x12019f;;;BA)"));
            ntfs.SetSecurity(@"$Extend\$Reparse", new RawSecurityDescriptor("O:" + localAdminString + "G:BAD:(A;;0x12019f;;;SY)(A;;0x12019f;;;BA)"));

            ntfs.CreateDirectory("System Volume Information");
            ntfs.SetAttributes("System Volume Information", FileAttributes.Hidden | FileAttributes.System | FileAttributes.Directory);
            ntfs.SetSecurity("System Volume Information", new RawSecurityDescriptor("O:BAG:SYD:(A;OICI;FA;;;SY)"));

            using (Stream s = ntfs.OpenFile(@"System Volume Information\MountPointManagerRemoteDatabase", FileMode.Create))
            {
            }

            ntfs.SetAttributes(@"System Volume Information\MountPointManagerRemoteDatabase", FileAttributes.Hidden | FileAttributes.System | FileAttributes.Archive);
            ntfs.SetSecurity(@"System Volume Information\MountPointManagerRemoteDatabase", new RawSecurityDescriptor("O:BAG:SYD:(A;;FA;;;SY)"));
            return(ntfs);
        }
Beispiel #20
0
        public static void GetFile(string DiskPath, string FilePath, string DestinationFile)
        {
            if (File.Exists(DiskPath) && Directory.Exists(Path.GetDirectoryName(DestinationFile)))
            {
                if (Path.GetFileName(DestinationFile) == "")
                {
                    DestinationFile += Path.GetFileName(FilePath);
                }

                VolumeManager volMgr = new VolumeManager();
                VirtualDisk   disk   = VirtualDisk.OpenDisk(DiskPath, FileAccess.Read);
                volMgr.AddDisk(disk);
                VolumeInfo volInfo = null;
                if (disk.Partitions.Count > 1)
                {
                    Console.WriteLine("\r\n[*] Target has more than one partition\r\n");
                    foreach (var physVol in volMgr.GetPhysicalVolumes())
                    {
                        Console.WriteLine("      Identity: " + physVol.Identity);
                        Console.WriteLine("          Type: " + physVol.VolumeType);
                        Console.WriteLine("       Disk Id: " + physVol.DiskIdentity);
                        Console.WriteLine("      Disk Sig: " + physVol.DiskSignature.ToString("X8"));
                        Console.WriteLine("       Part Id: " + physVol.PartitionIdentity);
                        Console.WriteLine("        Length: " + physVol.Length + " bytes");
                        Console.WriteLine(" Disk Geometry: " + physVol.PhysicalGeometry);
                        Console.WriteLine("  First Sector: " + physVol.PhysicalStartSector);
                        Console.WriteLine();
                        if (!string.IsNullOrEmpty(physVol.Identity))
                        {
                            volInfo = volMgr.GetVolume(physVol.Identity);
                        }
                        DiscUtils.FileSystemInfo fsInfo = FileSystemManager.DetectFileSystems(volInfo)[0];
                        using (NtfsFileSystem diskntfs = new NtfsFileSystem(physVol.Partition.Open()))
                        {
                            if (diskntfs.FileExists("\\\\" + FilePath))
                            {
                                long fileLength = diskntfs.GetFileLength("\\\\" + FilePath);
                                using (Stream bootStream = diskntfs.OpenFile("\\\\" + FilePath, FileMode.Open,
                                                                             FileAccess.Read))
                                {
                                    byte[] file      = new byte[bootStream.Length];
                                    int    totalRead = 0;
                                    while (totalRead < file.Length)
                                    {
                                        totalRead += bootStream.Read(file, totalRead, file.Length - totalRead);
                                        FileStream fileStream =
                                            File.Create(DestinationFile, (int)bootStream.Length);
                                        bootStream.CopyTo(fileStream);
                                        fileStream.Write(file, 0, (int)bootStream.Length);
                                    }

                                    long destinationLength = new FileInfo(DestinationFile).Length;
                                    if (fileLength != destinationLength)
                                    {
                                        Console.WriteLine(
                                            "[!] Something went wrong. Source file has size {0} and destination file has size {1}",
                                            fileLength, destinationLength);
                                    }
                                    else
                                    {
                                        Console.WriteLine("\r\n[*] File {0} was successfully copied to {1}",
                                                          FilePath, DestinationFile);
                                    }
                                }
                            }
                            else
                            {
                                Console.WriteLine("\r\n [!] File {0} can not be found", FilePath);
                            }
                        }
                    }
                }
                else
                {
                    foreach (var physVol in volMgr.GetPhysicalVolumes())
                    {
                        Console.WriteLine("      Identity: " + physVol.Identity);
                        Console.WriteLine("          Type: " + physVol.VolumeType);
                        Console.WriteLine("       Disk Id: " + physVol.DiskIdentity);
                        Console.WriteLine("      Disk Sig: " + physVol.DiskSignature.ToString("X8"));
                        Console.WriteLine("       Part Id: " + physVol.PartitionIdentity);
                        Console.WriteLine("        Length: " + physVol.Length + " bytes");
                        Console.WriteLine(" Disk Geometry: " + physVol.PhysicalGeometry);
                        Console.WriteLine("  First Sector: " + physVol.PhysicalStartSector);
                        Console.WriteLine();
                        NtfsFileSystem diskntfs = new NtfsFileSystem(disk.Partitions[0].Open());
                        if (diskntfs.FileExists("\\\\" + FilePath))
                        {
                            long fileLength = diskntfs.GetFileLength("\\\\" + FilePath);
                            using (Stream bootStream =
                                       diskntfs.OpenFile("\\\\" + FilePath, FileMode.Open, FileAccess.Read))
                            {
                                byte[] file      = new byte[bootStream.Length];
                                int    totalRead = 0;
                                while (totalRead < file.Length)
                                {
                                    totalRead += bootStream.Read(file, totalRead, file.Length - totalRead);
                                    FileStream fileStream = File.Create(DestinationFile, (int)bootStream.Length);
                                    bootStream.CopyTo(fileStream);
                                    fileStream.Write(file, 0, (int)bootStream.Length);
                                }
                            }

                            long destinationLength = new FileInfo(DestinationFile).Length;
                            if (fileLength != destinationLength)
                            {
                                Console.WriteLine(
                                    "[!] Something went wrong. Source file has size {0} and destination file has size {1}",
                                    fileLength, destinationLength);
                            }
                            else
                            {
                                Console.WriteLine("\r\n[*] File {0} was successfully copied to {1}", FilePath,
                                                  DestinationFile);
                            }
                        }
                        else
                        {
                            Console.WriteLine("\r\n [!] File {0} can not be found", FilePath);
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine(
                    "\r\n [!] The provided VMDK image does not exist / can not be accessed or the destination folder does not exist");
            }
        }