def on_epoch(self, agent, epoch, epoch_data): if self.status.newer_then_minutes(5): return data_keys = ['num_deauths', 'num_associations', 'num_handshakes'] has_interactions = any( [epoch_data[x] for x in data_keys if x in epoch_data]) if has_interactions: return epoch_duration = epoch_data['duration_secs'] # get last 10 lines last_lines = ''.join( list( TextIOWrapper( subprocess.Popen([ 'journalctl', '-n10', '-k', '--since', f"{epoch_duration} seconds ago" ], stdout=subprocess.PIPE).stdout))[-10:]) if len(self.pattern.findall(last_lines)) >= 5: display = agent.view() display.set('status', 'Blind-Bug detected. Restarting.') display.update(force=True) logging.info('[WATCHDOG] Blind-Bug detected. Restarting.') mode = 'MANU' if agent.mode == 'manual' else 'AUTO' import pwnagotchi pwnagotchi.reboot(mode=mode)
def set_name(new_name): if new_name is None: return new_name = new_name.strip() if new_name == '': return if not re.match(r'^[a-zA-Z0-9\-]{2,25}$', new_name): logging.warning("name '%s' is invalid: min length is 2, max length 25, only a-zA-Z0-9- allowed", new_name) return current = name() if new_name != current: global _name logging.info("setting unit hostname '%s' -> '%s'", current, new_name) with open('/etc/hostname', 'wt') as fp: fp.write(new_name) with open('/etc/hosts', 'rt') as fp: prev = fp.read() logging.debug("old hosts:\n%s\n", prev) with open('/etc/hosts', 'wt') as fp: patched = prev.replace(current, new_name, -1) logging.debug("new hosts:\n%s\n", patched) fp.write(patched) os.system("hostname '%s'" % new_name) pwnagotchi.reboot()
def on_internet_available(self, agent): with self.lock: logging.debug("[update] internet connectivity is available (ready %s)" % self.ready) if not self.ready: return if self.status.newer_then_hours(self.options['interval']): logging.debug("[update] last check happened less than %d hours ago" % self.options['interval']) return logging.info("[update] checking for updates ...") display = agent.view() prev_status = display.get('status') try: display.update(force=True, new_data={'status': 'Checking for updates ...'}) to_install = [] to_check = [ ('bettercap/bettercap', parse_version('bettercap -version'), True, 'bettercap'), ('evilsocket/pwngrid', parse_version('pwngrid -version'), True, 'pwngrid-peer'), ('evilsocket/pwnagotchi', pwnagotchi.__version__, False, 'pwnagotchi') ] for repo, local_version, is_native, svc_name in to_check: info = check(local_version, repo, is_native) if info['url'] is not None: logging.warning( "update for %s available (local version is '%s'): %s" % ( repo, info['current'], info['url'])) info['service'] = svc_name to_install.append(info) num_updates = len(to_install) num_installed = 0 if num_updates > 0: if self.options['install']: for update in to_install: plugins.on('updating') if install(display, update): num_installed += 1 else: prev_status = '%d new update%c available!' % (num_updates, 's' if num_updates > 1 else '') logging.info("[update] done") self.status.update() if num_installed > 0: display.update(force=True, new_data={'status': 'Rebooting ...'}) pwnagotchi.reboot() except Exception as e: logging.error("[update] %s" % e) display.update(force=True, new_data={'status': prev_status if prev_status is not None else ''})
def on_epoch(self, agent, epoch, epoch_data): # get last 10 lines last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl','-n10','-k', '--since', '-5m'], stdout=subprocess.PIPE).stdout))[-10:]) if len(self.pattern.findall(last_lines)) >= 5: display = agent.view() display.set('status', 'Blind-Bug detected. Restarting.') display.update(force=True) logging.info('[WATCHDOG] Blind-Bug detected. Restarting.') mode = 'MANU' if agent.mode == 'manual' else 'AUTO' import pwnagotchi pwnagotchi.reboot(mode=mode)
def _reboot(self): self.set_rebooting() self._save_recovery_data() pwnagotchi.reboot()
def run_task(name, options): task_service_name = "switcher-%s-task.service" % name # save all the commands to a shell script script_dir = '/usr/local/bin/' script_path = os.path.join(script_dir, 'switcher-%s.sh' % name) os.makedirs(script_dir, exist_ok=True) with open(script_path, 'wt') as script_file: script_file.write('#!/bin/bash\n') for cmd in options['commands']: script_file.write('%s\n' % cmd) os.system("chmod a+x %s" % script_path) # here we create the service which runs the tasks with open('/etc/systemd/system/%s' % task_service_name, 'wt') as task_service: task_service.write(""" [Unit] Description=Executes the tasks of the pwnagotchi switcher plugin After=pwnagotchi.service bettercap.service [Service] Type=oneshot RemainAfterExit=yes ExecStart=-/usr/local/bin/switcher-%s.sh ExecStart=-/bin/rm /etc/systemd/system/%s ExecStart=-/bin/rm /usr/local/bin/switcher-%s.sh [Install] WantedBy=multi-user.target """ % (name, task_service_name, name)) if 'reboot' in options and options['reboot']: # create a indication file! # if this file is set, we want the switcher-tasks to run open('/root/.switcher', 'a').close() # add condition systemd_dropin( "pwnagotchi.service", """ [Unit] ConditionPathExists=!/root/.switcher""") systemd_dropin( "bettercap.service", """ [Unit] ConditionPathExists=!/root/.switcher""") systemd_dropin( task_service_name, """ [Service] ExecStart=-/bin/rm /root/.switcher ExecStart=-/bin/rm /etc/systemd/system/switcher-reboot.timer""") with open('/etc/systemd/system/switcher-reboot.timer', 'wt') as reboot_timer: reboot_timer.write(""" [Unit] Description=Reboot when time is up ConditionPathExists=/root/.switcher [Timer] OnBootSec=%sm Unit=reboot.target [Install] WantedBy=timers.target """ % options['stopwatch']) systemctl("daemon-reload") systemctl("enable", "switcher-reboot.timer") systemctl("enable", task_service_name) reboot() return systemctl("daemon-reload") systemctl("start", task_service_name)
def on_internet_available(self, agent): if self.lock.locked(): return with self.lock: logging.debug("[auto-update] internet connectivity is available (ready %s)" % self.ready) if not self.ready: return if self.status.newer_then_hours(self.options['interval']): logging.debug("[auto-update] last check happened less than %d hours ago" % self.options['interval']) return logging.info("[auto-update] checking for updates ...") config = agent.config() display = agent.view() prev_status = display.get('status') try: display.update(force=True, new_data={'status': 'Checking for updates ...'}) to_install = [] to_check = [ ('dadav/bettercap', parse_version('bettercap -version'), True, 'bettercap'), ('dadav/pwnagotchi', pwnagotchi.__version__, False, 'pwnagotchi') ] for repo, local_version, is_native, svc_name in to_check: info = check(local_version, repo, is_native) if info['url'] is not None: logging.warning( "[auto-update] for %s available (local version is '%s'): %s" % ( repo, info['current'], info['url'])) info['service'] = svc_name to_install.append(info) num_updates = len(to_install) num_installed = 0 if num_updates > 0: if self.options['install']: for update in to_install: plugins.on('updating') if install(display, update): num_installed += 1 else: prev_status = '%d new update%c available!' % (num_updates, 's' if num_updates > 1 else '') if not self.done_caplets_check: prev_commit = self.status.data_field_or('caplets_version', '') try: logging.info('[auto-update] Checking for new caplets.') current_commit = fetch_last_commit('bettercap/caplets') if prev_commit != current_commit: logging.info('[auto-update] Updating caplets.') rc = os.system('bettercap -eval "caplets.update;q"') if rc == 0: self.status.update(data={'caplets_version': current_commit}) except Exception as ex: logging.error("[auto-update] %s", ex) finally: self.done_caplets_check = True # update plugins logging.info("[auto-update] Checking for new plugins") if plugin_update(config) == 0: logging.info("[auto-update] Upgrading plugins") plugin_upgrade(None, config) logging.info("[auto-update] done") self.status.update(data=self.status.data) if num_installed > 0: display.update(force=True, new_data={'status': 'Rebooting ...'}) pwnagotchi.reboot() except Exception as e: logging.error("[auto-update] %s", e) display.update(force=True, new_data={'status': prev_status if prev_status is not None else ''})
def on_internet_available(agent): global STATUS logging.debug("[update] internet connectivity is available (ready %s)" % READY) if READY: if STATUS.newer_then_hours(OPTIONS['interval']): logging.debug( "[update] last check happened less than %d hours ago" % OPTIONS['interval']) return logging.info("[update] checking for updates ...") display = agent.view() prev_status = display.get('status') try: display.update(force=True, new_data={'status': 'Checking for updates ...'}) to_install = [] to_check = [('bettercap/bettercap', subprocess.getoutput('bettercap -version').split(' ') [1].replace('v', ''), True, 'bettercap'), ('evilsocket/pwngrid', subprocess.getoutput('pwngrid -version').replace( 'v', ''), True, 'pwngrid-peer'), ('evilsocket/pwnagotchi', pwnagotchi.version, False, 'pwnagotchi')] for repo, local_version, is_native, svc_name in to_check: info = check(local_version, repo, is_native) if info['url'] is not None: logging.warning("update for %s available: %s" % (repo, info['url'])) info['service'] = svc_name to_install.append(info) num_updates = len(to_install) num_installed = 0 if num_updates > 0: if OPTIONS['install']: for update in to_install: if install(display, update): num_installed += 1 else: prev_status = '%d new update%c available!' % ( num_updates, 's' if num_updates > 1 else '') logging.info("[update] done") STATUS.update() if num_installed > 0: display.update(force=True, new_data={'status': 'Rebooting ...'}) pwnagotchi.reboot() except Exception as e: logging.error("[update] %s" % e) display.update(force=True, new_data={ 'status': prev_status if prev_status is not None else '' })