# W1seGuy

This is a solver function for the `W1seGuy` challenge of [tryhackme](https://tryhackme.com/r/room/w1seguy).

We get the implementation of the server we can connect to through the
downloaded file.
A key is a random string of alphanumeric characters with a length of 5.
We can take a look an see that there a key xored with the flag.
To execute the xor function the key has to be at the length of the flag. This
is achieved through the modulo over the length of the key. After the key has
been xored the resulting bytestring is changed to a hex representation.

We need to find out the key to xor it with the result we are given by the
server after we have been connected.

```python
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")
    print(hex_encoded)

    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()
```

## Solution

We need 5 characters to rebuild the key and solve the flag.
We know the flag starts with the chars `THM{` and ends with `}`, in total 5
characters.

That is enough information. We connect to the server, get the hexed and xored
flag. It is reversed to its bytestring representation and xored with a random
key. When the string `THM{` is found we've got 4 out of 5 characters of the
key. The fifth is found through iterating the alphanumeric string and xoring
the key with the flag again.

```python
import sys
from pwn import *
import binascii
import string
import random

def solve():
    p = remote(sys.argv[1], 1337)
    r = p.recv().strip().split()
    p.recv()
    alpha = string.ascii_letters + string.digits

    hex_encoded = r[7].decode()
    print(f"Got flag 1: {hex_encoded}")

    hex_decoded = binascii.unhexlify(hex_encoded).decode()
    print(f"Unhexed Key is: {hex_decoded} with a length of {len(hex_decoded)}")

    while True:
        _res = ''
        _key = str(''.join(random.choices(alpha, k=5)))
        _key = _key * (len(hex_decoded) // 5 )
        for i in range(0, len(hex_decoded)):
            _res += chr(ord(hex_decoded[i]) ^ ord(_key[i%len(_key)]))
        if _res.startswith("THM{"):
            for char in alpha:
                res = ''
                key = _key[:4] + char
                key = key * (len(hex_decoded) // 5)
                for i in range(0, len(hex_decoded)):
                    res += chr(ord(hex_decoded[i]) ^ ord(key[i%len(key)]))
                if res.endswith('}'):
                    print("Flag 1: " + res)
                    print("Key: " + key[:5])
                    p.send(key[:5].encode())
                    print(p.recv().decode())
                    return

if __name__ == "__main__":
    solve()
```
