public Version26(byte[] rawBytes, string sourceFilename) { SourceFilename = sourceFilename; RawBytes = rawBytes; Header = new Header(rawBytes.Take(84).ToArray()); //TODO factor out creation of File info blocks var fileInfoBytes = rawBytes.Skip(84).Take(224).ToArray(); FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0); FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4); TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8); TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12); FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16); FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20); VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24); VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28); VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32); //at offset 36 there are 8 unknown values, seemingly empty var runtimeBytes = fileInfoBytes.Skip(44).Take(64).ToArray(); LastRunTimes = new List<DateTimeOffset>(); for (var i = 0; i < 7; i++) { var rawTime = BitConverter.ToInt64(runtimeBytes, i*8); if (rawTime > 0) { LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime)); } } //at offset 108 there are 16 bytes of unknown, possibly previous data from runtimes RunCount = BitConverter.ToInt32(fileInfoBytes, 124); var unknown0 = BitConverter.ToInt32(fileInfoBytes, 128); var unknown1 = BitConverter.ToInt32(fileInfoBytes, 132); //at offset 136 there is 88 bytes of unknown, empty values var unknown2 = BitConverter.ToInt32(fileInfoBytes, 128); //TODO do something with stuff below here. relevant stuff must be moved to interface var fileMetricsBytes = rawBytes.Skip(FileMetricsOffset).Take(FileMetricsCount*32).ToArray(); var tempIndex = 0; //TODO must end up as a property var fileMetrics = new List<FileMetric23>(); while (tempIndex < fileMetricsBytes.Length) { fileMetrics.Add(new FileMetric23(fileMetricsBytes.Skip(tempIndex).Take(32).ToArray())); tempIndex += 32; } var traceChains = new List<TraceChain17>(); var traceChainBytes = rawBytes.Skip(TraceChainsOffset).Take(12*TraceChainsCount).ToArray(); var traceIndex = 0; while (traceIndex < traceChainBytes.Length) { traceChains.Add(new TraceChain17(traceChainBytes.Skip(traceIndex).Take(12).ToArray())); traceIndex += 12; } var filenameStringsBytes = rawBytes.Skip(FilenameStringsOffset).Take(FilenameStringsSize).ToArray(); var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes); var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries); Filenames = new List<string>(); Filenames.AddRange(fileNames); var volumeInfoBytes = rawBytes.Skip(VolumesInfoOffset).Take(VolumesInfoSize).ToArray(); var volumeDevicePathOffset = BitConverter.ToInt32(volumeInfoBytes, 0); var volDevicePathNumChars = BitConverter.ToInt32(volumeInfoBytes, 4); //TODO for all versions, need to loop to get all volumes, not just first one, based on VolumeCount VolumeDeviceName = Encoding.Unicode.GetString( rawBytes.Skip(VolumesInfoOffset + volumeDevicePathOffset).Take(volDevicePathNumChars*2).ToArray()); var ct = BitConverter.ToInt64(volumeInfoBytes, 8); VolumeCreatedOn = DateTimeOffset.FromFileTime(ct); VolumeSerialNumber = BitConverter.ToInt32(volumeInfoBytes, 16).ToString("X"); var fileRefOffset = BitConverter.ToInt32(volumeInfoBytes, 20); var fileRefSize = BitConverter.ToInt32(volumeInfoBytes, 24); var dirStringsOffset = BitConverter.ToInt32(volumeInfoBytes, 28); var numDirectoryStrings = BitConverter.ToInt32(volumeInfoBytes, 32); //filerefs are at VolumesInfoOffset + fileRefOffset var fileRefsIndex = VolumesInfoOffset + fileRefOffset; var fileRefBytes = rawBytes.Skip(fileRefsIndex).Take(fileRefSize).ToArray(); var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0); var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4); tempIndex = 8; FileReferences = new List<MFTInformation>(); while (tempIndex < fileRefBytes.Length && FileReferences.Count < numFileRefs) { FileReferences.Add(new MFTInformation(fileRefBytes.Skip(tempIndex).Take(8).ToArray())); tempIndex += 8; } DirectoryNames = new List<string>(); var dirStringsIndex = VolumesInfoOffset + dirStringsOffset; var dirStringsBytes = rawBytes.Skip(dirStringsIndex).ToArray(); tempIndex = 0; for (var i = 0; i < numDirectoryStrings; i++) { var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2; // double the count since its unicode and add 2 extra for null char tempIndex += 2; var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0'); DirectoryNames.Add(dirName); tempIndex += dirCharCount; } }
public Version23(byte[] rawBytes, string sourceFilename) { SourceFilename = sourceFilename; RawBytes = rawBytes; Header = new Header(rawBytes.Take(84).ToArray()); var fileInfoBytes = rawBytes.Skip(84).Take(156).ToArray(); FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0); FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4); TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8); TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12); FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16); FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20); VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24); VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28); VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32); //at offset 36 there are 8 unknown bytes var rawTime = BitConverter.ToInt64(fileInfoBytes, 44); LastRunTimes = new List<DateTimeOffset>(); LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime)); //at offset 52 there are 16 unknown bytes RunCount = BitConverter.ToInt32(fileInfoBytes, 68); //at offset 72, there are 4 unknown bytes //at offset 76, there are 80 unknown bytes //TODO do something with stuff below here. relevant stuff must be moved to interface var fileMetricsBytes = rawBytes.Skip(FileMetricsOffset).Take(FileMetricsCount*32).ToArray(); var tempIndex = 0; var fileMetrics = new List<FileMetric23>(); while (tempIndex < fileMetricsBytes.Length) { fileMetrics.Add(new FileMetric23(fileMetricsBytes.Skip(tempIndex).Take(32).ToArray())); tempIndex += 32; } var traceChains = new List<TraceChain17>(); var traceChainBytes = rawBytes.Skip(TraceChainsOffset).Take(12*TraceChainsCount).ToArray(); var traceIndex = 0; while (traceIndex < traceChainBytes.Length) { traceChains.Add(new TraceChain17(traceChainBytes.Skip(traceIndex).Take(12).ToArray())); traceIndex += 12; } var filenameStringsBytes = rawBytes.Skip(FilenameStringsOffset).Take(FilenameStringsSize).ToArray(); var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes); var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries); Filenames = new List<string>(); Filenames.AddRange(fileNames); var volumeInfoBytes = rawBytes.Skip(VolumesInfoOffset).Take(VolumesInfoSize).ToArray(); var volumeDevicePathOffset = BitConverter.ToInt32(volumeInfoBytes, 0); var volDevicePathNumChars = BitConverter.ToInt32(volumeInfoBytes, 4); VolumeDeviceName = Encoding.Unicode.GetString( rawBytes.Skip(VolumesInfoOffset + volumeDevicePathOffset).Take(volDevicePathNumChars*2).ToArray()); var ct = BitConverter.ToInt64(volumeInfoBytes, 8); VolumeCreatedOn = DateTimeOffset.FromFileTime(ct); VolumeSerialNumber = BitConverter.ToInt32(volumeInfoBytes, 16).ToString("X"); var fileRefOffset = BitConverter.ToInt32(volumeInfoBytes, 20); var fileRefSize = BitConverter.ToInt32(volumeInfoBytes, 24); var dirStringsOffset = BitConverter.ToInt32(volumeInfoBytes, 28); var numDirectoryStrings = BitConverter.ToInt32(volumeInfoBytes, 32); //filerefs are at VolumesInfoOffset + fileRefOffset var fileRefsIndex = VolumesInfoOffset + fileRefOffset; var fileRefBytes = rawBytes.Skip(fileRefsIndex).Take(fileRefSize).ToArray(); var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0); var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4); tempIndex = 8; FileReferences = new List<MFTInformation>(); while (tempIndex < fileRefBytes.Length && FileReferences.Count < numFileRefs) { FileReferences.Add(new MFTInformation(fileRefBytes.Skip(tempIndex).Take(8).ToArray())); tempIndex += 8; } DirectoryNames = new List<string>(); var dirStringsIndex = VolumesInfoOffset + dirStringsOffset; var dirStringsBytes = rawBytes.Skip(dirStringsIndex).ToArray(); tempIndex = 0; for (var i = 0; i < numDirectoryStrings; i++) { var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2; // double the count since its unicode and add 2 extra for null char tempIndex += 2; var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0'); DirectoryNames.Add(dirName); tempIndex += dirCharCount; } }
public Version17(byte[] rawBytes, string sourceFilename) { SourceFilename = sourceFilename; RawBytes = rawBytes; var headerBytes = new byte[84]; Buffer.BlockCopy(rawBytes, 0, headerBytes, 0, 84); Header = new Header(headerBytes); var fi = new FileInfo(sourceFilename); SourceCreatedOn = new DateTimeOffset(fi.CreationTimeUtc); SourceModifiedOn = new DateTimeOffset(fi.LastWriteTimeUtc); SourceAccessedOn = new DateTimeOffset(fi.LastAccessTimeUtc); var fileInfoBytes = new byte[68]; Buffer.BlockCopy(rawBytes, 84, fileInfoBytes, 0, 68); FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0); FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4); TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8); TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12); FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16); FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20); VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24); VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28); VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32); var rawTime = BitConverter.ToInt64(fileInfoBytes, 36); LastRunTimes = new List<DateTimeOffset>(); LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime).ToUniversalTime()); TotalDirectoryCount = -1; RunCount = BitConverter.ToInt32(fileInfoBytes, 60); var fileMetricsBytes = new byte[FileMetricsCount * 20]; Buffer.BlockCopy(rawBytes, FileMetricsOffset, fileMetricsBytes, 0, FileMetricsCount * 20); var tempIndex = 0; FileMetrics = new List<FileMetric>(); var fileMetricsTempBuffer = new byte[20]; while (tempIndex < fileMetricsBytes.Length) { Buffer.BlockCopy(fileMetricsBytes, tempIndex, fileMetricsTempBuffer, 0, 20); FileMetrics.Add(new FileMetric(fileMetricsTempBuffer, true)); tempIndex += 20; } TraceChains = new List<TraceChain>(); var traceChainBytes = new byte[12 * TraceChainsCount]; Buffer.BlockCopy(rawBytes, TraceChainsOffset, traceChainBytes, 0, 12 * TraceChainsCount); var traceIndex = 0; var traceChainTempBuffer = new byte[12]; while (traceIndex < traceChainBytes.Length) { Buffer.BlockCopy(traceChainBytes, traceIndex, traceChainTempBuffer, 0, 12); TraceChains.Add(new TraceChain(traceChainTempBuffer, false)); traceIndex += 12; } var filenameStringsBytes = new byte[FilenameStringsSize]; Buffer.BlockCopy(rawBytes, FilenameStringsOffset, filenameStringsBytes, 0, FilenameStringsSize); var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes); var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries); Filenames = new List<string>(); Filenames.AddRange(fileNames); var volumeInfoBytes = new byte[VolumesInfoSize]; Buffer.BlockCopy(rawBytes, VolumesInfoOffset, volumeInfoBytes, 0, VolumesInfoSize); VolumeInformation = new List<VolumeInfo>(); var volBytes = new byte[40]; for (var j = 0; j < VolumeCount; j++) { var skipSize = j*40; Buffer.BlockCopy(volumeInfoBytes, skipSize, volBytes, 0, 40); var volDevOffset = BitConverter.ToInt32(volBytes, 0); var volDevNumChar = BitConverter.ToInt32(volBytes, 4); var ct = BitConverter.ToInt64(volBytes, 8); var devNameBytes = new byte[volDevNumChar * 2]; Buffer.BlockCopy(rawBytes, VolumesInfoOffset + volDevOffset, devNameBytes, 0, volDevNumChar * 2); var devName = Encoding.Unicode.GetString(devNameBytes); var sn = BitConverter.ToInt32(volBytes, 16).ToString("X"); VolumeInformation.Add(new VolumeInfo(volDevOffset, DateTimeOffset.FromFileTime(ct).ToUniversalTime(), sn, devName)); var fileRefOffset = BitConverter.ToInt32(volBytes, 20); var fileRefSize = BitConverter.ToInt32(volBytes, 24); var dirStringsOffset = BitConverter.ToInt32(volBytes, 28); var numDirectoryStrings = BitConverter.ToInt32(volBytes, 32); //filerefs are at VolumesInfoOffset + fileRefOffset var fileRefsIndex = VolumesInfoOffset + fileRefOffset; var fileRefBytes = new byte[fileRefSize]; Buffer.BlockCopy(rawBytes, fileRefsIndex, fileRefBytes, 0, fileRefSize); var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0); var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4); tempIndex = 8; var tempFileRefBytes = new byte[8]; while (tempIndex < fileRefBytes.Length && VolumeInformation.Last().FileReferences.Count < numFileRefs) { Buffer.BlockCopy(fileRefBytes, tempIndex, tempFileRefBytes, 0, 8); VolumeInformation.Last() .FileReferences.Add(new MFTInformation(tempFileRefBytes)); tempIndex += 8; } var dirStringsIndex = VolumesInfoOffset + dirStringsOffset; var dirStringsBytes = new byte[rawBytes.Length - dirStringsIndex]; Buffer.BlockCopy(rawBytes, dirStringsIndex, dirStringsBytes, 0, rawBytes.Length - dirStringsIndex); tempIndex = 0; for (var k = 0; k < numDirectoryStrings; k++) { var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2; // double the count since its Unicode and add 2 extra for null char tempIndex += 2; var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0'); VolumeInformation.Last().DirectoryNames.Add(dirName); tempIndex += dirCharCount; } } }
public Version26(byte[] rawBytes, string sourceFilename) { SourceFilename = sourceFilename; RawBytes = rawBytes; var headerBytes = new byte[84]; Buffer.BlockCopy(rawBytes, 0, headerBytes, 0, 84); Header = new Header(headerBytes); var fi = new FileInfo(sourceFilename); SourceCreatedOn = new DateTimeOffset(fi.CreationTimeUtc); SourceModifiedOn = new DateTimeOffset(fi.LastWriteTimeUtc); SourceAccessedOn = new DateTimeOffset(fi.LastAccessTimeUtc); //TODO factor out creation of File info blocks var fileInfoBytes = new byte[224]; Buffer.BlockCopy(rawBytes, 84, fileInfoBytes, 0, 224); FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0); FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4); TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8); TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12); FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16); FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20); VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24); VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28); VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32); //at offset 36 there are 8 unknown values, seemingly empty TotalDirectoryCount = BitConverter.ToInt32(fileInfoBytes, 36); var runtimeBytes = fileInfoBytes.Skip(44).Take(64).ToArray(); LastRunTimes = new List<DateTimeOffset>(); for (var i = 0; i < 8; i++) { var rawTime = BitConverter.ToInt64(runtimeBytes, i*8); if (rawTime > 0) { LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime).ToUniversalTime()); } } //at offset 108 there are 16 bytes of unknown, possibly previous data from runtimes RunCount = BitConverter.ToInt32(fileInfoBytes, 124); var unknown0 = BitConverter.ToInt32(fileInfoBytes, 128); var unknown1 = BitConverter.ToInt32(fileInfoBytes, 132); //at offset 136 there is 88 bytes of unknown, empty values var unknown2 = BitConverter.ToInt32(fileInfoBytes, 128); var fileMetricsBytes = new byte[FileMetricsCount * 32]; Buffer.BlockCopy(rawBytes, FileMetricsOffset, fileMetricsBytes, 0, FileMetricsCount * 32); var tempIndex = 0; FileMetrics = new List<FileMetric>(); var fileMetricsTempBuffer = new byte[32]; while (tempIndex < fileMetricsBytes.Length) { Buffer.BlockCopy(fileMetricsBytes, tempIndex, fileMetricsTempBuffer, 0, 32); FileMetrics.Add(new FileMetric(fileMetricsTempBuffer, false)); tempIndex += 32; } TraceChains = new List<TraceChain>(); var traceChainBytes = new byte[12 * TraceChainsCount]; Buffer.BlockCopy(rawBytes, TraceChainsOffset, traceChainBytes, 0, 12 * TraceChainsCount); var traceIndex = 0; var traceChainTempBuffer = new byte[12]; while (traceIndex < traceChainBytes.Length) { Buffer.BlockCopy(traceChainBytes, traceIndex, traceChainTempBuffer, 0, 12); TraceChains.Add(new TraceChain(traceChainTempBuffer, false)); traceIndex += 12; } var filenameStringsBytes = new byte[FilenameStringsSize]; Buffer.BlockCopy(rawBytes, FilenameStringsOffset, filenameStringsBytes, 0, FilenameStringsSize); var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes); var fileNames = filenamesRaw.Split(new[] {'\0'}, StringSplitOptions.RemoveEmptyEntries); Filenames = new List<string>(); Filenames.AddRange(fileNames); var volumeInfoBytes = new byte[VolumesInfoSize]; Buffer.BlockCopy(rawBytes, VolumesInfoOffset, volumeInfoBytes, 0, VolumesInfoSize); VolumeInformation = new List<VolumeInfo>(); var volBytes = new byte[104]; for (var j = 0; j < VolumeCount; j++) { var skipSize = j*104; Buffer.BlockCopy(volumeInfoBytes, skipSize, volBytes, 0, 104); var volDevOffset = BitConverter.ToInt32(volBytes, 0); var volDevNumChar = BitConverter.ToInt32(volBytes, 4); var ct = BitConverter.ToInt64(volBytes, 8); var devNameBytes = new byte[volDevNumChar * 2]; Buffer.BlockCopy(rawBytes, VolumesInfoOffset + volDevOffset, devNameBytes, 0, volDevNumChar * 2); var devName = Encoding.Unicode.GetString(devNameBytes); var sn = BitConverter.ToInt32(volBytes, 16).ToString("X"); VolumeInformation.Add(new VolumeInfo(volDevOffset, DateTimeOffset.FromFileTime(ct).ToUniversalTime(), sn, devName)); var fileRefOffset = BitConverter.ToInt32(volBytes, 20); var fileRefSize = BitConverter.ToInt32(volBytes, 24); var dirStringsOffset = BitConverter.ToInt32(volBytes, 28); var numDirectoryStrings = BitConverter.ToInt32(volBytes, 32); //filerefs are at VolumesInfoOffset + fileRefOffset var fileRefsIndex = VolumesInfoOffset + fileRefOffset; var fileRefBytes = new byte[fileRefSize]; Buffer.BlockCopy(rawBytes, fileRefsIndex, fileRefBytes, 0, fileRefSize); var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0); var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4); tempIndex = 8; var tempFileRefBytes = new byte[8]; while (tempIndex < fileRefBytes.Length && VolumeInformation.Last().FileReferences.Count < numFileRefs) { Buffer.BlockCopy(fileRefBytes, tempIndex, tempFileRefBytes, 0, 8); VolumeInformation.Last() .FileReferences.Add(new MFTInformation(tempFileRefBytes)); tempIndex += 8; } var dirStringsIndex = VolumesInfoOffset + dirStringsOffset; var dirStringsBytes = new byte[rawBytes.Length - dirStringsIndex]; Buffer.BlockCopy(rawBytes, dirStringsIndex, dirStringsBytes, 0, rawBytes.Length - dirStringsIndex); tempIndex = 0; for (var k = 0; k < numDirectoryStrings; k++) { var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex)*2 + 2; // double the count since its Unicode and add 2 extra for null char tempIndex += 2; var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0'); VolumeInformation.Last().DirectoryNames.Add(dirName); tempIndex += dirCharCount; } } }
public Version23(byte[] rawBytes, string sourceFilename) { SourceFilename = sourceFilename; RawBytes = rawBytes; try { var headerBytes = new byte[84]; Buffer.BlockCopy(rawBytes, 0, headerBytes, 0, 84); Header = new Header(headerBytes); try { var fi = new FileInfo(sourceFilename); SourceCreatedOn = new DateTimeOffset(fi.CreationTimeUtc); SourceModifiedOn = new DateTimeOffset(fi.LastWriteTimeUtc); SourceAccessedOn = new DateTimeOffset(fi.LastAccessTimeUtc); } catch (Exception e) { } var fileInfoBytes = new byte[156]; Buffer.BlockCopy(rawBytes, 84, fileInfoBytes, 0, 156); FileMetricsOffset = BitConverter.ToInt32(fileInfoBytes, 0); FileMetricsCount = BitConverter.ToInt32(fileInfoBytes, 4); TraceChainsOffset = BitConverter.ToInt32(fileInfoBytes, 8); TraceChainsCount = BitConverter.ToInt32(fileInfoBytes, 12); FilenameStringsOffset = BitConverter.ToInt32(fileInfoBytes, 16); FilenameStringsSize = BitConverter.ToInt32(fileInfoBytes, 20); VolumesInfoOffset = BitConverter.ToInt32(fileInfoBytes, 24); VolumeCount = BitConverter.ToInt32(fileInfoBytes, 28); VolumesInfoSize = BitConverter.ToInt32(fileInfoBytes, 32); //at offset 36 there are 8 unknown bytes TotalDirectoryCount = BitConverter.ToInt32(fileInfoBytes, 36); var rawTime = BitConverter.ToInt64(fileInfoBytes, 44); LastRunTimes = new List <DateTimeOffset>(); LastRunTimes.Add(DateTimeOffset.FromFileTime(rawTime).ToUniversalTime()); //at offset 52 there are 16 unknown bytes RunCount = BitConverter.ToInt32(fileInfoBytes, 68); //at offset 72, there are 4 unknown bytes //at offset 76, there are 80 unknown bytes var fileMetricsBytes = new byte[FileMetricsCount * 32]; Buffer.BlockCopy(rawBytes, FileMetricsOffset, fileMetricsBytes, 0, FileMetricsCount * 32); var tempIndex = 0; FileMetrics = new List <FileMetric>(); var fileMetricsTempBuffer = new byte[32]; while (tempIndex < fileMetricsBytes.Length) { Buffer.BlockCopy(fileMetricsBytes, tempIndex, fileMetricsTempBuffer, 0, 32); FileMetrics.Add(new FileMetric(fileMetricsTempBuffer, false)); tempIndex += 32; } TraceChains = new List <TraceChain>(); var traceChainBytes = new byte[12 * TraceChainsCount]; Buffer.BlockCopy(rawBytes, TraceChainsOffset, traceChainBytes, 0, 12 * TraceChainsCount); var traceIndex = 0; var traceChainTempBuffer = new byte[12]; while (traceIndex < traceChainBytes.Length) { Buffer.BlockCopy(traceChainBytes, traceIndex, traceChainTempBuffer, 0, 12); TraceChains.Add(new TraceChain(traceChainTempBuffer, false)); traceIndex += 12; } var filenameStringsBytes = new byte[FilenameStringsSize]; Buffer.BlockCopy(rawBytes, FilenameStringsOffset, filenameStringsBytes, 0, FilenameStringsSize); var filenamesRaw = Encoding.Unicode.GetString(filenameStringsBytes); var fileNames = filenamesRaw.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries); Filenames = new List <string>(); Filenames.AddRange(fileNames); var volumeInfoBytes = new byte[VolumesInfoSize]; Buffer.BlockCopy(rawBytes, VolumesInfoOffset, volumeInfoBytes, 0, VolumesInfoSize); VolumeInformation = new List <VolumeInfo>(); var volBytes = new byte[104]; for (var j = 0; j < VolumeCount; j++) { var skipSize = j * 104; Buffer.BlockCopy(volumeInfoBytes, skipSize, volBytes, 0, 104); var volDevOffset = BitConverter.ToInt32(volBytes, 0); var volDevNumChar = BitConverter.ToInt32(volBytes, 4); var ct = BitConverter.ToInt64(volBytes, 8); var devNameBytes = new byte[volDevNumChar * 2]; Buffer.BlockCopy(rawBytes, VolumesInfoOffset + volDevOffset, devNameBytes, 0, volDevNumChar * 2); var devName = Encoding.Unicode.GetString(devNameBytes); var sn = BitConverter.ToInt32(volBytes, 16).ToString("X"); VolumeInformation.Add(new VolumeInfo(volDevOffset, DateTimeOffset.FromFileTime(ct).ToUniversalTime(), sn, devName)); var fileRefOffset = BitConverter.ToInt32(volBytes, 20); var fileRefSize = BitConverter.ToInt32(volBytes, 24); var dirStringsOffset = BitConverter.ToInt32(volBytes, 28); var numDirectoryStrings = BitConverter.ToInt32(volBytes, 32); //filerefs are at VolumesInfoOffset + fileRefOffset var fileRefsIndex = VolumesInfoOffset + fileRefOffset; var fileRefBytes = new byte[fileRefSize]; Buffer.BlockCopy(rawBytes, fileRefsIndex, fileRefBytes, 0, fileRefSize); var fileRefVer = BitConverter.ToInt32(fileRefBytes, 0); var numFileRefs = BitConverter.ToInt32(fileRefBytes, 4); tempIndex = 8; var tempFileRefBytes = new byte[8]; while (tempIndex < fileRefBytes.Length && VolumeInformation.Last().FileReferences.Count < numFileRefs) { Buffer.BlockCopy(fileRefBytes, tempIndex, tempFileRefBytes, 0, 8); VolumeInformation.Last() .FileReferences.Add(new MFTInformation(tempFileRefBytes)); tempIndex += 8; } var dirStringsIndex = VolumesInfoOffset + dirStringsOffset; var dirStringsBytes = new byte[rawBytes.Length - dirStringsIndex]; Buffer.BlockCopy(rawBytes, dirStringsIndex, dirStringsBytes, 0, rawBytes.Length - dirStringsIndex); tempIndex = 0; for (var k = 0; k < numDirectoryStrings; k++) { var dirCharCount = BitConverter.ToInt16(dirStringsBytes, tempIndex) * 2 + 2; // double the count since its Unicode and add 2 extra for null char tempIndex += 2; var dirName = Encoding.Unicode.GetString(dirStringsBytes, tempIndex, dirCharCount).Trim('\0'); VolumeInformation.Last().DirectoryNames.Add(dirName); tempIndex += dirCharCount; } } } catch (Exception) { ParsingError = true; } }