Skip to content

Commit

Permalink
Merge pull request #4 from evilsocket/master
Browse files Browse the repository at this point in the history
pr
  • Loading branch information
hmax42 authored Dec 27, 2019
2 parents 774d9c6 + 63dc672 commit 80eafb9
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 26 deletions.
4 changes: 3 additions & 1 deletion builder/data/etc/systemd/system/pwnagotchi.service
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ PermissionsStartOnly=true
ExecStart=/usr/bin/pwnagotchi-launcher
Restart=always
RestartSec=30
TasksMax=infinity
LimitNPROC=infinity

[Install]
WantedBy=multi-user.target
WantedBy=multi-user.target
14 changes: 7 additions & 7 deletions pwnagotchi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import subprocess
import os
import logging
import time
import re

import pwnagotchi.ui.view as view
import pwnagotchi

version = '1.4.1'
version = '1.4.3'

_name = None

Expand All @@ -27,17 +27,17 @@ def set_name(new_name):
if new_name != current:
global _name

logging.info("setting unit hostname '%s' -> '%s'" % (current, new_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)
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)
logging.debug("new hosts:\n%s\n", patched)
fp.write(patched)

os.system("hostname '%s'" % new_name)
Expand Down Expand Up @@ -109,7 +109,7 @@ def shutdown():


def restart(mode):
logging.warning("restarting in %s mode ..." % mode)
logging.warning("restarting in %s mode ...", mode)

if mode == 'AUTO':
os.system("touch /root/.pwnagotchi-auto")
Expand All @@ -123,7 +123,7 @@ def restart(mode):
def reboot(mode=None):
if mode is not None:
mode = mode.upper()
logging.warning("rebooting in %s mode ..." % mode)
logging.warning("rebooting in %s mode ...", mode)
else:
logging.warning("rebooting ...")

Expand Down
2 changes: 1 addition & 1 deletion pwnagotchi/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def get_access_points_by_channel(self):
ch = ap['channel']
# if we're sticking to a channel, skip anything
# which is not on that channel
if not channels and ch not in channels:
if channels and ch not in channels:
continue

if ch not in grouped:
Expand Down
19 changes: 9 additions & 10 deletions pwnagotchi/automata.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,18 @@ def __init__(self, config, view):
self._epoch = Epoch(config)

def _on_miss(self, who):
logging.info("it looks like %s is not in range anymore :/" % who)
logging.info("it looks like %s is not in range anymore :/", who)
self._epoch.track(miss=True)
self._view.on_miss(who)

def _on_error(self, who, e):
error = "%s" % e
# when we're trying to associate or deauth something that is not in range anymore
# (if we are moving), we get the following error from bettercap:
# error 400: 50:c7:bf:2e:d3:37 is an unknown BSSID or it is in the association skip list.
if 'is an unknown BSSID' in error:
if 'is an unknown BSSID' in str(e):
self._on_miss(who)
else:
logging.error("%s" % e)
logging.error(e)

def set_starting(self):
self._view.on_starting()
Expand Down Expand Up @@ -58,7 +57,7 @@ def set_lonely(self):
def set_bored(self):
factor = self._epoch.inactive_for / self._config['personality']['bored_num_epochs']
if not self._has_support_network_for(factor):
logging.warning("%d epochs with no activity -> bored" % self._epoch.inactive_for)
logging.warning("%d epochs with no activity -> bored", self._epoch.inactive_for)
self._view.on_bored()
plugins.on('bored', self)
else:
Expand All @@ -68,7 +67,7 @@ def set_bored(self):
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)
logging.warning("%d epochs with no activity -> sad", self._epoch.inactive_for)
self._view.on_sad()
plugins.on('sad', self)
else:
Expand All @@ -77,15 +76,15 @@ def set_sad(self):

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)
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 set_excited(self):
logging.warning("%d epochs with activity -> excited" % self._epoch.active_for)
logging.warning("%d epochs with activity -> excited", self._epoch.active_for)
self._view.on_excited()
plugins.on('excited', self)

Expand Down Expand Up @@ -118,7 +117,7 @@ def next_epoch(self):
if factor >= 2.0:
self.set_angry(factor)
else:
logging.warning("agent missed %d interactions -> lonely" % did_miss)
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']:
Expand All @@ -139,6 +138,6 @@ def next_epoch(self):
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)
logging.critical("%d epochs without visible access points -> rebooting ...", self._epoch.blind_for)
self._reboot()
self._epoch.blind_for = 0
24 changes: 22 additions & 2 deletions pwnagotchi/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
import os
import glob
import _thread
import threading
import importlib, importlib.util
import logging
from pwnagotchi.ui import view

default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default")
loaded = {}
database = {}
locks = {}


class Plugin:
@classmethod
def __init_subclass__(cls, **kwargs):
super().__init_subclass__(**kwargs)
global loaded
global loaded, locks

plugin_name = cls.__module__.split('.')[0]
plugin_instance = cls()
logging.debug("loaded plugin %s as %s" % (plugin_name, plugin_instance))
loaded[plugin_name] = plugin_instance

for attr_name in plugin_instance.__dir__():
if attr_name.startswith('on_'):
cb = getattr(plugin_instance, attr_name, None)
if cb is not None and callable(cb):
locks["%s::%s" % (plugin_name, attr_name)] = threading.Lock()


def toggle_plugin(name, enable=True):
"""
Load or unload a plugin
Expand Down Expand Up @@ -47,15 +58,24 @@ def on(event_name, *args, **kwargs):
one(plugin_name, event_name, *args, **kwargs)


def locked_cb(lock_name, cb, *args, **kwargs):
global locks
with locks[lock_name]:
cb(*args, *kwargs)


def one(plugin_name, event_name, *args, **kwargs):
global loaded

if plugin_name in loaded:
plugin = loaded[plugin_name]
cb_name = 'on_%s' % event_name
callback = getattr(plugin, cb_name, None)
if callback is not None and callable(callback):
try:
_thread.start_new_thread(callback, (*args, *kwargs))
lock_name = "%s::%s" % (plugin_name, cb_name)
locked_cb_args = (lock_name, callback, *args, *kwargs)
_thread.start_new_thread(locked_cb, locked_cb_args)
except Exception as e:
logging.error("error while running %s.%s : %s" % (plugin_name, cb_name, e))
logging.error(e, exc_info=True)
Expand Down
7 changes: 7 additions & 0 deletions pwnagotchi/plugins/default/gps.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ def on_ui_setup(self, ui):
),
)


def on_unload(self, ui):
with ui._lock:
ui.remove_element('latitude')
ui.remove_element('longitude')
ui.remove_element('altitude')

def on_ui_update(self, ui):
if self.coordinates and all([
# avoid 0.000... measurements
Expand Down
9 changes: 8 additions & 1 deletion pwnagotchi/plugins/default/memtemp.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ def on_ui_setup(self, ui):
elif ui.is_inky():
h_pos = (140, 68)
v_pos = (165, 54)
elif ui.is_waveshare27inch():
h_pos = (192, 138)
v_pos = (216, 122)
else:
h_pos = (155, 76)
v_pos = (180, 61)
Expand All @@ -67,6 +70,10 @@ def on_ui_setup(self, ui):
position=h_pos,
label_font=fonts.Small, text_font=fonts.Small))

def on_unload(self, ui):
with ui._lock:
ui.remove_element('memtemp')

def on_ui_update(self, ui):
if self.options['scale'] == "fahrenheit":
temp = (pwnagotchi.temperature() * 9 / 5) + 32
Expand All @@ -75,7 +82,7 @@ def on_ui_update(self, ui):
temp = pwnagotchi.temperature() + 273.15
symbol = "k"
else:
# default to celsius
# default to celsius
temp = pwnagotchi.temperature()
symbol = "c"

Expand Down
4 changes: 4 additions & 0 deletions pwnagotchi/plugins/default/ups_lite.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,9 @@ def on_ui_setup(self, ui):
ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 + 15, 0),
label_font=fonts.Bold, text_font=fonts.Medium))

def on_unload(self, ui):
with ui._lock:
ui.remove_element('ups')

def on_ui_update(self, ui):
ui.set('ups', "%2i%%" % self.ups.capacity())
3 changes: 3 additions & 0 deletions pwnagotchi/plugins/default/webgpsmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,9 @@ def timestamp_last(self):
elif 'Updated' in self._json:
# convert gps datetime to unix timestamp: "2019-10-05T23:12:40.422996+01:00"
date_iso_formated = self._json['Updated']
#fix timezone "Z": "2019-11-28T04:44:46.79231Z" >> "2019-11-28T04:44:46.79231+00:00"
if date_iso_formated.endswith("Z"):
date_iso_formated = date_iso_formated[:-1] + "+00:00"
# bad microseconds fix: fill/cut microseconds to 6 numbers
part1, part2, part3 = re.split('\.|\+', date_iso_formated)
part2 = part2.ljust(6, '0')[:6]
Expand Down
2 changes: 1 addition & 1 deletion pwnagotchi/ui/hw/waveshare27inch.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class Waveshare27inch(DisplayImpl):
def __init__(self, config):
super(Waveshare27inch, self).__init__(config, 'waveshare_2_7inch')
super(Waveshare27inch, self).__init__(config, 'waveshare27inch')
self._display = None

def layout(self):
Expand Down
15 changes: 14 additions & 1 deletion pwnagotchi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import json
import shutil
import gzip
import contextlib
import tempfile

import pwnagotchi

Expand Down Expand Up @@ -345,6 +347,17 @@ def extract_from_pcap(path, fields):

return results

@contextlib.contextmanager
def ensure_write(filename, mode='w'):
path = os.path.dirname(filename)
fd, tmp = tempfile.mkstemp(dir=path)

with os.fdopen(fd, mode) as f:
yield f
f.flush()
os.fsync(f.fileno())

os.replace(tmp, filename)

class StatusFile(object):
def __init__(self, path, data_format='raw'):
Expand Down Expand Up @@ -378,7 +391,7 @@ def newer_then_days(self, days):
def update(self, data=None):
self._updated = datetime.now()
self.data = data
with open(self._path, 'w') as fp:
with ensure_write(self._path, 'w') as fp:
if data is None:
fp.write(str(self._updated))

Expand Down
5 changes: 4 additions & 1 deletion pwnagotchi/voice.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ def on_rebooting(self):

def on_last_session_data(self, last_session):
status = self._('Kicked {num} stations\n').format(num=last_session.deauthed)
status += self._('Made {num} new friends\n').format(num=last_session.associated)
if last_session.associated > 999:
status += self._('Made >999 new friends\n')
else:
status += self._('Made {num} new friends\n').format(num=last_session.associated)
status += self._('Got {num} handshakes\n').format(num=last_session.handshakes)
if last_session.peers == 1:
status += self._('Met 1 peer')
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ requests==2.21.0
PyYAML==5.1
scapy==2.4.3
gym==0.14.0
scipy==1.3.1
stable-baselines==2.7.0
tensorflow==1.13.1
tensorflow-estimator==1.14.0
Expand All @@ -16,4 +17,4 @@ spidev==3.4
gast==0.2.2
flask==1.0.2
flask-cors==3.0.7
flask-wtf==0.14.2
flask-wtf==0.14.2

0 comments on commit 80eafb9

Please sign in to comment.