Beispiel #1
0
    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)}'))
Beispiel #2
0
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