def finalizePlayers(self, potential_players:Players, player_ids:[] = []): '''Match player_ids to saved_players and return Players() Params: potential_players Players object. players_ids list of [(message, player_id)]. Must be less than total number of possible players in game (5). ''' # Update console with player_ids found for message, player_id in player_ids: self.game_state = GAME_STATES['STARTED'] self.updateConsole(f'{message}: {player_id}') # temp_players = Players() # Doesn't work. Need to explicitly set players to [] temp_players = Players(players=[]) self.updateConsole(f'finalizePlayers temp_players size is {len(temp_players.players)}') # Match player_id with Players.players list and copy to new Players(). for message, final_player_id in player_ids: if player:= potential_players.get_player(final_player_id): # Reset player hand player.hand = {b'Defuse0.0'} temp_players.save_player(player) idx = temp_players.get_index(player.player_id) # Wipe any gui forms if exist. self.updateConsole(( f'finalizePlayers match found: {player.names} {idx} ' f'out of {len(temp_players.players)} list {len(player_ids)}'))
class EkGameCheat: def __init__(self, **kwargs): # List of final players who will play. self.saved_players = Players() # [{'player_id':'$840eb76e-aa1b-4345-978c-21919d189001s','player_names':['bob','carl'], 'cards':[]] # Collect data of potential players self.potential_players = Players() self.lock = Lock() self.VICTIM_IP = kwargs.get('victim_ip') self.SNIFF_INF = kwargs.get('sniff_inf') self.console_cb = kwargs.get('console_cb') self.status_cb = kwargs.get('status_cb') self.player_cb = kwargs.get('player_cb') self.GATEWAY_IP = kwargs.get('gateway_ip', self.getGatewayIp()) self.VICTIM_MAC = kwargs.get('victim_mac', get_mac_address(hostname=f'{self.VICTIM_IP}')) self.GATEWAY_MAC = kwargs.get('gateway_mac', get_mac_address(hostname=f'{self.GATEWAY_IP}')) self.MY_IP = kwargs.get('my_ip', self.getIpAddress(self.SNIFF_INF)) self.SNIFF_INF_MAC = kwargs.get('sniff_inf_mac', get_mac_address(interface=self.SNIFF_INF)) self.game_state = GAME_STATES['INIT'] self.game_actions = [] self.pkt_count = 0 self.console = '' self.game_state_cb = {} self.set_capture_type(conf) def set_capture_type(self, scapy_conf): my_os = platform.system() if my_os == 'Linux': scapy_conf.use_pcap = True elif my_os == "Darwin": # osx has issues with AF_PACKET. # Disabling libpcap seems to fix. scapy_conf.use_pcap = False elif my_os == 'Windows': raise Exception(f'Scapy packet library config setting.\nO/S {my_os} not supported') else: raise Exception(f'Scapy packet library config setting.\nO/S {repr(my_os)} not supported') def updateConsole(self, message, call_back=None): self.console = message if call_back == None: call_back = self.console_cb if callable(call_back): call_back(data = message) def updateStatus(self, message, call_back=None): self.console = message if call_back == None: call_back = self.status_cb if callable(call_back): call_back(data = message) def setGameStateCb(self, state:str, cb:str=None): if state in GAME_STATES.keys(): if callable(cb): self.game_state_cb[state] = cb def sendCb(self, **kwargs): def _sendCb(pkt): max_packet_size = 70 # bytes if not pkt.haslayer(IP): return src_ip = pkt[IP].src dst_ip = pkt[IP].dst if dst_ip == self.MY_IP: return if pkt.haslayer(UDP) and pkt.haslayer(Raw) and len(pkt[IP][UDP][Raw].load) > max_packet_size: # Increment packet count self.pkt_count += 1 # self.updateStatus(f'Packet count {self.pkt_count}') # TODO: Messages should be parsed in resepct to game state. self.playOpponentChosen2(pkt) self.playRegisterPlayers(pkt) self.playAddPlayersToGame(pkt) self.playCard(pkt) self.playDrawCard(pkt) self.playInsertCard(pkt) self.playPlayCard(pkt) self.playOpponentChosen(pkt) self.playXchange(pkt) #self.playEmote() self.playStarted(pkt) self.playDied(pkt) return _sendCb def playAddPlayersToGame(self, pkt): # This message indicates that the game and final list of players have started final_players_found = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_PLAYERS_QUEUED) if final_players_found and len(final_players_found) > 0: self.finalizePlayers(self.potential_players, final_players_found) # Erase potential_players self.potential_players = Players() #message = pprint.pformat(inspect.getmembers(saved_players.players), indent=2) #save_to_file(f'\n{len(saved_players.players)}\n{final_players_found}\n{message}', 'dump.txt') def playCard(self, pkt): # action, player_id, length, card. Looking for DrawFromBottom played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_PLAYCARD) if len(played_card) > 0: for action, player_id, length_n_card in played_card: card = self.getNextMessage(length_n_card) self.game_actions.append([action,player_id,card]) logging.debug(f'PLAYCARD: {action} by {self.saved_players.get_player_name(player_id)} card {card}') self.updateConsole(( f'PLAYCARD: {action} by {self.saved_players.get_player_name(player_id)} card {card}')) # Remove card from player hand self.saved_players.remove_card(player_id, card) def playDrawCard(self, pkt): # action, player_id, len_and_card played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_DRAWCARD) if len(played_card) > 0: for action, player_id, length_n_card in played_card: card = self.getNextMessage(length_n_card) logging.debug([action,player_id, card]) self.game_actions.append([action, player_id, card]) self.saved_players.save_card(player_id, card) self.updateConsole(f'{action} {self.saved_players.get_player_name(player_id)} {card}') def playInsertCard(self, pkt): # action, player_id, id, ek_pos. played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_INSERTCARD) if len(played_card) > 0: for action, player_id, len_n_card, ek_pos in played_card: # Get bomb placement position ek_pos = self.getNextMessage(ek_pos) ek_pos = int(ek_pos) + 1 # More accurate card = self.getNextMessage(len_n_card) logging.debug(f'{action} by {self.saved_players.get_player_name(player_id)} {card} ek placed {ek_pos}') self.game_actions.append([action,player_id,card, ek_pos]) self.updateConsole(( f'{action} by {self.saved_players.get_player_name(player_id)}' f' {card} ek placed {ek_pos}')) def playOpponentChosen2(self, pkt): # action, player_id, id, ek_pos. played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_OPPONENTCHOSEN2) if len(played_card) > 0: for action, player_id, gen_id, len_n_card in played_card: card = self.getNextMessage(len_n_card) logging.debug(f'{action} by {self.saved_players.get_player_name(player_id)} {self.saved_players.get_player_name(gen_id)}') self.game_actions.append([action,player_id,gen_id]) self.updateConsole(( f'playOpponentChosen2: {action} by ' f'{self.saved_players.get_player_name(player_id)} ' f'{self.saved_players.get_player_name(gen_id)}, {card}')) def playPlayCard(self, pkt): # Played card played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_PLAYCARD_0) if len(played_card) > 0: for action, player_id, length_n_card in played_card: card = self.getNextMessage(length_n_card) self.game_actions.append([action,player_id]) # Remove card from player hand self.saved_players.remove_card(player_id, card) logging.debug(f'REGEX_PLAYCARD_0: {action} by {self.saved_players.get_player_name(player_id)} card {card}') self.updateConsole(( f'REGEX_PLAYCARD_0: {action} by ' f'{self.saved_players.get_player_name(player_id)} card {card}')) def playOpponentChosen(self, pkt): # Game activity 2, usually 2 player ids # This could be something like a slap. played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_OPPONENTCHOSEN) if len(played_card) > 0: for action, player_id, opponent, length_and_card in played_card: card = self.getNextMessage(length_and_card) self.game_actions.append([player_id,card,opponent]) self.saved_players.remove_card(opponent, card) logging.debug(( f'REGEX_OPPONENTCHOSEN1: card {card}' f' by {self.saved_players.get_player_name(player_id)}' f' to {self.saved_players.get_player_name(opponent)}')) self.updateConsole(( f'playOpponentChosen: {action} card {card}' f' by {self.saved_players.get_player_name(player_id)}' f' to {self.saved_players.get_player_name(opponent)}')) def playRegisterPlayers(self, pkt): # Collect player details found_players = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_PLAYERS) if len(found_players) > 0: for player_id, username, did, len_and_avatarIds in found_players: avatarIds = self.getNextMessage(len_and_avatarIds) new_player = Player( player_id = player_id, names = [username], device_id = did, avatar_id = avatarIds, hand = {}, display_cb = self.player_cb, ) self.potential_players.save_player(new_player) logging.debug(f'Username: {username}, {player_id}, {avatarIds}, {did}') self.updateConsole(f'Username: {username}, {player_id}, {avatarIds}, {did}') def playXchange(self, pkt): # action, player_id, card played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_XCHG) if len(played_card) > 0: for action, player_id, player_id2, length_n_card in played_card: card = self.getNextMessage(length_n_card) self.game_actions.append([action,player_id,card]) self.saved_players.remove_card(player_id2, card) self.saved_players.save_card(player_id, card) logging.debug(f'REGEX_XCHG: {action} from {self.saved_players.get_player_name(player_id2)} to {self.saved_players.get_player_name(player_id)} card {card}') self.updateConsole(( f'REGEX_XCHG: {action} from ' f'{self.saved_players.get_player_name(player_id2)} to ' f'{self.saved_players.get_player_name(player_id)} card {card}')) def playDied(self, pkt): # action, player_id for action, player_id in self.containsAll(pkt[IP][UDP][Raw].load, REGEX_DIED): self.game_actions.append([action,player_id]) self.updateConsole(f'REGEX_DIED: {action} {self.saved_players.get_player_name(player_id)}') def playStarted(self, pkt): # action, player_id for action in self.containsAll(pkt[IP][UDP][Raw].load, REGEX_STARTED): self.game_actions.append([action]) self.updateConsole(f'REGEX_STARTED: {action}') self.game_state = GAME_STATES['STARTED'] # Callback to ui maybe? self.game_state_cb['STARTED']() def playEmote(self, pkt): # Collect player emotes played_card = self.containsAll(pkt[IP][UDP][Raw].load, REGEX_EMOTE) if len(played_card) > 0: for action, player_id, emote_len_and_emote in played_card: emote = self.getNextMessage(emote_len_and_emote) #print(f'{action}: {get_player_name(saved_players, player_id)} sends {emote}') # Attempt to send fake emotes TODO: wip if (self.saved_players.get_player_name(player_id) and self.saved_players.get_player_name(player_id)[0].decode() in 'capn'): #pkt.show() del pkt[IP].chksum del pkt[UDP].chksum del pkt[IP].len del pkt[UDP].len del pkt[Ether].dst del pkt[Ether].src #pkt[UDP].load = EMOTE_DRUNK #sendp(pkt) #pkt.show2() # New checksum def finalizePlayers(self, potential_players:Players, player_ids:[] = []): '''Match player_ids to saved_players and return Players() Params: potential_players Players object. players_ids list of [(message, player_id)]. Must be less than total number of possible players in game (5). ''' # Update console with player_ids found for message, player_id in player_ids: self.game_state = GAME_STATES['STARTED'] self.updateConsole(f'{message}: {player_id}') # temp_players = Players() # Doesn't work. Need to explicitly set players to [] temp_players = Players(players=[]) self.updateConsole(f'finalizePlayers temp_players size is {len(temp_players.players)}') # Match player_id with Players.players list and copy to new Players(). for message, final_player_id in player_ids: if player:= potential_players.get_player(final_player_id): # Reset player hand player.hand = {b'Defuse0.0'} temp_players.save_player(player) idx = temp_players.get_index(player.player_id) # Wipe any gui forms if exist. self.updateConsole(( f'finalizePlayers match found: {player.names} {idx} ' f'out of {len(temp_players.players)} list {len(player_ids)}')) self.saved_players = temp_players