1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
| """Solve HackThisSite Programming Mission 1."""
import html import os import re from pathlib import Path
import requests
BASE = "https://www.hackthissite.org" LEVEL_URL = f"{BASE}/missions/prog/1/" WORDLIST = Path(__file__).with_name("wordlist.txt") USER_AGENT = ( "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36" )
def session(): cookie = os.environ.get("HTS_COOKIE", "").strip().strip("'\"") if not cookie: raise SystemExit("HTS_COOKIE is not set")
client = requests.Session() client.headers.update( { "User-Agent": USER_AGENT, "Cookie": cookie, "Referer": f"{BASE}/missions/programming/", "Accept-Language": "en-US,en;q=0.9", } ) return client
def body_text(source): source = re.sub(r"<script.*?</script>", "", source, flags=re.S) source = re.sub(r"<br\s*/?>", "\n", source) source = re.sub(r"</(?:p|div|tr)>", "\n", source) source = re.sub(r"<[^>]+>", " ", source) source = html.unescape(source) source = re.sub(r"[ \t]+", " ", source) return re.sub(r"\n\s*\n+", "\n", source)
def load_wordlist(path): table = {} with path.open("r", encoding="utf-8", errors="replace") as fh: for line in fh: word = line.strip() if word: table.setdefault("".join(sorted(word)), word) return table
def parse_scrambled(page_text): marker = "List of scrambled words:" end_marker = "Answer:" if marker not in page_text or end_marker not in page_text: raise ValueError("could not find the scrambled-word section") chunk = page_text.split(marker, 1)[1].split(end_marker, 1)[0] return [token for token in re.split(r"[\s,]+", chunk) if token]
def unscramble(words, table): result = [] for word in words: key = "".join(sorted(word)) candidates = [value for value in table.values() if "".join(sorted(value)) == key] if not candidates: result.append(word) else: result.append(candidates[0]) return result
def submit(client, answer): response = client.post( f"{LEVEL_URL}index.php", data={"solution": answer, "submitbutton": "submit"}, headers={"Referer": LEVEL_URL}, timeout=30, ) response.raise_for_status() text = body_text(response.text).lower() success_markers = ( "congratulation", "you have completed", "completed this", "successfully", "correct", "well done", "mission accomplished", "complete!", ) failure_markers = ( "wrong", "incorrect", "not correct", "try again", "failed", "too late", "time is up", "sorry", ) success = any(marker in text for marker in success_markers) failure = any(marker in text for marker in failure_markers) if success and not failure: return True if failure and not success: return False return None
def main(): client = session() response = client.get(LEVEL_URL, timeout=20) response.raise_for_status() words = parse_scrambled(body_text(response.text)) table = load_wordlist(WORDLIST) answer = ",".join(unscramble(words, table)) print("scrambled:", words) print("answer :", answer) print("verdict :", submit(client, answer))
if __name__ == "__main__": main()
|