一周前才去上量子計算的課程,然後就突然發現 HTB 上居然有量子相關的 CTF 題目耶!

Challenge link: Hack The Box :: Global Hyperlink Zone Challenge

查看這段關鍵的原始碼:

def initialize_hyperlink(self, instructions, shots = 256):
    if len(instructions) == 0:
        return False

    circuit = self.generate_circuit(instructions)

    if not circuit:
        return False

    compiled = transpile(circuit, self.backend)
    results = self.backend.run(compiled, shots = shots, memory = True).result()

    shares = [""] * 5
    
    for bits in results.get_memory():
        for i, bit in enumerate(bits[::-1]):
            shares[i] += bit

    shares = [ int(share, 2).to_bytes(32, byteorder = "big") for share in shares ]

    if any(set(share) in ({0}, {255}) for share in shares):
        return False

    if (
        shares[0] == shares[1] and
        shares[1] == shares[3] and
        shares[2] == shares[4] and
        shares[4] != shares[0]
    ):
        return True

    return False
for bits in results.get_memory():
    for i, bit in enumerate(bits[::-1]):
        shares[i] += bit

results.get_memory() 是單次測量的結果,比如 00101 就代表 q0=1,q1=0,q2=1,q3=0,q4=0q_0=1, q_1=0, q_2=1,q_3=0,q_4=0。而之所以要把他翻轉 (bits[::-1]) 就是因為 IBM 的約定是最右邊的是 q0q_0,但 Python 是從最左邊開始讀。而那個 for 迴圈的功能便是將不同 qubits 的測量結果拆開。比如若跑完後 shares[0] = 01001100,就代表 q0q_0 第一次觀測結果為 0,第二次為 1,第三、四次為 0 等等。
伺服器印出 Flag 的條件是:

shares[0] == shares[1] and shares[1] == shares[3] and
shares[2] == shares[4] and shares[4] != shares[0]

也就是在每次測量都有

q0=q1=q3q2=q4q_0 = q_1 = q_3 \neq q_2 = q_4

同時不能有任何一個 qubits 的每次測量結果全為 0 或 1:
if any(set(share) in ({0}, {255}) for share in shares): return False

不難想到我們要構造出

12(01011+10100)\frac{1}{\sqrt2}\left( \vert{} 01011 \rangle + \vert{} 10100 \rangle \right)

一個很直覺的方法便是用 H Gate + CNOT Gate,而因為 q2,q4q_2, q_4 要和別人不一樣所以在被 CNOT 控制之前要先放一個 X GATE

我使用的 payload 如下:

X:2;X:4;H:0;CX:0,1;CX:0,2;CX:0,3;CX:0,4

輸入給 server 就能得到 Flag: HTB{4_57r4ng3_gr33nb3rg3r_h0rn3_z31L1ng3r_57473_1n1714L1z35_7h3_hyp3rL1nk!}