반응형

아직도 생각하면 멘탈 나가는 문제

양자 통신 프로토콜 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

+ Recent posts