아직도 생각하면 멘탈 나가는 문제
양자 통신 프로토콜 BB84를 구현한 문제이다.
https://ko.wikipedia.org/wiki/%EC%96%91%EC%9E%90%EC%95%94%ED%98%B8 : 위키백과
우리는 Alice와 Bob이 통신하는 것을 도청과 값을 바꿀 수 있는데, 이 때문에 Man in the Middle Attack이 가능하다.
일단 어떤 절차인지 알아보자
일단 이 프로그램은 편광필터(기저, Basis)를 Y와 Z로 구분했고 비트는 -1, 1이 존재한다.
1. Alice가 600개의 랜덤한 기저와 비트를 생성해서 Bob에게 보낸다. Bob은 Z기저 1을 보내어 ACK 확인을 한다.
2. Bob은 600개를 받는 즉시 기저를 Z에 맞추고, 추측한 600개의 기저를 Alice에게 Z로 추측했다면 -1을 Y로 추측했다면 1을 보내고, Alice는 Z기저로 추측한 기저가 맞다면 1을 틀리다면 -1을 보낸다.
3. Alice와 Bob은 도청이 있는지 확인하기 위해서 짝수번째 비트들을 Z기저를 통해 보낸다. Alice는 Z기저로 1을 보내어 ACK 확인을 한다.
4. 이후 Alice와 Bob은 도청이 없다고 확인한 뒤 홀수번째 비트들로 AES 128bit키를 만든다(-1 -> 0, 1 -> 1)
5. Alice와 Bob은 AES128-ECB 통신을 한다.
해석만 할 줄 알면 쉬운 문제였는데 문제는 통합 1500+a 통신을 하는 것을 감청하고 바꿔야 해서
한번 시도 하는데 30분이 넘게 걸려서 멘탈이 파쇄당했다. 한번에 비트들을 보냈으면 더 좋지 않았을까 한다.
from pwn import *
r = remote("bb8.chal.pwning.xxx",20811)
def GetQubit():
ZAq = []
ZBq = []
for i in range(599):
print i
r.sendlineafter("Bob, do you want to intercept (y/N)?","y")
r.sendlineafter("(Z/Y)","Z")
r.recvuntil("measured ")
K = r.recvuntil("\n")
ZAq.append(int(K))
r.sendlineafter("(Y)?","Y")
r.sendlineafter("(Z/Y)","Z")
r.sendlineafter("(-1/1)","-1")
ZBq.append(0)
r.sendlineafter("(y/N)?","N")
print "600"
r.sendlineafter("Bob, do you want to intercept (y/N)?","y")
r.sendlineafter("(Z/Y)","Z")
r.recvuntil("measured ")
K = r.recvuntil("\n")
ZAq.append(int(K))
r.sendlineafter("(Y)?","Y")
r.sendlineafter("(Z/Y)","Z")
ZBq.append(0)
r.sendlineafter("(-1/1)","-1")
return (ZAq,ZBq)
def WatchBases(ZAq,ZBq):
CAq = []
CBq = []
C = 0
T = 0
for i in range(600):
print i
r.sendlineafter("(y/N)?","y")
r.sendlineafter("(Z/Y)","Z")
r.recvuntil("measured ")
B = r.recvuntil("\n")
r.sendlineafter("(Y)?","Y")
r.sendlineafter("(Z/Y)","Z")
r.sendlineafter("(-1/1)","-1")
r.sendlineafter("(y/N)?","y")
r.sendlineafter("(Z/Y)","Z")
r.recvuntil("measured ")
K = r.recvuntil("\n")
if int(K) == 1:
CAq.append(ZAq[i])
C+=1
r.sendlineafter("(Y)?","Y")
r.sendlineafter("(Z/Y)","Z")
if T <= 256:
if int(B) == 1 or C == 0:
r.sendlineafter("(-1/1)","-1")
else:
T+=1
r.sendlineafter("(-1/1)","1")
CBq.append(ZBq[i])
C -= 1
else:
if C != 0:
r.sendlineafter("(-1/1)","1")
CBq.append(ZBq[i])
C -= 1
else:
r.sendlineafter("(-1/1)","-1")
return (CAq,CBq)
def Check(Cq):
for i in range(0, len(Cq), 2):
print i
r.sendlineafter("(y/N)?", "y")
r.sendlineafter("(Z/Y)","Z")
r.sendlineafter("(Y)?","Y")
r.sendlineafter("(Z/Y)","Z")
r.sendlineafter("(-1/1)",str(Cq[i]))
r.sendlineafter("(y/N)?","y")
r.sendlineafter("(Z/Y)","Z")
r.recvuntil("measured ")
K = r.recvuntil("\n")
if int(K) != 1:
print "fuck!"
r.sendlineafter("(Y)?","N")
def main():
ZAq,ZBq = GetQubit()
print ZAq
print ZBq
CAq,CBq = WatchBases(ZAq,ZBq)
print CAq
print CBq
print len(CAq)
print len(CBq)
assert(len(CAq) == len(CBq))
Check(CAq)
KeybitsA = []
KeybitsB = []
for i in range(len(CAq)):
if CAq[i] == -1:
KeybitsA.append(0)
else:
KeybitsA.append(1)
for i in range(len(CBq)):
if CBq[i] == -1:
KeybitsB.append(0)
else:
KeybitsB.append(1)
print KeybitsA
print KeybitsB
aes_keyA = 0
aes_keyB = 0
for i in range(128):
aes_keyA |= (KeybitsA[2*i+1] << (127-i))
aes_keyB |= (KeybitsB[2*i+1] << (127-i))
print "aes key A : " + hex(aes_keyA)
print "aes key B : " + hex(aes_keyB)
r.interactive()
if __name__ == "__main__":
main()
'CTF' 카테고리의 다른 글
2017 DIMICTF problems & 후기 (0) | 2017.07.22 |
---|---|
Google CTF 2017 Moon (0) | 2017.06.23 |
SSG 2017 Write Up (0) | 2017.06.02 |
Plaid CTF 2017 Down the Reversing Hole (0) | 2017.04.24 |
CodeGate 2017 Event Challenge Keypad (0) | 2017.04.14 |