162 lines
4.5 KiB
Python
162 lines
4.5 KiB
Python
from pwn import *
|
|
import ast
|
|
import random
|
|
from math import gcd
|
|
from Crypto.Util.number import bytes_to_long, long_to_bytes
|
|
|
|
from server import PRNG, Card, card_str_to_Card, determine_winner
|
|
|
|
import tqdm
|
|
|
|
def sim_round(deck, rng, phi, computer_e, computer_d):
|
|
deck = shuffle(rng, deck)
|
|
print("local hacks 1", rng.seed, rng.index, rng.state)
|
|
while computer_e < 2 or computer_d < 1:
|
|
e_array = []
|
|
for _ in range(6):
|
|
e_array.append(str(rng.getnum()))
|
|
computer_e = int(''.join(e_array))
|
|
if gcd(computer_e, phi) == 1:
|
|
computer_d = pow(computer_e,-1,phi)
|
|
|
|
return computer_e, computer_d, deck
|
|
|
|
def shuffle(rng, deck):
|
|
new_deck = []
|
|
for i in range(len(deck)):
|
|
x = rng.getnum()
|
|
if deck[x] not in new_deck:
|
|
new_deck.append(deck[x])
|
|
elif deck[i] not in new_deck:
|
|
new_deck.append(deck[i])
|
|
else:
|
|
for card in deck:
|
|
if card not in new_deck:
|
|
new_deck.append(card)
|
|
break
|
|
return new_deck
|
|
|
|
def exploit():
|
|
deck = []
|
|
deck_str = []
|
|
for suit in ["Spades", "Hearts", "Diamonds", "Clubs"]:
|
|
for i in range(16):
|
|
deck.append(Card(suit, i))
|
|
deck_str.append(str(deck[-1]))
|
|
deck_str = set(deck_str)
|
|
|
|
server_deck = list(deck)
|
|
|
|
# r = process(["python3", "server.py"])
|
|
r = remote("crypto.csaw.io", 5001)
|
|
|
|
r.recvuntil(b"Here are")
|
|
r.recvuntil(b"--> ")
|
|
|
|
p, q = r.recvline().decode().strip().split(", ")
|
|
p = int(p)
|
|
q = int(q)
|
|
phi = (p-1)*(q-1)
|
|
N = p*q
|
|
|
|
print("p=", p)
|
|
print("q=", q)
|
|
|
|
# player_e = 65537
|
|
# player_d = pow(player_e, -1, phi)
|
|
player_e = 1
|
|
player_d = 1
|
|
|
|
print("player_e=", player_e)
|
|
print("player_d=", player_d)
|
|
|
|
r.recvuntil(b">>")
|
|
r.sendline(str(player_e).encode())
|
|
r.recvuntil(b">>")
|
|
r.sendline(str(player_d).encode())
|
|
|
|
r.recvuntil(b"***")
|
|
roundline = r.recvline()
|
|
print("roundline", roundline)
|
|
print(r.recvuntil(b"--> "))
|
|
deck = r.recvline().strip().decode()
|
|
deck = ast.literal_eval(deck)
|
|
# print("recv deck", deck)
|
|
|
|
test_item = deck[0]
|
|
found_seed = None
|
|
for seed in tqdm.trange(2**10):
|
|
prng = PRNG(seed)
|
|
rand_values = []
|
|
for i in range(256):
|
|
rand_values.append(prng.getnum())
|
|
|
|
found = False
|
|
|
|
for offset in range(249):
|
|
e_array = [str(x) for x in rand_values[offset:offset+6]]
|
|
computer_e = int(''.join(e_array))
|
|
if gcd(computer_e, phi) != 1:
|
|
continue
|
|
computer_d = pow(computer_e, -1, phi)
|
|
|
|
test_card = long_to_bytes(pow(test_item, computer_d, N)).decode('iso-8859-1')
|
|
if test_card in deck_str:
|
|
print("found seed", test_card, seed)
|
|
found = True
|
|
found_seed = seed
|
|
break
|
|
|
|
if found:
|
|
break
|
|
|
|
prng = PRNG(found_seed)
|
|
computer_e, computer_d = -1, 0
|
|
|
|
for rndnum in range(10):
|
|
if rndnum > 0:
|
|
print(r.recvuntil(b"***"))
|
|
roundline = r.recvline()
|
|
print("roundline", roundline)
|
|
print(r.recvuntil(b"--> "))
|
|
deck = r.recvline().strip().decode()
|
|
deck = ast.literal_eval(deck)
|
|
# print("recv deck", deck)
|
|
|
|
computer_e, computer_d, server_deck = sim_round(server_deck, prng, phi, computer_e, computer_d)
|
|
print(computer_e, computer_d, prng.seed, prng.index, prng.state)
|
|
|
|
dec_cards = []
|
|
for enc_card in deck:
|
|
dec_card = long_to_bytes(pow(enc_card, computer_d, N)).decode()
|
|
dec_cards.append(card_str_to_Card(dec_card))
|
|
|
|
print([str(c) for c in dec_cards])
|
|
print([str(c) for c in server_deck])
|
|
|
|
while True:
|
|
random.shuffle(dec_cards)
|
|
computer_cards, player_cards = dec_cards[0:5], dec_cards[5:10]
|
|
computer_winner, player_winner = determine_winner(computer_cards, player_cards)
|
|
if player_winner and not computer_winner:
|
|
break
|
|
|
|
server_deck = list(dec_cards)
|
|
|
|
enc_deck = []
|
|
for card in dec_cards:
|
|
enc_deck.append(pow(bytes_to_long(str(card).encode()),computer_e,N))
|
|
|
|
for c in enc_deck:
|
|
r.recvuntil(b">> ")
|
|
r.sendline(str(c).encode())
|
|
|
|
r.recvuntil(b"HAHAHA")
|
|
r.recvline()
|
|
|
|
val = ast.literal_eval(r.recvline().decode())
|
|
print(long_to_bytes(pow(bytes_to_long(val),computer_d,N)))
|
|
|
|
if __name__ == "__main__":
|
|
exploit()
|