$ nc quiz.ais3.org 10234 +-------------------- welcome --------------------+ | omg hi! | | | | welcome to microchess, the minimal online chess | | platform. | | i am a super powerful chess AI! | | can you win against me and get the flag? | +---+--------------- main menu -------------------+ | 0 | read the rules of the game | | 1 | start a new game against me | | 2 | load a saved game | | 3 | leave | +---+---------------------------------------------+ what would you like to do? 1 +---+-------------- stones info ------------------+ | 0 | ooooooooooooo | | 1 | ooooo | | 2 | ooooooooooo | | 3 | o | | 4 | oooooooooooooooooooooooooooooo | | 5 | ooooooo | | 6 | ooooooooooooooooooooooooooo | +---+--------------- game menu -------------------+ | 0 | make a move | | 1 | save the current game and leave | | 2 | resign the game | +---+---------------------------------------------+ it's your turn to move! what do you choose? 0 which pile do you choose? 3 how many stones do you remove? 1 +--------------------- moved ---------------------+ | you removed 1 stones from pile 3 | +---+-------------- stones info ------------------+ | 0 | ooooooooooooo | | 1 | ooooo | | 2 | ooooooooooo | | 3 | oooooooooooooooooooooooooooooo | | 4 | ooooooo | | 5 | ooooooooooooooooooooooooooo | +--------------------- moved ---------------------+ | i removed 1 stones from pile 0 | +---+-------------- stones info ------------------+ | 0 | oooooooooooo | | 1 | ooooo | | 2 | ooooooooooo | | 3 | oooooooooooooooooooooooooooooo | | 4 | ooooooo | | 5 | ooooooooooooooooooooooooooo | +---+--------------- game menu -------------------+ | 0 | make a move | | 1 | save the current game and leave | | 2 | resign the game | +---+---------------------------------------------+ it's your turn to move! what do you choose?
classGame: ''' a simple Nim game with normal rules. grundy's theorem: if nim_sum() is zero, then the player to move has a winning strategy. otherwise, the other player has a winning strategy. '''
def__init__(self): self.stones = []
defgenerate_winning_game(self) -> None: '''generate a game such that the first player has a winning strategy''' self.stones = [] xor_sum = 0
piles = random.randint(6, 8) for i inrange(piles): self.stones.append(count := random.randint(1, 31)) xor_sum ^= count
if xor_sum == 0: self.stones.append(random.randint(1, 31))
defgenerate_losing_game(self) -> None: '''generate a game such that the second player has a winning strategy''' self.stones = [] xor_sum = 0
piles = random.randint(6, 8) for i inrange(piles): self.stones.append(count := random.randint(1, 31)) xor_sum ^= count
if xor_sum != 0: self.stones.append(xor_sum)
defmake_move(self, pile: int, count: int) -> bool: '''makes a move, returns whether the move is legal'''
if pile notinrange(0, len(self.stones)): returnFalse if count notinrange(1, self.stones[pile] + 1): returnFalse
defended(self) -> bool: ''' checks if the game has ended, i.e., the player has no more moves. if True, the current player loses the game ''' returnlen(self.stones) == 0
defshow(self) -> None: print('+---+-------------- stones info ------------------+') for pile, count inenumerate(self.stones): print(f'| {pile} | {"o" * count:<43} |')
defload(self, game_str: str) -> None: '''loads a saved game from string''' self.stones = list(map(int, game_str.split(',')))
defsave(self) -> str: '''returns the current game as a string''' return','.join(map(str, self.stones))
classAIPlayer: ''' a perfect Nim player. if there exists a winning strategy for a game, this player will always win. '''
def__init__(self): pass
defget_move(self, game: Game) -> Tuple[int, int]: ''' if there is a winning strategy, returns a move that guarantees a win. otherwise, returns a random move. ''' nim_sum = game.nim_sum()
if nim_sum == 0: # losing game, make a random move pile = random.randint(0, len(game.stones) - 1) count = random.randint(1, game.stones[pile])
else: # winning game, make a winning move for i, v inenumerate(game.stones): target = v ^ nim_sum if target < v: pile = i count = v - target break
+---+--------------- game menu -------------------+ | 0 | make a move | | 1 | save the current game and leave | | 2 | resign the game | +---+---------------------------------------------+ it's your turn to move! what do you choose? 3 +--------------------- moved ---------------------+ | you removed 3 stones from pile 1 | +---+-------------- stones info ------------------+ | 0 | o | | 1 | o | +--------------------- moved ---------------------+ | i removed 1 stones from pile 1 | +---+-------------- stones info ------------------+ | 0 | o | +---+--------------- game menu -------------------+ | 0 | make a move | | 1 | save the current game and leave | | 2 | resign the game | +---+---------------------------------------------+ it's your turn to move! what do you choose? 0 which pile do you choose? 0 how many stones do you remove? 1 +---------------- congratulations ----------------+ | you are a true grandmaster of chess! here is | | the flag for you: | | AIS3{5._e3_b5_6._a4_Bb4_7._Bd2_a5_8._axb5_Bxc3} | +-------------------------------------------------+
self.send(b'Welcome to ReSident evil villAge, sign the name "Ethan Winters" to get the flag.') self.send(b'n = ' + str(n).encode()) self.send(b'e = ' + str(e).encode())
$ nc quiz.ais3.org 42069 Welcome to ReSident evil villAge, sign the name "Ethan Winters" to get the flag. n = 116446349250477461211548564037305096646246352712613922877939621221682086442262006076658058243799666178199942844412251167013582517469698767681352409472676329468186602987766214457609857069612827869171818746620035374912701350547179213366848809313278051695960906542268549406826272373673111354786397335987091196949 e = 65537 1) sign 2) verify 3) exit 1 Name (in hex): 00457468616e2057696e74657273 Signature: 81461102639376645458445563890933604042666832496108067724180262424539703394619135196334363979456757148465714312599695970577392038142353089971541912561007212572874317390985050129115895139824645075534050013217923053352965259741321376550049801845665852962177362515169292380016928834541247529513691701369654301864 1) sign 2) verify 3) exit 2 Signature: 81461102639376645458445563890933604042666832496108067724180262424539703394619135196334363979456757148465714312599695970577392038142353089971541912561007212572874317390985050129115895139824645075534050013217923053352965259741321376550049801845665852962177362515169292380016928834541247529513691701369654301864 AIS3{R3M383R_70_HAsh_7h3_M3Ssa93_83F0r3_S19N1N9}
那我們需要把 p 跟 q 解出來嗎?不需要!分別得到 p,q 是因為我們需要計算的值,但現在我們有與兩個條件了,這樣便可以計算了。
接下來就是用簡單的 RSA 概念來解決它囉!
1 2 3 4 5 6 7 8 9 10
from Crypto.Util.number import *
n = 23662270311503602529211462628663973377651035055221337186547659666520360329842954292759496973737109678655075242892199643594552737098393308599593056828393773327639809644570618472781338585802514939812387999523164606025662379300143159103239039862833152034195535186138249963826772564309026532268561022599227047 e = 65537 c = 11458615427536252698065643586706850515055080432343893818398610010478579108516179388166781637371605857508073447120074461777733767824330662610330121174203247272860627922171793234818603728793293847713278049996058754527159158251083995933600335482394024095666411743953262490304176144151437205651312338816540536 k = 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848
phi = n-k+1 d = inverse(e, phi) print(long_to_bytes(pow(c, d, n)))