Skip to content

Instantly share code, notes, and snippets.

@ThanniKudam
Last active October 26, 2025 07:54
Show Gist options
  • Select an option

  • Save ThanniKudam/8c1137a9b2b8be6be261d6ad081a8c6f to your computer and use it in GitHub Desktop.

Select an option

Save ThanniKudam/8c1137a9b2b8be6be261d6ad081a8c6f to your computer and use it in GitHub Desktop.
dreadnode interact cli
"""If you are doing dreadnode challenges, this code will help you to interact with the server easily via cli."""
#!/usr/bin/env python3
"""
Enhanced dreadnode_cli.py
Beautiful terminal interface for Dreadnode CTF challenge interaction and flag submission.
"""
import os
import sys
import json
import requests
import textwrap
from pprint import pprint
try:
from colorama import init, Fore, Style
except ImportError:
os.system("pip install colorama --quiet")
from colorama import init, Fore, Style
init(autoreset=True)
# --- Configuration ---
CHALLENGE = "whatistheflag"
CRUCIBLE_URL = "https://platform.dreadnode.io"
CHALLENGE_URL = "https://whatistheflag.platform.dreadnode.io"
# ----------------------
def get_api_key():
key = os.environ.get("DREADNODE_API_KEY")
if key:
print(f"{Fore.GREEN}Using DREADNODE_API_KEY from environment.")
return key.strip()
k = input(f"{Fore.YELLOW}Enter your DREADNODE_API_KEY: {Style.RESET_ALL}").strip()
if not k:
print(f"{Fore.RED}No API key provided. Exiting.")
sys.exit(1)
return k
def query(api_key, input_data):
url = f"{CHALLENGE_URL}/score"
headers = {"X-API-Key": api_key}
payload = {"data": input_data}
try:
resp = requests.post(url, headers=headers, json=payload, timeout=15)
except requests.RequestException as e:
return {"error": f"request failed: {e}"}
try:
return resp.json()
except ValueError:
return {"status_code": resp.status_code, "text": resp.text}
def submit_flag(api_key, flag):
url = f"{CRUCIBLE_URL}/api/challenges/{CHALLENGE}/submit-flag"
headers = {"X-API-Key": api_key}
payload = {"challenge": CHALLENGE, "flag": flag}
try:
resp = requests.post(url, headers=headers, json=payload, timeout=15)
except requests.RequestException as e:
return {"error": f"request failed: {e}"}
try:
return {"status_code": resp.status_code, "body": resp.json()}
except ValueError:
return {"status_code": resp.status_code, "text": resp.text}
def pretty_print_response(res):
"""Nicely format the response output with colors and spacing."""
print(f"\n{Fore.CYAN}{'-'*60}{Style.RESET_ALL}")
print(f"{Fore.MAGENTA}Response:{Style.RESET_ALL}\n")
if isinstance(res, dict) and "output" in res:
output = res["output"]
wrapped = textwrap.fill(output, width=80)
print(f"{Fore.GREEN}{wrapped}{Style.RESET_ALL}")
else:
pprint(res)
print(f"{Fore.CYAN}{'-'*60}{Style.RESET_ALL}\n")
def interactive_mode(api_key):
print(f"""{Fore.CYAN}
╔══════════════════════════════════════════════════════════╗
║ INTERACTIVE MODE - DREADNODE ║
╚══════════════════════════════════════════════════════════╝
Type any message to send to the challenge.
Commands:
{Fore.YELLOW}:exit{Style.RESET_ALL} → quit interactive mode
{Fore.YELLOW}:submit <flag>{Style.RESET_ALL} → submit a flag directly
{Fore.YELLOW}:help{Style.RESET_ALL} → show this help again
───────────────────────────────────────────────────────────
""")
last_response = None
while True:
try:
prompt = input(f"{Fore.BLUE}you> {Style.RESET_ALL}").rstrip()
except (KeyboardInterrupt, EOFError):
print(f"\n{Fore.YELLOW}Exiting interactive mode.{Style.RESET_ALL}")
break
if not prompt:
continue
if prompt == ":exit":
print(f"{Fore.YELLOW}Bye.{Style.RESET_ALL}")
break
elif prompt == ":help":
print("Commands: :exit | :submit <flag> | :help")
continue
elif prompt.startswith(":submit "):
flag = prompt.partition(" ")[2].strip()
if not flag:
print(f"{Fore.RED}No flag provided after :submit.{Style.RESET_ALL}")
continue
print(f"{Fore.YELLOW}Submitting flag...{Style.RESET_ALL}")
res = submit_flag(api_key, flag)
pretty_print_response(res)
continue
print(f"{Fore.YELLOW}Sending to challenge...{Style.RESET_ALL}")
res = query(api_key, prompt)
last_response = res
pretty_print_response(res)
# Heuristic flag detection
def find_flag(obj):
if isinstance(obj, str) and obj.startswith("gAAAAA"):
return obj
if isinstance(obj, dict):
for v in obj.values():
f = find_flag(v)
if f:
return f
if isinstance(obj, list):
for v in obj:
f = find_flag(v)
if f:
return f
return None
found = find_flag(res)
if found:
print(f"{Fore.GREEN}⚑ Potential Flag Found: {Fore.YELLOW}{found}{Style.RESET_ALL}\n")
def submit_mode(api_key):
print(f"{Fore.CYAN}\n--- SUBMIT MODE ---{Style.RESET_ALL}")
flag = input(f"{Fore.YELLOW}Enter the flag to submit: {Style.RESET_ALL}").strip()
if not flag:
print(f"{Fore.RED}No flag provided. Abort.{Style.RESET_ALL}")
return
print(f"{Fore.YELLOW}Submitting flag...{Style.RESET_ALL}")
res = submit_flag(api_key, flag)
pretty_print_response(res)
if res.get("body", {}).get("correct") is True:
print(f"{Fore.GREEN}✅ The flag was correct. Congrats!{Style.RESET_ALL}")
else:
print(f"{Fore.RED}❌ Incorrect flag. Keep trying!{Style.RESET_ALL}")
def main():
print(f"{Fore.CYAN}Dreadnode CLI — interact with the challenge or submit a flag.{Style.RESET_ALL}")
api_key = get_api_key()
while True:
print(f"""
{Fore.CYAN}Choose an action:{Style.RESET_ALL}
{Fore.YELLOW}1){Style.RESET_ALL} Interact with the challenge
{Fore.YELLOW}2){Style.RESET_ALL} Submit a flag
{Fore.YELLOW}3){Style.RESET_ALL} Exit
""")
choice = input(f"{Fore.BLUE}select> {Style.RESET_ALL}").strip()
if choice == "1":
interactive_mode(api_key)
elif choice == "2":
submit_mode(api_key)
elif choice == "3":
print(f"{Fore.YELLOW}Goodbye!{Style.RESET_ALL}")
break
else:
print(f"{Fore.RED}Invalid choice. Please choose 1, 2, or 3.{Style.RESET_ALL}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment