Gone4ever

BearcatCTFby smothy

Gone 4 Ever - Forensics

Points: 498 | Flag: BCCTF{GonE_But_nOt_4GottEn} | Solved by: Smothy @ 0xN1umb

gone forever vibes

what we got

A directory ubuntu/ containing 101 JPG files (0.jpg through 100.jpg) plus some dotfiles: .bash_history, .viminfo, .bashrc, .profile, etc.

The images are all placeholder images from placehold.co showing numbers 0-100. Boring... except one of them has a secret.

the solve

step 1: read the bash history

.bash_history tells the whole story:

bash
cd
vi flag.txt
export pass=`hexdump -n 4 -e '4/1 "%02x"' /dev/urandom`
for i in {0..100}; do wget "https://placehold.co/400x400.jpg?text="$i -O $i".jpg"; done
steghide embed -ef flag.txt -cf $((RANDOM % 101))".jpg" -p $pass
rm flag.txt

so someone:

  1. created flag.txt with vim
  2. generated a random 8-char hex password from /dev/urandom
  3. downloaded 101 placeholder images
  4. embedded flag.txt into ONE random image using steghide
  5. deleted flag.txt

step 2: find the modified image

since all images came from placehold.co, we can just re-download the originals and diff them:

bash
mkdir -p /tmp/originals
for i in $(seq 0 100); do
    wget -q "https://placehold.co/400x400.jpg?text=$i" -O "/tmp/originals/$i.jpg"
done

for i in $(seq 0 100); do
    orig_md5=$(md5sum "/tmp/originals/$i.jpg" | cut -d' ' -f1)
    curr_md5=$(md5sum "ubuntu/$i.jpg" | cut -d' ' -f1)
    if [ "$orig_md5" != "$curr_md5" ]; then
        echo "DIFFERENT: $i.jpg"
    fi
done
DIFFERENT: 29.jpg (orig=4101 bytes, curr=5750 bytes, diff=+1649 bytes)

29.jpg is the one. steghide data made it 1649 bytes larger than the clean original.

step 3: crack the password

the password is 8 lowercase hex chars (4 bytes from urandom). thats 16^8 = 4,294,967,296 possible passwords. sounds like a lot but stegseek is an absolute beast.

rockyou.txt? nah, didn't have it. had to brute force the hex space.

wrote a quick C hex generator:

c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main(int argc, char *argv[]) {
    uint32_t start = 0, end = 0xFFFFFFFF;
    if (argc > 1) start = (uint32_t)strtoul(argv[1], NULL, 16);
    if (argc > 2) end = (uint32_t)strtoul(argv[2], NULL, 16);

    char buf[10];
    buf[8] = '\n';
    for (uint64_t i = start; i <= end; i++) {
        uint32_t v = (uint32_t)i;
        // fast hex conversion
        for (int j = 7; j >= 0; j--) {
            buf[j] = "0123456789abcdef"[v & 0xf];
            v >>= 4;
        }
        fwrite(buf, 1, 9, stdout);
    }
    return 0;
}

then chunked it into 500M password blocks and fed each to stegseek:

bash
for chunk in $(seq 0 8); do
    start=$((chunk * 500000000))
    end=$(((chunk + 1) * 500000000 - 1))
    ./hexgen $(printf '%08x' $start) $(printf '%08x' $end) > /tmp/hex_chunk.txt
    stegseek 29.jpg /tmp/hex_chunk.txt /tmp/flag.txt -f
done

stegseek was processing ~26M passwords/sec. hit the password at about 33% through the 4th chunk:

[i] Found passphrase: "a9bde906" [i] Original filename: "flag.txt"

ngl that was satisfying to watch

step 4: profit

bash
$ cat /tmp/flag.txt
BCCTF{GonE_But_nOt_4GottEn}

flag

BCCTF{GonE_But_nOt_4GottEn}


the key insight was re-downloading originals from placehold.co to diff against the challenge files. once you know which image has the data, its just a brute force game - and stegseek is absurdly fast at it. 4.3 billion hex passwords cracked in under 2 minutes fr

smothy out ✌️