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")); }
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")); }
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); } }
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); }
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]); }
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")); }
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]); } }
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); }
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); }
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); }
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")); }
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)); }
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")); }
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)); }
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]); } } } } } } } } }
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); }
/// <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); }
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"); } }