Hidden Handshake
(Very Easy Crypto Challenge)

OVERVIEW
Start The Instance and Download The Given Files:

Let’s see the given server.py
import random, hashlib, string
from Crypto.Cipher import AES
def kdf(pass1, pass2):
return hashlib.sha256(pass1 + pass2).digest()
def generate_password(length):
alphabet = string.ascii_lowercase + string.digits + '!'
return ''.join(random.choice(alphabet) for _ in range(length))
def encrypt(pass1, pass2, plaintext):
key = kdf(pass1, pass2)
cipher = AES.new(key, AES.MODE_CTR, nonce=pass2)
ciphertext = cipher.encrypt(plaintext)
return ciphertext
FLAG = open("flag.txt").read().strip()
print("=== Task Force Phoenix - Operation Blackout Interface ===")
print("Welcome, agent. Secure communications are now active.")
print("----------------------------------------------------------")
server_secret = generate_password(8)
while True:
try:
pass2 = input("Enter your secure access key: ")
user = input("Enter your Agent Codename: ")
assert len(pass2) == 8, "Secure access key must be 8 characters long."
assert len(user) < 1337, "Codename too long."
print("Establishing secure communication channel...")
shared_secret = f"Agent {user}, your clearance for Operation Blackout is: {FLAG}. It is mandatory that you keep this information confidential."
ciphertext = encrypt(server_secret.encode(), pass2.encode(), shared_secret.encode())
print(f"Encrypted transmission: {ciphertext.hex()}")
print("--- End of Transmission ---")
except Exception as e:
print(e)
print("Transmission error.")
So I analyzed it with the help of chatgpt and came to know that:
server_secretis generated once per server execution and used as the AES key derivation input. The server prints an encrypted message usingencrypt(server_secret.encode(), pass2.encode(), shared_secret.encode()).The
encryptfunction derives a key withkdf(pass1, pass2)and creates an AES-CTR cipher withnonce=pass2.The important detail is that the same
pass2value is used for every encryption made during that connection (the program readspass2from input each loop, but the exploit keeps the TCP connection open and reuses the singlepass2for multiple requests).So we exploit this by first obtaining the ciphertext that contains the flag, then requesting additional ciphertexts where we control the codename (sending carefully sized
"A"strings so an'A'aligns with each target flag byte), and finally XORing the target ciphertext with each controlled ciphertext to cancel the keystream — sinceC1 ⊕ C2 = P1 ⊕ P2andP2is'A', the flag bytes are recovered by(C_target ⊕ C_known)[pos] ⊕ 0x41
So the below script is used to retrieve the flag (Be sure to change the required fields such as HOST , PORT)
#!/usr/bin/env python3
import socket
import time
import binascii
import sys
HOST = "Use Your Host Here" #for eg "94.237.57.115"
PORT = <Use Your Port Here> #for eg 1337
PASS2 = "pass123!"
USER_TARGET = ""
MAX_FLAG_BYTES = 120
RECV_TIMEOUT = 3.0
PREFIX = "Agent "
MID = ", your clearance for Operation Blackout is: "
SUFFIX = ". It is mandatory that you keep this information confidential."
def recv_until(sock, marker, timeout=RECV_TIMEOUT):
sock.settimeout(0.7)
buf = ""
tstart = time.time()
while True:
if marker in buf:
return buf
if time.time() - tstart > timeout:
return buf
try:
data = sock.recv(4096)
if not data:
return buf
buf += data.decode(errors="ignore")
except socket.timeout:
continue
def send_and_get_cipher(sock, pass2, user):
recv_until(sock, "Enter your secure access key:")
sock.sendall((pass2 + "\n").encode())
recv_until(sock, "Enter your Agent Codename:")
sock.sendall((user + "\n").encode())
out = recv_until(sock, "--- End of Transmission ---", timeout=5.0)
if "Transmission error." in out:
return None
for line in out.splitlines():
if line.strip().startswith("Encrypted transmission:"):
_, hx = line.split("Encrypted transmission:", 1)
return hx.strip()
return None
def hex_to_bytes(hx):
return binascii.unhexlify(hx)
def xor_bytes(a, b):
return bytes(x ^ y for x, y in zip(a, b))
def recover_flag_online(host, port, pass2, user_target, max_bytes=MAX_FLAG_BYTES):
print(f"[+] connecting to {host}:{port} ...")
sock = socket.create_connection((host, port))
sock.settimeout(1.0)
banner = recv_until(sock, "Enter your secure access key:", timeout=4.0)
print(banner, end="")
print(f"[+] requesting target ciphertext with user='{user_target}' ...")
c_target_hex = send_and_get_cipher(sock, pass2, user_target)
if not c_target_hex:
print("[-] failed to get target ciphertext. Check pass2 and connectivity.")
sock.close()
return
c_target = hex_to_bytes(c_target_hex)
print(f"[+] got target ciphertext (len={len(c_target)} bytes)")
start_target = len(PREFIX) + len(user_target) + len(MID)
print(f"[+] computed FLAG start offset in plaintext = {start_target}")
recovered = bytearray()
for i in range(max_bytes):
absolute_pos = start_target + i
needed_user_len = absolute_pos - len(PREFIX) + 1
if needed_user_len <= 0:
needed_user_len = 1
user_known = "A" * needed_user_len
c_known_hex = send_and_get_cipher(sock, pass2, user_known)
if not c_known_hex:
print(f"[-] failed to get ciphertext for user_known length {needed_user_len}.")
break
c_known = hex_to_bytes(c_known_hex)
if absolute_pos >= len(c_target) or absolute_pos >= len(c_known):
print(f"[-] reached end of ciphertexts at pos {absolute_pos}. Stopping.")
break
pxor = xor_bytes(c_target, c_known)
recovered_byte = pxor[absolute_pos] ^ ord('A')
recovered.append(recovered_byte)
ch = chr(recovered_byte) if 32 <= recovered_byte <= 126 else f"\\x{recovered_byte:02x}"
print(f"[{i:03d}] pos={absolute_pos} -> {ch}")
if recovered_byte == ord('}') or (len(recovered) > 5 and recovered[-1] == 10):
print("[+] heuristic stop: found '}' or newline, stopping.")
break
sock.close()
flag = recovered.decode(errors="ignore")
print("\n[+] recovered bytes (best-effort):")
print(flag)
return flag
if __name__ == "__main__":
print("CTR keystream-reuse exploit script")
print("Make sure HOST/PORT and PASS2 are set at the top of this script.")
try:
recovered_flag = recover_flag_online(HOST, PORT, PASS2, USER_TARGET, MAX_FLAG_BYTES)
print("\nDone.")
except KeyboardInterrupt:
print("\nInterrupted by user.")
except Exception as e:
print("Error:", e)
raise
Use it as :
python3 filename.py #for kali linux, you can use python also in windows/linux

And Here We Got The Flag !!
WE FINALLY DID IT !!!! CHALLENGE SOLVED !!

For Any Query Or Problem Either Leave A Comment Or Contact At reapsec.com
THANKS FOR READING !!!




