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 server is generating a random key of len 5 and xoring the plaintext flag to provide an encrypted string.
in the setup function: if key len< flag len it repeats it
flag= 'THM{fakeflag}'
xored= ''
for i in len(0, len(flag)):
xored+= chr(ord(flag[i] ^ ord(key[i%len(key)]))
plaintext insight is first 4 letters are THM{ and last letter is }
We know, in xor encryption,
plaintext ^ key = cipher
also, cipher ^ plaintext= key
using 2nd eq to get the key part:
import argparse
def derive_key_part(hex_encoded, known_plaintext, start_index):
encoded_bytes= bytes.fromhex(hex_encoded)
derived_key=""
for i in range(len(known_plaintext)):
derived_key+=chr(encode_bytes[i+ start_index] ^ ord(know_plaintext[i])
return derived_key
def xor_decrypt(hex_encoded, key):
encrypted_bytes= bytes.fromhex(hex_encoded)
decrypted_plaintext=""
for i in range(len(hex_encoded)):
decrypted_plaintext+= chr(encrypted_bytes[i] ^ ord(key[i%len(key)])
return decrypted_plaintext
def main():
parser = argparse.ArgumentParser(description='W1seGuy XOR Decryption')
parser.add_argument('hex_encoded', type=str, help='Hex encoded string to decrypt')
#parser.add_argument('key_length', type=int, help='Length of the encryption key')
args = parser.parse_args()
hex_encoded = args.hex_encoded
key_length = 5
# Example usage
known_start_plaintext = 'THM{'
known_end_plaintext = '}'
# Derive the first part of the key using the known starting plaintext
derived_key_start = derive_key_part(hex_encoded, known_start_plaintext, 0)
print("Derived start of the key:", derived_key_start)
# Derive the last character of the key using the known ending plaintext
derived_key_end = derive_key_part(hex_encoded, known_end_plaintext, len(hex_encoded) // 2 - 1)
print("Derived end of the key:", derived_key_end)
# Since the key length is key_length, the derived key will repeat
derived_key = (derived_key_start + derived_key_end)[0:key_length]
print("Derived key:", derived_key)
# Decrypt the full message using the derived key
decrypted_message = xor_decrypt(hex_encoded, derived_key)
print("Decrypted message:", decrypted_message)
if __name__ == '__main__':
main()