h4cker/capture_the_flag/challenges/heavy_computation/encrypt.py
2020-05-11 01:56:21 -04:00

125 lines
4.9 KiB
Python

Heavy computation(400)
Question:
A friend of mine handed me this script and challenged me to recover the flag. However, I started running it on my school cluster and everything is burning now... Help me please!
Given files:
encrypt.py
from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from secret import password, flag
from hashlib import sha256
NB_ITERATIONS = 10871177237854734092489348927
e = 65538
#Old N : N = 16725961734830292192130856503318846470372809633859943564170796604233648911148664645199314305393113642834320744397102098813353759076302959550707448148205851497665038807780166936471173111197092391395808381534728287101705
N = 14968794114523720195251887716913440457986979987674770429103169854116498198112478103466085455257317270930523061714030307370028304505577267672733143013124254253285088080041831478700041394909740024011681885623055622400205
def derive_key(password):
start = bytes_to_long(password)
#Making sure I am safe from offline bruteforce attack
for i in range(NB_ITERATIONS):
start = start ** e
start %= N
#We are never too cautious let's make it harder
key = 1
for i in range(NB_ITERATIONS):
key = key ** e
key %= N
key *= start
key %= N
return sha256(long_to_bytes(key)).digest()
assert(len(password) == 2)
assert(password.decode().isprintable())
key = derive_key(password)
IV = b"random_and_safe!"
cipher = AES.new(key, AES.MODE_CBC,IV)
enc = cipher.encrypt(pad(flag,16))
with open("flag.enc","wb") as output_file:
output_file.write(enc)
flag.enc(dump)
0000 f4 d8 e5 a2 ac 80 6c e9 dc c1 ef 1e d5 c4 51 7c ......l.......Q|
0010 e3 d8 84 1a d7 c0 77 c9 9c b0 f6 f0 ab 13 63 b0 ......w.......c.
0020 f9 5e 8d cd 87 ce c7 d3 88 7a 4a 68 de a9 6f 96 .^.......zJh..o.
0030 77 cf 1e a7 95 a0 f8 1c be 3a 66 f0 aa 73 2c 3e w........:f..s,>
Solution:
Outline:
(1) For preparartion, we calcurate Euler's totient of N by FactorDb( http://www.factordb.com/ ):
N=5*23*61*701*3043975283150884175290138965903193067634156680289693153778518185326633105971710936004483047892546798724665417739250476586249010832824560305913279982496088828053414799963361876618585076997170323631281630177651847
(2) First part of the functuon "derive_key":
for i in range(NB_ITERATIONS):
start = start ** e
start %= N
It is easily simplificated by Euler's theorem.
start = pow(bytes_to_long(password),pow(e,NB_ITERATIONS,phi_N), N)
where phi_N is the totient of N,
phi_N=(5-1)* (23-1)* (61-1)* (701-1)* (3043975283150884175290138965903193067634156680289693153778518185326633105971710936004483047892546798724665417739250476586249010832824560305913279982496088828053414799963361876618585076997170323631281630177651847-1)
(3) Second Part of the functuon "derive_key":
key = 1
for i in range(NB_ITERATIONS):
key = key ** e
key %= N
key *= start
key %= N
We can replace it with the following (using "invert" function of gmpy2).
inv_e = gmpy2.invert(e-1,phi_N)
key = pow(start, (pow(e,NB_ITERATIONS,phi_N)-1) * inv_e, N)
(4) Finally, We brute force the password and get the flag!
Solver:
solve.py
from Crypto.Util.number import bytes_to_long, long_to_bytes
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from hashlib import sha256
import gmpy2
NB_ITERATIONS = 10871177237854734092489348927
e = 65538
N = 14968794114523720195251887716913440457986979987674770429103169854116498198112478103466085455257317270930523061714030307370028304505577267672733143013124254253285088080041831478700041394909740024011681885623055622400205
#Using FactorDB, we have N=5*23*61*701*3043975283150884175290138965903193067634156680289693153778518185326633105971710936004483047892546798724665417739250476586249010832824560305913279982496088828053414799963361876618585076997170323631281630177651847
phi_N = (5-1)*(23-1)*(61-1)*(701-1)*(3043975283150884175290138965903193067634156680289693153778518185326633105971710936004483047892546798724665417739250476586249010832824560305913279982496088828053414799963361876618585076997170323631281630177651847-1)
def derive_key(password):
start = bytes_to_long(password)
start = pow(start,pow(e,NB_ITERATIONS,phi_N), N)
inv_e = gmpy2.invert(e-1,phi_N)
key = pow(start, (pow(e,NB_ITERATIONS,phi_N)-1) * inv_e, N)
return sha256(long_to_bytes(key)).digest()
with open('flag.enc','rb') as f:
flag_enc = f.read()
for i in range(0x20, 0x100):
for j in range(0x20, 0x100):
password = long_to_bytes(i) + long_to_bytes(j)
key = derive_key(password)
IV = b"random_and_safe!"
cipher = AES.new(key, AES.MODE_CBC,IV)
flag = cipher.decrypt(flag_enc)
if(flag[0:6] == b'shkCTF'):
print(flag.decode('utf-8')[0:flag.decode('utf-8').find('}')+1])
break
Flag:
shkCTF{M4ths_0v3r_p4t13Nce_b4453d1f9f5386a1846e57a3ec95678f}