With 45 minutes left on the clock, I burned 20 of them on offset math.
The challenge was Forensics. One file: disk.img, 350MB, no hints. I ran file on it, saw ext2, and thought — okay, easy mount. Then got smacked with wrong fs type. Instead of stopping to think, I told myself it was just an offset problem and started cycling through sector sizes, running the same command over and over with different numbers.
Classic rabbit hole.
This post is about that. Not how to use mount — there are plenty of those. This is about when to use it, when not to, and what the actual decision point looks like mid-challenge.
Why I Didn’t Mount First — And Then Did
My initial assumption: “just a normal ext4”
The first thing I ran:
file disk.img
disk.img: Linux rev 1.0 ext2 filesystem data, UUID=...
My brain immediately went to: partition table present, ext4, flag is probably somewhere under /home. When you’ve done a few of these, you start moving on autopilot — and autopilot assumes things are structurally normal. That’s the trap.
-o loop failed immediately
sudo mount -o loop disk.img /mnt/target
mount: /mnt/target: wrong fs type, bad option, bad superblock on /dev/loop0,
missing codepage or helper program, or other error.
My first instinct: offset. I grabbed fdisk:
fdisk -l disk.img
Disk disk.img: 350 MiB, 367001600 bytes, 716800 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes Device Boot Start End Sectors Size Id Type disk.img1 2048 716799 714752 349M 83 Linux
Sector size 512, start at 2048, so offset = 2048 × 512 = 1048576. Fine.
sudo mount -o loop,offset=1048576 disk.img /mnt/target
Still failed.
The Rabbit Hole: 20 Minutes of Offset Obsession
This is where I fully dug in.
“Maybe the sector size is actually 4096.” “MBR header offset is different, right?” “What if there are two partitions and I’m calculating from the wrong one?”
# trying a different sector size assumption sudo mount -o loop,offset=1048576,sizelimit=... disk.img /mnt/target # recalculating with 4096 python3 -c "print(2048 * 4096)" # => 8388608 sudo mount -o loop,offset=8388608 disk.img /mnt/target
All of it failed.
Twenty minutes in, I was still searching for the “right” offset — and had never once considered that the partition table itself might be broken. I knew, in theory, that CTF disk images often have intentionally corrupt structures. But in practice I was still operating under the assumption that the image was structurally intact and I just hadn’t found the right numbers yet.
That’s the gap between knowing something and actually internalizing it.
The Turning Point: What binwalk and mmls Actually Showed Me
binwalk said nothing — which was informative
binwalk disk.img
DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------------------------------- 1048576 0x100000 Linux EXT filesystem, rev 1.0
No embedded files. Normal entropy. This ruled out the “hidden file stuffed inside” class of challenge. binwalk not finding anything is still a data point — it told me I wasn’t looking at a simple embed.
mmls showed something weird
mmls disk.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
000: Meta 0000000000 0000000000 0000000001 Primary Table (#0)
001: ------- 0000000000 0000002047 0000002048 Unallocated
002: 000:000 0000002048 0000206847 0000204800 Linux (0x83)
003: ------- 0000206848 0000716799 0000509952 Unallocated
That third entry — Unallocated, ~250MB — was too large to ignore. A region that size sitting there unused, at the end of a challenge image, isn’t an accident. Either a hidden partition, or a filesystem that had been deliberately removed from the table but not wiped.
That’s when I went back to mount — but with an actual hypothesis this time.
The Fix: Options That Actually Matter
ro wasn’t optional
I mounted the valid partition (slot 002) with the correct offset:
sudo mount -o loop,offset=1048576,ro disk.img /mnt/target
It worked.
The ro flag felt almost reflexive, but it turned out to be critical. The challenge had a timeline-based component, and mounting read-write would have silently updated access timestamps — potentially corrupting the evidence I needed. In forensics work, timestamps are evidence. Mounting rw is the kind of mistake you don’t notice until you’ve already broken something.
Here’s a comparison of what I tried and what happened:
| Option | Result | Impact |
|---|---|---|
-o loop | Failed | No offset specified |
-o loop,offset=1048576 | Failed | FS still not readable (earlier attempt) |
-o loop,offset=1048576,rw | Succeeded, but risky | Timestamps get modified |
-o loop,offset=1048576,ro | Succeeded, safe | Stable for forensic analysis |
Getting to the flag after mount
Mounting is the start, not the finish. Just running ls won’t show you much. There’s an order to this:
# 1. Check lost+found first — deleted file remnants live here ls -la /mnt/target/lost+found/ # 2. Sweep for hidden files find /mnt/target -name ".*" -type f 2>/dev/null # 3. bash_history is almost always worth reading cat /mnt/target/home/user/.bash_history # 4. Cache and logs find /mnt/target/home -name "*.cache" -o -name "*.log" 2>/dev/null
.bash_history had something suspicious in it. The flag was one step past that.
The point isn’t that mount was the right tool. It’s that mount alone wouldn’t have gotten me there — the exploration sequence after mounting is where the actual work happens.
Cases Where mount Was the Wrong First Move
This one worked out. Others haven’t.
Case 1: File carving challenge
Image contains an intentionally broken ext2. mount returns wrong fs type and there’s nowhere to go from there. The right tool is foremost or binwalk -e — carve through the raw bytes and let it reconstruct whatever’s buried.
foremost -i raw.img -o ./recovered/
Sticking with mount here costs 15+ minutes and yields nothing.
Case 2: LUKS encryption
file encrypted.img # => LUKS encrypted file, ver 2
mount will immediately error with unknown filesystem type 'crypto_LUKS'. You need cryptsetup first, then mount the decrypted device:
sudo cryptsetup luksOpen encrypted.img ctf_vol sudo mount /dev/mapper/ctf_vol /mnt/target
Case 3: qcow2 VM snapshot
Common in VM-based forensics challenges. Trying to mount a .qcow2 directly does nothing useful.
# Convert to raw first qemu-img convert -f qcow2 -O raw vm.qcow2 vm_raw.img # Then mount normally sudo mount -o loop,ro vm_raw.img /mnt/target
The extension .img doesn’t tell you the format. Always run file before assuming you can mount directly.
Tool Decision Cheatsheet
| Tool | Speed to First Info | Rabbit Hole Resistance | Failure Feedback | Switch to mount when… |
|---|---|---|---|---|
| mount | Medium | Low | Poor (cryptic errors) | FS integrity is confirmed |
| binwalk | Fast | Medium | Good (absence = info) | Embedded files are ruled out |
| mmls | Fast | High | Good (shows structure) | Partition layout is understood |
| Autopsy | Slow | High | Good (visual overview) | Time allows for full GUI pass |
| foremost | Medium | Medium | Medium | FS is confirmed broken |
The short version:
- If you know the FS is intact:
mountis the right call. - If you don’t know yet: run
mmlsorbinwalkfirst. - If
wrong fs typekeeps coming back: stop, step back, re-examine your assumptions.
Why mount Fails: The Superblock
When the kernel tries to mount an ext4 filesystem, it looks for the superblock at byte offset 1024 from the start of the partition. The superblock contains a magic number — 0xEF53 — that identifies it as ext.
If your offset calculation is off, the kernel reads garbage as a superblock, doesn’t find the magic number, and throws wrong fs type.
Partition start (sector 2048) → byte offset 1048576
↓
Superblock expected at: 1048576 + 1024 = 1049600 bytes
↓
If 0xEF53 isn't there → mount fails with "wrong fs type"
Once I understood this, wrong fs type stopped being a frustrating dead end and started being a diagnostic signal: either the offset is wrong, or the filesystem is genuinely damaged. Two different problems, two different next steps.
On the MBR vs GPT front: if fdisk reports “DOS Partition Table”, you’re dealing with MBR and the numbers are straightforward. If you see a GUID, it’s GPT — the offset math is different and you’ll want to use gdisk or parted instead.
Reproducible First-Move Flow
# 1. Identify the format file disk.img # 2. Read the partition structure mmls disk.img fdisk -l disk.img # 3. Look for anomalies # → Large unallocated region → possible hidden partition or wiped FS # → Broken partition table → skip mount, go to carving # 4. Mount with confirmed offset (ro is non-negotiable) sudo mount -o loop,offset=$(python3 -c "print(START_SECTOR * SECTOR_SIZE)"),ro disk.img /mnt/target # 5. If mount fails binwalk disk.img # check for embedded content foremost -i disk.img -o ./out/ # carve raw bytes file disk.img | grep -i luks # check for encryption # 6. If encrypted sudo cryptsetup luksOpen disk.img vol_name sudo mount /dev/mapper/vol_name /mnt/target
Closing: mount Is a Tool, Not a Starting Point
The most time I’ve wasted in disk forensics — CTF or otherwise — has come from reaching for a tool before forming a hypothesis. mount is powerful. When the filesystem is intact and you know your offset, it’s faster than almost anything else for getting a navigable view of the image. But it’s built on the assumption that things are structurally normal, and that assumption is exactly what a well-designed challenge will break.
Knowing when to use it is a different skill than knowing how to use it.
Next time you get a disk.img, start with file and mmls. Let the structure tell you what tool it needs. Mount can wait.
Further Reading
Most of the articles linked below come from alsavaudomila.com, a site focused on practical CTF write-ups and tool breakdowns. The writing tends to skip the theory-first approach and get straight to how tools behave in actual challenge conditions — which makes it a useful reference when you’re mid-competition and need to know what a tool does under pressure, not in a lab.
If this post got you interested in forensics tooling more broadly, CTF Forensics Tools: The Ultimate Guide for Beginners on that site is a solid place to build out your toolkit — it covers the landscape of tools you’ll encounter across different challenge types, not just disk images.
The site also has a few other tool-focused deep dives that pair well with what’s covered here. If you’ve run into challenges where the artifact isn’t a disk image but a PDF, pdfdumper in CTF: Extracting PDF Content and Common Challenge Patterns walks through the extraction workflow in the same practical style. Password-protected archives are another common Forensics staple — zip2john in CTF: Extracting ZIP Passwords and Common Challenge covers how to approach those without burning time on the wrong tool first. And if you’ve ever stared at a QR code embedded in a challenge image wondering what to do with it, zbarimg in CTF: QR/Barcode Decoding Techniques and Common Challenge Patterns has you covered.
Leave a Reply