The task’s description points at data recovery from a broken RAID array:
“One of my drives failed”
Reusing All of Internal Disks
The ZIP contains 3 disk images, the 2nd of which is faulty:
512M 1.img 0B 2.img 512M 3.img
3.img are different, ruling out a (completely trivial) RAID 1.
By far, the most common 3-drive configuration that allows for recovery (in case a single drive fails) is RAID 5. Let’s go with that.
Once you acquaint yourself with RAID 5 (you may wish to do so now), array reconstruction is fairly simple to implement. The hard part is detecting the array’s block size & drive order (as that affects the parity schedule) – but all it takes for this task is a few educated guesses and a modicum of luck.
import numpy as np def xor_blocks(lhs, rhs): assert len(lhs) == len(rhs) lhs = np.frombuffer(lhs, dtype=np.uint8) rhs = np.frombuffer(rhs, dtype=np.uint8) return (lhs ^ rhs).tostring() drives = ( open("1.img"), # Drive 0 - OK open("2.img"), # Drive 1 - Faulty open("3.img") # Drive 2 - OK ) extracted = open("recovered.img", 'w') parity_drive = 2 # The first stripe stores parity information on this drive. Rotates with every iteration. block_size = 64 * 1024 # An educated guess. It's possible that other sizes would work well enough for flag recovery. # Each iteration recovers a stripe while True: drive_blocks = [d.read(block_size) for d in drives] if len(drive_blocks) == 0: print "Done" exit() if parity_drive == 0: # 0 | Parity - Valid # 1 | Block1 - Missing # 2 | Block2 - Valid extracted.write(xor_blocks(drive_blocks, drive_blocks)) extracted.write(drive_blocks) elif parity_drive == 1: # 0 | Block1 - Valid # 1 | Parity - Missing # 2 | Block2 - Valid extracted.write(drive_blocks) extracted.write(drive_blocks) elif parity_drive == 2: # 0 | Block1 - Valid # 1 | Block2 - Missing # 2 | Parity - Valid extracted.write(drive_blocks) extracted.write(xor_blocks(drive_blocks, drive_blocks)) # Set the next stripe's parity drive (2, 0, 1, 2, 0, 1, 2, 0, 1, .....) parity_drive = (parity_drive + 1) % len(drives)
We tried booting from
recovered.img (Using VirtualBox &
VBoxManage convertfromraw to create a VDI) — as 1.img contains a proper MBR — but that failed spectacularly 🙁
Next, we ran PhotoRec on the recovered drive. It emitted a bunch of (useless) text files and a single JPG:
And that’s all there was to it!
(That’s literally the flag’s text in the picture – no conversion of any sort was required)