import struct CHUNK = 128*512 LV_START = 5120000*512 BSIZE = 4096 IPG = 8192 def read_virt(virt_byte, length): result = bytearray(length) pos = virt_byte remaining = length with open('/dev/md0','rb') as f: while remaining > 0: group = pos // (5*CHUNK) in_group = pos % (5*CHUNK) chunk_idx = in_group // CHUNK intra = in_group % CHUNK seg_len = min(CHUNK-intra, remaining) dst_off = pos - virt_byte if chunk_idx != 4: phys = LV_START + group*4*CHUNK + chunk_idx*CHUNK + intra f.seek(phys) data = f.read(seg_len) result[dst_off:dst_off+len(data)] = data pos += seg_len remaining -= seg_len return bytes(result) # Cache GDT print('Loading full GDT...') NUM_GROUPS = 35728 gdt_data = read_virt(BSIZE, NUM_GROUPS*64) print(f'GDT loaded: {len(gdt_data)} bytes') def get_inode_table_block(group): entry = gdt_data[group*64:(group+1)*64] it_lo = struct.unpack_from(' 1024: continue for b in range(min(ee_len,8)): blocks.append(start+b) return blocks def list_dir(inode_num): inode_data = read_inode(inode_num) mode = struct.unpack_from(' 0 and name_len > 0: name = blk_data[off+8:off+8+name_len].decode('utf-8',errors='replace') if name not in ('.','..'): entries.append((ino, name, ftype)) off += rec_len return entries # Walk tree from /var print() print('=== /var (inode 1310721) ===') for ino, name, ftype in list_dir(1310721): tname = {1:'file',2:'dir',7:'link'}.get(ftype,'?') print(f' {tname:4s} inode={ino:10d} {name!r}') print() for ino, name, ftype in list_dir(1310721): if name == 'lib': print(f'=== /var/lib (inode {ino}) ===') for i2,n2,f2 in list_dir(ino): tname = {1:'file',2:'dir',7:'link'}.get(f2,'?') print(f' {tname:4s} inode={i2:10d} {n2!r}') for i2,n2,f2 in list_dir(ino): if n2 == 'pterodactyl': print(f'\n=== /var/lib/pterodactyl (inode {i2}) ===') for i3,n3,f3 in list_dir(i2): tname = {1:'file',2:'dir',7:'link'}.get(f3,'?') print(f' {tname:4s} inode={i3:10d} {n3!r}')