SecurinetsQuals2k21 | Shilaformi

#securinetsquals2k21

import signal
from secret import flag
from Crypto.Random import random
from Crypto.Util.number import getPrime

#Odds and evens (hand game)
#https://en.wikipedia.org/wiki/Odds_and_evens_(hand_game)

def pad(choice, n):
    return 2*random.randint(1, n//2 - 1) + choice

def send(choice, n):
    choice = pad(choice, n)
    return pow(2, choice, n )

signal.alarm(360)
print ("Let's play odds and evens! If I win you loose 5 times the amount of money you have bet! I choose odd.\n")

WALLET = 10
while WALLET > 0:
    print("Your current wallet is {} $.\n".format(WALLET))

    if WALLET > 133337:
        print("Wow, You've got filthy rich. Here's your flag: {}".format(flag))
        exit()

    n = getPrime(1024)*getPrime(1024)
    print ("Public Modulus : {}\n".format(n))

    bet = int(input("Place your bet : "))
    assert bet <= WALLET and bet > 0

    choice = random.randint(0, 5)
    print ("Here's my choice : {}\n".format(send(choice, n)))

    player = int(input("Shilaaafooooooormi: "))
    assert player >= 0 and player < 6

    if (choice + player ) & 1:
        print("You lose.")
        WALLET -= 5*bet
    else:
        print("You win.")
        WALLET += bet

print("You got no money left in your wallet. Make sure to come back later!")

odd-even gameに何回も勝つやつ。相手の手 x 2^{2r + x} \mod nとして与えられるのでquadratic residueを見れば xの偶奇がわかる。しかし n合成数だが……とおもうもjacobi記号合成数 nにも通用する場合もある

 nは掛け金を決める前に教えてもらえるので、与えられた nがgood nかどうかを調査して勝てそうなら全bet、ダメそうなら1bet で堅実に行けば良い

from ptrlib import Socket
import proofofwork
import gmpy2
import random

sock = Socket("crypto2.q21.ctfsecurinets.com", 1337)
pat = sock.recvregex(r"sha256\(([A-Za-z]+) \+ X\) = 000000")[0]
print(pat)

s = proofofwork.sha256(
        '000000??????????????????????????????????????????????????????????',
        text=pat + b'?????')
print(s)
sock.sendline(s[len(pat):])

# sock = Socket("localhost", 19999)

while True:
    current = int(sock.recvregex(r"wallet is ([0-9]+) \$.\n")[0])
    print(current)
    if current > 133337:
        sock.interactive()
    n = int(sock.recvlineafter("Modulus : "))
    print("[+] got modulus")

    # check n
    flag = True
    for choice in range(0, 6):
        x = 2*random.randint(1, n//2 - 1) + choice
        y = pow(2, x, n)
        if (x % 2 == 0) != (gmpy2.jacobi(y, n) == 1):
            flag = False
    print("[+] check: {}".format(flag))

    bet = 1
    if flag:
        # surely win
        bet = current
    sock.sendlineafter("bet : ", str(bet))

    y = int(sock.recvlineafter("choice : "))
    sock.sendlineafter("mi: ", str(1 if gmpy2.jacobi(y, n) == -1 else 0))
    if b"win" in sock.recvline():
        current += bet
        print("Win! current money: {}".format(current))
    else:
        current -= bet*5
        print("Loose... current money: {}".format(current))

        if current <= 0:
            print("LOOSE")
            break