Rating:
### leaky_blinders.py
```python
#!/usr/bin/env python3.8
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import sys, os
FLAG = b"FwordCTF{###############################################################}"
WELCOME = '''
Welcome to Enc/Dec Oracle.
'''
key = os.urandom(32)
def xor(a, b):
return bytearray([a[i % len(a)] ^ b[i % len(b)] for i in range(max(len(a), len(b)))])
def encrypt(msg):
aes = AES.new(key, AES.MODE_ECB)
if len(msg) % 16 != 0:
msg = pad(msg, 16)
cipher = aes.encrypt(msg)
cipher = xor(cipher, key)
return cipher
def decrypt(cipher, k):
aes = AES.new(k, AES.MODE_ECB)
cipher = xor(cipher, k)
msg = unpad(aes.decrypt(cipher), 16)
return msg
class Leaky_Blinders:
def __init__(self):
print(WELCOME + f"Here is the encrypted flag : {encrypt(FLAG).hex()}")
def start(self):
try:
while True:
print("\n1- Encrypt")
print("2- Decrypt")
print("3- Leave")
c = input("> ")
if c == '1':
msg = os.urandom(32)
cipher = encrypt(msg)
if all(a != b for a, b in zip(cipher, key)):
print(cipher.hex())
else:
print("Something seems leaked !")
elif c == '2':
k = bytes.fromhex(input("\nKey : "))
cipher = bytes.fromhex(input("Ciphertext : "))
flag = decrypt(cipher, k)
if b"FwordCTF" in flag:
print(f"Well done ! Here is your flag : {FLAG}")
else:
sys.exit("Wrong key.")
elif c == '3':
sys.exit("Goodbye :)")
except Exception:
sys.exit("System error.")
if __name__ == "__main__":
challenge = Leaky_Blinders()
challenge.start()
```
When program runs, it generates a string of 32 **random bytes** with `os.urandom(32)`.
`key = os.urandom(32)`
Then, it defines some functions and a *class* `Leaky_Blinders`.
In class `Leaky_Blinders`, the **\_\_init\_\_** method prints the welcome message and **encrypted** flag in **hex**.
```python
def __init__(self):
print(WELCOME + f"Here is the encrypted flag : {encrypt(FLAG).hex()}")
```
The *start* method, loops forever and asks for *choice* (1.Encrypt, 2.Decrypt, 3.Leave).
Choice '2' is interesting!
```python
elif c == '2':
k = bytes.fromhex(input("\nKey : "))
cipher = bytes.fromhex(input("Ciphertext : "))
flag = decrypt(cipher, k)
if b"FwordCTF" in flag:
print(f"Well done ! Here is your flag : {FLAG}")
else:
sys.exit("Wrong key.")
```
It asks the *key* and *ciphertext* in hex and passes them to `decrypt` function.
If result of the `decrypt` function contains **FwordCTF**, it will print out the flag.
Let's see what's in `decrypt` function!
```python
def decrypt(cipher, k):
aes = AES.new(k, AES.MODE_ECB)
cipher = xor(cipher, k)
msg = unpad(aes.decrypt(cipher), 16)
return msg
```
It **xor** the *cipher* with *key* and decrypt the *cipher* in **AES**.
So, to get the flag, we have to encrypt a string that contains **FwordCTF** with random *key* in **AES** and *xor* the *cipher* with that random *key* and send that!
Let's try it!
### solve.py
```python
from pwn import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
key = b"A"*32 # key length is 32 so here 32 'A'
plain_text = b"FwordCTF"
# stole code from the challenge :-)
def xor(a, b):
return bytearray([a[i % len(a)] ^ b[i % len(b)] for i in range(max(len(a), len(b)))])
def encrypt(msg):
aes = AES.new(key, AES.MODE_ECB)
if len(msg) % 16 != 0:
msg = pad(msg, 16)
cipher = aes.encrypt(msg)
cipher = xor(cipher, key)
return cipher
cipher = encrypt(plain_text) # cipher to send
# connecting to target host
conn = remote("52.149.135.130", 4869)
conn.recvuntil(b"> ")
conn.sendline("2")
# Sending key and cipher in hex
conn.sendline(key.hex())
conn.sendline(cipher.hex())
conn.interactive()
```
```sh
$ python3 solve.py
[+] Opening connection to 52.149.135.130 on port 4869: Done
[*] Switching to interactive mode
Key : Ciphertext : Well done ! Here is your flag : b'FwordCTF{N3v3r_x0r_w1thout_r4nd0m1s1ng_th3_k3y_0r_m4yb3_s3cur3_y0ur_c0d3}'
1- Encrypt
2- Decrypt
3- Leave
> $
[*] Interrupted
[*] Closed connection to 52.149.135.130 port 4869
```
Yay! There is the flag!!!
*flag*: `wordCTF{N3v3r_x0r_w1thout_r4nd0m1s1ng_th3_k3y_0r_m4yb3_s3cur3_y0ur_c0d3}`