PwnDroid, new plugin for the companion app on Android to share GPS data from your Android phone.

Signed-off-by: Jeroen Oudshoorn <oudshoorn.jeroen@gmail.com>
This commit is contained in:
Jeroen Oudshoorn
2025-01-20 21:10:46 +01:00
parent cb0c6c6e44
commit 0e06d3bd76
2 changed files with 149 additions and 0 deletions

View File

@ -60,6 +60,7 @@ main.plugins.ohcapi.receive_email = "yes"
main.plugins.pwndroid.enabled = false
main.plugins.pwndroid.display = false # show coords on display
main.plugins.pwndroid.display_altitude = false # show altitude on display
main.plugins.pisugarx.enabled = false
main.plugins.pisugarx.rotation = false

View File

@ -0,0 +1,148 @@
import json
import logging
import requests
import subprocess
import pwnagotchi.plugins as plugins
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.components import LabeledValue
from pwnagotchi.ui.view import BLACK
class PwnDroid(plugins.Plugin):
__author__ = "Jayofelony"
__version__ = "1.0.6"
__license__ = "GPL3"
__description__ = "Plugin for the companion app PwnDroid to display GPS data on the Pwnagotchi screen."
LINE_SPACING = 10
LABEL_SPACING = 0
def __init__(self):
self.running = False
self.coordinates = dict()
self.options = dict()
def on_loaded(self):
logging.info("[PwnDroid] Plugin loaded")
def on_ready(self, agent):
# Check connection to 192.168.44.1:4555
while True:
if (subprocess.run(['bluetoothctl', 'info'], capture_output=True, text=True)).stdout.find('Connected: yes') != -1:
self.running = True
return False
def get_location_data(self, server_url):
try:
response = requests.get(server_url)
response.raise_for_status() # Raise an exception for HTTP errors
return response.json() # Parse the JSON response
except requests.exceptions.RequestException as e:
logging.warning(f"Error connecting to the server: {e}")
return None
def on_handshake(self, agent, filename, access_point, client_station):
if self.running:
server_url = f"http://192.168.44.1:8080"
location_data = self.get_location_data(server_url)
if location_data:
logging.info("Location Data:")
logging.info(f"Latitude: {location_data['Latitude']}")
logging.info(f"Longitude: {location_data['Longitude']}")
logging.info(f"Altitude: {location_data['Altitude']}")
logging.info(f"Speed: {location_data['Speed']}")
logging.info(f"Accuracy: {location_data['Accuracy']}")
logging.info(f"Bearing: {location_data['Bearing']}")
else:
logging.info("Failed to retrieve location data.")
self.coordinates = location_data
gps_filename = filename.replace(".pcap", ".gps.json")
if self.coordinates and all([
# avoid 0.000... measurements
self.coordinates["Latitude"], self.coordinates["Longitude"]
]):
logging.info(f"saving GPS to {gps_filename} ({self.coordinates})")
with open(gps_filename, "w+t") as fp:
json.dump(self.coordinates, fp)
else:
logging.info("[PwnDroid] not saving GPS. Couldn't find location.")
def on_ui_setup(self, ui):
try:
# Configure line_spacing
line_spacing = int(self.options['linespacing'])
except Exception as e:
# Set default value
logging.debug(f"[PwnDroid] Error on_ui_setup: {e}")
line_spacing = self.LINE_SPACING
try:
# Configure position
pos = self.options['position'].split(',')
pos = [int(x.strip()) for x in pos]
lat_pos = (pos[0] + 5, pos[1])
lon_pos = (pos[0], pos[1] + line_spacing)
alt_pos = (pos[0] + 5, pos[1] + (2 * line_spacing))
except Exception:
# Set default value based on display type
lat_pos = (127, 64)
lon_pos = (127, 74)
alt_pos = (127, 84)
ui.add_element(
"latitude",
LabeledValue(
color=BLACK,
label="lat:",
value="-",
position=lat_pos,
label_font=fonts.Small,
text_font=fonts.Small,
label_spacing=self.LABEL_SPACING,
),
)
ui.add_element(
"longitude",
LabeledValue(
color=BLACK,
label="long:",
value="-",
position=lon_pos,
label_font=fonts.Small,
text_font=fonts.Small,
label_spacing=self.LABEL_SPACING,
),
)
ui.add_element(
"altitude",
LabeledValue(
color=BLACK,
label="alt:",
value="-",
position=alt_pos,
label_font=fonts.Small,
text_font=fonts.Small,
label_spacing=self.LABEL_SPACING,
),
)
def on_unload(self, ui):
with ui._lock:
ui.remove_element('latitude')
ui.remove_element('longitude')
ui.remove_element('lltitude')
def on_ui_update(self, ui):
if self.options['display']:
with ui._lock:
if self.coordinates and all([
# avoid 0.000... measurements
self.coordinates["Latitude"], self.coordinates["Longitude"]
]):
ui.set("latitude", f"{self.coordinates['Latitude']:.4f} ")
ui.set("longitude", f"{self.coordinates['Longitude']:.4f} ")
if self.options['display_altitude']:
ui.set("altitude", f"{self.coordinates['Altitude']:.1f}m ")