Cubic#
Helpers#
import numpy as np
import os
import requests
import time
from dotenv import load_dotenv
from string import ascii_uppercase as CHARS
load_dotenv()
API_KEY = os.environ["API_KEY"]
URL_QUERY = "https://%s.crucible.dreadnode.io/%s"
URL_FLAG = "https://crucible.dreadnode.io/api/challenges/%s/submit-flag"
CHALLENGE = "cubic"
def query(data, route="score"):
response = requests.post(
URL_QUERY % (CHALLENGE, route),
headers={ "X-API-Key": API_KEY },
json={ "data": data }
)
return response.json()
def submit(flag):
response = requests.post(
URL_FLAG % CHALLENGE,
headers={ "X-API-Key": API_KEY },
json={ "challenge": CHALLENGE, "flag": flag }
)
return False if response.status_code != 200 else response.json().get("correct")
Solution#
If we submit some random values to the endpoint we can see that it returns 12 logits.
data = np.zeros((64, 1))
query(data.tolist(), route="predict")["prediction"]
[[0.27251669404844703],
[0.26096517762029814],
[0.2632274650925554],
[0.31077285026202944],
[0.31527584262764974],
[0.2507438205101342],
[0.2499624217505734],
[0.27631836345169647],
[0.27471431660350865],
[0.2710597178020978],
[0.31458430128313064],
[0.3137506504889416]]
Similar to Genigma, for each of the 12 logits we can submit 64 different queries where each query contains 63 zeros and a single large value. If we take the index which maximizes the logit and then reverse index into the alphabet we can find the flag.
Note: for convenience, the below code only submits 26 different queries as it turns out that the logit is always maximized within the first 26 values.
flag_chars = []
for logit in range(12):
max_value = 0.0
max_option = 0
for option in range(26):
data = np.zeros((64, 1))
data[option][0] = 100
response = query(data.tolist(), route="predict")
value = response["prediction"][logit][0]
if value > max_value:
max_value = value
max_option = option
time.sleep(1)
flag_chars.append(CHARS[25 - max_option])
flag = "".join(flag_chars)
print(flag)
print("Flag accepted:", submit(query(flag)["flag"]))
THREEBYTHREE
Flag accepted: True