# PicoCTF - Easy Peasy ###### tags: `PicoCTF` `CTF` `Crypto` Challenge: [Easy Peasy]() ## Background ## Source code :::spoiler source code ```python= #!/usr/bin/python3 -u import os.path KEY_FILE = "key" KEY_LEN = 50000 FLAG_FILE = "flag" def startup(key_location): flag = open(FLAG_FILE).read() kf = open(KEY_FILE, "rb").read() start = key_location stop = key_location + len(flag) key = kf[start:stop] key_location = stop result = list(map(lambda p, k: "{:02x}".format(ord(p) ^ k), flag, key)) print("This is the encrypted flag!\n{}\n".format("".join(result))) return key_location def encrypt(key_location): ui = input("What data would you like to encrypt? ").rstrip() if len(ui) == 0 or len(ui) > KEY_LEN: return -1 start = key_location stop = key_location + len(ui) kf = open(KEY_FILE, "rb").read() if stop >= KEY_LEN: stop = stop % KEY_LEN key = kf[start:] + kf[:stop] else: key = kf[start:stop] key_location = stop result = list(map(lambda p, k: "{:02x}".format(ord(p) ^ k), ui, key)) print("Here ya go!\n{}\n".format("".join(result))) return key_location print("******************Welcome to our OTP implementation!******************") c = startup(0) while c >= 0: c = encrypt(c) ``` ::: ## Exploit - Reuse Key 1. Observe the length of key It's 50000. So, we can reuse it after sending the trash value with length $50000 - len(flag)\ /\ 2$ 2. Then send a given strings with length 32 After sending the trash data, we can reuse the key and though we do not know the flag nor key, we can send something with size 32 that we construct ourselves such as `'a' * 32` The workflow is as below: $flag\ xor\ key = A$ $\{'a'*32\}\ xor\ key = B$ The exploit is $\to$ $B\ xor\ \{'a'*32\}=key$ $key\ xor\ A=flag$ So, the whole expression is $B\ xor\ \{'a'*32\}\ xor\ A=flag$ 3. These code aimed to find the cipher flag and cipher `'a'*32` ```python!= from pwn import * import sys r = remote('mercury.picoctf.net', 11188) context.arch = 'amd64' r.recvline() r.recvline() cipher_flag = r.recvlineS(keepends = False) log.info(f"Cipher flag: {cipher_flag}") r.recvline() r.sendline(b'a'*(50000 - int(len(cipher_flag) / 2))) r.recvline() r.recvline() r.recvline() r.sendline(b'a' * 32) r.recvline() encrypt_32a = r.recvlineS(keepends = False) log.info(f"Cipher 'a' * 32: {encrypt_32a}") plaintext_32a = '61' * 32 log.info(f"Plaintext 'a' * 32: {plaintext_32a}") r.interactive() ``` 4. Find flag ```bash $ python >>> a = 0x551e6c4c5e55644b56566d1b5100153d4004026a4b52066b4a5556383d4b0007 >>> b = 0x03463d1959523d1907513d190503163d1903543d1904573d1900003b3d190457 >>> c = 0x6161616161616161616161616161616161616161616161616161616161616161 >>> '{:x}'.format(a^b^c) '3739303466663833306631633562626138663736333730373234376261336531' >>> print(bytes.fromhex(d).decode('utf-8')) 7904ff830f1c5bba8f763707247ba3e1 ``` The flag is **`picoCTF{7904ff830f1c5bba8f763707247ba3e1}`** ## Reference [picoCTF 2021 easypeasy](https://youtu.be/VodIW2TT_ag) [Easy Peasy - write up](https://github.com/Dvd848/CTFs/blob/master/2021_picoCTF/Easy_Peasy.md)