Initial remote commit
This commit is contained in:
70
misc_tools/search_var.py
Normal file
70
misc_tools/search_var.py
Normal file
@@ -0,0 +1,70 @@
|
||||
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('<I', block, off)[0]
|
||||
rec_len = struct.unpack_from('<H', block, off+4)[0]
|
||||
name_len= block[off+6]
|
||||
ftype = block[off+7]
|
||||
if rec_len < 8: break
|
||||
if (10 < ino < 500_000_000 and
|
||||
0 < name_len <= rec_len-8 and
|
||||
ftype in (1,2,7) and
|
||||
rec_len % 4 == 0):
|
||||
name = block[off+8:off+8+name_len].decode('utf-8',errors='replace')
|
||||
if name.isprintable():
|
||||
entries.append((ino,name,ftype))
|
||||
off += rec_len
|
||||
|
||||
if len(entries) >= 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)
|
||||
Reference in New Issue
Block a user