/* * parseLongFilename - Parses long file name of one or more entries with FileStream and first entry bytes */ private string parseLongFilename(byte[] data, BufferedDiskReader disk) { string result = ""; //Parse first entry bytes LongFilenameEntry entry = new LongFilenameEntry(data); //Add to result result += entry.FilenamePart; //Sequence number is first entry's sequence number XOR 0x40 int sequenceNumber = entry.SequenceNumber ^ 0x40; //Iterate over following entries for (int i = 0; i < sequenceNumber - 1; i++) { //Read next entry disk.Read(data, 0, data.Length); //Parse entry bytes entry = new LongFilenameEntry(data); //Add to result - they are in reverse order result = entry.FilenamePart + result; } return(result); }
/* * ParseDirectoryEntries - Seeks disk to Directory Table start then begins recursive creation * */ public void ParseDirectoryEntries(BufferedDiskReader disk) { disk.SeekAbsolute((ulong)this.clusterBeginLBA * BootSector.BPB.BytesPerSector); int error = Marshal.GetLastWin32Error(); byte[] data = new byte[32]; disk.Read(data, 0, data.Length); rootDirectory = new DirectoryEntry(data, disk, this); if (!rootDirectory.IsVolumeID) { DirectoryEntry entry = rootDirectory; rootDirectory = new DirectoryEntry(); rootDirectory.Children.Add(entry); disk.Read(data, 0, data.Length); entry = new DirectoryEntry(data, disk, this); while (entry.Type != DirectoryEntryType.EndOfDirectory) { if (entry.Type != DirectoryEntryType.Unused) { rootDirectory.Children.Add(entry); } disk.Read(data, 0, data.Length); entry = new DirectoryEntry(data, disk, this); } } }
public byte[] OpenFile(BufferedDiskReader disk, DirectoryEntry file) { if (file.IsDirectory) { return(null); } if (FAT == null) { ReadFAT(disk); } byte[] data = ReadCluster(disk, file.FirstCluster); uint nextCluster = ReadNextFAT(file.FirstCluster); uint clusterCount = 1; while (nextCluster < 0x0FFFFFF8) { clusterCount++; byte[] temp = ReadCluster(disk, nextCluster); byte[] tempData = data; data = new byte[clusterCount * temp.Length]; Array.Copy(tempData, 0, data, 0, tempData.Length); Array.Copy(temp, 0, data, tempData.Length, temp.Length); nextCluster = ReadNextFAT(nextCluster); } return(data); }
/* * parseDirectoryTree - Start directory tree parsing from physical disk * Return - Enumerates partition's rootDirectory structure */ private void parseDirectoryTree(Partition partition) { //Create handle //SafeFileHandle handle = Exports.CreateFile(partition.Hdd.DeviceId, // (uint)FileAccess.Read, // (uint)FileShare.None, // IntPtr.Zero, // (uint)FileMode.Open, // Exports.FILE_FLAG_NO_BUFFERING, // IntPtr.Zero); BufferedDiskReader disk = new BufferedDiskReader(partition.Hdd.DeviceId); if (disk.IsInvalid) { MessageBox.Show(String.Format("Error Opening Partition ")); return; } //Wrap handle in extended FileStream //PreciseFileStream disk = new PreciseFileStream(handle, FileAccess.Read); //Hand off FileStream to workhorse partition.ParseDirectoryEntries(disk); //Don't forget to close disk.Close(); }
public void enumerateFATDevices() { disks = new List <HardDrive>(); ManagementObjectSearcher search = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive"); //Iterate over each search result - list of HD's from WMI foreach (ManagementObject wmi_HD in search.Get()) { HardDrive hdd = new HardDrive(); hdd.Model = wmi_HD["Model"].ToString(); hdd.Type = wmi_HD["InterfaceType"] == null ? "" : wmi_HD["InterfaceType"].ToString(); hdd.DeviceId = wmi_HD["DeviceId"].ToString(); BufferedDiskReader disk = new BufferedDiskReader(hdd.DeviceId); //Occurs when in use or insufficient privileges if (disk.IsInvalid) { int error = Marshal.GetLastWin32Error(); MessageBox.Show(this, "Please verify you have Administrator Privileges and disks are not in use.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); continue; } //HDD is valid, add to our list disks.Add(hdd); //Sector buffer byte[] data = new byte[512]; //Fill Buffer disk.Read(data, 0, 512); //Deserialize data into MasterBootRecord hdd.MBR = new MasterBootRecord(data); //Iterate over partitions in MBR foreach (PartitionTableEntry entry in hdd.MBR.PartitionTable.Partitions) { //Clear data buffer data = new byte[512]; //Seek to Partition start (FAT32 boot sector, location given in Partition table entry in Sectors) disk.SeekAbsolute((ulong)entry.LBA_Begin1 * BYTES_PER_SECTOR); //Read FAT32 BootSector - Volume Info disk.Read(data, 0, data.Length); //Deserialize data into Partition object hdd.Partitions.Add(new Partition(data, hdd, entry)); } //Got to remember to close the disk disk.Close(); } }
/* * ReadFAT - Read FAT table 1 into memory */ public void ReadFAT(BufferedDiskReader disk) { byte[] fatBytes = new byte[(bootSector.BPB.SectorsPerFAT32 * bootSector.BPB.BytesPerSector)]; FAT = new uint[fatBytes.Length / 4]; disk.SeekAbsolute((ulong)(bootSector.BPB.BytesPerSector * fatBeginLBA)); disk.Read(fatBytes, 0, fatBytes.Length); for (int i = 0; i < FAT.Length; i++) { FAT[i] = (uint)(fatBytes[i * 4 + 3] << 24 | fatBytes[i * 4 + 2] << 16 | fatBytes[i * 4 + 1] << 8 | fatBytes[i * 4 + 0]); } }
private void treeViewDirectory_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e) { if (e.Node.Tag is DirectoryEntry) { DirectoryEntry entry = e.Node.Tag as DirectoryEntry; if (entry.IsDirectory || entry.IsVolumeID) { return; } Partition partition = (comboBoxPartitions.SelectedItem as ComboBoxItem).Value as Partition; BufferedDiskReader disk = new BufferedDiskReader(partition.Hdd.DeviceId); byte[] fileBytes = partition.OpenFile(disk, entry); disk.Close(); string output = Encoding.UTF8.GetString(fileBytes); Editor editor = new Editor(output); editor.Show(); } }
private byte[] ReadCluster(BufferedDiskReader disk, uint cluster) { byte[] clusterBytes = new byte[(ulong)bootSector.BPB.BytesPerSector * (ulong)bootSector.BPB.SectorsPerCluster]; //Calculate LBA for first cluster uint clusterLBA = (uint)(ClusterBeginLBA + (cluster - 2) * BootSector.BPB.SectorsPerCluster); ulong clusterStartByte = (ulong)bootSector.BPB.BytesPerSector * (ulong)clusterLBA; disk.SeekAbsolute(clusterStartByte); //for (int i = 0; i < bootSector.BPB.SectorsPerCluster; i++) //{ // byte[] data = new byte[bootSector.BPB.BytesPerSector]; // disk.Read(data, 0, data.Length); // Array.Copy(data, 0, clusterBytes, i * bootSector.BPB.BytesPerSector, bootSector.BPB.BytesPerSector); //} disk.Read(clusterBytes, 0, clusterBytes.Length); return(clusterBytes); }
/* * CTOR - Creates current entry data's node then attaches any children, recurses into children directories * **NOTE** Individual values are Little-Endian on disk, except strings **NOTE** */ public DirectoryEntry(byte[] data, BufferedDiskReader disk, Partition partition) { //Attribute byte attributeByte = data[0x0B]; //0xE5 is unused - 0x2E is . or .. (need to figure out how to handle) if (data[0] == 0xE5 || data[0] == 0x2E) { type = DirectoryEntryType.Unused; return; } //0x00 is end of directory entry if (data[0] == 0x00) { type = DirectoryEntryType.EndOfDirectory; return; } //Four least significant bits set means long file name if ((attributeByte & 0x0F) == 0x0F) { //Set type type = DirectoryEntryType.LongFileName; //Type parse long file name longFilename = parseLongFilename(data, disk); //Read next entry after long file name disk.Read(data, 0, data.Length); //Get new attribute byte attributeByte = data[0x0B]; //Normal entry always follows long filename entry type = DirectoryEntryType.Normal; } else { type = DirectoryEntryType.Normal; } //Bit 4 is directory flag isDirectory = (attributeByte & 16) != 0; //Bit 3 alone is VolumeId flag isVolumeID = (attributeByte ^ 8) == 0; //Get short name byte[] shortNameBytes = new byte[11]; Array.Copy(data, 0, shortNameBytes, 0, shortNameBytes.Length); //Convert to string shortFilename = Encoding.ASCII.GetString(shortNameBytes); //First cluster of entry - Little-Endian firstCluster = (uint)(data[0x15] << 24 | data[0x14] << 16 | data[0x1B] << 8 | data[0x1A]); //Calculate LBA for first cluster firstClusterLBA = (uint)(partition.ClusterBeginLBA + (firstCluster - 2) * partition.BootSector.BPB.SectorsPerCluster); //If directory or volume we need to attach children if (isDirectory || isVolumeID) { children = new List <DirectoryEntry>(); //Save old position for recursion ulong oldPos = disk.Position; //If this is directory seek to directory entry location if (isDirectory) { ulong firstClusterAddress = ((ulong)firstClusterLBA * (ulong)partition.BootSector.BPB.BytesPerSector); disk.SeekAbsolute(firstClusterAddress); } //Read next entry disk.Read(data, 0, data.Length); //Recurse on next entry bytes DirectoryEntry entry = new DirectoryEntry(data, disk, partition); //Iterate until end of directory entry is found while (entry.Type != DirectoryEntryType.EndOfDirectory) { //Attach child unless unused if (entry.Type != DirectoryEntryType.Unused) { children.Add(entry); } //Read new bytes disk.Read(data, 0, data.Length); //Recurse on next entry bytes entry = new DirectoryEntry(data, disk, partition); if (entry.ShortFilename != null && entry.ShortFilename.Contains("2014")) { entry = entry; } } //Seek to start Pos since we're going back up a level disk.SeekAbsolute(oldPos); } }