Skip to content

Instantly share code, notes, and snippets.

@Bono-iPad
Created December 10, 2017 06:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Bono-iPad/20ea24ace03262f19f584e5720957cd2 to your computer and use it in GitHub Desktop.
Save Bono-iPad/20ea24ace03262f19f584e5720957cd2 to your computer and use it in GitHub Desktop.
SECCON 2017 Qual Crypto&PPC 300 Man-in-the-middle on SECP384R1
#!/usr/bin/python3
import socket
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import *
import hashlib
from Crypto.Cipher import AES
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
private_key = ec.generate_private_key( ec.SECP384R1(), default_backend() )
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "mitm.pwn.seccon.jp"
s.connect((host, 8000))
data = s.recv(len("[dev0 to dev1]:"))
print (data)
data = s.recv(120)
#print (data)
k1 = load_der_public_key(data,backend=default_backend())
print (k1)
payload = private_key.public_key().public_bytes(encoding=Encoding.DER, format=PublicFormat.SubjectPublicKeyInfo)
s.send(payload)
data = s.recv(len("\n[dev1 to dev0]: OK\n"))
print (data)
data = s.recv(len("[dev1 to dev0]:"))
print (data)
data = s.recv(120)
#print (data)
k2 = load_der_public_key(data,backend=default_backend())
print (k2)
payload = private_key.public_key().public_bytes(encoding=Encoding.DER, format=PublicFormat.SubjectPublicKeyInfo)
s.send(payload)
data = s.recv(len("\n[dev0 to dev1]: OK\n"))
print (data)
# let's calc key!
sk1 = private_key.exchange(ec.ECDH(),k1) # k1 = dxG
sk2 = private_key.exchange(ec.ECDH(),k2) # k2 = dyG
print (repr(sk1))
print (repr(sk2))
data = s.recv(len("[KBKDF: SHA256, Encryption: AES]\n"))
print (data)
## derive keys
aesk1 = hashlib.sha256(sk1)
aesk2 = hashlib.sha256(sk2)
a1 = AES.new( aesk1.digest(),AES.MODE_CBC,"0000000000000000")
print ("key1: %s" % aesk1.hexdigest() )
print ("key2: %s" % aesk2.hexdigest() )
data = s.recv(len("[dev0 to dev1]:"))
print (data)
data = s.recv(256)
print ("received: ")
print (repr(data))
q = a1.decrypt(data)
print ("decrypt: ")
print (repr(q))
print (len(q))
iv = q[0:16]
a2 = AES.new( aesk2.digest(),AES.MODE_CBC,"0000000000000000")
## todo
# mitm
ct = a2.encrypt(iv + b"0"*240)
print (repr(ct))
print (len(ct))
print (a2.decrypt(ct))
s.send(ct)
data = s.recv(len("\n[dev1 to dev0]: OK\n"))
print (data)
data = s.recv(len("[dev1 to dev0]:"))
print (data)
data = s.recv(256)
print (data)
## todo
# decrypt
a2 = AES.new( aesk2.digest(),AES.MODE_CBC,"0000000000000000")
print (a2.decrypt(data))
# SECCON{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFCB3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF00000000000000000000000000000000000000000000000000000000}
@Bono-iPad
Copy link
Author

Bono-iPad commented Dec 10, 2017

やること自体はWikipediaに書いてあるDH鍵交換の中間者攻撃( https://ja.wikipedia.org/wiki/ディフィー・ヘルマン鍵共有 )そのものなのですが

  1. 鍵交換のフォーマットがDER
  2. AESとはAES-256-CBCのこと(ECBではない)
  3. ivはやりとりされていないので、まずiv="\x00"*16とかにして、そこからdecryptされた文章より、多分ivの最後は"0"が3つのような気がする、じゃあ適当に全部"0"にしてみるか……あ、当たった

などのguessingのプロセスが必要となり、本質と異なるところで難易度が上がっている印象でした。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment