def store_flags(self, team, round): from gameserver import cheapMethodFromRoundNumber, cheapMethods, GameServer, GameServerCrypto, SHA512_HEX_LEN, \ methods flagsStored = 0 method = cheapMethodFromRoundNumber(round) flagIndex = cheapMethods.index(method) flagId = self.get_flag_id(team, round, 0) flag = self.get_flag(team, round, flagIndex) msg = GameServer.generatePlaintext() % flag # Check if the flag is already stored # We could in theory just try to store the flag and check for an IntegrityException from sqlite. # However, this approach might not work if teams tinker with their DB layout. flagAlreadyStored = True try: GameServer.retrieveCipher(team.ip, PORT, flagId) except FlagMissingException: flagAlreadyStored = False if not flagAlreadyStored: cipher, params, msg = GameServerCrypto.encrypt(msg, method) paramHash = msg[-SHA512_HEX_LEN:] self.store(team, round, f"paramhash_{flagIndex}", paramHash) self.store(team, round, f"msg_{flagIndex}", msg) GameServer.storeCipher(team.ip, PORT, flagId, cipher, params) flagsStored += 1 flagIndex = methods.index("schwenk") flagId = self.get_flag_id(team, round, 1) flag = self.get_flag(team, round, flagIndex) msg = GameServer.generatePlaintext() % flag flagAlreadyStored = True try: GameServer.retrieveCipher(team.ip, PORT, flagId) except FlagMissingException: flagAlreadyStored = False if not flagAlreadyStored: cipher, params, msg = GameServerCrypto.schwenkNew( msg, skipKeyAndIV=False) paramHash = GameServerCrypto.parameterHash(params) self.store(team, round, f"paramhash_{flagIndex}", paramHash) self.store(team, round, "schwenk_msg", msg) # Random key + IV are added. GameServer.storeCipher(team.ip, PORT, flagId, cipher, params) flagsStored += 1 return flagsStored
# print(e) continue # No try here: At this point, we are very sure that we have decrypted correctly so far. Backtracking here would also be rather messy. c_plain = c_elem.nthRoot( k_b_out.toNumber() ^ xorParams[blockIndex]).toString() if not isValidPlaintext(c_plain): continue plain = c_plain + plain print("Found plaintext fragment:", c_plain) bFound = True break if not bFound: raise Exception("Decryption failed.") remainingCipher = remainingCipher[:-bExpected - bOffset] k_next_out = k_b_out IV_next_out = IV_b_out return plain.decode("utf-8") if __name__ == "__main__": assert len(sys.argv) >= 4, "Needs flag ids in fourth argument" target = sys.argv[1] flagIds = sys.argv[3].split(",") for flagId in flagIds: cipher, params = GameServer.retrieveCipher(target, PORT, flagId) if params["method"] == "schwenk": plain = exploit(cipher, params) print(plain)