mirror of
https://github.com/jayofelony/pwnagotchi.git
synced 2025-07-01 18:37:27 -04:00
Version 2.2.9:
Signed-off-by: Jeroen Oudshoorn <oudshoorn.jeroen@gmail.com>
This commit is contained in:
@ -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)
|
||||
|
@ -1 +1 @@
|
||||
__version__ = '2.2.8'
|
||||
__version__ = '2.2.9'
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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/'
|
||||
|
||||
|
||||
|
@ -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')
|
||||
]
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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')
|
@ -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 = {
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user