Back to writing

OSINT Industries CTF 2025 — Writeup

August 23, 202612 min read

Hài

OSINT Industries ran a capture-the-flag built entirely around open-source intelligence — no binaries, no shells, no exploitation. Every answer already existed in public, and the whole game was whether you could find it and prove it.

Challenges were grouped under agency names — GEOINT, FSB, GRU, INTERPOL, EUROPOL — which sounds thematic but is really a difficulty ladder. The early ones hand you one strong lead. The later ones hand you three weak ones and expect you to make them agree.

What follows is how I approached three of them. The reasoning is the point; if you are working the same challenges, the reasoning transfers even where the answers have since changed.

The challenge board

Challenges sat under agency-themed categories. This is what I could confirm from the platform and from published writeups — the board was larger than this, and the list is marked where I could not verify a name.

Challenge Category What it asks
Find the Masked Man GEOINT Geolocate a photograph taken in central Paris on 3 December 2023 around 18:00, then name the nearest metro station.
DEPIX OSINT Recover passenger name, seat and destination IATA code from a heavily pixelated boarding pass.
Holehe & The Secret Email FSB Trace the first public appearance of the holehe author's email address, and date it.
On the Traces of the Silk Road EUROPOL Pivot from the Silk Road case record to a specific profile and a review tied to a location.
Found the Hacker OSINT Identify an individual from the traces left around an intrusion.

The categories in play were GEOINT, OSINT, FSB, GRU, INTERPOL and EUROPOL. The agency names read as flavour but function as a difficulty ladder: the early categories hand you one strong lead, the later ones hand you three weak ones and expect you to make them agree.

A caveat worth stating plainly: not every challenge has a public writeup, and the platform's scoreboard is behind a login. Where a solution is not already public, I have put mine behind a key rather than publishing it — see below.

The toolkit

Almost everything came from a small set:

Search operators      site:, filetype:, intitle:, "exact phrase", before:/after:
Reverse image         Google Lens, Yandex, Bing Visual Search
Mapping               Google Maps + Street View, OpenStreetMap, Overpass Turbo
Time travel           Wayback Machine, archive.today, Google cache
Code history          GitHub commit history, `git log --follow`, PyPI release pages
People/handle pivots  WhoisXML, holehe, sherlock, Have I Been Pwned
Photo metadata        exiftool, sun position calculators

Yandex is worth calling out. For photographs taken in Europe it consistently beat Google Lens during this event — different index, different strengths.

GEOINT — Find the Masked Man

A photograph taken in Paris on 3 December 2023, around 18:00. Name the metro station nearest to where it was taken.

Three constraints come free with the brief, and each one narrows the search before you look at the image at all.

The date and time do real work. Paris on 3 December sunsets around 16:55, so 18:00 is fully dark. Anything in the frame that looks like daylight means you have the wrong photograph or the wrong assumption. Artificial light also tells you about the setting: shopfront light, streetlight colour temperature, and Christmas illuminations, which in early December are already up.

Read the frame before searching it. The habit that pays here is to inventory everything legible and rank it by how unique it is:

  • Street furniture — Paris has a distinctive vocabulary of bollards, Morris columns, Wallace fountains, and Guimard metro entrances. A Guimard entrance alone narrows you to a known list of stations.
  • Building form — Haussmann facades are everywhere, so they are near-useless. A corner cut at 45°, an unusual roofline, or a non-Haussmann block is worth far more.
  • Text — shop names, awnings, street plaques, bus stop names, event posters. A business name plus "Paris" in a search is often the whole challenge.
  • Road markings and lane geometry, which pin the exact side of a street once you are close.

Then confirm, do not guess. Reverse image search gives you a candidate. What turns a candidate into an answer is lining up at least two independent fixed features in Street View — a specific balcony ironwork pattern and the angle of a side street, say. One match is a coincidence; two that agree from the same camera position is a location.

Once the position is fixed, the nearest station is a mapping question rather than an OSINT one. Watch for the trap in the wording: nearest means nearest by walking distance, not the station whose name you recognise, and Paris is dense enough that those differ.

Find the Masked Man — my answer

This part is not published. There is no key for it.

FSB — Holehe & The Secret Email

holehe checks whether an email address is registered on a given site. Find the first appearance of its creator's email address online, and the date that address was created.

This is a software-archaeology challenge wearing an OSINT hat, and it splits cleanly in two.

Finding the address. A maintainer's email is rarely written on a page; it is committed. Every git commit carries an author email, so the repository is the primary source:

git clone https://github.com/megadose/holehe
git log --format='%an <%ae>' | sort -u

The oldest commits are the interesting ones. Developers tighten up their public identity over time — a personal address in a 2019 commit often gets replaced by a noreply address later, but git never forgets the earlier one. Packaging metadata is the other reliable place: setup.py, pyproject.toml, and the PyPI project page all carry an author email, and old PyPI releases preserve whatever was current when they shipped.

Dating it. "When was this address created" is not answerable directly — no provider publishes that. So the question is really what is the earliest evidence of it existing, and the answer is whatever public artefact carries it with a trustworthy timestamp. Candidates, roughly in order of how much I trust the date:

  1. A git commit's author date — precise, though rewritable, so sanity-check it against when the repository was actually created.
  2. A PyPI or npm release page — publication dates are server-side and hard to forge.
  3. A mailing list or forum archive with the address in a header.
  4. A Wayback capture of a page containing it — gives you no later than, not created on.

The lesson that generalises: an OSINT answer is a claim plus the artefact that supports it. If you cannot name the artefact, you have a guess.

Holehe & The Secret Email — my answer

This part is not published. There is no key for it.

EUROPOL — On the Traces of the Silk Road

Questions about the Silk Road marketplace and the investigation that ended it.

Everything needed here is in the public record, and the record is unusually good: the case produced a criminal complaint, a full trial, and a large volume of exhibits, most of it online.

The move that matters is to go to primary sources instead of news coverage. Court filings are the highest-quality OSINT source you will ever get for free — they are specific, dated, and adversarially checked. Reporting compresses and occasionally garbles them.

Complaint and indictment        the FBI complaint, USAO SDNY filings
Trial exhibits                  chat logs, server images, seizure records
Contemporaneous forum posts     Bitcointalk, and the Shroomery post that
                                connected an early handle to a real identity
Archived marketplace pages      Wayback captures of the .onion mirrors

The single most instructive thread in the whole case is the operational-security failure that started the identification: an early promotional post made under a handle that was, elsewhere and earlier, tied to a real name and a real email. Nothing about that was decrypted or hacked. It was searched.

That is the whole point of the category. The exercise is not to be clever, it is to correlate: one handle, one address, one timestamp, until independent sources say the same thing.

Silk Road — my answers

This part is not published. There is no key for it.

OSINT — DEPIX

A boarding pass, pixelated. Recover the passenger's first and last name, the seat number, and the arrival airport's IATA code.

The name is a nod to depix, which recovers text from pixelated screenshots by searching for the source glyphs that would produce the observed blocks. That works on rendered text of a known font and background — and it is worth trying — but a photographed document usually resists it.

The reliable path on this one is that a boarding pass carries far more than its pixelated text. The barcode is the real payload: PDF417 on most boarding passes, encoding an IATA BCBP string with passenger name, flight, seat and airports in plain text. If the code survived the pixelation at all, decoding it answers all three sub-questions at once and the blurred glyphs never matter.

Failing that, the pass's own layout is a fingerprint — airline branding, fare class positioning, and font choices narrow it to a carrier, and a reverse image search on the unpixelated regions often finds the original.

DEPIX — my solve

This part is not published. There is no key for it.

OSINT — Found the Hacker

Identify an individual from the traces left around an intrusion.

Attribution challenges are handle-pivot challenges. You are given one artefact that carries an identifier — a username, an email, a wallet, a PGP key fingerprint, a domain — and the work is to find where else that identifier appears, then find where the person forgot to keep the personas separate.

The pivot order I default to:

handle    -> sherlock / WhatsMyName across platforms
email     -> holehe for registrations, HIBP for breach corroboration
domain    -> WHOIS history, certificate transparency, passive DNS
PGP key   -> keyserver lookups, the email in the UID
wallet    -> block explorer -> exchange deposit tags -> forum posts
timestamps -> commit times and post times reveal a working timezone

The last one is underrated. A scatter plot of someone's public activity timestamps usually shows a sleep gap, and that gap is a timezone.

Found the Hacker — my solve

This part is not published. There is no key for it.

What I took away

Read the prompt as a set of constraints. "Paris, 3 December 2023, 18:00" is not scene-setting. It is three filters, and applying them before you search removes most of the wrong answers for free.

Two weak signals beat one strong one. A single reverse-image hit is a hypothesis. It becomes an answer when a second, independent feature agrees.

Timestamps are evidence, and not all of them are equal. A commit date, a package release, and a Wayback capture make very different claims. Knowing which one you have is most of the discipline.

When stuck, re-read your assumptions rather than searching harder. Most of the time I was stuck, the problem was something I had decided early and stopped questioning — that a light source was daylight, that an address was current, that a well-known station was the closest one.


Screenshots for the geolocation steps go in content/blog/_images/osint-industries-ctf-2025/ and are referenced by bare filename.