public void SimpleFile() { byte[] randomData = new byte[65 * 4096]; _random.NextBytes(randomData); using (TempFile tmpFile = new TempFile()) { // Create a file File.WriteAllBytes(tmpFile.File.FullName, randomData); // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
public void SparseFile() { byte[] randomData = new byte[35 * 4096]; _random.NextBytes(randomData); // Clear the 16 * 4096 -> 32 * 4096 range Array.Clear(randomData, 16 * 4096, 16 * 4096); using (TempFile tmpFile = new TempFile()) { // Create a file File.WriteAllBytes(tmpFile.File.FullName, randomData); using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName)) { wrapper.FileSystemSetSparseFile(true); wrapper.FileSystemSetZeroData(16 * 4096, 16 * 4096); FILE_ALLOCATED_RANGE_BUFFER[] rangesData = wrapper.FileSystemQueryAllocatedRanges(0, randomData.Length); // We should have 2 ranges on non-zero data Assert.AreEqual(2, rangesData.Length); } // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.SparseFile)); AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single(); Assert.IsTrue(attributeData.DataFragments.Length > 1); Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsSparseFragment)); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
public void CompressedFile() { using (TempFile tmpFile = new TempFile()) { // Create a file // Write file data using (FileStream fs = File.OpenWrite(tmpFile.File.FullName)) { byte[] data = Encoding.ASCII.GetBytes("The white bunny jumps over the brown dog in a carparking lot"); for (int i = 0; i < 20000; i++) { fs.Write(data, 0, data.Length); } } using (FilesystemDeviceWrapper wrapper = Win32.GetFileWrapper(tmpFile.File.FullName)) { wrapper.FileSystemSetCompression(COMPRESSION_FORMAT.LZNT1); } // Discover it via the NTFS lib char driveLetter = tmpFile.File.FullName[0]; RawDisk disk = new RawDisk(driveLetter); NTFSDiskProvider provider = new NTFSDiskProvider(disk); NTFSWrapper ntfsWrapper = new NTFSWrapper(provider, 0); NtfsDirectory ntfsDir = NTFSHelpers.OpenDir(ntfsWrapper, tmpFile.File.DirectoryName); NtfsFile ntfsFile = NTFSHelpers.OpenFile(ntfsDir, tmpFile.File.Name); Assert.IsNotNull(ntfsFile); Assert.IsTrue(tmpFile.File.Attributes.HasFlag(FileAttributes.Compressed)); AttributeData attributeData = ntfsFile.MFTRecord.Attributes.OfType <AttributeData>().Single(); Assert.IsTrue(attributeData.DataFragments.Any(s => s.IsCompressed)); // Read it using (Stream actualStream = File.OpenRead(tmpFile.File.FullName)) using (Stream ntfsStream = ntfsFile.OpenRead()) { bool equal = StreamUtils.CompareStreams(actualStream, ntfsStream); Assert.IsTrue(equal); } } }
private byte[] GetFileBytes(NtfsFile file) { byte[] result = new byte[] { }; // If we made it this far, attempt to read the bytes using (MemoryStream ms = new MemoryStream((int)this.Length)) { using (Stream ntfsStream = file.OpenRead()) { int read; byte[] buffer = new byte[16 * 1024]; while ((read = ntfsStream.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); CancellationHelper.ThrowIfCancelled(); } buffer = null; } result = ms.ToArray(); } return(result); }
public void PopulateFileProperties(FileEnumeratorParameters parameters, char driveLetter, NtfsFile ntfsFile) { if (parameters == null) { return; } if (ntfsFile == null) { return; } CancellationHelper.SetCancellationToken(parameters.CancelToken); CancellationHelper.ThrowIfCancelled(); MFTNumber = ntfsFile.MFTRecord.MFTNumber; SequenceNumber = ntfsFile.MFTRecord.SequenceNumber; DriveLetter = driveLetter; FileName = ntfsFile.Name; MftTimeAccessed = ntfsFile.TimeAccessed; MftTimeCreation = ntfsFile.TimeCreation; MftTimeModified = ntfsFile.TimeModified; MftTimeMftModified = ntfsFile.TimeMftModified; DirectoryLocation = GetDirectory(ntfsFile); Extension = Path.GetExtension(FileName); FullPath = Path.Combine(DriveLetter.ToString() + DirectoryLocation, FileName); this.Length = ntfsFile.AllocatedSize; CancellationHelper.ThrowIfCancelled(); if (this.Length != 0) { // Some entries in the MFT are greater than int.MaxValue !! That or the size is corrupt. Either way, we handle that here. if (this.Length >= (int.MaxValue - 1)) { using (Stream ntfsStream = ntfsFile.OpenRead()) { this.Sha256Hash = GetSha256Hash_BigFile(ntfsStream); this.Length = ntfsStream.Length; } this.PeData = PeDataObject.TryGetPeDataObject(FileName, parameters.OnlineCertValidation); CancellationHelper.ThrowIfCancelled(); this.Authenticode = AuthenticodeData.TryGetAuthenticodeData(FileName); CancellationHelper.ThrowIfCancelled(); } else { byte[] fileBytes = GetFileBytes(ntfsFile); CancellationHelper.ThrowIfCancelled(); this.PeData = PeDataObject.TryGetPeDataObject(fileBytes, parameters.OnlineCertValidation); if (IsPeDataPopulated) { this.Sha256Hash = PeData.SHA256Hash; } else { this.Sha256Hash = GetSha256Hash(fileBytes); } CancellationHelper.ThrowIfCancelled(); if (parameters.CalculateEntropy) { this.Entropy = EntropyHelper.CalculateFileEntropy(fileBytes); CancellationHelper.ThrowIfCancelled(); } this.Authenticode = AuthenticodeData.TryGetAuthenticodeData(fileBytes); CancellationHelper.ThrowIfCancelled(); if (!string.IsNullOrWhiteSpace(parameters.YaraRulesFilePath) && File.Exists(parameters.YaraRulesFilePath)) { this.YaraRulesMatched = YaraRules.Scan(fileBytes, parameters.YaraRulesFilePath); CancellationHelper.ThrowIfCancelled(); } fileBytes = null; } } PopulateFileInfoProperties(FullPath); CancellationHelper.ThrowIfCancelled(); this.Attributes = new Attributes(FullPath); CancellationHelper.ThrowIfCancelled(); PopulateShellFileInfo(FullPath); CancellationHelper.ThrowIfCancelled(); }