import struct CHUNK = 128*512 LV_START = 5120000*512 BSIZE = 4096 # Search for /var directory block by looking for its known contents # /var should contain: lib, log, cache, spool, tmp, www, etc. # inode 1310721 with links=15 means 15 entries # The directory block must contain entry for 'lib' pointing to a valid inode # Let's search all of md0 for a 4KB block containing 'lib' as a dir entry # where the parent context suggests it's /var targets = [b'log', b'cache', b'spool', b'backups', b'mail'] print('Searching for /var directory block...') print('Looking for block containing multiple /var subdirectory names') chunk_size = 32*1024*1024 offset = LV_START # start from filesystem area found_blocks = {} with open('/dev/md0','rb') as f: f.seek(0,2) disk_size = f.tell() f.seek(offset) pos = offset while pos < disk_size: data = f.read(min(chunk_size, disk_size-pos)) if not data: break # Look for blocks containing multiple target strings for blk_off in range(0, len(data)-BSIZE, BSIZE): block = data[blk_off:blk_off+BSIZE] matches = sum(1 for t in targets if t in block) if matches >= 2: abs_byte = pos + blk_off # Verify as directory block entries = [] off = 0 while off < BSIZE-8: ino = struct.unpack_from('= 3: abs_block = (abs_byte - LV_START) // BSIZE print(f'Candidate at md0 byte {abs_byte} ' f'(block {abs_block}):') for ino,name,ftype in entries[:10]: tname={1:\"file\",2:\"dir\",7:\"link\"}.get(ftype,'?') print(f' {tname} inode={ino} {name!r}') print() pos += chunk_size if pos % (10*1024**3) == 0: print(f' Scanned {pos//1024**3}GB...', flush=True)