public static byte[] GetHiveBytes(string path) { // Get bytes for the specific record string volume = "\\\\.\\" + path.Split('\\')[0]; IndexEntry entry = IndexEntry.Get(path); FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, (int)entry.RecordNumber), volume, true); return record.GetBytes(); }
public static byte[] GetBytes(string path) { // Get bytes for the specific record string volume = "\\\\.\\" + path.Split('\\')[0]; IndexEntry entry = IndexEntry.Get(path); FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, (int)entry.RecordNumber), volume); byte[] bytes = record.GetBytes(); // Registry Header return NativeMethods.GetSubArray(bytes, 0x00, 0x200); }
internal static NonResident GetDataAttr(FileRecord fileRecord) { foreach (Attr attr in fileRecord.Attribute) { if (attr.Name == Attr.ATTR_TYPE.DATA) { return attr as NonResident; } } throw new Exception("No DATA attribute found."); }
internal static VolumeName GetVolumeNameAttr(FileRecord fileRecord) { foreach (Attr attr in fileRecord.Attribute) { if (attr.Name == Attr.ATTR_TYPE.VOLUME_NAME) { return attr as VolumeName; } } throw new Exception("No VOLUME_NAME attribute found."); }
internal static VolumeInformation GetVolumeInformationAttr(FileRecord fileRecord) { foreach (Attr attr in fileRecord.Attribute) { if (attr.Name == Attr.ATTR_TYPE.VOLUME_INFORMATION) { return attr as VolumeInformation; } } throw new Exception("No VOLUME_INFORMATION attribute found."); }
public static Mactime[] Get(FileRecord record) { #region DetermineTime Dictionary<DateTime, ACTIVITY_TYPE> dictionary = new Dictionary<DateTime, ACTIVITY_TYPE>(); // Modified Time dictionary[record.ModifiedTime] = ACTIVITY_TYPE.m; // Access Time if (dictionary.ContainsKey(record.AccessedTime)) { dictionary[record.AccessedTime] = dictionary[record.AccessedTime] | ACTIVITY_TYPE.a; } else { dictionary.Add(record.AccessedTime, ACTIVITY_TYPE.a); } // MFT Changed Time if (dictionary.ContainsKey(record.ChangedTime)) { dictionary[record.ChangedTime] = dictionary[record.ChangedTime] | ACTIVITY_TYPE.c; } else { dictionary.Add(record.ChangedTime, ACTIVITY_TYPE.c); } // Born Time if (dictionary.ContainsKey(record.BornTime)) { dictionary[record.BornTime] = dictionary[record.BornTime] | ACTIVITY_TYPE.b; } else { dictionary.Add(record.BornTime, ACTIVITY_TYPE.b); } #endregion DetermineTime List<Mactime> macs = new List<Mactime>(); foreach (var time in dictionary) { //macs.Add(new Mactime(time.Key, record.Size, (ushort)time.Value, record.RecordNumber, record.FullPath, record.Deleted)); macs.Add(new Mactime(time.Key, record.RealSize, (ushort)time.Value, record.RecordNumber, record.Name, record.Deleted)); } return macs.ToArray(); }
public static HiveBinHeader[] GetInstances(string path) { // Get bytes for the specific record string volume = "\\\\.\\" + path.Split('\\')[0]; IndexEntry entry = IndexEntry.Get(path); FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, (int)entry.RecordNumber), volume); byte[] bytes = record.GetBytes(); // Registry Header RegistryHeader header = new RegistryHeader(NativeMethods.GetSubArray(bytes, 0x00, 0x200)); // Hive Bin Headers HiveBinHeader[] headerArray = new HiveBinHeader[header.HiveBinsDataSize / 0x1000]; byte[] hbinHeaderBytes = new byte[0x20]; uint i = 0x1000; while (i < header.HiveBinsDataSize + 0x1000) { HiveBinHeader hbinHeader = new HiveBinHeader(NativeMethods.GetSubArray(bytes, i, 0x20)); headerArray[((i / 0x1000) - 1)] = hbinHeader; i += hbinHeader.hBinSize; } return headerArray; }
internal static AttrDef[] GetInstances(string volume, int index) { return(AttrDef.GetInstances(new FileRecord(FileRecord.GetRecordBytes(volume, index), volume).GetBytes())); }
internal static ScheduledJob Get(string volume, int recordNumber) { FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, recordNumber), volume, true); return new ScheduledJob(record.GetBytes()); }
internal static ScheduledJob Get(string path) { string volume = "\\\\.\\" + path.Split('\\')[0]; IndexEntry index = IndexEntry.Get(path); FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, (int)index.RecordNumber), volume, true); return new ScheduledJob(record.GetBytes()); }
public static Prefetch Get(string filePath) { // Get volume path from filePath string volume = @"\\.\" + filePath.Split('\\')[0]; // Get a handle to the volume IntPtr hVolume = NativeMethods.getHandle(volume); // Get MFT Index for specified file int index = (int)(IndexEntry.Get(filePath)).RecordNumber; // Get bytes for specific Prefetch file byte[] fileBytes = new FileRecord(FileRecord.GetRecordBytes(volume, index), volume, true).GetBytes(); try { // Return a Prefetch object for the Prefetch file stored at filePath return new Prefetch(fileBytes); } catch { throw new Exception("Error parsing Prefetch file"); } }
public FileRecord(byte[] recordBytes, string volume) { VolumePath = volume; Signature = Encoding.ASCII.GetString(recordBytes, 0x00, 0x04); if (Signature == "FILE") { // Parse File Record Header OffsetOfUS = BitConverter.ToUInt16(recordBytes, 4); SizeOfUS = BitConverter.ToUInt16(recordBytes, 6); #region UpdateSequenceNumber byte[] usnBytes = new byte[2]; Array.Copy(recordBytes, OffsetOfUS, usnBytes, 0, usnBytes.Length); UpdateSequenceNumber = BitConverter.ToUInt16(usnBytes, 0); #endregion UpdateSequenceNumber #region UpdateSequenceArray UpdateSequenceArray = new byte[(2 * SizeOfUS) - 2]; Array.Copy(recordBytes, (OffsetOfUS + 2), UpdateSequenceArray, 0, UpdateSequenceArray.Length); #endregion UpdateSequenceArray LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 8); SequenceNumber = BitConverter.ToUInt16(recordBytes, 16); Hardlinks = BitConverter.ToUInt16(recordBytes, 18); OffsetOfAttribute = BitConverter.ToUInt16(recordBytes, 20); Flags = BitConverter.ToUInt16(recordBytes, 22); #region Deleted if ((Flags & (ushort)FILE_RECORD_FLAG.INUSE) == (ushort)FILE_RECORD_FLAG.INUSE) { Deleted = false; } else { Deleted = true; } #endregion Deleted #region Directory if ((Flags & (ushort)FILE_RECORD_FLAG.DIR) == (ushort)FILE_RECORD_FLAG.DIR) { Directory = true; } else { Directory = false; } #endregion Directory RealSize = BitConverter.ToUInt32(recordBytes, 24); AllocatedSize = BitConverter.ToUInt32(recordBytes, 28); ReferenceToBase = BitConverter.ToUInt64(recordBytes, 32); NextAttrId = BitConverter.ToUInt16(recordBytes, 40); RecordNumber = BitConverter.ToUInt32(recordBytes, 44); #region Attribute // Create a byte array representing the attribute array byte[] attrArrayBytes = new byte[RealSize - OffsetOfAttribute]; Array.Copy(recordBytes, OffsetOfAttribute, attrArrayBytes, 0, attrArrayBytes.Length); // Instantiate an empty list of Attr Objects (We don't know how many attributes the record contains) List<Attr> AttributeList = new List<Attr>(); // Initialize the offset value to 0 int currentOffset = 0; if (currentOffset < (attrArrayBytes.Length - 8)) { do { // Get attribute size int attrSizeOffset = currentOffset + 4; int attrSize = BitConverter.ToInt32(attrArrayBytes, attrSizeOffset); // Create new byte array with just current attribute's bytes byte[] currentAttrBytes = new byte[attrSize]; Array.Copy(attrArrayBytes, currentOffset, currentAttrBytes, 0, currentAttrBytes.Length); // Increment currentOffset currentOffset += attrSize; Attr attr = AttributeFactory.Get(currentAttrBytes, volume); if (attr != null) { if (attr.Name == Attr.ATTR_TYPE.STANDARD_INFORMATION) { StandardInformation stdInfo = attr as StandardInformation; ModifiedTime = stdInfo.ModifiedTime; AccessedTime = stdInfo.AccessedTime; ChangedTime = stdInfo.ChangedTime; BornTime = stdInfo.BornTime; Permission = stdInfo.Permission; } else if (attr.Name == Attr.ATTR_TYPE.FILE_NAME) { FileName fN = attr as FileName; if (!(fN.Namespace == 2)) { Name = fN.Filename; ParentSequenceNumber = fN.ParentSequenceNumber; ParentRecordNumber = fN.ParentRecordNumber; FNModifiedTime = fN.ModifiedTime; FNAccessedTime = fN.AccessedTime; FNChangedTime = fN.ChangedTime; FNBornTime = fN.BornTime; } } AttributeList.Add(attr); } } while (currentOffset < (attrArrayBytes.Length - 8)); } Attribute = AttributeList.ToArray(); #endregion Attribute #region FullName StringBuilder sb = new StringBuilder(); if (RecordNumber == 0) { sb.Append(volume.Split('\\')[3]); sb.Append('\\'); sb.Append(Name); FullName = sb.ToString(); } else if (RecordNumber == 5) { FullName = volume.Split('\\')[3]; } else { FileRecord parent = new FileRecord(FileRecord.GetRecordBytes(volume, (int)ParentRecordNumber), volume); if(parent.SequenceNumber == this.ParentSequenceNumber) { sb.Append(parent.FullName); } else { sb.Append(@"$OrphanFiles"); } if (Name != null) { sb.Append('\\'); FullName = sb.Append(Name).ToString(); } else { FullName = sb.ToString(); } } #endregion FullName } }
internal static Data GetMaxStream(FileRecord fileRecord) { foreach (Attr attr in fileRecord.Attribute) { if (attr.NameString == "$Max") { return attr as Data; } } throw new Exception("No $MAX attribute found."); }
internal static NonResident GetJStream(FileRecord fileRecord) { foreach (Attr attr in fileRecord.Attribute) { if (attr.NameString == "$J") { return attr as NonResident; } } throw new Exception("No $J attribute found."); }
public FileRecord GetParentFileRecord() { FileRecord record = new FileRecord(FileRecord.GetRecordBytes(this.VolumePath, (int)this.ParentFileRecordNumber), this.VolumePath); if (record.SequenceNumber == this.ParentFileSequenceNumber) { return record; } else { throw new Exception("Desired FileRecord has been overwritten"); } }
protected override void ProcessRecord() { int indexNo = 0; byte[] contentArray = null; #region Encoding System.Text.Encoding contentEncoding = System.Text.Encoding.Default; bool asBytes = false; if(this.MyInvocation.BoundParameters.ContainsKey("Encoding")) { if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.Ascii) { contentEncoding = System.Text.Encoding.ASCII; } else if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.BigEndianUnicode) { contentEncoding = System.Text.Encoding.BigEndianUnicode; } else if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.Byte) { asBytes = true; } else if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.String) { contentEncoding = System.Text.Encoding.Unicode; } else if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.Unicode) { contentEncoding = System.Text.Encoding.Unicode; } else if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.Unknown) { asBytes = true; } else if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.UTF7) { contentEncoding = System.Text.Encoding.UTF7; } else if (encoding == Microsoft.PowerShell.Commands.FileSystemCmdletProviderEncoding.UTF8) { contentEncoding = System.Text.Encoding.UTF8; } } #endregion Encoding if (this.MyInvocation.BoundParameters.ContainsKey("Path")) { string volLetter = filePath.Split('\\')[0]; string volume = @"\\.\" + volLetter; indexNo = (int)IndexEntry.Get(filePath).RecordNumber; contentArray = new FileRecord(FileRecord.GetRecordBytes(volume, indexNo), volume, true).GetBytes(); } else if(this.MyInvocation.BoundParameters.ContainsKey("IndexNumber")) { NativeMethods.getVolumeName(ref volume); contentArray = new FileRecord(FileRecord.GetRecordBytes(volume, index), volume, true).GetBytes(); } if (asBytes) { WriteObject(contentArray); } else { string[] outputArray = contentEncoding.GetString(contentArray).Split('\n'); if (this.MyInvocation.BoundParameters.ContainsKey("TotalCount") && this.MyInvocation.BoundParameters.ContainsKey("Tail")) { throw new InvalidOperationException("The parameters TotalCount and Tail cannot be used together. Please specify only one parameter."); } else if (this.MyInvocation.BoundParameters.ContainsKey("TotalCount")) { for (int i = 0; (i < totalCount) && (i < outputArray.Length); i++) { WriteObject(outputArray[i]); } } else if (this.MyInvocation.BoundParameters.ContainsKey("Tail")) { for (long i = tail; (i > 0); i--) { if (i > outputArray.Length) { i = outputArray.Length; } WriteObject(outputArray[outputArray.Length - i]); } } else { WriteObject(outputArray); } } }
internal static FileRecord GetFileRecord(string volume) { return(new FileRecord(FileRecord.GetRecordBytes(volume, VOLUME_INDEX), volume, true)); }
internal static IndexEntry Get(string path) { string[] paths = path.TrimEnd('\\').Split('\\'); // Determine Volume Name string volume = @"\\.\" + paths[0]; // Test volume path NativeMethods.getVolumeName(ref volume); int index = -1; List<IndexEntry> indexEntryList = new List<IndexEntry>(); for (int i = 0; i < paths.Length; i++) { if (index == -1) { index = 5; } else{ bool match = false; foreach (IndexEntry entry in indexEntryList) { if (entry.Entry.Filename.ToUpper() == paths[i].ToUpper()) { index = (int)entry.RecordNumber; match = true; } } if (!(match)) { throw new Exception("Path " + path + " not found."); } } FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, index), volume); indexEntryList.Clear(); if (i < paths.Length - 1) { foreach (Attr attr in record.Attribute) { if (attr.Name == Attr.ATTR_TYPE.INDEX_ROOT) { foreach (IndexEntry entry in (attr as IndexRoot).Entries) { if (entry.Entry.Namespace != 0x02) { indexEntryList.Add(entry); } } } else if (attr.Name == Attr.ATTR_TYPE.INDEX_ALLOCATION) { // Get INDEX_ALLOCATION bytes IndexAllocation IA = new IndexAllocation(attr as NonResident, volume); foreach (IndexEntry entry in IA.Entries) { if (entry.Entry.Namespace != 0x02) { indexEntryList.Add(entry); } } } } } else { return new IndexEntry(record); } } throw new Exception("The IndexEntry object for the specified path could not be found."); }
public static IndexEntry[] GetInstances(string path) { string[] paths = path.TrimEnd('\\').Split('\\'); // Determine Volume Name string volume = @"\\.\" + paths[0]; // Test volume path NativeMethods.getVolumeName(ref volume); int index = -1; List<IndexEntry> indexEntryList = new List<IndexEntry>(); for (int i = 0; i < paths.Length; i++) { if (index == -1) { index = 5; } else { bool match = false; foreach (IndexEntry entry in indexEntryList) { if (entry.Entry.Filename.ToUpper() == paths[i].ToUpper()) { index = (int)entry.RecordNumber; match = true; } } if (!(match)) { throw new Exception("Path " + path + " not found."); } } FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, index), volume); indexEntryList.Clear(); if (record.Directory) { foreach (Attr attr in record.Attribute) { if (attr.Name == Attr.ATTR_TYPE.INDEX_ROOT) { try { foreach (IndexEntry entry in (attr as IndexRoot).Entries) { if (entry.Entry.Namespace != 0x02) { StringBuilder sb = new StringBuilder(); sb.Append(path.TrimEnd('\\')); sb.Append("\\"); sb.Append(entry.Filename); entry.FullName = sb.ToString(); indexEntryList.Add(entry); } } } catch { return null; } } else if (attr.Name == Attr.ATTR_TYPE.INDEX_ALLOCATION) { // Get INDEX_ALLOCATION bytes IndexAllocation IA = new IndexAllocation(attr as NonResident, volume); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); foreach (IndexEntry entry in IA.Entries) { if (entry.Entry.Namespace != 0x02) { StringBuilder sb = new StringBuilder(); sb.Append(path.TrimEnd('\\')); sb.Append("\\"); sb.Append(entry.Filename); entry.FullName = sb.ToString(); indexEntryList.Add(entry); } } } } } else { IndexEntry[] indexArray = new IndexEntry[1]; indexArray[0] = new IndexEntry(record); return indexArray; } } return indexEntryList.ToArray(); }
public FileRecord(ref FileRecord[] array, byte[] recordBytes, string volume) { VolumePath = volume; Signature = Encoding.ASCII.GetString(recordBytes, 0x00, 0x04); if (Signature == "FILE") { // Parse File Record Header OffsetOfUS = BitConverter.ToUInt16(recordBytes, 4); SizeOfUS = BitConverter.ToUInt16(recordBytes, 6); #region UpdateSequenceNumber byte[] usnBytes = new byte[2]; Array.Copy(recordBytes, OffsetOfUS, usnBytes, 0, usnBytes.Length); UpdateSequenceNumber = BitConverter.ToUInt16(usnBytes, 0); #endregion UpdateSequenceNumber #region UpdateSequenceArray UpdateSequenceArray = new byte[(2 * SizeOfUS) - 2]; Array.Copy(recordBytes, (OffsetOfUS + 2), UpdateSequenceArray, 0, UpdateSequenceArray.Length); #endregion UpdateSequenceArray LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 8); SequenceNumber = BitConverter.ToUInt16(recordBytes, 16); Hardlinks = BitConverter.ToUInt16(recordBytes, 18); OffsetOfAttribute = BitConverter.ToUInt16(recordBytes, 20); Flags = BitConverter.ToUInt16(recordBytes, 22); #region Deleted if ((Flags & (ushort)FILE_RECORD_FLAG.INUSE) == (ushort)FILE_RECORD_FLAG.INUSE) { Deleted = false; } else { Deleted = true; } #endregion Deleted #region Directory if ((Flags & (ushort)FILE_RECORD_FLAG.DIR) == (ushort)FILE_RECORD_FLAG.DIR) { Directory = true; } else { Directory = false; } #endregion Directory RealSize = BitConverter.ToUInt32(recordBytes, 24); AllocatedSize = BitConverter.ToUInt32(recordBytes, 28); ReferenceToBase = BitConverter.ToUInt64(recordBytes, 32); NextAttrId = BitConverter.ToUInt16(recordBytes, 40); RecordNumber = BitConverter.ToUInt32(recordBytes, 44); #region Attribute // Create a byte array representing the attribute array byte[] attrArrayBytes = new byte[RealSize - OffsetOfAttribute]; Array.Copy(recordBytes, OffsetOfAttribute, attrArrayBytes, 0, attrArrayBytes.Length); // Instantiate an empty list of Attr Objects (We don't know how many attributes the record contains) List<Attr> AttributeList = new List<Attr>(); // Initialize the offset value to 0 int currentOffset = 0; if (currentOffset < (attrArrayBytes.Length - 8)) { do { // Get attribute size int attrSizeOffset = currentOffset + 4; int attrSize = BitConverter.ToInt32(attrArrayBytes, attrSizeOffset); // Create new byte array with just current attribute's bytes byte[] currentAttrBytes = new byte[attrSize]; Array.Copy(attrArrayBytes, currentOffset, currentAttrBytes, 0, currentAttrBytes.Length); // Increment currentOffset currentOffset += attrSize; Attr attr = AttributeFactory.Get(currentAttrBytes, volume); if (attr != null) { if (attr.Name == Attr.ATTR_TYPE.STANDARD_INFORMATION) { StandardInformation stdInfo = attr as StandardInformation; ModifiedTime = stdInfo.ModifiedTime; AccessedTime = stdInfo.AccessedTime; ChangedTime = stdInfo.ChangedTime; BornTime = stdInfo.BornTime; Permission = stdInfo.Permission; } else if (attr.Name == Attr.ATTR_TYPE.FILE_NAME) { FileName fN = attr as FileName; if (!(fN.Namespace == 2)) { Name = fN.Filename; ParentSequenceNumber = fN.ParentSequenceNumber; ParentRecordNumber = fN.ParentRecordNumber; FNModifiedTime = fN.ModifiedTime; FNAccessedTime = fN.AccessedTime; FNChangedTime = fN.ChangedTime; FNBornTime = fN.BornTime; } } AttributeList.Add(attr); } } while (currentOffset < (attrArrayBytes.Length - 8)); } Attribute = AttributeList.ToArray(); #endregion Attribute #region FullName StringBuilder sb = new StringBuilder(); // Record 5 is the root of the drive if (RecordNumber == 5) { sb.Append(volume.Split('\\')[3]); } else { // Derive Path by looking at ParentRecord's FullName if (array[(int)ParentRecordNumber] != null) { sb.Append(array[(int)ParentRecordNumber].FullName); } // If record for Parent does not already exist then instantiate it and add it to the array else { //Console.WriteLine("RecordIndex: {0}, ParentIndex: {1}", RecordNumber, ParentRecordNumber); // This is where the recursive call should live... //array[(int)ParentRecordNumber] = new FileRecord(ref array, FileRecord.GetRecordBytes(volume, (int)ParentRecordNumber), volume); //sb.Append(array[(int)ParentRecordNumber].FullName); } // Add file name to end of path sb.Append(Name); } // Add trailing \ to any file that is a directory if (Directory) { sb.Append('\\'); } // Figure out a way to have record 15 not have a name of $MFT... FullName = sb.ToString(); #endregion FullName } }
public FileRecord(byte[] recordBytes, string volume) { VolumePath = volume; Signature = Encoding.ASCII.GetString(recordBytes, 0x00, 0x04); if (Signature == "FILE") { // Parse File Record Header OffsetOfUS = BitConverter.ToUInt16(recordBytes, 4); SizeOfUS = BitConverter.ToUInt16(recordBytes, 6); #region UpdateSequenceNumber byte[] usnBytes = new byte[2]; Array.Copy(recordBytes, OffsetOfUS, usnBytes, 0, usnBytes.Length); UpdateSequenceNumber = BitConverter.ToUInt16(usnBytes, 0); #endregion UpdateSequenceNumber #region UpdateSequenceArray UpdateSequenceArray = new byte[(2 * SizeOfUS) - 2]; Array.Copy(recordBytes, (OffsetOfUS + 2), UpdateSequenceArray, 0, UpdateSequenceArray.Length); #endregion UpdateSequenceArray LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 8); SequenceNumber = BitConverter.ToUInt16(recordBytes, 16); Hardlinks = BitConverter.ToUInt16(recordBytes, 18); OffsetOfAttribute = BitConverter.ToUInt16(recordBytes, 20); Flags = BitConverter.ToUInt16(recordBytes, 22); #region Deleted if ((Flags & (ushort)FILE_RECORD_FLAG.INUSE) == (ushort)FILE_RECORD_FLAG.INUSE) { Deleted = false; } else { Deleted = true; } #endregion Deleted #region Directory if ((Flags & (ushort)FILE_RECORD_FLAG.DIR) == (ushort)FILE_RECORD_FLAG.DIR) { Directory = true; } else { Directory = false; } #endregion Directory RealSize = BitConverter.ToUInt32(recordBytes, 24); AllocatedSize = BitConverter.ToUInt32(recordBytes, 28); ReferenceToBase = BitConverter.ToUInt64(recordBytes, 32); NextAttrId = BitConverter.ToUInt16(recordBytes, 40); RecordNumber = BitConverter.ToUInt32(recordBytes, 44); #region Attribute // Create a byte array representing the attribute array byte[] attrArrayBytes = new byte[RealSize - OffsetOfAttribute]; Array.Copy(recordBytes, OffsetOfAttribute, attrArrayBytes, 0, attrArrayBytes.Length); // Instantiate an empty list of Attr Objects (We don't know how many attributes the record contains) List <Attr> AttributeList = new List <Attr>(); // Initialize the offset value to 0 int currentOffset = 0; if (currentOffset < (attrArrayBytes.Length - 8)) { do { // Get attribute size int attrSizeOffset = currentOffset + 4; int attrSize = BitConverter.ToInt32(attrArrayBytes, attrSizeOffset); // Create new byte array with just current attribute's bytes byte[] currentAttrBytes = new byte[attrSize]; Array.Copy(attrArrayBytes, currentOffset, currentAttrBytes, 0, currentAttrBytes.Length); // Increment currentOffset currentOffset += attrSize; Attr attr = AttributeFactory.Get(currentAttrBytes, volume); if (attr != null) { if (attr.Name == Attr.ATTR_TYPE.STANDARD_INFORMATION) { StandardInformation stdInfo = attr as StandardInformation; ModifiedTime = stdInfo.ModifiedTime; AccessedTime = stdInfo.AccessedTime; ChangedTime = stdInfo.ChangedTime; BornTime = stdInfo.BornTime; Permission = stdInfo.Permission; } else if (attr.Name == Attr.ATTR_TYPE.FILE_NAME) { FileName fN = attr as FileName; if (!(fN.Namespace == 2)) { Name = fN.Filename; ParentSequenceNumber = fN.ParentSequenceNumber; ParentRecordNumber = fN.ParentRecordNumber; FNModifiedTime = fN.ModifiedTime; FNAccessedTime = fN.AccessedTime; FNChangedTime = fN.ChangedTime; FNBornTime = fN.BornTime; } } AttributeList.Add(attr); } } while (currentOffset < (attrArrayBytes.Length - 8)); } Attribute = AttributeList.ToArray(); #endregion Attribute #region FullName StringBuilder sb = new StringBuilder(); if (RecordNumber == 0) { sb.Append(volume.Split('\\')[3]); sb.Append('\\'); sb.Append(Name); FullName = sb.ToString(); } else if (RecordNumber == 5) { FullName = volume.Split('\\')[3]; } else { FileRecord parent = new FileRecord(FileRecord.GetRecordBytes(volume, (int)ParentRecordNumber), volume); if (parent.SequenceNumber == this.ParentSequenceNumber) { sb.Append(parent.FullName); } else { sb.Append(@"$OrphanFiles"); } if (Name != null) { sb.Append('\\'); FullName = sb.Append(Name).ToString(); } else { FullName = sb.ToString(); } } #endregion FullName } }
private IndexEntry(FileRecord record) { RecordNumber = record.RecordNumber; Filename = record.Name; FullName = record.FullName; }
public static FileRecord[] GetInstances(string volume) { IntPtr hVolume = NativeMethods.getHandle(volume); using (FileStream streamToRead = NativeMethods.getFileStream(hVolume)) { // Get the FileRecord for the $MFT file //FileRecord mftRecord = new FileRecord(FileRecord.GetRecordBytes(volume, 0), volume); byte[] mftBytes = MasterFileTable.GetBytes(streamToRead, volume); // Determine the size of an MFT File Record int bytesPerFileRecord = (int)(VolumeBootRecord.Get(streamToRead)).BytesPerFileRecord; // Calulate the number of entries in the MFT int fileCount = mftBytes.Length / bytesPerFileRecord; // Instantiate an array of FileRecord objects FileRecord[] recordArray = new FileRecord[fileCount]; // Instantiate a byte array large enough to store the bytes belonging to a file record byte[] recordBytes = new byte[bytesPerFileRecord]; // Now we need to iterate through all possible index values for (int index = 0; index < fileCount; index++) { // Check if current record has been instantiated if (recordArray[index] == null) { // Copy filerecord bytes into the recordBytes byte[] Array.Copy(mftBytes, index * bytesPerFileRecord, recordBytes, 0, recordBytes.Length); // Take UpdateSequence into account ApplyFixup(ref recordBytes); // Instantiate FileRecord object recordArray[index] = new FileRecord(ref recordArray, recordBytes, volume); } } return recordArray; } }
public byte[] GetBytes() { foreach (Attr attr in this.Attribute) { if (attr.Name == Attr.ATTR_TYPE.DATA) { if (attr.NonResident) { return (attr as NonResident).GetBytes(this.VolumePath); } else { return (attr as Data).RawData; } } else if (attr.Name == Attr.ATTR_TYPE.ATTRIBUTE_LIST) { AttributeList attrlist = attr as AttributeList; foreach (AttrRef ar in attrlist.AttributeReference) { if (ar.Name == "DATA") { FileRecord record = new FileRecord(FileRecord.GetRecordBytes(this.VolumePath, (int)ar.RecordNumber), this.VolumePath); return record.GetBytes(); } } } } throw new Exception("Could not locate file contents"); }
internal static FileRecord GetFileRecord(string volume) { return new FileRecord(FileRecord.GetRecordBytes(volume, BADCLUS_INDEX), volume, true); }