$ cat writeup.md…
$ cat writeup.md…
hackthebox
Given a file `chal.txt` with 84 lines of analogies in the format: ``` Like non-mainstream is to efl, battery-powered is to? Like sycophancy is to بالشهادة, cont is to? ... Like raving is to سگن, happy is to? ```
Words carry semantic information. Similar to how people can infer meaning based on a word's context, AI can derive representations for words based on their context too! However, the kinds of meaning that a model uses may not match ours. We've found a pair of AIs speaking in metaphors that we can't make any sense of! The embedding model is glove-twitter-25. Note that the flag should be fully ASCII and starts with 'htb{'.
Given a file chal.txt with 84 lines of analogies in the format:
Like non-mainstream is to efl, battery-powered is to?
Like sycophancy is to بالشهادة, cont is to?
...
Like raving is to سگن, happy is to?
Task format: Classic word analogies — "A is to B as C is to D". Need to find D for each of the 84 lines.
Model: Explicitly specified — glove-twitter-25 (GloVe embeddings trained on Twitter, 25-dimensional vectors). Available via gensim.downloader.
Model vocabulary: ~1.2M words, including words in various languages (Arabic, Japanese, Korean, Turkish, etc.), as well as Unicode characters — all present in Twitter data.
Key math: Classic word2vec analogy:
D = B - A + C
Then find the nearest word to vector D by cosine similarity.
Unicode gotcha: The GloVe vocabulary contains fullwidth Unicode digits (0123456789) as separate tokens. The analogy results contain these fullwidth digits instead of ASCII, so a final conversion is needed.
#!/usr/bin/env python3.12 import re import gensim.downloader as api import numpy as np print("[*] Loading glove-twitter-25 model...") model = api.load("glove-twitter-25") print(f"[*] Model loaded. Vocab size: {len(model.key_to_index)}") with open("chal.txt", "r") as f: lines = f.readlines() results = [] for i, line in enumerate(lines): line = line.strip() if not line: continue m = re.match(r"Like (.+?) is to (.+?), (.+?) is to\?", line) if not m: results.append("???") continue a_word = m.group(1).strip() b_word = m.group(2).strip() c_word = m.group(3).strip() if not all(w in model.key_to_index for w in [a_word, b_word, c_word]): results.append("???") continue # Analogy: D = B - A + C vec = model[b_word] - model[a_word] + model[c_word] similar = model.similar_by_vector(vec, topn=1) answer = similar[0][0] results.append(answer) print("".join(results))
Result (with fullwidth Unicode digits):
htb{REDACTED}
#!/usr/bin/env python3.12 raw = "htb{REDACTED}" fw_to_ascii = { "0": "0", "1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "6": "6", "7": "7", "8": "8", "9": "9", } result = "" for ch in raw: result += fw_to_ascii.get(ch, ch) print("Flag:", result)
gensim.downloader.load("glove-twitter-25") — loads the model automatically (~200MB)positive=[B, C], negative=[A] is equivalent to B - A + Cmodel.similar_by_vector(vec, topn=N) — finds N nearest words to the vector$ cat /etc/motd
Liked this one?
Pro unlocks every writeup, every flag, and API access. $9/mo.
$ cat pricing.md$ grep --similar