Dreamhack Textbook-DH

0

전체세션과제

목록 보기
3/4

https://dreamhack.io/wargame/challenges/120/

Description

  • Alice와 Bob의 통신을 중간자 드림이가 엿보고 있습니다. 둘의 키교환 과정을 공격해 플래그를 획득해주세요



중간자 공격(man in the middle attack, MITM)

  • 네트워크 통신을 조작하여 통신 내용을 도청하거나 조작하는 공격 기법
    MITM

    (출처 : https://textbook.cs161.org/crypto/key-exchange.html)

    즉, 중간자는 Alice와 Bob이 교환하던 키를 탈취해 변조하여 세션키 K1, K2를 얻어낸다.



challenge.py 코드

from Crypto.Util.number import getPrime
from Crypto.Util.Padding import pad, unpad
from Crypto.Cipher import AES
import hashlib
import random

class Person(object):
    def __init__(self, p):
        self.p = p
        self.g = 2
        self.x = random.randint(2, self.p - 1)
    
    def calc_key(self):
        self.k = pow(self.g, self.x, self.p)
        return self.k

    def set_shared_key(self, k):
        self.sk = pow(k, self.x, self.p)
        aes_key = hashlib.md5(str(self.sk).encode()).digest()
        self.cipher = AES.new(aes_key, AES.MODE_ECB)

    def encrypt(self, pt):
        return self.cipher.encrypt(pad(pt, 16)).hex()

    def decrypt(self, ct):
        return unpad(self.cipher.decrypt(bytes.fromhex(ct)), 16)

flag = open("flag", "r").read().encode()
prime = getPrime(1024)
print(f"Prime: {hex(prime)}")
alice = Person(prime)
bob = Person(prime)

alice_k = alice.calc_key()
print(f"Alice sends her key to Bob. Key: {hex(alice_k)}")
print("Let's inturrupt !")
alice_k = int(input(">> "))
if alice_k == alice.g:
    exit("Malicious key !!")
bob.set_shared_key(alice_k)

bob_k = bob.calc_key()
print(f"Bob sends his key to Alice. Key: {hex(bob_k)}")
print("Let's inturrupt !")
bob_k = int(input(">> "))
if bob_k == bob.g:
    exit("Malicious key !!")
alice.set_shared_key(bob_k)

print("They are sharing the part of flag")
print(f"Alice: {alice.encrypt(flag[:len(flag) // 2])}")
print(f"Bob: {bob.encrypt(flag[len(flag) // 2:])}")

해당 코드는 두 송수신자가 키를 교환하여 세션키를 얻어내는 과정으로, g는 2임을 알았기 때문에 중간자는 이를 이용하여 둘 사이의 세션키를 탈취할 수 있다.

<공격 프로세스>

  1. 중간자는 Alice가 보내는 2^a mod p를 탈취하여 저장
  2. Bob에게 2^a mod p 대신 2^m mod p 을 전송 후 (2^a)^m mod p을 계산
  3. Bob이 보내는 2^b mod p를 탈취하여 저장
  4. Alice에게 2^b mod p 대신 2^m mod p 을 전송 후 (2^b)^m mod p을 계산

해당 프로세스를 기반으로 solution.py 코드를 만들어내 플래그를 탈취한다.

solution.py 코드

#!/usr/bin/python3
from pwn import *

from Cryptodome.Util.number import getPrime
from Cryptodome.Util.Padding import pad, unpad
from Cryptodome.Cipher import AES
import hashlib
import random

class Person(object):
    def __init__(self, p):
        self.p = p
        self.g = 2
        self.x = random.randint(2, self.p - 1)
    
    def calc_key(self):
        self.k = pow(self.g, self.x, self.p)
        return self.k

    def set_shared_key(self, k):
        self.sk = pow(k, self.x, self.p)
        aes_key = hashlib.md5(str(self.sk).encode()).digest()
        self.cipher = AES.new(aes_key, AES.MODE_ECB)

    def encrypt(self, pt):
        return self.cipher.encrypt(pad(pt, 16)).hex()

    def decrypt(self, ct):
        return unpad(self.cipher.decrypt(bytes.fromhex(ct)), 16)

p = remote("host3.dreamhack.games",20278)

# p 받아옴
p.recvuntil(b"Prime: ")
prime = int(p.recvline()[:-1],16)

# 클래스 생성
attacker_a = Person(prime)
attacker_b= Person(prime)

# Alice의 공개키 탈취
p.recvuntil(b"Alice sends her key to Bob. Key: ")
alice_k = int(p.recvline()[:-1],16)
attacker_a.set_shared_key(alice_k)

p.sendafter(b">> ",b'32\n')

# Bob의 공개키 탈취
p.recvuntil(b"Bob sends his key to Alice. Key: ")
bob_k = int(p.recvline()[:-1],16)
attacker_b.set_shared_key(bob_k)

p.sendafter(b">> ",b'32\n')

# flag 복호화
p.recvuntil(b"Alice: ")
alice_encrypt_message = p.recvline()[:-1].decode()
p.recvuntil(b"Bob: ")
bob_encrypt_message = p.recvline()[:-1].decode()

flag = ''
flag = attacker_a.decrypt(alice_encrypt_message)
flag += attacker_b.decrypt(bob_encrypt_message)

print("FLAG : {}".format(flag))

0개의 댓글