Merge updated 'master' into gps_config

This commit is contained in:
Thomas Bouve
2021-04-18 17:22:00 +02:00
30 changed files with 778 additions and 237 deletions

View File

@ -1,6 +1,6 @@
# memtemp shows memory infos and cpu temperature
#
# mem usage, cpu load, cpu temp
# mem usage, cpu load, cpu temp, cpu frequency
#
###############################################################
#
@ -16,8 +16,15 @@
# - Added CPU load
# - Added horizontal and vertical orientation
#
# 19-09-2020 by crahan <crahan@n00.be>
# - Added CPU frequency
# - Made field types and order configurable (max 3 fields)
# - Made line spacing and position configurable
# - Updated code to dynamically generate UI elements
# - Changed horizontal UI elements to Text
# - Updated to version 1.0.2
###############################################################
from pwnagotchi.ui.components import LabeledValue
from pwnagotchi.ui.components import LabeledValue, Text
from pwnagotchi.ui.view import BLACK
import pwnagotchi.ui.fonts as fonts
import pwnagotchi.plugins as plugins
@ -27,54 +34,31 @@ import logging
class MemTemp(plugins.Plugin):
__author__ = 'https://github.com/xenDE'
__version__ = '1.0.1'
__version__ = '1.0.2'
__license__ = 'GPL3'
__description__ = 'A plugin that will display memory/cpu usage and temperature'
ALLOWED_FIELDS = {
'mem': 'mem_usage',
'cpu': 'cpu_load',
'temp': 'cpu_temp',
'freq': 'cpu_freq'
}
DEFAULT_FIELDS = ['mem', 'cpu', 'temp']
LINE_SPACING = 10
LABEL_SPACING = 0
FIELD_WIDTH = 4
def on_loaded(self):
logging.info("memtemp plugin loaded.")
def mem_usage(self):
return int(pwnagotchi.mem_usage() * 100)
return f"{int(pwnagotchi.mem_usage() * 100)}%"
def cpu_load(self):
return int(pwnagotchi.cpu_load() * 100)
return f"{int(pwnagotchi.cpu_load() * 100)}%"
def on_ui_setup(self, ui):
if ui.is_waveshare_v2():
h_pos = (180, 80)
v_pos = (180, 61)
elif ui.is_waveshare_v1():
h_pos = (170, 80)
v_pos = (170, 61)
elif ui.is_waveshare144lcd():
h_pos = (53, 77)
v_pos = (78, 67)
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)
if self.options['orientation'] == "vertical":
ui.add_element('memtemp', LabeledValue(color=BLACK, label='', value=' mem:-\n cpu:-\ntemp:-',
position=v_pos,
label_font=fonts.Small, text_font=fonts.Small))
else:
# default to horizontal
ui.add_element('memtemp', LabeledValue(color=BLACK, label='', value='mem cpu temp\n - - -',
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):
def cpu_temp(self):
if self.options['scale'] == "fahrenheit":
temp = (pwnagotchi.temperature() * 9 / 5) + 32
symbol = "f"
@ -85,11 +69,116 @@ class MemTemp(plugins.Plugin):
# default to celsius
temp = pwnagotchi.temperature()
symbol = "c"
return f"{temp}{symbol}"
def cpu_freq(self):
with open('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq', 'rt') as fp:
return f"{round(float(fp.readline())/1000000, 1)}G"
def pad_text(self, data):
return " " * (self.FIELD_WIDTH - len(data)) + data
def on_ui_setup(self, ui):
try:
# Configure field list
self.fields = self.options['fields'].split(',')
self.fields = [x.strip() for x in self.fields if x.strip() in self.ALLOWED_FIELDS.keys()]
self.fields = self.fields[:3] # limit to the first 3 fields
except Exception:
# Set default value
self.fields = self.DEFAULT_FIELDS
try:
# Configure line_spacing
line_spacing = int(self.options['linespacing'])
except Exception:
# Set default value
line_spacing = self.LINE_SPACING
try:
# Configure position
pos = self.options['position'].split(',')
pos = [int(x.strip()) for x in pos]
if self.options['orientation'] == "vertical":
v_pos = (pos[0], pos[1])
else:
h_pos = (pos[0], pos[1])
except Exception:
# Set default position based on screen type
if ui.is_waveshare_v2():
h_pos = (178, 84)
v_pos = (197, 74)
elif ui.is_waveshare_v1():
h_pos = (170, 80)
v_pos = (165, 61)
elif ui.is_waveshare144lcd():
h_pos = (53, 77)
v_pos = (73, 67)
elif ui.is_inky():
h_pos = (140, 68)
v_pos = (160, 54)
elif ui.is_waveshare27inch():
h_pos = (192, 138)
v_pos = (211, 122)
else:
h_pos = (155, 76)
v_pos = (175, 61)
if self.options['orientation'] == "vertical":
ui.set('memtemp',
" mem:%s%%\n cpu:%s%%\ntemp:%s%s" % (self.mem_usage(), self.cpu_load(), temp, symbol))
# Dynamically create the required LabeledValue objects
for idx, field in enumerate(self.fields):
v_pos_x = v_pos[0]
v_pos_y = v_pos[1] + ((len(self.fields) - 3) * -1 * line_spacing)
ui.add_element(
f"memtemp_{field}",
LabeledValue(
color=BLACK,
label=f"{self.pad_text(field)}:",
value="-",
position=(v_pos_x, v_pos_y + (idx * line_spacing)),
label_font=fonts.Small,
text_font=fonts.Small,
label_spacing=self.LABEL_SPACING,
)
)
else:
# default to horizontal
ui.set('memtemp',
" mem cpu temp\n %s%% %s%% %s%s" % (self.mem_usage(), self.cpu_load(), temp, symbol))
h_pos_x = h_pos[0] + ((len(self.fields) - 3) * -1 * 25)
h_pos_y = h_pos[1]
ui.add_element(
'memtemp_header',
Text(
color=BLACK,
value=" ".join([self.pad_text(x) for x in self.fields]),
position=(h_pos_x, h_pos_y),
font=fonts.Small,
)
)
ui.add_element(
'memtemp_data',
Text(
color=BLACK,
value=" ".join([self.pad_text("-") for x in self.fields]),
position=(h_pos_x, h_pos_y + line_spacing),
font=fonts.Small,
)
)
def on_unload(self, ui):
with ui._lock:
if self.options['orientation'] == "vertical":
for idx, field in enumerate(self.fields):
ui.remove_element(f"memtemp_{field}")
else:
# default to horizontal
ui.remove_element('memtemp_header')
ui.remove_element('memtemp_data')
def on_ui_update(self, ui):
if self.options['orientation'] == "vertical":
for idx, field in enumerate(self.fields):
ui.set(f"memtemp_{field}", getattr(self, self.ALLOWED_FIELDS[field])())
else:
# default to horizontal
data = " ".join([self.pad_text(getattr(self, self.ALLOWED_FIELDS[x])()) for x in self.fields])
ui.set('memtemp_data', data)

View File

@ -110,9 +110,8 @@ class OnlineHashCrack(plugins.Plugin):
if handshake_new:
logging.info("OHC: Internet connectivity detected. Uploading new handshakes to onlinehashcrack.com")
for idx, handshake in enumerate(handshake_new):
display.set('status',
f"Uploading handshake to onlinehashcrack.com ({idx + 1}/{len(handshake_new)})")
display.update(force=True)
display.on_uploading(f"onlinehashcrack.com ({idx + 1}/{len(handshake_new)})")
try:
self._upload_to_ohc(handshake)
if handshake not in reported:
@ -127,6 +126,9 @@ class OnlineHashCrack(plugins.Plugin):
self.skip.append(handshake)
logging.debug("OHC: %s", os_e)
continue
display.on_normal()
if 'dashboard' in self.options and self.options['dashboard']:
cracked_file = os.path.join(handshake_dir, 'onlinehashcrack.cracked')
if os.path.exists(cracked_file):

View File

@ -7,14 +7,18 @@
# For Raspberry Pi Zero Ups Power Expansion Board with Integrated Serial Port S3U4
# https://www.ebay.de/itm/For-Raspberry-Pi-Zero-Ups-Power-Expansion-Board-with-Integrated-Serial-Port-S3U4/323873804310
# https://www.aliexpress.com/item/32888533624.html
#
# To display external power supply status you need to bridge the necessary pins on the UPS-Lite board. See instructions in the UPS-Lite repo.
import logging
import struct
import RPi.GPIO as GPIO
import pwnagotchi
import pwnagotchi.plugins as plugins
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.components import LabeledValue
from pwnagotchi.ui.view import BLACK
import pwnagotchi.ui.fonts as fonts
import pwnagotchi.plugins as plugins
import pwnagotchi
# TODO: add enable switch in config.yml an cleanup all to the best place
@ -43,6 +47,14 @@ class UPS:
except:
return 0.0
def charging(self):
try:
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN)
return '+' if GPIO.input(4) == GPIO.HIGH else '-'
except:
return '-'
class UPSLite(plugins.Plugin):
__author__ = 'evilsocket@gmail.com'
@ -66,7 +78,8 @@ class UPSLite(plugins.Plugin):
def on_ui_update(self, ui):
capacity = self.ups.capacity()
ui.set('ups', "%2i%%" % capacity)
charging = self.ups.charging()
ui.set('ups', "%2i%s" % (capacity, charging))
if capacity <= self.options['shutdown']:
logging.info('[ups_lite] Empty battery (<= %s%%): shuting down' % self.options['shutdown'])
ui.update(force=True, new_data={'status': 'Battery exhausted, bye ...'})

View File

@ -33,4 +33,4 @@ class Watchdog(plugins.Plugin):
logging.info('[WATCHDOG] Blind-Bug detected. Restarting.')
mode = 'MANU' if agent.mode == 'manual' else 'AUTO'
import pwnagotchi
pwnagotchi.restart(mode=mode)
pwnagotchi.reboot(mode=mode)

View File

@ -9,6 +9,7 @@ from datetime import datetime
from pwnagotchi.utils import WifiInfo, FieldNotFoundError, extract_from_pcap, StatusFile, remove_whitelisted
from threading import Lock
from pwnagotchi import plugins
from pwnagotchi._version import __version__ as __pwnagotchi_version__
def _extract_gps_data(path):
@ -34,14 +35,14 @@ def _format_auth(data):
return out
def _transform_wigle_entry(gps_data, pcap_data):
def _transform_wigle_entry(gps_data, pcap_data, plugin_version):
"""
Transform to wigle entry in file
"""
dummy = StringIO()
# write kismet header
dummy.write(
"WigleWifi-1.4,appRelease=20190201,model=Kismet,release=2019.02.01.{},device=kismet,display=kismet,board=kismet,brand=kismet\n")
"WigleWifi-1.4,appRelease={},model=pwnagotchi,release={},device=pwnagotchi,display=kismet,board=kismet,brand=pwnagotchi\n".format(plugin_version, __pwnagotchi_version__))
dummy.write(
"MAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type")
@ -62,7 +63,7 @@ def _transform_wigle_entry(gps_data, pcap_data):
return dummy.getvalue()
def _send_to_wigle(lines, api_key, timeout=30):
def _send_to_wigle(lines, api_key, donate=True, timeout=30):
"""
Uploads the file to wigle-net
"""
@ -76,7 +77,7 @@ def _send_to_wigle(lines, api_key, timeout=30):
headers = {'Authorization': f"Basic {api_key}",
'Accept': 'application/json'}
data = {'donate': 'false'}
data = {'donate': 'on' if donate else 'false'}
payload = {'file': dummy, 'type': 'text/csv'}
try:
@ -112,6 +113,9 @@ class Wigle(plugins.Plugin):
if not 'whitelist' in self.options:
self.options['whitelist'] = list()
if not 'donate' in self.options:
self.options['donate'] = True
self.ready = True
def on_internet_available(self, agent):
@ -172,14 +176,14 @@ class Wigle(plugins.Plugin):
logging.debug("WIGLE: %s", sc_e)
self.skip.append(gps_file)
continue
new_entry = _transform_wigle_entry(gps_data, pcap_data)
new_entry = _transform_wigle_entry(gps_data, pcap_data, self.__version__)
csv_entries.append(new_entry)
no_err_entries.append(gps_file)
if csv_entries:
display.set('status', "Uploading gps-data to wigle.net ...")
display.update(force=True)
display.on_uploading('wigle.net')
try:
_send_to_wigle(csv_entries, self.options['api_key'])
_send_to_wigle(csv_entries, self.options['api_key'], donate=self.options['donate'])
reported += no_err_entries
self.report.update(data={'reported': reported})
logging.info("WIGLE: Successfully uploaded %d files", len(no_err_entries))
@ -189,3 +193,5 @@ class Wigle(plugins.Plugin):
except OSError as os_e:
self.skip += no_err_entries
logging.debug("WIGLE: Got the following error: %s", os_e)
display.on_normal()

View File

@ -82,6 +82,7 @@ class WpaSec(plugins.Plugin):
self.options['whitelist'] = list()
self.ready = True
logging.info("WPA_SEC: plugin loaded")
def on_webhook(self, path, request):
from flask import make_response, redirect
@ -110,8 +111,8 @@ class WpaSec(plugins.Plugin):
if handshake_new:
logging.info("WPA_SEC: Internet connectivity detected. Uploading new handshakes to wpa-sec.stanev.org")
for idx, handshake in enumerate(handshake_new):
display.set('status', f"Uploading handshake to wpa-sec.stanev.org ({idx + 1}/{len(handshake_new)})")
display.update(force=True)
display.on_uploading(f"wpa-sec.stanev.org ({idx + 1}/{len(handshake_new)})")
try:
self._upload_to_wpasec(handshake)
reported.append(handshake)
@ -125,6 +126,8 @@ class WpaSec(plugins.Plugin):
logging.debug("WPA_SEC: %s", os_e)
continue
display.on_normal()
if 'download_results' in self.options and self.options['download_results']:
cracked_file = os.path.join(handshake_dir, 'wpa-sec.cracked.potfile')
if os.path.exists(cracked_file):