Files
ctf/2025/glacier/rev/guessy-timezones/solve.py
2025-11-22 21:21:24 +01:00

80 lines
2.4 KiB
Python

from pwn import remote, log
import ctypes
import sys
import re
# Set up the connection
host = 'challs.glacierctf.com'
port = 13386
p = remote(host, port)
# Load the C library (Liquids/glibc)
# This is required to match the server's random number generation.
# Note: This usually requires running on Linux to match a Linux server.
try:
libc = ctypes.CDLL('libc.so.6')
except OSError:
# Fallback for Mac/others, though values might differ from the Linux server
libc = ctypes.CDLL(None)
log.warning("Could not explicitly load libc.so.6. Using default system libc. If on Windows/Mac, numbers might not match server.")
def solve():
# 1. Wait for the initial prompt '>'
p.recvuntil(b'>')
# 2. "Write time" -> Send the command to get the seed info
log.info("Sending 'time' command...")
p.sendline(b'time')
# 3. Wait for ':' (The prompt for timezone)
p.recvuntil(b':')
# 4. Write "Europe/Berlin"
log.info("Sending timezone 'Europe/Berlin'...")
p.sendline(b'Europe/Berlin')
# 5. Receive the output containing the seed
# We expect:
# THIS IS THE STRING: 20251122201640
# THIS IS THE SEED: 351401000
response = p.recvuntil(b'>', drop=True).decode() # Read until next prompt/menu
print(f"\nServer Response:\n{response}\n")
# 6. Parse the seed using Regex
# Looking for: "THIS IS THE SEED: <number>"
match = re.search(r'THIS IS THE SEED:\s*(\d+)', response)
if match:
seed = int(match.group(1))
log.success(f"Extracted Seed: {seed}")
else:
log.error("Could not find seed in server response!")
return
# 7. Initialize srand with the extracted seed
libc.srand(seed)
log.info("Initialized local C library with seed.")
# 8. Generate the number
# This should match the server's next rand() call
generated_number = libc.rand()
log.success(f"Predicted Random Number: {generated_number}")
# 9. "Write solve" -> Send the solve command
log.info("Sending 'solve' command...")
p.sendline(b'solve')
# 10. Wait for ':' (The prompt for the random number)
p.recvuntil(b':')
# 11. Send the generated number
log.info(f"Sending predicted number: {generated_number}")
p.sendline(str(generated_number).encode())
# 12. Switch to interactive mode to see the flag/result
p.interactive()
if __name__ == "__main__":
solve()