Let’s analyse the code :
import random
import socketserver
import socket, os
import string
flag = open('flag.txt','r').read().strip()
def send_message(server, message):
enc = message.encode()
server.send(enc)
def setup(server, key):
flag = 'THM{thisisafakeflag}'
xored = ""
for i in range(0,len(flag)):
xored += chr(ord(flag[i]) ^ ord(key[i%len(key)]))
hex_encoded = xored.encode().hex()
return hex_encoded
def start(server):
res = ''.join(random.choices(string.ascii_letters + string.digits, k=5))
key = str(res)
hex_encoded = setup(server, key)
send_message(server, "This XOR encoded text has flag 1: " + hex_encoded + "\n")
send_message(server,"What is the encryption key? ")
key_answer = server.recv(4096).decode().strip()
try:
if key_answer == key:
send_message(server, "Congrats! That is the correct key! Here is flag 2: " + flag + "\n")
server.close()
else:
send_message(server, 'Close but no cigar' + "\n")
server.close()
except:
send_message(server, "Something went wrong. Please try again. :)\n")
server.close()
class RequestHandler(socketserver.BaseRequestHandler):
def handle(self):
start(self.request)
if __name__ == '__main__':
socketserver.ThreadingTCPServer.allow_reuse_address = True
server = socketserver.ThreadingTCPServer(('0.0.0.0', 1337), RequestHandler)
server.serve_forever()
The listener:
- Creates a random 5-character key using ASCII letters and digits.
- Encrypts the first flag with this key using the XOR operator (
^
). - Prints the encrypted flag (in hexadecimal format).
- Asks the user for the key. If it’s correct, it prints the second flag; otherwise, we get nothing.
Therefore, we know the format of the flags: THM{......}
, so we can calculate the first 4 characters of the key. Once we have the first 4 characters of the key, we can try all possible ASCII letters and digits for the fifth character (62 possibilities in total) and attempt to decrypt the given ciphertext with each possible key. If the decrypted string starts with THM{
and ends with }
, we have succeeded.
So let’s write the Python script give_me_the_key.py
:
import string
ciphertext = "1571793129705858242d0441400b2d350d57213a00574679382d754d220c334d4d7a2c33417b3824"
ciphertext = bytes.fromhex(ciphertext)
# evaluate the firts 4 characters of the key
key = []
key.append(chr(ciphertext[0] ^ ord('T')))
key.append(chr(ciphertext[1] ^ ord('H')))
key.append(chr(ciphertext[2] ^ ord('M')))
key.append(chr(ciphertext[3] ^ ord('{')))
def decrypt(ciphertext, k):
plaintext = ""
for i in range(len(ciphertext)):
p_char = chr(ciphertext[i] ^ ord(k[i % len(k)]))
plaintext += p_char
return plaintext
# define all possible candidates
chars = string.ascii_letters + string.digits
for c in chars:
# define the possible entire key
k_test = ''.join(key) + c
decrypted = decrypt(ciphertext, k_test)
if decrypted.startswith("THM{") and decrypted.endswith("}"):
print(f"[+] Founded possible key : {k_test} -> {decrypted}")
break
and try it :
~ ❯ nc 10.10.103.250 1337
This XOR encoded text has flag 1: ^1571793129705858242d0441400b2d350d57213a00574679382d754d220c334d4d7a2c33417b3824
What is the encryption key? A94JY
Congrats! That is the correct key! Here is flag 2: THM{BrUt3_ForC1nG_XOR_cAn_B3_FuN_nO?}
~ ❯ python3 give_me_the_key.py
[+] Founded possible key : A94JY -> THM{p1alntExtAtt4ckcAnr3alLyhUrty0urxOr}