# [Cryptohack] Static Client - Static Client2 ## 1. Static Client ![](https://i.imgur.com/rfb3Y6Z.png) Nhìn vào ảnh thì mình có thể đoán được đây là dạng tấn công Meet-in-the-middle và Bob với ALice đang sử dụng giao thức trao đổi khóa Diffie Hellman: * Alice và Bob thỏa thuận 1 số module P và g * Alice chọn một số nguyên bí mật A, sau đó gửi cho Bob A = g^a^ (Mod P) * Bob chọn một số nguyên bí mật B, sau đó gửi cho Alice B = g^b^ (Mod P) * Alice tính toán key = B^a^ (mod p) * Bob tính toán key = A^b^ (mod P) * Giờ Alice và Bob đã có chung Key. Chúng ta biết rằng sau khi mình gửi parameters (p,g,A) thì Bob sẽ gửi lại B = g^b^ (Mod P). Vậy nếu mình thay g = A, p giữ nguyên và A là số gì cũng được thì Bob sẽ gửi lại A^b^ (mod P) và đây chính là khóa mình cần tìm :)) Có được khóa thì mình chỉ cần giải mã theo đúng trình tự của AES.mode CBC là ra được flag :triangular_flag_on_post: solve.py ```python= import json from pwn import * import hashlib from Crypto.Cipher import AES from Crypto.Util.Padding import pad,unpad def is_pkcs7_padded(message): padding = message[-message[-1]:] return all(padding[i] == len(padding) for i in range(0, len(padding))) con=remote('socket.cryptohack.org',13373,level='debug') con.recvuntil(b'Intercepted from Alice: ') alice=json.loads(con.recvline()) p_hex,g_hex,A_hex=alice['p'],alice['g'],alice['A'] con.recvuntil(b'Intercepted from Bob: ') B_hex=json.loads(con.recvline())['B'] con.recvuntil(b'Intercepted from Alice: ') content=json.loads(con.recvline()) iv_hex,enc_flag_hex=content['iv'],content['encrypted'] to_bob={"p":p_hex,"g":A_hex,"A":'0x1'} con.sendline(json.dumps(to_bob)) con.recvuntil(b'Bob says to you: ') shared_secret=int(json.loads(con.recvline())['B'],16) con.recvline() def decrypt_flag(shared_secret: int, iv: str, ciphertext: str): # Derive AES key from shared secret sha1 = hashlib.sha1() sha1.update(str(shared_secret).encode('ascii')) key = sha1.digest()[:16] # Decrypt flag ciphertext = bytes.fromhex(ciphertext) iv = bytes.fromhex(iv) cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(ciphertext) if is_pkcs7_padded(plaintext): return unpad(plaintext, 16).decode('ascii') else: return plaintext.decode('ascii') print(decrypt_flag(shared_secret,iv_hex, enc_flag_hex)) ``` **Flag** : crypto{n07_3ph3m3r4l_3n0u6h} ## 2. Static Client2 ![](https://i.imgur.com/LSP0SvB.png) Chall này có vẻ giống bài ở trên nhưng dùng cách đấy lại không hiệu quả . Mình thử một cách khác, thay đổi parameters gửi cho Bob như sau : * g' = 2 * p' sao cho p'-1 là [smooth-number](https://en.wikipedia.org/wiki/Smooth_number) và số bit của p' > p. * A' = A Sau khi gửi thì chúng ta sẽ nhận lại từ Bob B = g^b^ mod(smoothp).Với cách chọn p' như trên cho chúng ta có thể áp dụng thuật toán Pohlig–Hellman để giải quyết bài toán logarit rời rạc B từ đó tìm được b. Mọi người có thể tìm hiểu thêm về Pohlig–Hellman [tại đây](https://en.wikipedia.org/wiki/Pohlig%E2%80%93Hellman_algorithm). solve.py ```python= from pwn import * from Crypto.Util.number import * import json from Crypto.Cipher import AES from Crypto.Util.Padding import pad, unpad import hashlib from sympy.ntheory.residue_ntheory import discrete_log r = remote('socket.cryptohack.org', 13378) def json_recv(): line = r.recvline() return json.loads(line.decode()) def json_send(hsh): request = json.dumps(hsh).encode() r.sendline(request) def smooth_p(): mul = 1 i = 1 while 1: mul *= i if (mul + 1).bit_length() >= p.bit_length() and isPrime(mul + 1): return mul + 1 i += 1 r.recvuntil("Intercepted from Alice: ") res = json_recv() p = int(res["p"], 16) g = int(res["g"], 16) A = int(res["A"], 16) r.recvuntil("Intercepted from Bob: ") res = json_recv() B = int(res["B"], 16) r.recvuntil("Intercepted from Alice: ") res = json_recv() iv = res["iv"] ciphertext = res["encrypted"] s_p = smooth_p() print(s_p.bit_length()) r.recvuntil("send him some parameters: ") json_send({ "p": hex(s_p), "g": hex(2), "A": hex(A) }) r.recvuntil("Bob says to you: ") res = json_recv() B = int(res["B"], 16) b = discrete_log(s_p, B, 2) shared_secret = pow(A, b, p) def is_pkcs7_padded(message): padding = message[-message[-1]:] return all(padding[i] == len(padding) for i in range(0, len(padding))) def decrypt_flag(shared_secret: int, iv: str, ciphertext: str): # Derive AES key from shared secret sha1 = hashlib.sha1() sha1.update(str(shared_secret).encode('ascii')) key = sha1.digest()[:16] # Decrypt flag ciphertext = bytes.fromhex(ciphertext) iv = bytes.fromhex(iv) cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(ciphertext) if is_pkcs7_padded(plaintext): return unpad(plaintext, 16).decode('ascii') else: return plaintext.decode('ascii') print(decrypt_flag(shared_secret, iv, ciphertext)) r.interactive() ``` **flag:** crypto{uns4f3_pr1m3_sm4ll_oRd3r}