*CTF 2021 | Guess Key

*CTF 2021

from random import randint
import os
from flag import flag
import sys

N=64
key=randint(0,2**N)
# print key
key=bin(key)[2:].rjust(N,'0')
count=0
while True:
    zeros=[0] # indices of 0 in key
    for j in range(len(key)):
        if key[j]=='0':
            zeros.append(j)

    p=zeros[randint(0,len(zeros))-1] # pos of 0
    q=zeros[randint(0,len(zeros))-1] # pos of 0
    if p>q:
        tmp=q
        q=p
        p=tmp
    # assert p < q


    try:
        sys.stdout.write("mask:")
        sys.stdout.flush()
        mask=int(raw_input())
    except:
        exit(0)
    mask=bin(mask)[2:]

    cnt = 0
    new_key=''
    for j in range(0,N):
        if j in range(p,q+1):
            new_key += str(int(mask[cnt])^int(key[j]))
        else:
            new_key += key[j]
        cnt = (cnt + 1) % len(mask)

    key=new_key
    try:
        sys.stdout.write("guess:")
        sys.stdout.flush()
        guess=int(raw_input())
    except:
        exit(0)
    if guess==int(key,2):
        count+=1
        print 'Nice.'
    else:
        count=0
        print 'Oops.'
    if count>2:
        print flag

64bitの乱数列が生成されて、値が0であるような2箇所が選ばれ、その間をmask で bit flip できる。 mask を1にして何度もbit flipを繰り返せば全部が1になるのでGuess は簡単

from ptrlib import Socket


sock = Socket("52.163.228.53", 8082)
# sock = Socket("localhost", 9999)

print("[+] iterating...", end="")
for i in range(200):
    print("{},".format(i+1), end="", flush=True)
    sock.sendlineafter("mask:", "1")
    sock.sendlineafter("guess:", "0")

print("\n[+] done")

sock.sendlineafter("mask:", "1")
sock.sendlineafter("guess:", str(int("1" * 64, 2)))

line = sock.recvline()
count = 0
if b"Nice" in line:
    count += 1
print(line)

sock.sendlineafter("mask:", "0" if count else "1")
sock.sendlineafter("guess:", str(int("1" * 64, 2)))
print(sock.recvline())
count += 1

sock.sendlineafter("mask:", "0")
sock.sendlineafter("guess:", str(int("1" * 64, 2)))
print(sock.recvline())
count += 1

if count > 2:
    print(sock.recvline())
    quit()


sock.sendlineafter("mask:", "0")
sock.sendlineafter("guess:", str(int("1" * 64, 2)))
print(sock.recvline())
print(sock.recvline())