[tryhackme] w1seguy

김기훈·2024년 7월 29일

tryhackme

목록 보기
1/12


이번 문제는 처음 풀어보는 crypto 문제이다.
아래는 서버의 소스코드이다.

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

요약하자면 서버는 문자와 숫자로 이루어진 랜덤한 5자리 Key를 생성하여 flag를 xor 암호화한 뒤 hex 인코딩하여 우리에게 보여준다.
우리는 key를 알아내고 평문을 찾아내야 한다.

nc로 접속해보니 xor 암호화한뒤 hex 인코딩한 문자열이 출력됐고 Key가 뭔지 물어보고 있다.
우리는 tryhackme의 flag 형식을 알고 있기에 평문 일부를 알고 암호문도 알고 있으니 이를 통해 Key를 알아낼 수 있다.

K(암호키) = P(평문) ⊕ C(암호문)


cyberchef에서 입력에 THM{을 넣고 Key에는 출력된 암호문 중 문자열 4자리에 해당되는 앞 8자리 hex값을 넣는다.
그렇게 평문 4자리 THM{ 에 대응되는 Key 4자리 LGyT 를 알아냈다.

마지막 Key 하나는 어떻게 알 수 있을까?
숫자, 영문자 하나씩 대입해보면서 금방 알아낼 수도 있지만 XOR 암호화의 특징을 이용할 수도 있다.

일단 키의 길이와 상관없이 암호문의 길이는 평문의 길이와 같다.
주어진 암호문은 총 40Byte이기 때문에 똑같이 평문도 40Byte이다.
키의 길이가 5Byte이면 평문 40Byte를 암호화할 때 8번 반복해서 암호화를 시킨다.

따라서, 마지막 키 1자리는 평문 마지막 글자가 } 인 것을 이용해서 풀 수 있다.

완전한 키 LGyT7를 얻었고 암호문을 키로 XOR 암호화하면 평문을 얻을 수 있다.

이제 nc 접속으로 돌아가서 Key를 제출하면 두번째 flag까지 얻을 수 있다.

0개의 댓글