private static VolumeInformation Get(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."); }
internal static NonResident GetDataAttr(FileRecord fileRecord) { foreach (FileRecordAttribute attr in fileRecord.Attribute) { if (attr.Name == FileRecordAttribute.ATTR_TYPE.DATA) { return attr as NonResident; } } throw new Exception("No DATA attribute found."); }
private static VolumeName Get(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 NonResident GetBadStream(FileRecord fileRecord) { foreach (Attr attr in fileRecord.Attribute) { if (attr.NameString == "$Bad") { return attr as NonResident; } } throw new Exception("No $Bad attribute found."); }
private static VolumeInformation Get(FileRecord record) { foreach (FileRecordAttribute attr in record.Attribute) { VolumeInformation volInfo = attr as VolumeInformation; if(volInfo != null) { return volInfo; } } throw new Exception("No VOLUME_INFORMATION attribute found."); }
private static VolumeName Get(FileRecord fileRecord) { foreach (FileRecordAttribute attr in fileRecord.Attribute) { VolumeName volName = attr as VolumeName; if(volName != null) { return volName; } } throw new Exception("No VOLUME_NAME 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(); }
private static AlternateDataStream[] GetInstances(FileRecord record) { List<AlternateDataStream> adsList = new List<AlternateDataStream>(); if (record.Attribute != null) { foreach (FileRecordAttribute attr in record.Attribute) { if (attr.Name == FileRecordAttribute.ATTR_TYPE.DATA) { if (attr.NameString.Length > 0) { adsList.Add(new AlternateDataStream(record.FullName, record.Name, attr.NameString)); } } } } return adsList.ToArray(); }
internal static byte[] GetBytes(FileStream streamToRead, string volume) { FileRecord mftRecord = GetRecord(streamToRead, volume); return(mftRecord.GetContent()); }
public static ForensicTimeline[] GetInstances(FileRecord[] input) { List<ForensicTimeline> list = new List<ForensicTimeline>(); foreach (FileRecord r in input) { foreach (ForensicTimeline t in Get(r)) { list.Add(t); } } return list.ToArray(); }
public static VolumeInformation GetVolumeInformation(string volume) { FileRecord record = FileRecord.Get(volume, VOLUME_INDEX, true); return(GetVolumeInformation(record)); }
private static FileRecord[] GetInstances(byte[] bytes, string volume) { // Determine the size of an MFT File Record int bytesPerFileRecord = (int)(VolumeBootRecord.Get(volume)).BytesPerFileRecord; // Calulate the number of entries in the MFT int fileCount = bytes.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(bytes, index * bytesPerFileRecord, recordBytes, 0, recordBytes.Length); // Take UpdateSequence into account ApplyFixup(ref recordBytes); // Instantiate FileRecord object recordArray[index] = new FileRecord(ref recordArray, bytes, recordBytes, bytesPerFileRecord, volume); } } return recordArray; }
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."); }
public static UsnJrnlDetail Get(string path) { FileRecord record = FileRecord.Get(path, true); return(new UsnJrnlDetail(GetMaxStream(record).RawData)); }
private static UsnJrnl[] GetInstances(string volume, int recordnumber) { // Check for valid Volume name Util.getVolumeName(ref volume); // Set up FileStream to read volume IntPtr hVolume = Util.getHandle(volume); FileStream streamToRead = Util.getFileStream(hVolume); // Get VolumeBootRecord object for logical addressing VolumeBootRecord VBR = VolumeBootRecord.Get(streamToRead); FileRecord record = FileRecord.Get(volume, recordnumber, true); // Get the $J Data attribute (contains UsnJrnl details NonResident J = UsnJrnl.GetJStream(record); List <UsnJrnl> usnList = new List <UsnJrnl>(); for (int i = 0; i < J.DataRun.Length; i++) { if (!(J.DataRun[i].Sparse)) { long clusterCount = J.DataRun[i].ClusterLength; byte[] fragmentBytes = Util.readDrive(streamToRead, ((ulong)J.DataRun[i].StartCluster * VBR.BytesPerCluster), ((ulong)clusterCount * VBR.BytesPerCluster)); byte[] clusterBytes = new byte[VBR.BytesPerCluster]; for (long j = 0; j < clusterCount; j++) { Array.Copy(fragmentBytes, ((long)j * VBR.BytesPerCluster), clusterBytes, 0, clusterBytes.Length); int offset = 0; do { if (clusterBytes[offset] == 0) { break; } try { UsnJrnl usn = new UsnJrnl(clusterBytes, volume, ref offset); if (usn.Version > USN40Version) { break; } usnList.Add(usn); } catch { break; } } while (offset >= 0 && offset < clusterBytes.Length); } } } return(usnList.ToArray()); }
internal static IndexEntry Get(string path) { string[] paths = path.TrimEnd('\\').Split('\\'); // Determine Volume Name string volume = Helper.GetVolumeFromPath(path); // Test volume path Helper.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 = FileRecord.Get(volume, index, false); indexEntryList.Clear(); if (i < paths.Length - 1) { foreach (FileRecordAttribute attr in record.Attribute) { if (attr.Name == FileRecordAttribute.ATTR_TYPE.INDEX_ROOT) { foreach (IndexEntry entry in (attr as IndexRoot).Entries) { if (entry.Entry.Namespace != 0x02) { indexEntryList.Add(entry); } } } else if (attr.Name == FileRecordAttribute.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."); }
private IndexEntry(FileRecord record) { RecordNumber = record.RecordNumber; Filename = record.Name; FullName = record.FullName; }
public static IndexEntry[] GetInstances(string path) { string[] paths = path.TrimEnd('\\').Split('\\'); // Determine Volume Name string volume = Helper.GetVolumeFromPath(path); // Test volume path Helper.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 = FileRecord.Get(volume, index, true); indexEntryList.Clear(); if (record.Directory) { foreach (FileRecordAttribute attr in record.Attribute) { if (attr.Name == FileRecordAttribute.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 == FileRecordAttribute.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) { 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()); }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <returns></returns> public static VolumeInformation GetByPath(string path) { return(Get(FileRecord.Get(path, true))); }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <returns></returns> public static byte[] GetBytesByPath(string path) { FileRecord record = FileRecord.Get(path, true); return(record.GetContent()); }
/// <summary> /// /// </summary> /// <param name="volume"></param> /// <param name="recordnumber"></param> /// <param name="usn"></param> /// <returns></returns> private static UsnJrnl Get(string volume, int recordnumber, long usn) { // Check for valid Volume name Helper.getVolumeName(ref volume); // Set up FileStream to read volume FileStream streamToRead = Helper.getFileStream(volume); // Get VolumeBootRecord object for logical addressing VolumeBootRecord VBR = VolumeBootRecord.Get(streamToRead); FileRecord record = FileRecord.Get(volume, recordnumber, true); // Get the $J Data attribute (contains UsnJrnl details NonResident J = UsnJrnl.GetJStream(record); // Determine the length of the initial sparse pages long SparseLength = J.DataRun[0].ClusterLength * VBR.BytesPerCluster; if (usn > SparseLength) { // Subtract length of sparse data from desired usn offset long usnOffset = usn - SparseLength; // Iterate through each data run for (int i = 1; i < J.DataRun.Length; i++) { // Determine length of current DataRun long dataRunLength = J.DataRun[i].ClusterLength * VBR.BytesPerCluster; // Check if usnOffset resides in current DataRun if (dataRunLength <= usnOffset) { // If not, subtract length of DataRun from usnOffset usnOffset -= dataRunLength; } // If usnOffset resides within DataRun, parse associated UsnJrnl Entry else { // Read DataRun from disk byte[] fragmentBytes = Helper.readDrive(streamToRead, (J.DataRun[i].StartCluster * VBR.BytesPerCluster), (J.DataRun[i].ClusterLength * VBR.BytesPerCluster)); // Instatiate a byte array that is the size of a single cluster byte[] clusterBytes = new byte[VBR.BytesPerCluster]; // Iterate through the clusters in the DataRun for (int j = 0; j < J.DataRun[i].ClusterLength; j++) { // If usnOffset is not in current cluster, then subtract cluster size from offset and iterate if (VBR.BytesPerCluster <= usnOffset) { usnOffset -= VBR.BytesPerCluster; } // Else if usnOffset is in current cluster else { // Copy current cluster bytes to clusterBytes variable Array.Copy(fragmentBytes, (int)(j * VBR.BytesPerCluster), clusterBytes, 0, clusterBytes.Length); // Parse desired UsnJrnl entry from cluster int offset = (int)usnOffset; return(new UsnJrnl(clusterBytes, volume, ref offset)); } } } } return(null); } else { throw new Exception("UsnJrnl entry has has been overwritten"); } }
public static byte[] GetBytes(string path) { FileRecord record = FileRecord.Get(path, true); return(GetMaxStream(record).RawData); }
public static UsnJrnlDetail GetByPath(string path) { FileRecord record = FileRecord.Get(path, true); return(new UsnJrnlDetail(record.GetContent(@"$Max"))); }
public static FileRecord[] GetInstances(string volume) { FileRecord record = new FileRecord(FileRecord.GetRecordBytes(volume, 0), volume, true); byte[] mftBytes = record.GetContent(); return GetInstances(mftBytes, volume); }
/// <summary> /// /// </summary> /// <param name="volume"></param> /// <returns></returns> public static VolumeName Get(string volume) { Helper.getVolumeName(ref volume); return(Get(FileRecord.Get(volume, MftIndex.VOLUME_INDEX, true))); }
public byte[] GetTestContent(string streamName) { foreach (Attr attr in this.Attribute) { if (attr.Name == Attr.ATTR_TYPE.DATA) { if (attr.NameString.ToUpper() == streamName.ToUpper()) { if (attr.NonResident) { return (attr as NonResident).GetBytes(this.VolumePath); } else { return (attr as Data).RawData; } } } AttributeList attrList = attr as AttributeList; if (attrList != null) { foreach (AttrRef ar in attrList.AttributeReference) { if (ar.Name == "DATA") { FileRecord record = new FileRecord(FileRecord.GetRecordBytes(this.VolumePath, (int)ar.RecordNumber), this.VolumePath, true); return record.GetTestContent(streamName); } } } } throw new Exception("Could not locate desired stream"); }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <returns></returns> public static VolumeName GetByPath(string path) { return(Get(FileRecord.Get(path, true))); }
public byte[] GetMftSlack() { byte[] bytes = FileRecord.GetRecordBytes(this.VolumePath, (int)this.RecordNumber); return(NativeMethods.GetSubArray(bytes, this.RealSize - 1, this.AllocatedSize - this.RealSize)); }
// GetInstances Constructor private FileRecord(ref FileRecord[] recordArray, byte[] bytes, int offset, int bytesPerFileRecord, string volume, bool fast) { if (Encoding.ASCII.GetString(bytes, 0x00 + offset, 0x04) == "FILE") { OffsetOfUS = BitConverter.ToUInt16(bytes, 0x04 + offset); SizeOfUS = BitConverter.ToUInt16(bytes, 0x06 + offset); LogFileSequenceNumber = BitConverter.ToUInt64(bytes, 0x08 + offset); SequenceNumber = BitConverter.ToUInt16(bytes, 0x10 + offset); Hardlinks = BitConverter.ToUInt16(bytes, 0x12 + offset); OffsetOfAttribute = BitConverter.ToUInt16(bytes, 0x14 + offset); Flags = (FILE_RECORD_FLAG)BitConverter.ToUInt16(bytes, 0x16 + offset); Deleted = isDeleted(Flags); Directory = isDirectory(Flags); RealSize = BitConverter.ToInt32(bytes, 0x18 + offset); AllocatedSize = BitConverter.ToInt32(bytes, 0x1C + offset); ReferenceToBase = BitConverter.ToUInt64(bytes, 0x20 + offset); NextAttrId = BitConverter.ToUInt16(bytes, 0x28 + offset); RecordNumber = BitConverter.ToUInt32(bytes, 0x2C + offset); Attribute = FileRecordAttribute.GetInstances(bytes, OffsetOfAttribute + offset, bytesPerFileRecord, volume); #region AttributeProperties foreach (FileRecordAttribute attr in Attribute) { if (attr.Name == FileRecordAttribute.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 == FileRecordAttribute.ATTR_TYPE.ATTRIBUTE_LIST) { if (!(Deleted)) { AttributeList attrList = null; List <FileRecordAttribute> list = new List <FileRecordAttribute>(); list.AddRange(Attribute); if (attr.NonResident) { attrList = new AttributeList(attr as NonResident); } else { attrList = attr as AttributeList; } foreach (AttrRef attribute in attrList.AttributeReference) { if (attribute.RecordNumber != RecordNumber) { FileRecord record = null; // Test if we have already parse the record if (recordArray[attribute.RecordNumber] != null) { record = recordArray[attribute.RecordNumber]; } else { // If not parse it and add it to the array record = new FileRecord(ref recordArray, bytes, bytesPerFileRecord * (int)attribute.RecordNumber, bytesPerFileRecord, volume, fast); recordArray[attribute.RecordNumber] = record; } // Add the attributes to the attribute array list.AddRange(record.Attribute); list.Remove(attr); } } Attribute = list.ToArray(); } } else if (attr.Name == FileRecordAttribute.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; } } } #endregion AttributeProperties #region FullName if (fast) { FullName = Name; } else { StringBuilder sb = new StringBuilder(); string volLetter = Helper.GetVolumeLetter(volume); if (RecordNumber == 0) { sb.Append(volLetter); sb.Append('\\'); sb.Append(Name); FullName = sb.ToString(); } else if (RecordNumber == 5) { FullName = volLetter; } else { FileRecord parent = null; if (recordArray[this.ParentRecordNumber] != null) { parent = recordArray[this.ParentRecordNumber]; } else { parent = new FileRecord(ref recordArray, bytes, bytesPerFileRecord * (int)this.ParentRecordNumber, bytesPerFileRecord, volume, fast); recordArray[this.ParentRecordNumber] = parent; } 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 } }
public static ForensicTimeline[] Get(FileRecord input) { List<ForensicTimeline> macs = new List<ForensicTimeline>(); if (input.SequenceNumber != 0) { #region DetermineTime Dictionary<DateTime, ACTIVITY_TYPE> dictionary = new Dictionary<DateTime, ACTIVITY_TYPE>(); // Modified Time dictionary[input.ModifiedTime] = ACTIVITY_TYPE.m; // Access Time if (dictionary.ContainsKey(input.AccessedTime)) { dictionary[input.AccessedTime] = dictionary[input.AccessedTime] | ACTIVITY_TYPE.a; } else { dictionary.Add(input.AccessedTime, ACTIVITY_TYPE.a); } // MFT Changed Time if (dictionary.ContainsKey(input.ChangedTime)) { dictionary[input.ChangedTime] = dictionary[input.ChangedTime] | ACTIVITY_TYPE.c; } else { dictionary.Add(input.ChangedTime, ACTIVITY_TYPE.c); } // Born Time if (dictionary.ContainsKey(input.BornTime)) { dictionary[input.BornTime] = dictionary[input.BornTime] | ACTIVITY_TYPE.b; } else { dictionary.Add(input.BornTime, ACTIVITY_TYPE.b); } #endregion DetermineTime foreach (var time in dictionary) { string activity = ToFriendlyString(time.Value); macs.Add(new ForensicTimeline(time.Key, activity, "MFT", "", input.FullName, input.ToString())); } return macs.ToArray(); } else { macs.Add(new ForensicTimeline(new DateTime(1), "MACB", "MFT", "", "", "")); return macs.ToArray(); } }
// Get Constructor private FileRecord(byte[] recordBytes, string volume, int bytesPerFileRecord, bool fast) { if (Encoding.ASCII.GetString(recordBytes, 0x00, 0x04) == "FILE") { VolumePath = volume; OffsetOfUS = BitConverter.ToUInt16(recordBytes, 0x04); SizeOfUS = BitConverter.ToUInt16(recordBytes, 0x06); LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 0x08); SequenceNumber = BitConverter.ToUInt16(recordBytes, 0x10); Hardlinks = BitConverter.ToUInt16(recordBytes, 0x12); OffsetOfAttribute = BitConverter.ToUInt16(recordBytes, 0x14); Flags = (FILE_RECORD_FLAG)BitConverter.ToUInt16(recordBytes, 0x16); Deleted = isDeleted(Flags); Directory = isDirectory(Flags); RealSize = BitConverter.ToInt32(recordBytes, 0x18); AllocatedSize = BitConverter.ToInt32(recordBytes, 0x1C); ReferenceToBase = BitConverter.ToUInt64(recordBytes, 0x20); NextAttrId = BitConverter.ToUInt16(recordBytes, 40); RecordNumber = BitConverter.ToUInt32(recordBytes, 44); Attribute = FileRecordAttribute.GetInstances(recordBytes, OffsetOfAttribute, bytesPerFileRecord, volume); #region AttributeProperties foreach (FileRecordAttribute attr in Attribute) { if (attr.Name == FileRecordAttribute.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 == FileRecordAttribute.ATTR_TYPE.ATTRIBUTE_LIST) { if (!(Deleted)) { AttributeList attrList = null; List <FileRecordAttribute> list = new List <FileRecordAttribute>(); list.AddRange(Attribute); if (attr.NonResident) { attrList = new AttributeList(attr as NonResident); } else { attrList = attr as AttributeList; } foreach (AttrRef attribute in attrList.AttributeReference) { if (attribute.RecordNumber != RecordNumber) { FileRecord record = FileRecord.Get(volume, (int)attribute.RecordNumber); list.AddRange(record.Attribute); list.Remove(attr); } } Attribute = list.ToArray(); } } else if (attr.Name == FileRecordAttribute.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; } } } #endregion AttributeProperties #region FullName if (fast) { FullName = Name; } else { StringBuilder sb = new StringBuilder(); string volLetter = Helper.GetVolumeLetter(volume); if (RecordNumber == 0) { sb.Append(volLetter); sb.Append('\\'); sb.Append(Name); FullName = sb.ToString(); } else if (RecordNumber == 5) { FullName = volLetter; } else { FileRecord parent = new FileRecord(GetRecordBytes(volume, (int)ParentRecordNumber), volume, bytesPerFileRecord, false); 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 ShellLink(byte[] bytes, FileRecord record) { Path = record.FullName; HeaderSize = BitConverter.ToInt32(bytes, 0x00); if (HeaderSize == 0x4C) { #region SHELL_LINK_HEADER LinkCLSID = new Guid(NativeMethods.GetSubArray(bytes, 0x04, 0x10)); LinkFlags = (LINK_FLAGS)BitConverter.ToUInt32(bytes, 0x14); FileAttributes = (FILEATTRIBUTE_FLAGS)BitConverter.ToUInt32(bytes, 0x18); CreationTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0x1C)); AccessTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0x24)); WriteTime = DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0x2C)); FileSize = BitConverter.ToUInt32(bytes, 0x34); IconIndex = BitConverter.ToInt32(bytes, 0x38); ShowCommand = (SHOWCOMMAND)BitConverter.ToUInt32(bytes, 0x3C); #region HotKey HotKey = new HOTKEY_FLAGS[2]; HotKey[0] = (HOTKEY_FLAGS)bytes[0x40]; HotKey[1] = (HOTKEY_FLAGS)bytes[0x41]; #endregion HotKey int offset = 0x4C; #endregion SHELL_LINK_HEADER // I want to remove one layer of objects #region LINKTARGET_IDLIST if ((LinkFlags & LINK_FLAGS.HasLinkTargetIdList) == LINK_FLAGS.HasLinkTargetIdList) { IdListSize = BitConverter.ToUInt16(bytes, offset); IdList = new IdList(bytes, offset + 0x02, IdListSize); offset += IdListSize + 0x02; } #endregion LINKTARGET_IDLIST #region LINKINFO if ((LinkFlags & LINK_FLAGS.HasLinkInfo) == LINK_FLAGS.HasLinkInfo) { LinkInfoSize = BitConverter.ToUInt32(bytes, offset); LinkInfoHeaderSize = BitConverter.ToUInt32(bytes, offset + 0x04); LinkInfoFlags = (LINKINFO_FLAGS)BitConverter.ToUInt32(bytes, offset + 0x08); if ((LinkInfoFlags & LINKINFO_FLAGS.VolumeIDAndLocalBasePath) == LINKINFO_FLAGS.VolumeIDAndLocalBasePath) { VolumeIdOffset = BitConverter.ToUInt32(bytes, offset + 0x0C); VolumeId = new VolumeId(bytes, offset + (int)VolumeIdOffset); LocalBasePathOffset = BitConverter.ToUInt32(bytes, offset + 0x10); LocalBasePath = Encoding.Default.GetString(bytes, offset + (int)LocalBasePathOffset, (int)LinkInfoSize - (int)LocalBasePathOffset).Split('\0')[0]; } if ((LinkInfoFlags & LINKINFO_FLAGS.CommonNetworkRelativeLinkAndPathSuffix) == LINKINFO_FLAGS.CommonNetworkRelativeLinkAndPathSuffix) { CommonNetworkRelativeLinkOffset = BitConverter.ToUInt32(bytes, offset + 0x14); CommonNetworkRelativeLink = new CommonNetworkRelativeLink(bytes, offset + (int)CommonNetworkRelativeLinkOffset); CommonPathSuffixOffset = BitConverter.ToUInt32(bytes, offset + 0x18); CommonPathSuffix = Encoding.Default.GetString(bytes, offset + (int)CommonPathSuffixOffset, (int)LinkInfoSize - (int)CommonPathSuffixOffset).Split('\0')[0]; } if (LinkInfoHeaderSize >= 0x24) { LocalBasePathOffsetUnicode = BitConverter.ToUInt32(bytes, offset + 0x1C); LocalBasePathUnicode = Encoding.Unicode.GetString(bytes, offset + (int)LocalBasePathOffsetUnicode, (int)LinkInfoSize - (int)LocalBasePathOffsetUnicode).Split('\0')[0]; CommonPathSuffixOffsetUnicode = BitConverter.ToUInt32(bytes, offset + 0x20); CommonPathSuffixUnicode = Encoding.Unicode.GetString(bytes, offset + (int)CommonPathSuffixOffsetUnicode, (int)LinkInfoSize - (int)CommonPathSuffixOffsetUnicode).Split('\0')[0]; } offset += (int)LinkInfoSize; } #endregion LINKINFO #region STRING_DATA if ((LinkFlags & LINK_FLAGS.HasName) == LINK_FLAGS.HasName) { NameSize = BitConverter.ToUInt16(bytes, offset); Name = Encoding.Unicode.GetString(bytes, offset + 0x02, NameSize * 2); offset += 2 + (NameSize * 2); } if ((LinkFlags & LINK_FLAGS.HasRelativePath) == LINK_FLAGS.HasRelativePath) { RelativePathSize = BitConverter.ToUInt16(bytes, offset); RelativePath = Encoding.Unicode.GetString(bytes, offset + 0x02, RelativePathSize * 2); offset += 2 + (RelativePathSize * 2); } if ((LinkFlags & LINK_FLAGS.HasWorkingDir) == LINK_FLAGS.HasWorkingDir) { WorkingDirectorySize = BitConverter.ToUInt16(bytes, offset); WorkingDirectory = Encoding.Unicode.GetString(bytes, offset + 0x02, WorkingDirectorySize * 2); offset += 2 + (WorkingDirectorySize * 2); } if ((LinkFlags & LINK_FLAGS.HasArguments) == LINK_FLAGS.HasArguments) { CommandLineArgumentsSize = BitConverter.ToUInt16(bytes, offset); CommandLineArguments = Encoding.Unicode.GetString(bytes, offset + 0x02, CommandLineArgumentsSize * 2); offset += 2 + (CommandLineArgumentsSize * 2); } if ((LinkFlags & LINK_FLAGS.HasIconLocation) == LINK_FLAGS.HasIconLocation) { IconLocationSize = BitConverter.ToUInt16(bytes, offset); IconLocation = Encoding.Unicode.GetString(bytes, offset + 0x02, IconLocationSize * 2); offset += 2 + (IconLocationSize * 2); } #endregion STRING_DATA #region EXTRA_DATA List<ExtraData> edList = new List<ExtraData>(); int datalength = 0; do { datalength = BitConverter.ToInt32(bytes, offset); switch (BitConverter.ToUInt32(bytes, offset + 0x04)) { case 0xA0000001: edList.Add(new EnvironmentVariableDataBlock(bytes, offset)); break; case 0xA0000002: edList.Add(new ConsoleDataBlock(bytes, offset)); break; case 0xA0000003: edList.Add(new TrackerDataBlock(bytes, offset)); break; case 0xA0000004: edList.Add(new ConsoleFeDataBlock(bytes, offset)); break; case 0xA0000005: edList.Add(new SpecialFolderDataBlock(bytes, offset)); break; case 0xA0000006: edList.Add(new DarwinDataBlock(bytes, offset)); break; case 0xA0000007: edList.Add(new IconEnvironmentDataBlock(bytes, offset)); break; case 0xA0000008: edList.Add(new ShimDataBlock(bytes, offset)); break; case 0xA0000009: edList.Add(new PropertyStoreDataBlock(bytes, offset)); break; case 0xA000000B: edList.Add(new KnownFolderDataBlock(bytes, offset)); break; case 0xA000000C: edList.Add(new VistaAndAboveIDListDataBlock(bytes, offset)); break; } offset += datalength; } while (offset < bytes.Length - 0x04); ExtraData = edList.ToArray(); #endregion EXTRA_DATA } else { throw new Exception("Invalid ShellLink Header."); } }
public static byte[] GetContentBytes(string path, string streamName) { FileRecord record = Get(path, true); return(record.GetTestContent(streamName)); }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <returns></returns> public static AttrDef[] GetInstancesByPath(string path) { FileRecord record = FileRecord.Get(path, true); return(AttrDef.GetInstances(record.GetContent())); }
public byte[] GetMftSlack() { byte[] bytes = FileRecord.GetRecordBytes(this.VolumePath, (int)this.RecordNumber); return(Helper.GetSubArray(bytes, (int)this.RealSize - 1, (int)this.AllocatedSize - (int)this.RealSize)); }
internal static FileRecord GetFileRecord(string volume) { return(FileRecord.Get(volume, MftIndex.LOGFILE_INDEX, true)); }
private FileRecord(byte[] recordBytes, string volume, int bytesPerFileRecord, bool fast) { if (Encoding.ASCII.GetString(recordBytes, 0x00, 0x04) == "FILE") { VolumePath = volume; OffsetOfUS = BitConverter.ToUInt16(recordBytes, 0x04); SizeOfUS = BitConverter.ToUInt16(recordBytes, 0x06); LogFileSequenceNumber = BitConverter.ToUInt64(recordBytes, 0x08); SequenceNumber = BitConverter.ToUInt16(recordBytes, 0x10); Hardlinks = BitConverter.ToUInt16(recordBytes, 0x12); OffsetOfAttribute = BitConverter.ToUInt16(recordBytes, 0x14); Flags = (FILE_RECORD_FLAG)BitConverter.ToUInt16(recordBytes, 0x16); Deleted = isDeleted(Flags); Directory = isDirectory(Flags); RealSize = BitConverter.ToInt32(recordBytes, 0x18); AllocatedSize = BitConverter.ToInt32(recordBytes, 0x1C); ReferenceToBase = BitConverter.ToUInt64(recordBytes, 0x20); NextAttrId = BitConverter.ToUInt16(recordBytes, 40); RecordNumber = BitConverter.ToUInt32(recordBytes, 44); Attribute = FileRecordAttribute.GetInstances(recordBytes, OffsetOfAttribute, bytesPerFileRecord, volume); #region AttributeProperties //bool hasAttributeList = false; //List<FileRecordAttribute> ListOfAttributes = new List<FileRecordAttribute>(); foreach (FileRecordAttribute attr in Attribute) { if (attr.Name == FileRecordAttribute.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 == FileRecordAttribute.ATTR_TYPE.ATTRIBUTE_LIST) { if (!(attr.NonResident)) { AttributeList attributeList = attr as AttributeList; hasAttributeList = true; List<ulong> numList = new List<ulong>(); foreach (AttrRef attrRef in attributeList.AttributeReference) { if (!(numList.Contains(attrRef.RecordNumber))) { numList.Add(attrRef.RecordNumber); } } foreach (ulong i in numList) { if (recordArray[i] == null) { recordArray[i] = new FileRecordTest(ref recordArray, bytes, bytesPerFileRecord * (int)i, bytesPerFileRecord, volume, false); } ListOfAttributes.AddRange(recordArray[i].Attribute); } } }*/ else if (attr.Name == FileRecordAttribute.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; } } } #endregion AttributeProperties #region FullName if (fast) { FullName = Name; } else { StringBuilder sb = new StringBuilder(); string volLetter = Helper.GetVolumeLetter(volume); if (RecordNumber == 0) { sb.Append(volLetter); sb.Append('\\'); sb.Append(Name); FullName = sb.ToString(); } else if (RecordNumber == 5) { FullName = volLetter; } else { FileRecord parent = new FileRecord(GetRecordBytes(volume, (int)ParentRecordNumber), volume, bytesPerFileRecord, false); 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 static FileRecord[] GetInstances(byte[] bytes, string volume, bool fast) { VolumeBootRecord vbr = VolumeBootRecord.Get(volume); // Determine the size of an MFT File Record int bytesPerFileRecord = (int)vbr.BytesPerFileRecord; // Calulate the number of entries in the MFT int fileCount = bytes.Length / bytesPerFileRecord; // Instantiate an array of FileRecord objects FileRecord[] recordArray = new FileRecord[fileCount]; // Apply fixup values across MFT Bytes ApplyFixup(ref bytes, (int)vbr.BytesPerFileRecord); // Now we need to iterate through all possible index values for (int index = 0x00; index < fileCount; index++) { // Check if current record has been instantiated if (recordArray[index] == null) { // Instantiate FileRecord object recordArray[index] = new FileRecord(ref recordArray, bytes, index * bytesPerFileRecord, bytesPerFileRecord, volume, fast); } } return recordArray; }
internal static FileRecord GetFileRecord(string volume) { return(FileRecord.Get(volume, BADCLUS_INDEX, true)); }
public static VolumeName Get(string volume) { FileRecord record = FileRecord.Get(volume, MftIndex.VOLUME_INDEX, true); return(Get(record)); }
public static VolumeInformation GetVolumeInformationByPath(string path) { FileRecord record = FileRecord.Get(path, true); return(GetVolumeInformation(record)); }
public static IndexEntry[] GetInstances(string path) { string[] paths = path.TrimEnd('\\').Split('\\'); // Determine Volume Name string volume = Util.GetVolumeFromPath(path); // Test volume path Util.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, true); 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); 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 static VolumeName GetByPath(string path) { FileRecord record = FileRecord.Get(path, true); return(Get(record)); }
private static FileRecord[] GetInstancesTest(byte[] bytes, string volume) { // Determine the size of an MFT File Record int bytesPerFileRecord = (int)(VolumeBootRecord.Get(volume)).BytesPerFileRecord; // Calulate the number of entries in the MFT int fileCount = bytes.Length / bytesPerFileRecord; // Instantiate an array of FileRecord objects FileRecord[] recordArray = new FileRecord[fileCount]; // 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) { int offset = index * bytesPerFileRecord; // Take UpdateSequence into account ApplyFixupTest(ref bytes, offset); // Instantiate FileRecord object recordArray[index] = new FileRecord(ref recordArray, bytes, offset, volume, (uint)bytesPerFileRecord); } } return recordArray; }
private FileRecord(ref FileRecord[] array, byte[] bytes, int offset, string volume, uint bytesPerFileRecord) { Signature = Encoding.ASCII.GetString(bytes, 0x00 + offset, 0x04); if (Signature == "FILE") { OffsetOfUS = BitConverter.ToUInt16(bytes, 0x04 + offset); SizeOfUS = BitConverter.ToUInt16(bytes, 0x06 + offset); LogFileSequenceNumber = BitConverter.ToUInt64(bytes, 0x08 + offset); SequenceNumber = BitConverter.ToUInt16(bytes, 0x10 + offset); Hardlinks = BitConverter.ToUInt16(bytes, 0x12 + offset); OffsetOfAttribute = BitConverter.ToUInt16(bytes, 0x14 + offset); Flags = BitConverter.ToUInt16(bytes, 0x16 + offset); Deleted = IsDeleted(Flags); Directory = IsDirectory(Flags); RealSize = BitConverter.ToUInt32(bytes, 0x18 + offset); AllocatedSize = BitConverter.ToUInt32(bytes, 0x1C + offset); ReferenceToBase = BitConverter.ToUInt64(bytes, 0x20 + offset); NextAttrId = BitConverter.ToUInt16(bytes, 0x28 + offset); RecordNumber = BitConverter.ToUInt32(bytes, 0x2C + offset); #region Attribute // Instantiate an empty list of Attr Objects (We don't know how many attributes the record contains) List<FileRecordAttribute> AttributeList = new List<FileRecordAttribute>(); int currentOffset = offset + OffsetOfAttribute; do { FileRecordAttribute attr = FileRecordAttribute.GetTest(bytes, currentOffset, volume); if (attr != null) { if (attr.Name == FileRecordAttribute.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 == FileRecordAttribute.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); } // Get attribute size int attrSizeOffset = currentOffset + 0x04; int attrSize = BitConverter.ToInt32(bytes, attrSizeOffset); if (attrSize == 0) { break; } // Increment currentOffset currentOffset += attrSize; } while ((currentOffset - offset) < bytesPerFileRecord); Attribute = AttributeList.ToArray(); #endregion Attribute /*#region FullName StringBuilder sb = new StringBuilder(); // Record 5 is the root of the drive if (RecordNumber == 5) { sb.Append(Helper.GetVolumeLetter(volume)); } else { // Derive Path by looking at ParentRecord's FullName if (array[(int)ParentRecordNumber] != null) { if (ParentSequenceNumber == array[(int)ParentRecordNumber].SequenceNumber) { sb.Append(array[(int)ParentRecordNumber].FullName); } else { sb.Append(@"$OrphanFiles\"); } } // If record for Parent does not already exist then instantiate it and add it to the array else { int parentOffset = (int)bytesPerFileRecord * (int)ParentRecordNumber; array[(int)ParentRecordNumber] = new FileRecord(ref array, bytes, parentOffset, volume, bytesPerFileRecord); if (ParentSequenceNumber == array[(int)ParentRecordNumber].SequenceNumber) { sb.Append(array[(int)ParentRecordNumber].FullName); } else { sb.Append(@"$OrphanFiles\"); } } // 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*/ } }
internal static NonResident GetJStream(FileRecord fileRecord) { foreach (Attr attr in fileRecord.Attribute) { if (attr.NameString == "$J") { return attr as NonResident; } AttributeList attrList = attr as AttributeList; if (attrList != null) { foreach (AttrRef ar in attrList.AttributeReference) { if (ar.NameString == "$J") { FileRecord record = new FileRecord(FileRecord.GetRecordBytes(fileRecord.VolumePath, (int)ar.RecordNumber), fileRecord.VolumePath, true); return GetJStream(record); } } } } throw new Exception("No $J attribute found."); }
private FileRecord(ref FileRecord[] array, byte[] mftBytes, byte[] recordBytes, int bytesPerFileRecord, 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); UpdateSequenceNumber = BitConverter.ToUInt16(recordBytes, OffsetOfUS); #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]; ApplyFixup(ref recordBytes); 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) { if (ParentSequenceNumber == array[(int)ParentRecordNumber].SequenceNumber) { sb.Append(array[(int)ParentRecordNumber].FullName); } else { sb.Append(@"$OrphanFiles\"); } } // If record for Parent does not already exist then instantiate it and add it to the array else { byte[] parentBytes = NativeMethods.GetSubArray(mftBytes, (uint)bytesPerFileRecord * (uint)ParentRecordNumber, (uint)bytesPerFileRecord); array[(int)ParentRecordNumber] = new FileRecord(ref array, mftBytes, parentBytes, bytesPerFileRecord, volume); if (ParentSequenceNumber == array[(int)ParentRecordNumber].SequenceNumber) { sb.Append(array[(int)ParentRecordNumber].FullName); } else { sb.Append(@"$OrphanFiles\"); } } // 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 } }
private FileRecord(ref FileRecord[] array, byte[] mftBytes, byte[] recordBytes, int bytesPerFileRecord, 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); UpdateSequenceNumber = BitConverter.ToUInt16(recordBytes, OffsetOfUS); #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]; ApplyFixup(ref recordBytes); 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) { if (ParentSequenceNumber == array[(int)ParentRecordNumber].SequenceNumber) { sb.Append(array[(int)ParentRecordNumber].FullName); } else { sb.Append(@"$OrphanFiles\"); } } // If record for Parent does not already exist then instantiate it and add it to the array else { byte[] parentBytes = Util.GetSubArray(mftBytes, (uint)bytesPerFileRecord * (uint)ParentRecordNumber, (uint)bytesPerFileRecord); array[(int)ParentRecordNumber] = new FileRecord(ref array, mftBytes, parentBytes, bytesPerFileRecord, volume); if (ParentSequenceNumber == array[(int)ParentRecordNumber].SequenceNumber) { sb.Append(array[(int)ParentRecordNumber].FullName); } else { sb.Append(@"$OrphanFiles\"); } } // 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 static FileRecord Get(string volume, int index, bool fast) { return(new FileRecord(FileRecord.GetRecordBytes(volume, index), volume, fast)); }
public static FileRecord[] GetInstancesByPath(string path) { string volume = Util.GetVolumeFromPath(path); FileRecord record = new FileRecord(FileRecord.GetRecordBytes(path), volume, true); byte[] mftBytes = record.GetContent(); return GetInstances(mftBytes, volume); }
internal FileRecord(byte[] recordBytes, string volume, bool fast) { 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); UpdateSequenceNumber = BitConverter.ToUInt16(recordBytes, OffsetOfUS); #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 if (fast) { FullName = Name; } else { 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, false); 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 byte[] GetContent(VolumeBootRecord VBR) { foreach (Attr attr in this.Attribute) { if (attr.Name == Attr.ATTR_TYPE.DATA) { if (attr.NonResident) { return (attr as NonResident).GetBytes(this.VolumePath, VBR); } 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, true); return record.GetContent(); } } } } throw new Exception("Could not locate file contents"); }
public FileRecord GetParent() { return(FileRecord.Get(this.VolumePath, (int)this.ParentRecordNumber, false)); }
internal FileRecord(byte[] recordBytes, string volume, bool fast) { 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); UpdateSequenceNumber = BitConverter.ToUInt16(recordBytes, OffsetOfUS); #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 if (fast) { FullName = Name; } else { 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, false); 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 } }
public static AttrDef[] GetInstances(string volume) { FileRecord record = FileRecord.Get(volume, ATTRDEF_INDEX, true); return(AttrDef.GetInstances(record.GetContent())); }