Version 2.2.9:

Signed-off-by: Jeroen Oudshoorn <oudshoorn.jeroen@gmail.com>
This commit is contained in:
Jeroen Oudshoorn
2023-09-05 20:29:09 +02:00
parent 173c0eced2
commit 8c9519f2ee
10 changed files with 66 additions and 217 deletions

View File

@ -12,7 +12,7 @@ from pwnagotchi.plugins import cmd as plugins_cmd
from pwnagotchi import log
from pwnagotchi import restart
from pwnagotchi import fs
from pwnagotchi.utils import DottedTomlEncoder
from pwnagotchi.utils import DottedTomlEncoder, parse_version as version_to_tuple
def do_clear(display):
@ -118,6 +118,11 @@ if __name__ == '__main__':
parser.add_argument('--print-config', dest="print_config", action="store_true", default=False,
help="Print the configuration.")
parser.add_argument('--check-update', dest="check_update", action="store_true", default=False,
help="Check for updates on Pwnagotchi.")
parser.add_argument('--donate', dest="donate", action="store_true", default=False,
help="How to donate to this project.")
args = parser.parse_args()
if plugins_cmd.used_plugin_cmd(args):
@ -126,6 +131,26 @@ if __name__ == '__main__':
rc = plugins_cmd.handle_cmd(args, config)
sys.exit(rc)
if args.donate:
print("Donations can made @ https://www.patreon.com/pwnagotchi_torch \n\nBut only if you really want to!")
if args.check_update:
resp = requests.get("https://api.github.com/repos/jayofelony/pwnagotchi/releases/latest")
latest = resp.json()
latest_ver = latest['tag_name'].replace('v', '')
local = version_to_tuple(pwnagotchi.__version__)
remote = version_to_tuple(latest_ver)
if remote > local:
user_input = input("There is a new version available! Update to %s? [y(es)/n(o)]" % latest_ver)
# input validation
if user_input.lower() in ('y', 'yes'):
os.system("rm /root/.auto-update && systemctl restart pwnagotchi")
elif user_input.lower() in ('n', 'no'): # using this elif for readability
print("Okay, guess not!")
else:
print("You are currently on the latest release, %s." % pwnagotchi.__version__)
if args.version:
print(pwnagotchi.__version__)
sys.exit(0)

View File

@ -1 +1 @@
__version__ = '2.2.8'
__version__ = '2.2.9'

View File

@ -51,7 +51,18 @@ class Client(object):
logging.debug("Lost websocket connection. Reconnecting...")
except websockets.exceptions.WebSocketException as wex:
logging.debug("Websocket exception (%s)", wex)
except Exception as e:
logging.exception("Other error while opening websocket (%s) with parameter %s", e, s)
def run(self, command, verbose_errors=True):
r = requests.post("%s/session" % self.url, auth=self.auth, json={'cmd': command})
return decode(r, verbose_errors=verbose_errors)
def run(self, command, verbose_errors=True):
for _ in range(0, 2):
try:
r = requests.post("%s/session" % self.url, auth=self.auth, json={'cmd': command})
except requests.exceptions.ConnectionError as e:
logging.exception("Request connection error (%s) while running command (%s)", e, command)
sleep(1) # Sleep for 1-s before trying a second time
else:
break
return decode(r, verbose_errors=verbose_errors)

View File

@ -46,9 +46,9 @@ main.plugins.grid.exclude = [
"YourHomeNetworkHere"
]
main.plugins.auto-update.enabled = false
main.plugins.auto-update.install = false
main.plugins.auto-update.interval = 24
main.plugins.auto-update.enabled = true
main.plugins.auto-update.install = true
main.plugins.auto-update.interval = 1
main.plugins.net-pos.enabled = false
main.plugins.net-pos.api_key = "test"
@ -119,32 +119,6 @@ main.plugins.ups_lite.shutdown = 2
main.plugins.gpio_buttons.enabled = false
main.plugins.led.enabled = false
main.plugins.led.led = 0
main.plugins.led.delay = 200
main.plugins.led.patterns.loaded = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.updating = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.unread_inbox = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.ready = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.ai_ready = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.ai_training_start = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.ai_best_reward = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.ai_worst_reward = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.bored = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.sad = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.excited = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.lonely = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.rebooting = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.wait = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.sleep = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.wifi_update = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.association = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.deauthentication = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.handshake = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.epoch = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.peer_detected = "oo oo oo oo oo oo oo"
main.plugins.led.patterns.peer_lost = "oo oo oo oo oo oo oo"
main.plugins.webcfg.enabled = true
main.plugins.logtail.enabled = false

View File

@ -10,7 +10,7 @@ from pwnagotchi.utils import download_file, unzip, save_config, parse_version, m
from pwnagotchi.plugins import default_path
SAVE_DIR = '/usr/local/share/pwnagotchi/availaible-plugins/'
SAVE_DIR = '/usr/local/share/pwnagotchi/available-plugins/'
DEFAULT_INSTALL_PATH = '/usr/local/share/pwnagotchi/installed-plugins/'

View File

@ -123,8 +123,13 @@ def install(display, update):
if not os.path.exists(source_path):
source_path = "%s-%s" % (source_path, update['available'])
# setup.py is going to install data files for us
os.system("cd %s && pip3 install ." % source_path)
if "pwngrid" in source_path:
os.system("cd %s && make && make install" % source_path)
elif "bettercap" in source_path:
os.system("cd %s && make && make install" % source_path)
else:
# setup.py is going to install data files for us
os.system("cd %s && pip3 install ." % source_path)
return True
@ -182,7 +187,7 @@ class AutoUpdate(plugins.Plugin):
to_install = []
to_check = [
('jayofelony/bettercap', parse_version('bettercap -version'), True, 'bettercap'),
('evilsocket/pwngrid', parse_version('pwngrid -version'), True, 'pwngrid-peer'),
('jayofelony/pwngrid', parse_version('pwngrid -version'), True, 'pwngrid-peer'),
('jayofelony/pwnagotchi', pwnagotchi.__version__, False, 'pwnagotchi')
]

View File

@ -35,9 +35,8 @@ class Fix_BRCMF(plugins.Plugin):
self.options = dict()
self.pattern = re.compile(r'brcmf_cfg80211_nexmon_set_channel.*?Set Channel failed')
self.pattern2 = re.compile(r'wifi error while hopping to channel')
self.pattern3 = re.compile(r'Firmware has halted or crashed')
self.pattern3 = re.compile(r'error 400: could not find interface wlan0mon')
self.pattern4 = re.compile(r'AI not loaded!')
self.pattern5 = re.compile(r'ConnectionError')
self.isReloadingMon = False
self.connection = None
self.LASTTRY = 0
@ -113,6 +112,8 @@ class Fix_BRCMF(plugins.Plugin):
stdout=subprocess.PIPE).stdout))[-10:])
other_last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl', '-n10'],
stdout=subprocess.PIPE).stdout))[-10:])
other_other_last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['tail', '-n10', '/var/log/pwnagotchi.log'],
stdout=subprocess.PIPE).stdout))[-10:])
# don't check if we ran a reset recently
logging.debug("[FixBRCMF]**** epoch")
if time.time() - self.LASTTRY > 180:
@ -159,7 +160,7 @@ class Fix_BRCMF(plugins.Plugin):
logging.error("[FixBRCMF wifi.recon flip] %s" % repr(err))
# Look for pattern 3
elif len(self.pattern3.findall(other_last_lines)) >= 1:
elif len(self.pattern3.findall(other_other_last_lines)) >= 1:
logging.info("[FixBRCMF] Firmware has halted or crashed. Restarting wlan0mon.")
if hasattr(agent, 'view'):
display = agent.view()
@ -167,14 +168,14 @@ class Fix_BRCMF(plugins.Plugin):
display.update(force=True)
try:
# Run the monstart command to restart wlan0mon
cmd_output = restart("AUTO")
cmd_output = subprocess.check_output("monstart", shell=True)
self._status = "up"
logging.info("[FixBRCMF monstart]: %s" % repr(cmd_output))
except Exception as err:
logging.error("[FixBRCMF monstart]: %s" % repr(err))
# Look for pattern 4
elif len(self.pattern4.findall(other_last_lines)) >= 1:
elif len(self.pattern4.findall(other_other_last_lines)) >= 1:
logging.info("[FixBRCMF] Having a brain meltdown. Deleting myself.")
if hasattr(agent, 'view'):
display = agent.view()
@ -190,20 +191,6 @@ class Fix_BRCMF(plugins.Plugin):
except Exception as err:
logging.error("[FixBRCMF brain]: %s" % repr(err))
# Look for pattern 5
elif len(self.pattern5.findall(other_last_lines)) >= 1:
logging.info("[FixBRCMF] Bettercap connection failure. Restarting Bettercap.")
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Bettercap connection failure. Restarting Bettercap.')
try:
# Delete brain /root/brain.nn and restarting pwnagotchi service
cmd_output = subprocess.check_output("systemctl restart bettercap",
shell=True)
self._status = "up"
logging.info("[FixBRCMF bettercap]: %s" % repr(cmd_output))
except Exception as err:
logging.error("[FixBRCMF bettercap]: %s" % repr(err))
else:
print("logs look good")

View File

@ -1,159 +0,0 @@
from threading import Event
import _thread
import logging
import time
import pwnagotchi.plugins as plugins
class Led(plugins.Plugin):
__author__ = 'evilsocket@gmail.com'
__version__ = '1.0.0'
__license__ = 'GPL3'
__description__ = 'This plugin blinks the PWR led with different patterns depending on the event.'
def __init__(self):
self._is_busy = False
self._event = Event()
self._event_name = None
self._led_file = "/sys/class/leds/led0/brightness"
self._delay = 200
# called when the plugin is loaded
def on_loaded(self):
self._led_file = "/sys/class/leds/led%d/brightness" % self.options['led']
self._delay = int(self.options['delay'])
logging.info("[led] plugin loaded for %s" % self._led_file)
self._on_event('loaded')
_thread.start_new_thread(self._worker, ())
def _on_event(self, event):
if not self._is_busy:
self._event_name = event
self._event.set()
logging.debug("[led] event '%s' set", event)
else:
logging.debug("[led] skipping event '%s' because the worker is busy", event)
def _led(self, on):
with open(self._led_file, 'wt') as fp:
fp.write(str(on))
def _blink(self, pattern):
logging.debug("[led] using pattern '%s' ..." % pattern)
for c in pattern:
if c == ' ':
self._led(1)
else:
self._led(0)
time.sleep(self._delay / 1000.0)
# reset
self._led(0)
def _worker(self):
while True:
self._event.wait()
self._event.clear()
self._is_busy = True
try:
if self._event_name in self.options['patterns']:
pattern = self.options['patterns'][self._event_name]
self._blink(pattern)
else:
logging.debug("[led] no pattern defined for %s" % self._event_name)
except Exception as e:
logging.exception("[led] error while blinking")
finally:
self._is_busy = False
# called when the unit is updating its software
def on_updating(self):
self._on_event('updating')
# called when there's one or more unread pwnmail messages
def on_unread_inbox(self, num_unread):
self._on_event('unread_inbox')
# called when there's internet connectivity
def on_internet_available(self, agent):
self._on_event('internet_available')
# called when everything is ready and the main loop is about to start
def on_ready(self, agent):
self._on_event('ready')
# called when the AI finished loading
def on_ai_ready(self, agent):
self._on_event('ai_ready')
# called when the AI starts training for a given number of epochs
def on_ai_training_start(self, agent, epochs):
self._on_event('ai_training_start')
# called when the AI got the best reward so far
def on_ai_best_reward(self, agent, reward):
self._on_event('ai_best_reward')
# called when the AI got the worst reward so far
def on_ai_worst_reward(self, agent, reward):
self._on_event('ai_worst_reward')
# called when the status is set to bored
def on_bored(self, agent):
self._on_event('bored')
# called when the status is set to sad
def on_sad(self, agent):
self._on_event('sad')
# called when the status is set to excited
def on_excited(self, agent):
self._on_event('excited')
# called when the status is set to lonely
def on_lonely(self, agent):
self._on_event('lonely')
# called when the agent is rebooting the board
def on_rebooting(self, agent):
self._on_event('rebooting')
# called when the agent is waiting for t seconds
def on_wait(self, agent, t):
self._on_event('wait')
# called when the agent is sleeping for t seconds
def on_sleep(self, agent, t):
self._on_event('sleep')
# called when the agent refreshed its access points list
def on_wifi_update(self, agent, access_points):
self._on_event('wifi_update')
# called when the agent is sending an association frame
def on_association(self, agent, access_point):
self._on_event('association')
# called when the agent is deauthenticating a client station from an AP
def on_deauthentication(self, agent, access_point, client_station):
self._on_event('deauthentication')
# called when a new handshake is captured, access_point and client_station are json objects
# if the agent could match the BSSIDs to the current list, otherwise they are just the strings of the BSSIDs
def on_handshake(self, agent, filename, access_point, client_station):
self._on_event('handshake')
# called when an epoch is over (where an epoch is a single loop of the main algorithm)
def on_epoch(self, agent, epoch, epoch_data):
self._on_event('epoch')
# called when a new peer is detected
def on_peer_detected(self, agent, peer):
self._on_event('peer_detected')
# called when a known peer is lost
def on_peer_lost(self, agent, peer):
self._on_event('peer_lost')

View File

@ -3,6 +3,8 @@ import pwnagotchi.ui.fonts as fonts
class DisplayImpl(object):
def __init__(self, config, name):
if fonts.Medium is None:
fonts.init(config)
self.name = name
self.config = config['ui']['display']
self._layout = {

View File

@ -101,6 +101,10 @@ def main():
main:
lang: {lang}
ui:
font:
name: 'DejaVuSansMono'
size_offset: 0
size: 0
fps: 0.3
display:
enabled: false
@ -110,7 +114,7 @@ def main():
type: {display}
web:
enabled: true
address: "0.0.0.0"
address: '::'
port: 8080
faces: