def init_display(self): if self._enabled: self._implementation.initialize() plugins.on('display_setup', self._implementation) else: logging.warning("display module is disabled") self.on_render(self._on_view_rendered)
def set_training(self, training, for_epochs=0): self._is_training = training self._training_epochs = for_epochs if training: plugins.on('ai_training_start', self, for_epochs) else: plugins.on('ai_training_end', self)
def set_lonely(self): if not self._has_support_network_for(1.0): logging.info("unit is lonely") self._view.on_lonely() plugins.on('lonely', self) else: logging.info("unit is grateful instead of lonely") self.set_grateful()
def set_angry(self, factor): if not self._has_support_network_for(factor): logging.warning("%d epochs with no activity -> angry" % self._epoch.inactive_for) self._view.on_angry() plugins.on('angry', self) else: logging.info("unit is grateful instead of angry") self.set_grateful()
def _event_poller(self): self._load_recovery_data() self.run('events.clear') while True: time.sleep(1) new_shakes = 0 logging.debug("polling events ...") try: s = self.session() self._update_uptime(s) self._update_advertisement(s) self._update_peers() self._update_counters() for h in [ e for e in self.events() if e['tag'] == 'wifi.client.handshake' ]: filename = h['data']['file'] sta_mac = h['data']['station'] ap_mac = h['data']['ap'] key = "%s -> %s" % (sta_mac, ap_mac) if key not in self._handshakes: self._handshakes[key] = h new_shakes += 1 ap_and_station = self._find_ap_sta_in( sta_mac, ap_mac, s) if ap_and_station is None: logging.warning( "!!! captured new handshake: %s !!!" % key) self._last_pwnd = ap_mac plugins.on('handshake', self, filename, ap_mac, sta_mac) else: (ap, sta) = ap_and_station self._last_pwnd = ap[ 'hostname'] if ap['hostname'] != '' and ap[ 'hostname'] != '<hidden>' else ap_mac logging.warning("!!! captured new handshake on channel %d: %s (%s) -> %s [%s (%s)] !!!" % ( \ ap['channel'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'])) plugins.on('handshake', self, filename, ap, sta) except Exception as e: logging.error("error: %s" % e) finally: self._update_handshakes(new_shakes)
def set_sad(self): factor = self._epoch.inactive_for / self._config['personality'][ 'sad_num_epochs'] if not self._has_support_network_for(factor): logging.warning("%d epochs with no activity -> sad" % self._epoch.inactive_for) self._view.on_sad() plugins.on('sad', self) else: logging.info("unit is grateful instead of sad") self.set_grateful()
def on_ai_policy(self, new_params): plugins.on('ai_policy', self, new_params) logging.info("[ai] setting new policy:") for name, value in new_params.items(): if name in self._config['personality']: curr_value = self._config['personality'][name] if curr_value != value: logging.info("[ai] ! %s: %s -> %s" % (name, curr_value, value)) self._config['personality'][name] = value else: logging.error("[ai] param %s not in personality configuration!" % name) self.run('set wifi.ap.ttl %d' % self._config['personality']['ap_ttl']) self.run('set wifi.sta.ttl %d' % self._config['personality']['sta_ttl']) self.run('set wifi.rssi.min %d' % self._config['personality']['min_rssi'])
def next_epoch(self): logging.debug("agent.next_epoch()") was_stale = self.is_stale() did_miss = self._epoch.num_missed self._epoch.next() # after X misses during an epoch, set the status to lonely or angry if was_stale: factor = did_miss / self._config['personality'][ 'max_misses_for_recon'] if factor >= 2.0: self.set_angry(factor) else: logging.warning("agent missed %d interactions -> lonely" % did_miss) self.set_lonely() # after X times being bored, the status is set to sad or angry elif self._epoch.inactive_for >= self._config['personality'][ 'sad_num_epochs']: factor = self._epoch.inactive_for / self._config['personality'][ 'sad_num_epochs'] if factor >= 2.0: self.set_angry(factor) else: self.set_sad() # after X times being inactive, the status is set to bored elif self._epoch.inactive_for >= self._config['personality'][ 'bored_num_epochs']: self.set_bored() # after X times being active, the status is set to happy / excited elif self._epoch.active_for >= self._config['personality'][ 'excited_num_epochs']: self.set_excited() elif self._epoch.active_for >= 5 and self._has_support_network_for( 5.0): self.set_grateful() plugins.on('epoch', self, self._epoch.epoch - 1, self._epoch.data()) if self._epoch.blind_for >= self._config['main'][ 'mon_max_blind_epochs']: logging.critical( "%d epochs without visible access points -> rebooting ..." % self._epoch.blind_for) self._reboot() self._epoch.blind_for = 0
def get_access_points(self): whitelist = self._config['main']['whitelist'] aps = [] try: s = self.session() plugins.on("unfiltered_ap_list", self, s['wifi']['aps']) for ap in s['wifi']['aps']: if ap['encryption'] == '' or ap['encryption'] == 'OPEN': continue elif ap['hostname'] not in whitelist: if self._filter_included(ap): aps.append(ap) except Exception as e: logging.exception("error") aps.sort(key=lambda ap: ap['channel']) return self.set_access_points(aps)
def associate(self, ap, throttle=0): if self.is_stale(): logging.debug("recon is stale, skipping assoc(%s)" % ap['mac']) return if self._config['personality']['associate'] and self._should_interact( ap['mac']): self._view.on_assoc(ap) try: logging.info("sending association frame to %s (%s %s) on channel %d [%d clients]..." % ( \ ap['hostname'], ap['mac'], ap['vendor'], ap['channel'], len(ap['clients']))) self.run('wifi.assoc %s' % ap['mac']) self._epoch.track(assoc=True) except Exception as e: self._on_error(ap['mac'], e) plugins.on('association', self, ap) if throttle > 0: time.sleep(throttle) self._view.on_normal()
def update(self, force=False, new_data={}): for key, val in new_data.items(): self.set(key, val) with self._lock: if self._frozen: return changes = self._state.changes(ignore=self._ignore_changes) if force or len(changes): self._canvas = Image.new('1', (self._width, self._height), WHITE) drawer = ImageDraw.Draw(self._canvas) plugins.on('ui_update', self) for key, lv in self._state.items(): lv.draw(self._canvas, drawer) for cb in self._render_cbs: cb(self._canvas) self._state.reset()
def deauth(self, ap, sta, throttle=0): if self.is_stale(): logging.debug("recon is stale, skipping deauth(%s)" % sta['mac']) return if self._config['personality']['deauth'] and self._should_interact( sta['mac']): self._view.on_deauth(sta) try: logging.info( "deauthing %s (%s) from %s (%s %s) on channel %d ..." % (sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'], ap['channel'])) self.run('wifi.deauth %s' % sta['mac']) self._epoch.track(deauth=True) except Exception as e: self._on_error(sta['mac'], e) plugins.on('deauthentication', self, ap, sta) if throttle > 0: time.sleep(throttle) self._view.on_normal()
def set_channel(self, channel, verbose=True): if self.is_stale(): logging.debug("recon is stale, skipping set_channel(%d)" % channel) return # if in the previous loop no client stations has been deauthenticated # and only association frames have been sent, we don't need to wait # very long before switching channel as we don't have to wait for # such client stations to reconnect in order to sniff the handshake. wait = 0 if self._epoch.did_deauth: wait = self._config['personality']['hop_recon_time'] elif self._epoch.did_associate: wait = self._config['personality']['min_recon_time'] if channel != self._current_channel: if self._current_channel != 0 and wait > 0: if verbose: logging.info("waiting for %ds on channel %d ..." % (wait, self._current_channel)) else: logging.debug("waiting for %ds on channel %d ..." % (wait, self._current_channel)) self.wait_for(wait) if verbose and self._epoch.any_activity: logging.info("CHANNEL %d" % channel) try: self.run('wifi.recon.channel %d' % channel) self._current_channel = channel self._epoch.track(hop=True) self._view.set('channel', '%d' % channel) plugins.on('channel_hop', self, channel) except Exception as e: logging.error("error: %s" % e)
def on_ai_ready(self): self._view.on_ai_ready() plugins.on('ai_ready', self)
def set_grateful(self): self._view.on_grateful() plugins.on('grateful', self)
def set_ready(self): plugins.on('ready', self)
def _on_lost_peer(self, peer): logging.info("lost peer %s" % peer.full_name()) self._view.on_lost_peer(peer) plugins.on('peer_lost', self, peer)
def set_access_points(self, aps): self._access_points = aps plugins.on('wifi_update', self, aps) self._epoch.observe(aps, list(self._peers.values())) return self._access_points
def _on_new_peer(self, peer): logging.info("new peer %s detected (%d encounters)" % (peer.full_name(), peer.encounters)) self._view.on_new_peer(peer) plugins.on('peer_detected', self, peer)
def set_excited(self): logging.warning("%d epochs with activity -> excited" % self._epoch.active_for) self._view.on_excited() plugins.on('excited', self)
def set_rebooting(self): self._view.on_rebooting() plugins.on('rebooting', self)
def __init__(self, config, impl, state=None): global ROOT # setup faces from the configuration in case the user customized them faces.load_from_config(config['ui']['faces']) self._agent = None self._render_cbs = [] self._config = config self._canvas = None self._frozen = False self._lock = Lock() self._voice = Voice(lang=config['main']['lang']) self._implementation = impl self._layout = impl.layout() self._width = self._layout['width'] self._height = self._layout['height'] self._state = State(state={ 'channel': LabeledValue(color=BLACK, label='CH', value='00', position=self._layout['channel'], label_font=fonts.Bold, text_font=fonts.Medium), 'aps': LabeledValue(color=BLACK, label='APS', value='0 (00)', position=self._layout['aps'], label_font=fonts.Bold, text_font=fonts.Medium), 'uptime': LabeledValue(color=BLACK, label='UP', value='00:00:00', position=self._layout['uptime'], label_font=fonts.Bold, text_font=fonts.Medium), 'line1': Line(self._layout['line1'], color=BLACK), 'line2': Line(self._layout['line2'], color=BLACK), 'face': Text(value=faces.SLEEP, position=self._layout['face'], color=BLACK, font=fonts.Huge), 'friend_face': Text(value=None, position=self._layout['friend_face'], font=fonts.Bold, color=BLACK), 'friend_name': Text(value=None, position=self._layout['friend_name'], font=fonts.BoldSmall, color=BLACK), 'name': Text(value='%s>' % 'cleanagotchi', position=self._layout['name'], color=BLACK, font=fonts.Bold), 'status': Text(value=self._voice.default(), position=self._layout['status']['pos'], color=BLACK, font=self._layout['status']['font'], wrap=True, # the current maximum number of characters per line, assuming each character is 6 pixels wide max_length=self._layout['status']['max']), 'shakes': LabeledValue(label='PWND ', value='0 (00)', color=BLACK, position=self._layout['shakes'], label_font=fonts.Bold, text_font=fonts.Medium), 'mode': Text(value='AUTO', position=self._layout['mode'], font=fonts.Bold, color=BLACK), }) if state: for key, value in state.items(): self._state.set(key, value) plugins.on('ui_setup', self) if config['ui']['fps'] > 0.0: _thread.start_new_thread(self._refresh_handler, ()) self._ignore_changes = () else: logging.warning("ui.fps is 0, the display will only update for major changes") self._ignore_changes = ('uptime', 'name') ROOT = self
def on_ai_training_step(self, _locals, _globals): self._model.env.render() plugins.on('ai_training_step', self, _locals, _globals)
def on_ai_worst_reward(self, r): logging.info("[ai] worst reward so far: %s" % r) self._view.on_demotivated(r) plugins.on('ai_worst_reward', self, r)
def wait_for(self, t, sleeping=True): plugins.on('sleep' if sleeping else 'wait', self, t) self._view.wait(t, sleeping) self._epoch.track(sleep=True, inc=t)