- WRAVEN
- Posts
- How WRAVEN does OSINT + more!
How WRAVEN does OSINT + more!
ECX Inc. writeups for the UMDCTF challenges that we solved!
UMDCTF 2025: ECX Inc. Writeups
Gerard Manley Hopkins (UMDCTF 2025)
Category: OSINT
This challenge gave a 360-degree street view image with no context, titled “Gerard Manley Hopkins” (a poet nod). The goal was to identify the exact address.
My Approach
Key clues:
A DAILEY’S garbage bin with the phone number 532-4667.
A house number: 1121 on a white house across the street.


What I Did
Googled Dailey’s trash service + number, found it was based in southern Ohio.
Focused on Wellsville, OH, and matched 1121 Hillcrest Rd via Google Street View.
Flag
UMDCTF{Hillcrest Rd, Wellsville, OH 43968}
The Master (UMDCTF 2025)
Category: OSINT

Dropped into a 360-degree view with no extra hints. The only clue? A Morgan marker visible on the left side of the shot.
What I Did
Recognized it as part of General John Hunt Morgan’s raid trail across Ohio.
Used the Historical Marker Database to find a match.
Confirmed it was the marker on Main Street in Lore City, Ohio.
Flag
UMDCTF{Main St, Lore City, OH 43755}
Swag Like Ohio (UMDCTF 2025)
Category: OSINT
This one gave a clear photo of a bridge, no other context. The name hinted at Ohio.

What I Did
Ran a reverse image search immediately.
Found it was the Putnam Bridge in Marietta, Ohio.
Flag
UMDCTF{Putnam Bridge, Marietta, OH 45750}
Sunshine (UMDCTF 2025)
Category: OSINT
Another 360-degree street view, titled “Sunshine.”
What I Did
Noticed a distinctive white house on the left.
The challenge name reminded me of the Michael Jordan “you are my sunshine” meme.
Reverse searched the house and confirmed it was his childhood home at:
Flag
UMDCTF{356 Hillwood Dr, Akron, OH 44320}
Beauty (UMDCTF 2025)
Category: OSINT
We got a Google Maps photosphere with no clear hints, just the title “Beauty.”
What I Did
Recognized it was somewhere in Columbus, Ohio based on landmarks.
Cross-referenced a nearby bridge and checked local photospheres.
Found the photographer’s name listed as Neil Larimore.
Flag
UMDCTF{Neil Larimore}
The Blueprint (UMDCTF 2025)
Category: OSINT
This challenge dropped a view with no obvious identifiers: just a tree-covered mound and a closed road.

What I Did
Tried reverse searching everything: the house, the road sign, even Google’s watermark. Nothing worked.
Finally ran a basic reverse image search on the main scene—and that cracked it.
It was the Alligator Mound in Granville, Ohio.
Flag
UMDCTF{Bryn Du Dr, Granville, OH 43023}
Basic XOR Reversing (UMDCTF 2025)
Category: Reversing
We got a binary file, and in Ghidra, two sections stood out:
Offset 0x2000: a 52-byte mask.
Offset 0x2034: a 52-byte encrypted blob.
This looked like a basic XOR setup.
Steps I Took
1️⃣ Grabbed the mask bytes:
dd if=challenge.bin bs=1 skip=$((0x2000)) count=52 2>/dev/null | xxd -p > mask.hex
2️⃣ Grabbed the encrypted bytes:
dd if=challenge.bin bs=1 skip=$((0x2034)) count=52 2>/dev/null | xxd -p > enc.hex
3️⃣ XORed them:
python3 - << 'EOF'
mask = bytes.fromhex(open('mask.hex').read().strip())
enc = bytes.fromhex(open('enc.hex').read().strip())
flag = ''.join(chr(m ^ e) for m, e in zip(mask, enc))
print(flag)
EOF
Flag
UMDCTF{r3v3R$E-i$_Th3_#B3ST#_4nT!-M@lW@r3_t3chN!Qu3}
TikTok Ban (UMDCTF 2025)
Category: Misc / Networking
The challenge simulated a DNS service that blocked any request for tiktok.com, case-insensitively.
What I Did
Built a Python script that:
Constructed a DNS TXT query manually.
Sent the query using a TCP socket.
Used mixed casing (TiKtOk.CoM) to bypass the filter.
Script
#!/usr/bin/env python3
import socket, struct, re
def build_query(qname):
hdr = struct.pack('!H H H H H H',
0x1234, 0x0100,
1, 0, 0, 0)
labels = qname.split('.')
q = b''.join(struct.pack('B', len(lbl)) + lbl.encode() for lbl in labels)
q += b'\x00'
q += struct.pack('!H H', 16, 1)
return hdr + q
def main():
domain = 'TiKtOk.CoM'
query = build_query(domain)
pkt = struct.pack('!I', len(query)) + query
with socket.create_connection(('challs.umdctf.io', 32300)) as s:
s.sendall(pkt)
resp = b''
while True:
chunk = s.recv(4096)
if not chunk:
break
resp += chunk
m = re.search(rb'(UMDCTF\{.*?\})', resp)
if m:
print("Flag:", m.group(1).decode())
else:
print("No flag found. Raw response:")
print(''.join((chr(b) if 32<=b<127 else '.') for b in resp))
if __name__ == '__main__':
main()
Result
The bypass worked and returned the flag successfully.
Find the Seeds (UMDCTF 2025)
Category: Crypto / Reversing
We were given a secret.bin and a script using Python’s PRNG seeded with int(time.time()):
import random
import time
seed = int(time.time())
random.seed(seed)
plaintext = b"UMDCTF{REDACTED}"
keystream = bytes([random.getrandbits(8) for _ in range(len(plaintext))])
ciphertext = bytes([p ^ k for p, k in zip(plaintext, keystream)])
with open("secret.bin", "wb") as f:
f.write(ciphertext)
My Approach
1️⃣ We know the flag starts with UMDCTF{, so the first 7 plaintext bytes were known.
2️⃣ XORed those with the first 7 bytes of the ciphertext to get the first 7 PRNG outputs.
3️⃣ Brute-forced timestamps from around April 15–30, 2025.
4️⃣ Found the seed: 1745447710 (2025-04-23 22:35:10 UTC).
5️⃣ Reseeded Python’s random and rebuilt the full keystream.
Flag
UMDCTF{pseudo_entropy_hidden_seed}
Final Thoughts
UMDCTF 2025 was seriously fun—super creative challenges, and lots of ways to flex different skills. ECX Inc. (WMU’s official CTF team, and I’m hyped to be captain) had a blast pushing through this set. We’re ready for the next one.