← Back to Writeups
CUSTOMMediumForensics

Time Capsule

XESXOR9/2/20263 min read
#forensics#custom#medium#ascii_decoding#filesystem_forensics#inode_metadata_extraction#timestamp_analysis#linux

Time Capsule

Platform: tamuctf | Category: Forensics | Type: Challenge | Difficulty: Medium | OS: Linux | Author: XESXOR | Date: 2026-03-22 | Status: Solved Techniques: ascii_decoding, filesystem_forensics, inode_metadata_extraction, timestamp_analysis

Summary

Task: ext4 disk image with 17 image files, flag hidden somewhere. Solution: timestamps encode ASCII via minutes×60+seconds formula, reading files in order spells the flag.

Time Capsule — TAMUctf 2026

Description

My friend Bob found an old drive of his with a bunch of images from his childhood dated back to 2007. You could almost call it a time capsule of sorts. To motivate people to go through the images, he has hidden a flag somewhere. Do you think you could try to find it for me?

Given: time-capsule.tar.gz containing time-capsule.img — a 50MB ext4 filesystem image with 17 image files (memory_1.jpg through memory_17.jpg/png/webp/avif) in /home/bob/nostalgia/. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Goal: Find the hidden flag within the disk image.

Analysis

Initial Reconnaissance

Extracted the tar.gz and identified the file as a Linux ext4 filesystem:

bash
tar -xzf time-capsule.tar.gz
file time-capsule.img
# time-capsule.img: Linux rev 1.0 ext4 filesystem data

Filesystem Analysis with Sleuth Kit

Used fls to recursively list all files:

bash
fls -r time-capsule.img

Found 17 image files in /home/bob/nostalgia/ and 3 deleted/orphan inodes (33, 34, 35) — but these had 0 size with no recoverable data. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Dead Ends Explored

  1. String search — No "gigem" string found anywhere in raw disk image (even searched base64-encoded variants)
  2. EXIF/metadata — No flag hidden in image metadata
  3. PNG analysis — No appended data after IEND chunks
  4. Slack space — No data in slack or unallocated space
  5. Deleted files — Orphan inodes were empty
  6. Steganography — No hidden data in pixel values

Key Insight — Timestamps Encode the Flag

The challenge title "Time Capsule" and the specific mention of "2007" were hints pointing at timestamps. ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Using istat to examine inode metadata revealed that all files had modification timestamps set to 2007-01-01 10:MM:SS — but with different minute:second values:

bash
istat time-capsule.img 17  # memory_1.jpg
# Modify: 2007-01-01 10:01:43

The pattern: minutes × 60 + seconds = ASCII character code

Solution

Extract timestamps from each file's inode and decode:

python
#!/usr/bin/env python3
import subprocess
import re

# File inodes in order (memory_1 through memory_17)
files = [
    (17, "memory_1.jpg"),
    (18, "memory_2.jpg"),
    (19, "memory_3.jpg"),
    (20, "memory_4.jpg"),
    (21, "memory_5.jpg"),
    (22, "memory_6.jpg"),
    (23, "memory_7.jpg"),
    (24, "memory_8.jpg"),
    (25, "memory_9.jpg"),
    (26, "memory_10.jpg"),
    (27, "memory_11.jpg"),
    (28, "memory_12.jpg"),
    (29, "memory_13.jpg"),
    (30, "memory_14.png"),
    (31, "memory_15.webp"),
    (32, "memory_16.avif"),
    (16, "memory_17.jpg"),
]
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

flag = ""
for inode, name in files:
    result = subprocess.run(
        ["istat", "time-capsule.img", str(inode)],
        capture_output=True, text=True
    )
    # Extract modification time (format: 2007-01-01 10:MM:SS)
    match = re.search(r"Modify:\s+\d{4}-\d{2}-\d{2}\s+10:(\d{2}):(\d{2})", result.stdout)
    if match:
        minutes, seconds = int(match.group(1)), int(match.group(2))
        ascii_val = minutes * 60 + seconds
        char = chr(ascii_val)
        flag += char
        print(f"{name}: 10:{minutes:02d}:{seconds:02d} → {minutes}×60+{seconds} = {ascii_val} → '{char}'")
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

print(f"\nFlag: {flag}")

Decoding Table

FileTimestampCalculationASCIIChar
memory_110:01:431×60+43103g
memory_210:01:451×60+45105i
memory_310:01:431×60+43103g
memory_410:01:411×60+41101e
memory_510:01:491×60+49109m
memory_610:02:032×60+3123{
memory_710:01:381×60+3898b
memory_810:02:012×60+1121y
memory_910:01:431×60+43103g
memory_1010:00:480×60+48480
memory_1110:01:501×60+50110n
memory_1210:00:510×60+51513
memory_1310:01:351×60+3595_
memory_1410:00:510×60+51513
memory_1510:01:541×60+54114r
memory_1610:00:520×60+52524
memory_1710:02:052×60+5125}
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍