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)
Example #2
0
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()
Example #3
0
    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 ''})
Example #4
0
 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)
Example #5
0
 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)
Example #7
0
    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 ''})
Example #8
0
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 ''
                       })