I need someone to please sanity check my manual NTFS recovery process so far because it's lead me to a brick wall.
Background:
- I had a 1TB NTFS external drive (WD Elements) which contained mostly photos.
- Somehow, it's corrupted and appears as a raw disk on Windows.
- It appears on a Linux system in the
/dev/disk/by-path
(andby-id
,by-uuid
etc.) directories and appears as/dev/sdb
. - EaseUS is able to find (nearly?) all of my photos on there with a quick scan (not the heavy lifting deep scan)
- EaseUS finds about 70GB of files (mostly photos).
- I think the NTFS records are corrupted i.e. it's not a mechanical failure.
- I'd like to attempt recovery myself for fun and profit.
- I don't have another drive large enough to make a complete image of the corrupted drive.
I need to parse the NTFS MFT $File records because:
- I'd like to get the original file names and directory structure back.
- If an image is not written in contiguous clusters I won't successfully recover it just by looking for image file signatures.
The plan is:
- Image a portion of the corrupted disk.
- Parse it to identify and read MFT $File records.
- Use the $File records (and specifically the $Data attribute thereof) to determine the data runs of each file.
- Knowing the data runs for a file, I can pick out the bytes of a file from the image I created using
ddrescue
. - Rinse and repeat until I'm done.
Firstly - does that sound like a reasonable plan?
What I've done:
- Found a bunch of $File records
- Parsed one to get the data runs
- Read the raw bytes at the location specified by the data run.
Specifically:
- Used
ddrescue
to image 100GB (starting at 0) of the corrupted disk.- I imagine that nearly all of the actual data I need is written within the first 100GB since the total volume of interesting data is 70GB. I can repeat this whole process over subsequent 100GB portions if necessary.
- The command I used to image the first 100GB was
ddrescue /dev/sdb ~/mydisk.img ~/mydisk.map --size=100G
. ddrescue
did encounter I/O errors and reported that it only recovered about 99.57%.- The start of the image (first 20MB or so) seems empty so this might be the reason for the drive failure. I'm ignoring that for now.
- Read over the 100GB image and located all instances of the ASCII string "FILE" which denotes the start of a $File record in the MFT.
- This has also triggered on false positives such as the word "PROFILE" in the middle of an arbitrary file.
- Therefore I'm only considering results where the distance between one occurrence of "FILE" and the next is <= 1024 bytes since that's the maximum MFT record size. If there's 3MB between one occurrence of "FILE" and the next then it's unlikely to be a $File record.
- Iterate over presumed $File records (size <= 1024 bytes) and extracted $Data attributes.
- Parsed it for data runs (ignoring the discussion about resident vs non-resident attributes which I think I understand but isn't part of my question).
So I went through the above process and selected one of the $File records and identified its data runs. Here's the $Data attribute (header and contents):
80 00 00 00 48 00 00 00 01 00 00 00 00 00 01 00
00 00 00 00 00 00 00 00 FA 03 00 00 00 00 00 00
40 00 00 00 00 00 00 00 00 B0 3F 00 00 00 00 00
F4 AC 3F 00 00 00 00 00 F4 AC 3F 00 00 00 00 00
32 FB 03 ED C8 11 00 00 FF FF FF FF 82 79 47 11
The data run details are the first half of the last row, just before the FF FF FF FF
end of attribute marker:
- length byte:
32
- cluster run number:
FB 03
(little endian) = 1019 clusters in the run - cluster start number:
ED C8 11
= 1165549 is the first cluster of the run - the next
00
indicates that there are no more runs.
Now, considering there are 512 bytes per sector and 128 sectors per cluster, I read (1019 * 128 * 512) bytes from the 100GB image starting at (1165549 * 128 * 512).
Unfortunately that left me with a 66.8MB file of mostly 0x00 although towards the end there was some data. I'm pretty sure I've got something wrong and I just found some data by accident (although I do happen to end on a JPG end-of-file marker (DD F9).
Is my approach to this whole task reasonable and I've just made a small error somewhere?
Or have I misunderstood something fundamental about NTFS and this is completely the wrong idea?