Rating:
# b00t2root 2020 CTF - Crypto Challenges
I represent to you my writeups for all Crypto challenges from b00t2root 2020 CTF.


## Challenge 1 : _Try try but don't cry_

We were given a source code :
```python
import random
def xor(a,b):
l=""
for i in range(min(len(a), len(b))):
l+=chr(ord(a[i]) ^ ord(b[i]))
return l
def encrypt(flag):
l=random.randrange(2)
if(l==0):
return flag.encode('base64')
elif(l==1):
return flag.encode('hex')
flag="################"
assert(len(flag)==22)
c=xor(flag[:11], flag[11:])
c=c.encode('hex')
n=random.randint(1,20)
#print(n)
for _ in range(n):
c=encrypt(c)
f=open('chall.txt', 'w')
f.write(c)
f.close()
```
The main problem here is that we don't know when it's Base64 or Hex. So i just wrote a script to decode it manualy by entering H if it's Hex or B if it's Base64, then since i know a part of the flag which is "_b00t2root{}_" with length **11**, I can retrive the flag.
**Solver :**
```python
from pwn import xor
import base64
cipher = open("chall.txt").read().strip()
while len(cipher) != 22:
print(cipher)
ans = input('> ').strip()
if ans == 'H':
cipher = bytes.fromhex(cipher).decode()
elif ans == 'B':
cipher = base64.b64decode(cipher).decode()
cipher = bytes.fromhex(cipher).decode()
s = b"b00t2root{"
s += xor(cipher[-1], '}')
t = xor(s, cipher[:len(s)])
flag = s+t
print(flag)
```

FLAG is **_b00t2root{fantasticcc}_**

## Challenge 2 : _Euler's Empire_

I'll skip this cause it's almost the same challenge as [Time Capsule](https://github.com/pberba/ctf-solutions/blob/master/20190810-crytoctf/crypto-122-time-capsule/time-capsule-solution.ipynb) from Crypto CTF 2019.
FLAG is **_b00t2root{Eul3r_w4s_4_G3niu5}_**

## Challenge 3 : _007_

We were given a source code :
```python
import random
def rot(s, num):
l=""
for i in s:
if(ord(i) in range(97,97+26)):
l+=chr((ord(i)-97+num)%26+97)
else:
l+=i
return l
def xor(a, b):
return chr(ord(a)^ord(b))
def encrypt(c):
cipher = c
x=random.randint(1,1000)
for i in range(x):
cipher = rot(cipher, random.randint(1,26))
cipher = cipher.encode('base64')
l = ""
for i in range(len(cipher)):
l += xor(cipher[i], cipher[(i+1)%len(cipher)])
return l.encode('base64')
flag = "#################"
print "cipher =", encrypt(flag)
#OUTPUT: cipher = MRU2FDcePBQlPwAdVXo5ElN3MDwMNURVDCc9PgwPORJTdzATN2wAN28=
```
To reverse the xor loop, we have to know the first character of the _cipher_. It should be in [a-z], so with simple bruteforce we can retrieve the correct rotated string. Then we try all rotations from 1 to 26 and get the flag.
**Solver :**
```python
import random
import base64
def rot(s, num):
l=""
for i in s:
if(ord(i) in range(97,97+26)):
l+=chr((ord(i)-97+num)%26+97)
else:
l+=i
return l
def xor(a, b):
return chr(ord(a)^ord(b))
enc = base64.b64decode("MRU2FDcePBQlPwAdVXo5ElN3MDwMNURVDCc9PgwPORJTdzATN2wAN28=").decode('latin-1')
for i in range(97,123):
xored = chr(i)
j = -1
while j != -len(enc):
xored = xor(enc[j],xored[0]) + xored
j -= 1
xored = xored[-1] + xored[:-1]
try:
res = base64.b64decode(xored).decode()
for i in range(1, 26):
flag = rot(res, i)
if "b00t2root{" in flag:
print(flag)
except:
pass
```
FLAG is **_b00t2root{Bond. James Bond.}_**

## Challenge 4 : _brokenRSA_

We were given a source code :
```python
from Crypto.Util.number import *
import random
e = 4
def func(m):
while(True):
n = getPrime(512)
x = pow(m, e, n)
if(pow(x, (n-1)//2, n) == 1):
return n
flag = bytes_to_long(b"############################")
n = func(flag)
print("n =", n)
print("c =", pow(flag, e, n))
# OUTPUT
# n = 11183632493295722900188836927564142822637910363304123337597708503476804292242860556684644449701772313571249316546794463854991452685201761786385895405863639
# c = 8939043592146774508422725937231398285333145869395369605787177287036646137314173055510198460479672008589091362568215564488685390459997440273900039337645280
```
We can observe that the modulus ```n``` is a prime number. So since the exponent ```e``` is a power of 2, we can take consecutive square roots to find the eth root.
Therefore we will use [Tonelli Shanks Algorithm](https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm) to compute module square roots and convert each one to get the correct flag.
**Solver :**
```python
from Crypto.Util.number import long_to_bytes
n = 11183632493295722900188836927564142822637910363304123337597708503476804292242860556684644449701772313571249316546794463854991452685201761786385895405863639
c = 8939043592146774508422725937231398285333145869395369605787177287036646137314173055510198460479672008589091362568215564488685390459997440273900039337645280
e = 4
def legendre(a, p):
return pow(a, (p - 1) // 2, p)
def tonelli(n, p):
assert legendre(n, p) == 1, "not a square (mod p)"
q = p - 1
s = 0
while q % 2 == 0:
q //= 2
s += 1
if s == 1:
return pow(n, (p + 1) // 4, p)
for z in range(2, p):
if p - 1 == legendre(z, p):
break
c = pow(z, q, p)
r = pow(n, (q + 1) // 2, p)
t = pow(n, q, p)
m = s
t2 = 0
while (t - 1) % p != 0:
t2 = (t * t) % p
for i in range(1, m):
if (t2 - 1) % p == 0:
break
t2 = (t2 * t2) % p
b = pow(c, 1 << (m - i - 1), p)
r = (r * b) % p
c = (b * b) % p
t = (t * c) % p
m = i
return r
def find_square_roots(c, e):
if e == 1:
flag = long_to_bytes(c)
if b"b00t2root" in flag:
print(flag)
return
elif pow(c,(n-1)//2,n) != 1:
return
else:
rt1 = tonelli(c, n)
find_square_roots(rt1, e//2)
rt2 = n - rt1
find_square_roots(rt2, e//2)
return
find_square_roots(c, e)
```
FLAG is **_b00t2root{finally_legendre_symbol_came_in_handy}_**

## Challenge 5 : _The Heist_

We were given a netcat server and a source code of the program running on it :
```python
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad,unpad
import binascii
import sys
key = b"****************"
iv = key
flag = "***********************"
def encrypt(str1):
obj = AES.new(key, AES.MODE_CBC, iv)
str1 = pad(str1,16)
ciphertext = obj.encrypt(str1)
return binascii.hexlify(ciphertext)
def decrypt(str2):
obj=AES.new(key, AES.MODE_CBC, iv)
plaintext=obj.decrypt(str2)
return binascii.hexlify(plaintext)
s="""
1. Enter key and get flag
2. Encrypt plaintext
3. Decrypt ciphertext
Enter option: """
while(True):
try:
print(s, end='')
opt=int(input())
if(opt==1):
KEY = input("Enter hex key: ")
KEY = binascii.unhexlify(KEY)
if(KEY==key):
print(flag)
break;
elif(opt==2):
pt = input("Enter hex plaintext: ")
pt = pt.encode('utf-8')
pt = binascii.unhexlify(pt)
print("Ciphertext: ", encrypt(pt).decode('utf-8'))
elif(opt==3):
ct = input("Enter hex ciphertext: ")
ct = ct.encode('utf-8')
ct = binascii.unhexlify(ct)
print("Plaintext: ", decrypt(ct).decode('utf-8'))
else:
print("The input should be in between 1 and 3")
except:
print("Error")
```
When we connect to the server, it gives us 3 choices :

The encryption/decryption is based on AES CBC mode.
To get the flag we should retrieve the _KEY_. We can see that ```IV = KEY``` so we need to know the value of _IV_ in order to get the _KEY_. Let's do some analysis :
Suppose we encrypt a plaintext with 3 blocks (48 bytes) and we get our ciphertext. Now we are going to decrypt it, so the equations for each plaintext block will be :
```
P1 = D(C1) xor IV
P2 = D(C2) xor C1
P3 = D(C3) xor C2
```
When C1 = C3 and C2 is an empty block (which means 16*"\x00"), then :
```
P1 = D(C1) xor IV
P3 = D(C3) xor 0 = D(C3) = D(C1)
```
So by xoring P1 and P3 we get the _IV_.
**Solver :**
```python
from pwn import *
cipher = "414141414141414141414141414141410000000000000000000000000000000041414141414141414141414141414141"
conn = remote("157.230.237.229",2200)
conn.recvuntil("Enter option: ")
conn.sendline('3')
conn.recvuntil("Enter hex ciphertext: ")
conn.sendline(cipher)
plaintext = conn.recvline().decode().strip().split(' ')[2]
plaintext = bytes.fromhex(plaintext)
IV = xor(plaintext[0:16],plaintext[32:48]).hex()
conn.recvuntil("Enter option: ")
conn.sendline('1')
conn.recvuntil("Enter hex key: ")
conn.sendline(IV)
flag = conn.recv().strip().decode()
print(flag)
```

FLAG is **_b00t2root{th3y_4r3_g0ing_t0_k1ll_u5}_**