forensics::ctf

forensics disk · ext4 artifacts · timeline
Recon Mount File Recovery Deleted Files Steganography Strings & Carving Metadata Encoding MAC Timeline Tools Workflow
01Initial Recon
Identify the image
# What is it?
file partition4.img
xxd partition4.img | head -4   # magic bytes

# Filesystem info
fsstat partition4.img           # sleuthkit: full fs stats
dumpe2fs partition4.img         # ext2/3/4 superblock details
tune2fs -l partition4.img       # another view of ext metadata

# Quick size/entropy overview
ls -lh partition4.img
binwalk partition4.img          # embedded files / signatures
Magic Bytes Reference
HexTypeNotes
53 EFext2/3/4at offset 0x438 in superblock
89 50 4E 47PNG.PNG\r\n
FF D8 FFJPEGalso ends FF D9
25 50 44 46PDF%PDF
50 4B 03 04ZIP/docx/jarPK..
7F 45 4C 46ELF binary.ELF
1F 8Bgzipalso tar.gz
42 5A 68bzip2BZh
52 61 72 21RARRar!
4F 67 67 53OGGaudio/video
02Mount & Browse
Mount the image
# Simple mount (read-only, safe)
sudo mkdir /mnt/img
sudo mount -o ro,loop partition4.img /mnt/img

# ext4 with recovery (if dirty/unclean)
sudo mount -o ro,loop,noload partition4.img /mnt/img

# Browse everything including hidden files
ls -laR /mnt/img
find /mnt/img -type f | sort
find /mnt/img -name ".*"     # hidden files
find /mnt/img -size +0c      # non-empty files

# Unmount when done
sudo umount /mnt/img
Filesystem tree & timestamps
# Full tree with sizes
tree -ash /mnt/img

# Sort by modification time (newest first)
find /mnt/img -type f -printf "%T@ %p\n" | \
  sort -rn | head -20

# Files modified in last 24h (relative to img)
find /mnt/img -newer /mnt/img -type f

# istat: inode details (sleuthkit)
istat partition4.img <inode_number>

# fls: file listing with inode info
fls -r partition4.img          # recursive
fls -rd partition4.img         # deleted files only
03File Analysis
Identify & extract everything
# Identify all files by magic (not extension)
find /mnt/img -type f -exec file {} \;

# binwalk: scan for embedded files
binwalk -e suspicious_file     # extract embedded
binwalk -Me suspicious_file    # recursive extract
binwalk --dd='.*' file          # extract ALL signatures

# foremost: file carving by header/footer
foremost -i partition4.img -o ./carved/
foremost -t jpg,png,pdf,zip -i partition4.img

# photorec: comprehensive carving (interactive)
photorec partition4.img
Archives & compressed files
# Test and list zip contents
unzip -l file.zip
unzip -t file.zip              # test integrity
unzip -P password file.zip     # with password

# Crack zip password
zip2john file.zip > hash.txt
john hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
# or
hashcat -m 13600 hash.txt rockyou.txt

# tar/gz
tar -tzvf archive.tar.gz        # list contents
tar -xzvf archive.tar.gz        # extract
04Deleted File Recovery (ext4)
Sleuthkit / TSK
# List ALL files including deleted (marked with *)
fls -r partition4.img
fls -rd partition4.img          # deleted only
fls -rp partition4.img          # full paths

# Get inode number from fls output, then:
# icat: extract file by inode
icat partition4.img <inode> > recovered_file

# istat: metadata for an inode
istat partition4.img <inode>

# ils: list inodes (including deleted)
ils -e partition4.img           # everything
ils partition4.img | head -30
extundelete & ext4magic
# extundelete: recover deleted from ext3/4
extundelete partition4.img --restore-all
extundelete partition4.img --restore-directory /home
extundelete partition4.img --restore-file /etc/passwd

# ext4magic: more powerful ext4 recovery
ext4magic partition4.img -R    # recover all deleted
ext4magic partition4.img -f /  # specific directory

# debugfs: interactive ext2/3/4 explorer
debugfs partition4.img
# inside debugfs:
#   ls -d /          list all incl. deleted
#   lsdel            list deleted inodes
#   dump <inode> /tmp/out   dump by inode
Journal analysis
# ext4 keeps a journal — may contain old data
# Extract the journal inode (usually inode 8)
icat partition4.img 8 > journal.bin

# Strings from journal
strings journal.bin | grep -i "flag\|CTF\|picoCTF"

# jcat / jls (sleuthkit journal tools)
jls partition4.img
jcat partition4.img <seq> > block.bin
Autopsy (GUI)
# Full forensic suite — good for ext4
autopsy
# Then open browser to http://localhost:9999/autopsy
# Add image → analyze → deleted files tab

# CLI equivalent batch mode:
autopsy -c /path/to/case.conf

# Autopsy finds:
#   - deleted files (unallocated space)
#   - file slack space
#   - hidden partitions
#   - keyword search across image
05Steganography
Images (JPEG / PNG)
# steghide: embed/extract from JPEG/BMP/WAV
steghide info image.jpg         # check if data embedded
steghide extract -sf image.jpg  # extract (prompts passphrase)
steghide extract -sf image.jpg -p ""  # empty passphrase

# stegseek: crack steghide passphrase
stegseek image.jpg /usr/share/wordlists/rockyou.txt

# zsteg: LSB steg in PNG/BMP
zsteg image.png                 # try all channels
zsteg -a image.png              # all methods
zsteg -e b1,rgb,lsb,xy img.png # specific channel

# stegsolve (java GUI): visual analysis
java -jar stegsolve.jar

# exiftool: check all metadata
exiftool image.jpg
exiftool -comment image.jpg     # just the comment field
Audio (WAV / MP3)
# Open in Audacity → view spectrogram
# Flags often hidden in spectrogram view
audacity audio.wav

# sonic-visualiser: spectrogram analysis
sonic-visualiser audio.wav

# mp3stego / wav steg tools
steghide extract -sf audio.wav

# DeepSound (Windows tool via wine)
# Decode DTMF tones
multimon-ng -t wav -a DTMF audio.wav

# LSB in WAV with python
python3 -c "
import wave, struct
w = wave.open('audio.wav')
frames = w.readframes(w.getnframes())
bits = [frame & 1 for frame in frames]
chars = [chr(int(''.join(map(str,bits[i:i+8])),2)) for i in range(0,len(bits)-8,8)]
print(''.join(chars)[:200])
"
Other steg techniques
# outguess: JPEG steg
outguess -r image.jpg output.txt

# jsteg
jsteg reveal image.jpg output.txt

# whitespace steg (SNOW)
stegsnow -C file.txt            # tabs/spaces hide data

# Binary image: bin → bytes → PNG (like your challenge)
python3 -c "
bits = open('data.txt').read().replace('\n','').replace(' ','')
data = bytes(int(bits[i:i+8],2) for i in range(0,len(bits),8))
open('out.bin','wb').write(data)
"
file out.bin   # identify what it is

# Least significant bit manual check
python3 -c "
from PIL import Image
img = Image.open('image.png').convert('RGB')
bits = [px[c]&1 for px in img.getdata() for c in range(3)]
chars = [chr(int(''.join(map(str,bits[i:i+8])),2)) for i in range(0,len(bits)-8,8)]
print(''.join(filter(lambda c: 32<=ord(c)<127, chars))[:300])
"
06Strings & Data Carving
strings & grep
# Basic strings
strings partition4.img | grep -i "flag\|CTF\|pico"

# Wide strings (Unicode / Windows)
strings -el partition4.img      # little-endian 16-bit
strings -eb partition4.img      # big-endian 16-bit

# Minimum length filter
strings -n 6 partition4.img | grep "picoCTF{"

# Hex dump around a hit
grep -boa "picoCTF{" partition4.img  # byte offset
xxd partition4.img | grep "picoCTF"

# Bulk extract printable
strings -n 4 partition4.img > all_strings.txt
grep -iE "password|secret|flag|key|token|admin" all_strings.txt
dd & raw extraction
# Extract bytes at specific offset
dd if=partition4.img of=chunk.bin \
   bs=1 skip=<offset> count=<size>

# Skip in blocks (faster for large images)
dd if=partition4.img of=sector.bin \
   bs=512 skip=<sector> count=1

# Extract unallocated space
blkls partition4.img > unalloc.bin
strings unalloc.bin | grep "picoCTF"

# blkcat: dump a specific block
blkcat partition4.img <block_number>
07Metadata & File Properties
exiftool
# Full metadata dump
exiftool file.jpg

# All files in a directory
exiftool /mnt/img/ -r

# Interesting fields to check
exiftool -Comment -Artist -Copyright \
         -GPSLatitude -GPSLongitude \
         -CreateDate -ModifyDate file.jpg

# GPS coordinates → copy to Google Maps
exiftool -n -GPSLatitude -GPSLongitude file.jpg

# Remove all metadata (for comparison)
exiftool -all= file.jpg
PDF / Office / misc
# PDF analysis
pdfinfo file.pdf
pdf-parser file.pdf             # peepdf alternative
pdfextract file.pdf             # extract embedded files
strings file.pdf | grep -i "flag"

# Office documents (docx = zip)
unzip -l file.docx
unzip file.docx -d ./docx_extracted/
cat ./docx_extracted/word/document.xml

# olevba: macros in Office
olevba file.doc

# pngcheck: PNG chunk analysis
pngcheck -v image.png
08Encoding & Crypto Identification
Decode common encodings
# base64
echo "cGljb0NURnt..." | base64 -d

# base32
echo "NBSWY3DPE..." | base32 -d

# hex
echo "7069636f435446" | xxd -r -p
python3 -c "print(bytes.fromhex('7069636f435446').decode())"

# rot13
echo "cvpbPGS{..." | tr 'A-Za-z' 'N-ZA-Mn-za-m'

# URL decode
python3 -c "from urllib.parse import unquote; print(unquote('%70%69%63%6f'))"

# identify unknown encoding
cyberchef  # use "Magic" recipe online
dcode.fr   # cipher identifier
Hash identification & cracking
# Identify hash type
hash-identifier <hash>
hashid <hash>
nth -t <hash>                    # name-that-hash

# Common hash lengths
# 32 chars  = MD5
# 40 chars  = SHA1
# 56 chars  = SHA224
# 64 chars  = SHA256
# 128 chars = SHA512

# Crack with hashcat
hashcat -m 0   hash.txt rockyou.txt  # MD5
hashcat -m 100 hash.txt rockyou.txt  # SHA1
hashcat -m 1400 hash.txt rockyou.txt # SHA256

# Online rainbow tables
# crackstation.net / hashes.com
09MAC Timeline & Timestomping
Build the timeline
# Step 1: generate bodyfile (TSK format)
# -r recursive  -m prepend mountpoint  / = root
fls -r -m / partition4.img > bodyfile.txt

# Step 2: convert to human-readable timeline
mactime -b bodyfile.txt -d > timeline.csv

# Step 3: sort by date — anomalies float to top/bottom
sort timeline.csv | head -30       # oldest first
sort -r timeline.csv | head -30    # newest first

# Filter to specific date range
mactime -b bodyfile.txt 1970-01-01,1990-01-01
mactime -b bodyfile.txt -d -z UTC 1980-01-01,2000-01-01
Spot anomalous timestamps
# Grep for suspicious years
grep "1970\|1969\|1971\|1985\|1980" timeline.csv

# Sort bodyfile directly by mtime (field 9, epoch int)
sort -t'|' -k9 -n bodyfile.txt | head -20

# bodyfile format (pipe-delimited):
# MD5|name|inode|perms|uid|gid|size|atime|mtime|ctime|crtime
#  1    2    3     4    5   6   7     8     9     10    11

# Example anomalous line:
# Tue Jan 01 1985 18:00:00,41,macb,r/rrw-r--r--,0,0,4945,"/bin/bcab"
#   ↑ impossible date       ↑size                 ↑inode  ↑path
Extract the timestomped file
# File accessible via mount? Try icat directly instead
# "Bad message" on mount = inode metadata mangled on purpose
# icat bypasses VFS and reads raw blocks from image

# Get inode from timeline (7th CSV field, or field 3 in bodyfile)
grep "1985\|1970" timeline.csv
# → Tue Jan 01 1985 18:00:00,41,macb,...,4945,"/bin/bcab"
#                                          ↑ inode = 4945

# Extract by inode directly
icat partition4.img 4945 > /tmp/recovered
file /tmp/recovered
cat /tmp/recovered
strings /tmp/recovered
xxd /tmp/recovered | head
binwalk -e /tmp/recovered
MAC timestamps explained
LetterMeaningUpdated when
MModifiedFile content written
AAccessedFile read
CChangedInode metadata changed
BBorn (crtime)File created (ext4 only)
Timestomping tellWhat it means
macb all same timeTool set all at once (sloppy)
M before B (born)Modified before created — impossible
Epoch 0 / 1970Timestamp zeroed out
M/A normal, C oldOnly mtime/atime touched
Year far in pastArbitrary fake timestamp set
10Tool Reference
Sleuth Kit (TSK)
CommandPurpose
fsstatFilesystem metadata
fls -rFile listing (incl. deleted)
istatInode details
icatExtract file by inode
ilsList inodes
blklsUnallocated space
blkcatDump specific block
jls / jcatJournal entries
Steg Tools
ToolFormat
steghideJPEG, BMP, WAV common
stegseekCrack steghide fast
zstegPNG, BMP LSB
stegsolvePNG visual analysis
outguessJPEG alternative
wavstegWAV LSB
stegoveritasRuns all steg tools
exiftoolAll metadata
Recovery Tools
ToolUse
extundeleteext3/4 deleted files
ext4magicext4 advanced recovery
debugfsInteractive ext explorer
photorecFile carving (many types)
foremostHeader/footer carving
scalpelConfig-driven carving
binwalkEmbedded file extraction
autopsyGUI forensic suite
11CTF Workflow for an ext4 Image
Decision tree
file / fsstat mount -o ro,loop fls -r (deleted?) icat → recover
fls -r -m / → bodyfile mactime → anomaly icat <inode> bypass bad mount
strings | grep CTF binwalk -e find hidden files exiftool / steghide
blkls (unalloc) foremost carve debugfs lsdel extundelete --restore-all
Full checklist for partition4.img
# 1. Recon
file partition4.img
fsstat partition4.img
dumpe2fs partition4.img | head -40

# 2. Mount and browse
sudo mount -o ro,noload,loop partition4.img /mnt/img
find /mnt/img -type f | xargs file
find /mnt/img -name ".*"          # hidden files
ls -laR /mnt/img

# 3. Grep for flag directly
strings partition4.img | grep "picoCTF{"
grep -ria "picoCTF" /mnt/img/

# 4. MAC timeline — spot timestomped files
fls -r -m / partition4.img > bodyfile.txt
mactime -b bodyfile.txt -d | grep "197[0-9]\|198[0-9]\|Jan 01 1970"
# extract suspicious inode directly:
icat partition4.img <inode> > /tmp/timestomped && cat /tmp/timestomped

# 5. Check deleted files
fls -rd partition4.img
# recover suspicious inodes:
icat partition4.img <inode> > /tmp/recovered

# 5. Carve unallocated space
blkls partition4.img > /tmp/unalloc.bin
foremost -i /tmp/unalloc.bin -o /tmp/carved/
strings /tmp/unalloc.bin | grep "picoCTF"

# 6. Full recovery attempt
extundelete partition4.img --restore-all
ls RECOVERED_FILES/
Common hiding spots in CTF images
LocationHow to find it
Timestomped filefls -r -m / img > body.txtmactimeicat
Deleted filefls -rdicat
Hidden file (.name)find -name ".*"
File inside filebinwalk -e
Image metadataexiftool comment/artist/GPS
Image LSB stegzsteg / steghide
Unallocated spaceblkls + strings
Journal blocksicat img 8 → strings
Slack spaceblkls -s (file slack)
Superblock backupdumpe2fs backup locations
Extended attributesgetfattr -R /mnt/img
Alternate data streamrare on ext4, common on NTFS
Encoded in filenamefls -r | base64 -d
QUICK START for partition4.img →  ① sudo mount -o ro,noload,loop partition4.img /mnt/img  ② strings partition4.img | grep "picoCTF{"  ③ fls -rd partition4.img (deleted files → icat)  ④ fls -r -m / partition4.img > body.txt && mactime -b body.txt -d | grep "197\|198" (timestomping)  ⑤ icat partition4.img <inode> > /tmp/out (bypass bad mount)  ⑥ blkls partition4.img | strings | grep picoCTF  ⑦ extundelete partition4.img --restore-all