mirror of
https://github.com/jayofelony/pwnagotchi.git
synced 2026-04-28 09:53:06 -07:00
Update to 2.9.5.5
Signed-off-by: Jeroen Oudshoorn <oudshoorn.jeroen@gmail.com>
This commit is contained in:
11
.idea/deployment.xml
generated
11
.idea/deployment.xml
generated
@@ -1,6 +1,15 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="PublishConfigData" filePermissions="493" folderPermissions="493" remoteFilesAllowedToDisappearOnAutoupload="false" confirmBeforeUploading="false">
|
<component name="PublishConfigData" serverName="pwnagotchi" filePermissions="493" folderPermissions="493" remoteFilesAllowedToDisappearOnAutoupload="false" confirmBeforeUploading="false">
|
||||||
<option name="confirmBeforeUploading" value="false" />
|
<option name="confirmBeforeUploading" value="false" />
|
||||||
|
<serverData>
|
||||||
|
<paths name="pwnagotchi">
|
||||||
|
<serverdata>
|
||||||
|
<mappings>
|
||||||
|
<mapping deploy="/home/pi/.pwn/lib/python3.13" local="$PROJECT_DIR$" web="/" />
|
||||||
|
</mappings>
|
||||||
|
</serverdata>
|
||||||
|
</paths>
|
||||||
|
</serverData>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -3,7 +3,7 @@
|
|||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.11 (pwnagotchi)" />
|
<option name="sdkName" value="Python 3.11 (pwnagotchi)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.14 (pwnagotchi)" project-jdk-type="Python SDK" />
|
||||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||||
<option name="version" value="3" />
|
<option name="version" value="3" />
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
2
.idea/pwnagotchi.iml
generated
2
.idea/pwnagotchi.iml
generated
@@ -5,7 +5,7 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.13" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.14 (pwnagotchi)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PyDocumentationSettings">
|
<component name="PyDocumentationSettings">
|
||||||
|
|||||||
2
.idea/sshConfigs.xml
generated
2
.idea/sshConfigs.xml
generated
@@ -2,7 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="SshConfigs">
|
<component name="SshConfigs">
|
||||||
<configs>
|
<configs>
|
||||||
<sshConfig authType="PASSWORD" connectionConfig="{"serverAliveInterval":300}" id="8b69df7d-cec5-421f-8edf-53ed6233f6b6" port="22" customName="pwnagotchi" nameFormat="CUSTOM" useOpenSSHConfig="true">
|
<sshConfig authType="PASSWORD" connectionConfig="{"hostKeyVerifier":{"hashKnownHosts":true},"serverAliveInterval":300}" host="pwnagotchi.local" id="8b69df7d-cec5-421f-8edf-53ed6233f6b6" port="22" customName="pwnagotchi" nameFormat="CUSTOM" username="pi" useOpenSSHConfig="true">
|
||||||
<option name="customName" value="pwnagotchi" />
|
<option name="customName" value="pwnagotchi" />
|
||||||
</sshConfig>
|
</sshConfig>
|
||||||
</configs>
|
</configs>
|
||||||
|
|||||||
4
.idea/webServers.xml
generated
4
.idea/webServers.xml
generated
@@ -3,9 +3,9 @@
|
|||||||
<component name="WebServers">
|
<component name="WebServers">
|
||||||
<option name="servers">
|
<option name="servers">
|
||||||
<webServer id="cf2a1148-a103-4472-a782-7debdc6dabf9" name="pwnagotchi">
|
<webServer id="cf2a1148-a103-4472-a782-7debdc6dabf9" name="pwnagotchi">
|
||||||
<fileTransfer accessType="SFTP" port="22" sshConfigId="8b69df7d-cec5-421f-8edf-53ed6233f6b6" sshConfig="pwnagotchi">
|
<fileTransfer accessType="SFTP" host="pwnagotchi.local" port="22" sshConfigId="8b69df7d-cec5-421f-8edf-53ed6233f6b6" sshConfig="pwnagotchi">
|
||||||
<advancedOptions>
|
<advancedOptions>
|
||||||
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" />
|
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" isUseSudo="true" />
|
||||||
</advancedOptions>
|
</advancedOptions>
|
||||||
</fileTransfer>
|
</fileTransfer>
|
||||||
</webServer>
|
</webServer>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
__version__ = '2.9.5.4'
|
__version__ = '2.9.5.5'
|
||||||
|
|||||||
@@ -6,11 +6,9 @@ import sys
|
|||||||
import tomlkit
|
import tomlkit
|
||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
|
|
||||||
import pwnagotchi
|
import pwnagotchi
|
||||||
from pwnagotchi import utils
|
from pwnagotchi import utils
|
||||||
from pwnagotchi.google import cmd as google_cmd
|
|
||||||
from pwnagotchi.plugins import cmd as plugins_cmd
|
from pwnagotchi.plugins import cmd as plugins_cmd
|
||||||
from pwnagotchi import log
|
from pwnagotchi import log
|
||||||
from pwnagotchi import fs
|
from pwnagotchi import fs
|
||||||
@@ -104,9 +102,6 @@ def pwnagotchi_cli():
|
|||||||
# Add parsers from plugins_cmd
|
# Add parsers from plugins_cmd
|
||||||
plugins_cmd.add_parsers(subparsers)
|
plugins_cmd.add_parsers(subparsers)
|
||||||
|
|
||||||
# Add parsers from google_cmd
|
|
||||||
google_cmd.add_parsers(subparsers)
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(prog="pwnagotchi")
|
parser = argparse.ArgumentParser(prog="pwnagotchi")
|
||||||
# pwnagotchi --help
|
# pwnagotchi --help
|
||||||
parser.add_argument('-C', '--config', action='store', dest='config', default='/etc/pwnagotchi/default.toml',
|
parser.add_argument('-C', '--config', action='store', dest='config', default='/etc/pwnagotchi/default.toml',
|
||||||
@@ -130,9 +125,7 @@ def pwnagotchi_cli():
|
|||||||
parser.add_argument('--print-config', dest="print_config", action="store_true", default=False,
|
parser.add_argument('--print-config', dest="print_config", action="store_true", default=False,
|
||||||
help="Print the configuration.")
|
help="Print the configuration.")
|
||||||
|
|
||||||
# Jayofelony added these
|
|
||||||
parser.add_argument('--wizard', dest="wizard", action="store_true", default=False,
|
|
||||||
help="Interactive installation of your personal configuration.")
|
|
||||||
parser.add_argument('--check-update', dest="check_update", action="store_true", default=False,
|
parser.add_argument('--check-update', dest="check_update", action="store_true", default=False,
|
||||||
help="Check for updates on Pwnagotchi. And tells current version.")
|
help="Check for updates on Pwnagotchi. And tells current version.")
|
||||||
parser.add_argument('--donate', dest="donate", action="store_true", default=False,
|
parser.add_argument('--donate', dest="donate", action="store_true", default=False,
|
||||||
@@ -147,133 +140,11 @@ def pwnagotchi_cli():
|
|||||||
log.setup_logging(args, config)
|
log.setup_logging(args, config)
|
||||||
rc = plugins_cmd.handle_cmd(args, config)
|
rc = plugins_cmd.handle_cmd(args, config)
|
||||||
sys.exit(rc)
|
sys.exit(rc)
|
||||||
if google_cmd.used_google_cmd(args):
|
|
||||||
config = utils.load_config(args)
|
|
||||||
log.setup_logging(args, config)
|
|
||||||
rc = google_cmd.handle_cmd(args)
|
|
||||||
sys.exit(rc)
|
|
||||||
|
|
||||||
if args.version:
|
if args.version:
|
||||||
print(pwnagotchi.__version__)
|
print(pwnagotchi.__version__)
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
if args.wizard:
|
|
||||||
def is_valid_hostname(hostname):
|
|
||||||
if len(hostname) > 255:
|
|
||||||
return False
|
|
||||||
if hostname[-1] == ".":
|
|
||||||
hostname = hostname[:-1] # strip exactly one dot from the right, if present
|
|
||||||
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
|
|
||||||
return all(allowed.match(x) for x in hostname.split("."))
|
|
||||||
|
|
||||||
pwn_restore = input("Do you want to restore the previous configuration?\n\n"
|
|
||||||
"[Y/N]: ")
|
|
||||||
if pwn_restore in ('y', 'yes'):
|
|
||||||
os.system("cp -f /etc/pwnagotchi/config.toml.bak /etc/pwnagotchi/config.toml")
|
|
||||||
print("Your previous configuration is restored, and I will restart in 5 seconds.")
|
|
||||||
time.sleep(5)
|
|
||||||
os.system("service pwnagotchi restart")
|
|
||||||
else:
|
|
||||||
pwn_check = input("This will create a new configuration file and overwrite your current backup, are you sure?\n\n"
|
|
||||||
"[Y/N]: ")
|
|
||||||
if pwn_check.lower() in ('y', 'yes'):
|
|
||||||
os.system("mv -f /etc/pwnagotchi/config.toml /etc/pwnagotchi/config.toml.bak")
|
|
||||||
with open("/etc/pwnagotchi/config.toml", "a+") as f:
|
|
||||||
f.write("# Do not edit this file if you do not know what you are doing!!!\n\n")
|
|
||||||
# Set pwnagotchi name
|
|
||||||
print("Welcome to the interactive installation of your personal Pwnagotchi configuration!\n"
|
|
||||||
"My name is Jayofelony, how may I call you?\n\n")
|
|
||||||
pwn_name = input("Pwnagotchi name (no spaces): ")
|
|
||||||
if pwn_name == "":
|
|
||||||
pwn_name = "Pwnagotchi"
|
|
||||||
print("I shall go by Pwnagotchi from now on!")
|
|
||||||
pwn_name = (f"[main]\n"
|
|
||||||
f"name = \"{pwn_name}\"\n")
|
|
||||||
f.write(pwn_name)
|
|
||||||
else:
|
|
||||||
if is_valid_hostname(pwn_name):
|
|
||||||
print(f"I shall go by {pwn_name} from now on!")
|
|
||||||
pwn_name = (f"[main]\n"
|
|
||||||
f"name = \"{pwn_name}\"\n")
|
|
||||||
f.write(pwn_name)
|
|
||||||
else:
|
|
||||||
print("You have chosen an invalid name. Please start over.")
|
|
||||||
exit()
|
|
||||||
pwn_whitelist = input("How many networks do you want to whitelist? "
|
|
||||||
"We will also ask a MAC for each network?\n"
|
|
||||||
"Each SSID and BSSID count as 1 network. \n\n"
|
|
||||||
"Be sure to use digits as your answer.\n\n"
|
|
||||||
"Amount of networks: ")
|
|
||||||
if int(pwn_whitelist) > 0:
|
|
||||||
f.write("whitelist = [\n")
|
|
||||||
for x in range(int(pwn_whitelist)):
|
|
||||||
ssid = input("SSID (Name): ")
|
|
||||||
bssid = input("BSSID (MAC): ")
|
|
||||||
f.write(f"\t\"{ssid}\",\n")
|
|
||||||
if bssid != "":
|
|
||||||
f.write(f"\t\"{bssid}\",\n")
|
|
||||||
f.write("]\n")
|
|
||||||
# set bluetooth tether
|
|
||||||
pwn_bluetooth = input("Do you want to enable BT-Tether?\n\n"
|
|
||||||
"[Y/N] ")
|
|
||||||
if pwn_bluetooth.lower() in ('y', 'yes'):
|
|
||||||
f.write("[main.plugins.bt-tether]\n"
|
|
||||||
"enabled = true\n\n")
|
|
||||||
pwn_bluetooth_phone_name = input("What name uses your phone, check settings?\n\n")
|
|
||||||
if pwn_bluetooth_phone_name != "":
|
|
||||||
f.write(f"phone-name = \"{pwn_bluetooth_phone_name}\"\n")
|
|
||||||
pwn_bluetooth_device = input("What device do you use? android or ios?\n\n"
|
|
||||||
"Device: ")
|
|
||||||
if pwn_bluetooth_device != "":
|
|
||||||
if pwn_bluetooth_device != "android" and pwn_bluetooth_device != "ios":
|
|
||||||
print("You have chosen an invalid device. Please start over.")
|
|
||||||
exit()
|
|
||||||
f.write(f"phone = \"{pwn_bluetooth_device.lower()}\"\n")
|
|
||||||
if pwn_bluetooth_device == "android":
|
|
||||||
f.write("ip = \"192.168.44.44\"\n")
|
|
||||||
elif pwn_bluetooth_device == "ios":
|
|
||||||
f.write("ip = \"172.20.10.6\"\n")
|
|
||||||
pwn_bluetooth_mac = input("What is the bluetooth MAC of your device?\n\n"
|
|
||||||
"MAC: ")
|
|
||||||
if pwn_bluetooth_mac != "":
|
|
||||||
f.write(f"mac = \"{pwn_bluetooth_mac}\"\n")
|
|
||||||
# set up display settings
|
|
||||||
pwn_display_enabled = input("Do you want to enable a display?\n\n"
|
|
||||||
"[Y/N]: ")
|
|
||||||
if pwn_display_enabled.lower() in ('y', 'yes'):
|
|
||||||
f.write("[ui.display]\n"
|
|
||||||
"enabled = true\n")
|
|
||||||
pwn_display_type = input("What display do you use?\n\n"
|
|
||||||
"Be sure to check for the correct display type @ \n"
|
|
||||||
"https://github.com/jayofelony/pwnagotchi/blob/master/pwnagotchi/utils.py#L240-L501\n\n"
|
|
||||||
"Display type: ")
|
|
||||||
if pwn_display_type != "":
|
|
||||||
f.write(f"type = \"{pwn_display_type}\"\n")
|
|
||||||
pwn_display_invert = input("Do you want to invert the display colors?\n"
|
|
||||||
"N = Black background\n"
|
|
||||||
"Y = White background\n\n"
|
|
||||||
"[Y/N]: ")
|
|
||||||
if pwn_display_invert.lower() in ('y', 'yes'):
|
|
||||||
f.write("[ui]\n"
|
|
||||||
"invert = true\n")
|
|
||||||
f.close()
|
|
||||||
if pwn_bluetooth.lower() in ('y', 'yes'):
|
|
||||||
if pwn_bluetooth_device.lower == "android":
|
|
||||||
print("To visit the webui when connected with your phone, visit: http://192.168.44.44:8080\n"
|
|
||||||
"Be sure to run `sudo bluetoothctl` to set-up the bluetooth connection for the first time. And read the wiki step 4.\n"
|
|
||||||
"Your configuration is done, and I will restart in 5 seconds.")
|
|
||||||
|
|
||||||
elif pwn_bluetooth_device.lower == "ios":
|
|
||||||
print("To visit the webui when connected with your phone, visit: http://172.20.10.6:8080\n"
|
|
||||||
"Your configuration is done, and I will restart in 5 seconds.")
|
|
||||||
else:
|
|
||||||
print("Your configuration is done, and I will restart in 5 seconds.")
|
|
||||||
time.sleep(5)
|
|
||||||
os.system("service pwnagotchi restart")
|
|
||||||
else:
|
|
||||||
print("Ok, doing nothing.")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if args.donate:
|
if args.donate:
|
||||||
print("Donations can be made @ \n "
|
print("Donations can be made @ \n "
|
||||||
"https://github.com/sponsors/jayofelony \n\n"
|
"https://github.com/sponsors/jayofelony \n\n"
|
||||||
|
|||||||
@@ -30,22 +30,16 @@ enabled = true
|
|||||||
enabled = false
|
enabled = false
|
||||||
interval = "daily" # or "hourly", or a number (minutes)
|
interval = "daily" # or "hourly", or a number (minutes)
|
||||||
max_tries = 0
|
max_tries = 0
|
||||||
backup_location = "/home/pi/"
|
backup_location = "/etc/pwnagotchi/"
|
||||||
files = [
|
files = [
|
||||||
"/root/settings.yaml",
|
|
||||||
"/root/client_secrets.json",
|
|
||||||
"/root/.api-report.json",
|
"/root/.api-report.json",
|
||||||
"/root/.ssh",
|
"/root/.ssh",
|
||||||
"/root/.bashrc",
|
"/root/.bashrc",
|
||||||
"/root/.profile",
|
"/root/.profile",
|
||||||
"/home/pi/handshakes",
|
|
||||||
"/root/peers",
|
|
||||||
"/etc/pwnagotchi/",
|
"/etc/pwnagotchi/",
|
||||||
"/usr/local/share/pwnagotchi/custom-plugins",
|
"/root/peers",
|
||||||
"/etc/ssh/",
|
"/etc/ssh/",
|
||||||
"/home/pi/.bashrc",
|
"/root/.auto-backup"
|
||||||
"/home/pi/.profile",
|
|
||||||
"/home/pi/.wpa_sec_uploads"
|
|
||||||
]
|
]
|
||||||
exclude = [ "/etc/pwnagotchi/logs/*"]
|
exclude = [ "/etc/pwnagotchi/logs/*"]
|
||||||
commands = [ "tar cf {backup_file} {files}"]
|
commands = [ "tar cf {backup_file} {files}"]
|
||||||
@@ -58,12 +52,12 @@ token = "" # Create a personal access token (classic) with scope set to public_r
|
|||||||
|
|
||||||
[main.plugins.bt-tether]
|
[main.plugins.bt-tether]
|
||||||
enabled = false
|
enabled = false
|
||||||
phone-name = "" # name as shown on the phone i.e. "Pwnagotchi's Phone"
|
auto_reconnect = true # Auto reconnect on disconnect (default: true)
|
||||||
mac = ""
|
show_on_screen = true # Master switch: show status on display
|
||||||
phone = "" # android or ios
|
show_mini_status = true # Show mini status indicator (C/N/P/D)
|
||||||
ip = "" # optional, default : 192.168.44.2 if android or 172.20.10.2 if ios
|
mini_status_position = [110, 0] # Position for mini status
|
||||||
gateway = "" #optional, default : 192.168.44.1 if android or 172.20.10.2 if ios
|
show_detailed_status = true # Show detailed status line with IP
|
||||||
dns = "8.8.8.8 1.1.1.1" # optional, default (google): "8.8.8.8 1.1.1.1". Consider using anonymous DNS like OpenNic :-)
|
detailed_status_position = [0, 82] # Position for detailed status line
|
||||||
|
|
||||||
[main.plugins.fix_services]
|
[main.plugins.fix_services]
|
||||||
enabled = true
|
enabled = true
|
||||||
@@ -71,12 +65,6 @@ enabled = true
|
|||||||
[main.plugins.cache]
|
[main.plugins.cache]
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
[main.plugins.gdrivesync]
|
|
||||||
enabled = false
|
|
||||||
backupfiles = [""]
|
|
||||||
backup_folder = "PwnagotchiBackups"
|
|
||||||
interval = 1
|
|
||||||
|
|
||||||
[main.plugins.gpio_buttons]
|
[main.plugins.gpio_buttons]
|
||||||
enabled = false
|
enabled = false
|
||||||
|
|
||||||
@@ -85,9 +73,6 @@ enabled = false
|
|||||||
speed = 19200
|
speed = 19200
|
||||||
device = "/dev/ttyUSB0" # for GPSD: "localhost:2947"
|
device = "/dev/ttyUSB0" # for GPSD: "localhost:2947"
|
||||||
|
|
||||||
[main.plugins.gps_listener]
|
|
||||||
enabled = false
|
|
||||||
|
|
||||||
[main.plugins.grid]
|
[main.plugins.grid]
|
||||||
enabled = true
|
enabled = true
|
||||||
report = true
|
report = true
|
||||||
@@ -126,7 +111,7 @@ key = ""
|
|||||||
|
|
||||||
[main.plugins.session-stats]
|
[main.plugins.session-stats]
|
||||||
enabled = false
|
enabled = false
|
||||||
save_directory = "/var/tmp/pwnagotchi/sessions/"
|
save_directory = "/etc/pwnagotchi/sessions/"
|
||||||
|
|
||||||
[main.plugins.ups_hat_c]
|
[main.plugins.ups_hat_c]
|
||||||
enabled = false
|
enabled = false
|
||||||
@@ -243,7 +228,7 @@ rotation = 180
|
|||||||
type = "waveshare_4"
|
type = "waveshare_4"
|
||||||
|
|
||||||
[bettercap]
|
[bettercap]
|
||||||
handshakes = "/home/pi/handshakes"
|
handshakes = "/etc/pwnagotchi/handshakes"
|
||||||
silence = [
|
silence = [
|
||||||
"ble.device.new",
|
"ble.device.new",
|
||||||
"ble.device.lost",
|
"ble.device.lost",
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ def check(version, repo, native=True, token=""):
|
|||||||
|
|
||||||
|
|
||||||
def make_path_for(name):
|
def make_path_for(name):
|
||||||
path = os.path.join("/home/pi/", name)
|
path = os.path.join("/opt/", name)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
logging.debug("[update] deleting %s" % path)
|
logging.debug("[update] deleting %s" % path)
|
||||||
shutil.rmtree(path, ignore_errors=True, onerror=None)
|
shutil.rmtree(path, ignore_errors=True, onerror=None)
|
||||||
@@ -155,7 +155,7 @@ def install(display, update):
|
|||||||
try:
|
try:
|
||||||
# Activate the virtual environment and install the package
|
# Activate the virtual environment and install the package
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["bash", "-c", f"source /home/pi/.pwn/bin/activate && pip install {source_path}"],
|
["bash", "-c", f"source /opt/.pwn/bin/activate && pip install {source_path}"],
|
||||||
check=True
|
check=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,233 +0,0 @@
|
|||||||
import json
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import threading
|
|
||||||
|
|
||||||
import pwnagotchi.plugins as plugins
|
|
||||||
import pwnagotchi.ui.fonts as fonts
|
|
||||||
from pwnagotchi.ui.components import LabeledValue
|
|
||||||
from pwnagotchi.ui.view import BLACK
|
|
||||||
|
|
||||||
"""
|
|
||||||
# Android
|
|
||||||
# Termux:API : https://f-droid.org/en/packages/com.termux.api/
|
|
||||||
# Termux : https://f-droid.org/en/packages/com.termux/
|
|
||||||
pkg install termux-api socat bc
|
|
||||||
|
|
||||||
-----
|
|
||||||
#!/data/data/com.termux/files/usr/bin/bash
|
|
||||||
|
|
||||||
# Server details
|
|
||||||
SERVER_IP="192.168.44.44" # IP of the socat receiver
|
|
||||||
SERVER_PORT="5000" # UDP port to send data to
|
|
||||||
|
|
||||||
# Function to calculate checksum
|
|
||||||
calculate_checksum() {
|
|
||||||
local sentence="$1"
|
|
||||||
local checksum=0
|
|
||||||
# Loop through each character in the sentence
|
|
||||||
for ((i = 0; i < ${#sentence}; i++)); do
|
|
||||||
checksum=$((checksum ^ $(printf '%d' "'${sentence:i:1}")))
|
|
||||||
done
|
|
||||||
# Return checksum in hexadecimal
|
|
||||||
printf "%02X" $checksum
|
|
||||||
}
|
|
||||||
|
|
||||||
# Infinite loop to send GPS data
|
|
||||||
while true; do
|
|
||||||
# Get location data
|
|
||||||
LOCATION=$(termux-location -p gps)
|
|
||||||
|
|
||||||
# Extract latitude, longitude, altitude, speed, and bearing
|
|
||||||
LATITUDE=$(echo "$LOCATION" | jq '.latitude')
|
|
||||||
LONGITUDE=$(echo "$LOCATION" | jq '.longitude')
|
|
||||||
ALTITUDE=$(echo "$LOCATION" | jq '.altitude')
|
|
||||||
SPEED=$(echo "$LOCATION" | jq '.speed') # Speed in meters per second
|
|
||||||
BEARING=$(echo "$LOCATION" | jq '.bearing')
|
|
||||||
|
|
||||||
# Convert speed from meters per second to knots and km/h
|
|
||||||
SPEED_KNOTS=$(echo "$SPEED" | awk '{printf "%.1f", $1 * 1.943844}')
|
|
||||||
SPEED_KMH=$(echo "$SPEED" | awk '{printf "%.1f", $1 * 3.6}')
|
|
||||||
|
|
||||||
# Format latitude and longitude for NMEA
|
|
||||||
LAT_DEGREES=$(printf "%.0f" "${LATITUDE%.*}")
|
|
||||||
LAT_MINUTES=$(echo "(${LATITUDE#${LAT_DEGREES}} * 60)" | bc -l)
|
|
||||||
LAT_DIRECTION=$(if (( $(echo "$LATITUDE >= 0" | bc -l) )); then echo "N"; else echo "S"; fi)
|
|
||||||
LON_DEGREES=$(printf "%.0f" "${LONGITUDE%.*}")
|
|
||||||
LON_MINUTES=$(echo "(${LONGITUDE#${LON_DEGREES}} * 60)" | bc -l)
|
|
||||||
LON_DIRECTION=$(if (( $(echo "$LONGITUDE >= 0" | bc -l) )); then echo "E"; else echo "W"; fi)
|
|
||||||
|
|
||||||
# Format the NMEA GGA sentence
|
|
||||||
RAW_NMEA_GGA="GPGGA,123519,$(printf "%02d%07.4f" ${LAT_DEGREES#-} $LAT_MINUTES),$LAT_DIRECTION,$(printf "%03d%07.4f" ${LON_DEGREES#-} $LON_MINUTES),$LON_DIRECTION,1,08,0.9,$(printf "%.1f" $ALTITUDE),M,46.9,M,,"
|
|
||||||
CHECKSUM=$(calculate_checksum "$RAW_NMEA_GGA")
|
|
||||||
NMEA_GGA="\$${RAW_NMEA_GGA}*${CHECKSUM}"
|
|
||||||
|
|
||||||
# Format the VTG sentence
|
|
||||||
RAW_NMEA_VTG="GPVTG,$(printf "%.1f" $BEARING),T,,M,$(printf "%.1f" $SPEED_KNOTS),N,$(printf "%.1f" $SPEED_KMH),K"
|
|
||||||
CHECKSUM_VTG=$(calculate_checksum "$RAW_NMEA_VTG")
|
|
||||||
NMEA_VTG="\$${RAW_NMEA_VTG}*${CHECKSUM_VTG}"
|
|
||||||
|
|
||||||
# Send data via UDP
|
|
||||||
echo "$NMEA_GGA"
|
|
||||||
echo "$NMEA_GGA" | socat - UDP:$SERVER_IP:$SERVER_PORT
|
|
||||||
#echo "$NMEA_VTG"
|
|
||||||
#echo "$NMEA_VTG" | socat - UDP:$SERVER_IP:$SERVER_PORT
|
|
||||||
|
|
||||||
sleep 1
|
|
||||||
done
|
|
||||||
-----
|
|
||||||
|
|
||||||
# Pwnagotchi
|
|
||||||
main.plugins.gps_listener.enabled = true
|
|
||||||
|
|
||||||
# packages
|
|
||||||
sudo apt-get install socat
|
|
||||||
"""
|
|
||||||
|
|
||||||
class GPS(plugins.Plugin):
|
|
||||||
__author__ = 'https://github.com/krishenriksen'
|
|
||||||
__version__ = "1.0.0"
|
|
||||||
__license__ = "GPL3"
|
|
||||||
__description__ = "Receive GPS coordinates via termux-location and save whenever an handshake is captured."
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.listen_ip = self.get_ip_address('bnep0')
|
|
||||||
self.listen_port = "5000"
|
|
||||||
self.write_virtual_serial = "/dev/ttyUSB1"
|
|
||||||
self.read_virtual_serial = "/dev/ttyUSB0"
|
|
||||||
self.baud_rate = "19200"
|
|
||||||
self.socat_process = None
|
|
||||||
self.stop_event = threading.Event()
|
|
||||||
self.status_lock = threading.Lock()
|
|
||||||
self.status = '-'
|
|
||||||
self.socat_thread = threading.Thread(target=self.run_socat)
|
|
||||||
|
|
||||||
def get_ip_address(self, interface):
|
|
||||||
try:
|
|
||||||
result = subprocess.run(
|
|
||||||
["ip", "addr", "show", interface],
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
check=True
|
|
||||||
)
|
|
||||||
for line in result.stdout.split('\n'):
|
|
||||||
if 'inet ' in line:
|
|
||||||
ip_address = line.strip().split()[1].split('/')[0]
|
|
||||||
return ip_address
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
logging.warning(f"Could not get IP address for interface {interface}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
def set_status(self, status):
|
|
||||||
with self.status_lock:
|
|
||||||
self.status = status
|
|
||||||
|
|
||||||
def get_status(self):
|
|
||||||
with self.status_lock:
|
|
||||||
return self.status
|
|
||||||
|
|
||||||
def on_loaded(self):
|
|
||||||
logging.info("GPS Listener plugin loaded")
|
|
||||||
self.cleanup_virtual_serial_ports()
|
|
||||||
self.create_virtual_serial_ports()
|
|
||||||
self.socat_thread.start()
|
|
||||||
|
|
||||||
def cleanup_virtual_serial_ports(self):
|
|
||||||
if os.path.exists(self.write_virtual_serial):
|
|
||||||
logging.info(f"Removing old {self.write_virtual_serial}")
|
|
||||||
os.remove(self.write_virtual_serial)
|
|
||||||
|
|
||||||
if os.path.exists(self.read_virtual_serial):
|
|
||||||
logging.info(f"Removing old {self.read_virtual_serial}")
|
|
||||||
os.remove(self.read_virtual_serial)
|
|
||||||
|
|
||||||
def create_virtual_serial_ports(self):
|
|
||||||
self.socat_process = subprocess.Popen(
|
|
||||||
["socat", "-d", "-d", f"pty,link={self.write_virtual_serial},mode=777",
|
|
||||||
f"pty,link={self.read_virtual_serial},mode=777"],
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
|
|
||||||
def run_socat(self):
|
|
||||||
while not self.stop_event.is_set():
|
|
||||||
self.socat_process = subprocess.Popen(
|
|
||||||
["socat", f"UDP-RECVFROM:{self.listen_port},reuseaddr,bind={self.listen_ip}", "-"],
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
text=True
|
|
||||||
)
|
|
||||||
|
|
||||||
self.set_status('C')
|
|
||||||
|
|
||||||
with open(self.write_virtual_serial, 'w') as serial_port:
|
|
||||||
for line in self.socat_process.stdout:
|
|
||||||
if self.stop_event.is_set():
|
|
||||||
break
|
|
||||||
serial_port.write(line)
|
|
||||||
serial_port.flush() # Ensure the data is written immediately
|
|
||||||
self.status = 'C'
|
|
||||||
|
|
||||||
self.socat_process.wait()
|
|
||||||
if self.stop_event.is_set():
|
|
||||||
break
|
|
||||||
|
|
||||||
self.set_status('-')
|
|
||||||
|
|
||||||
def cleanup(self):
|
|
||||||
if self.socat_process:
|
|
||||||
self.socat_process.terminate()
|
|
||||||
self.socat_process.wait() # Ensure the process is reaped
|
|
||||||
self.stop_event.set()
|
|
||||||
self.socat_thread.join()
|
|
||||||
self.cleanup_virtual_serial_ports()
|
|
||||||
|
|
||||||
def on_ready(self, agent):
|
|
||||||
if os.path.exists(self.read_virtual_serial):
|
|
||||||
logging.info(
|
|
||||||
f"enabling bettercap's gps module for {self.read_virtual_serial}"
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
agent.run("gps off")
|
|
||||||
except Exception:
|
|
||||||
logging.info(f"bettercap gps module was already off")
|
|
||||||
pass
|
|
||||||
|
|
||||||
agent.run(f"set gps.device {self.read_virtual_serial}")
|
|
||||||
agent.run(f"set gps.baudrate {self.baud_rate}")
|
|
||||||
agent.run("gps on")
|
|
||||||
|
|
||||||
logging.info(f"bettercap gps module enabled on {self.read_virtual_serial}")
|
|
||||||
else:
|
|
||||||
self.set_status('NF')
|
|
||||||
logging.warning("no GPS detected")
|
|
||||||
|
|
||||||
def on_handshake(self, agent, filename, access_point, client_station):
|
|
||||||
info = agent.session()
|
|
||||||
coordinates = info["gps"]
|
|
||||||
gps_filename = filename.replace(".pcap", ".gps.json")
|
|
||||||
|
|
||||||
if coordinates and all([
|
|
||||||
# avoid 0.000... measurements
|
|
||||||
coordinates["Latitude"], coordinates["Longitude"]
|
|
||||||
]):
|
|
||||||
self.set_status('S')
|
|
||||||
logging.info(f"saving GPS to {gps_filename} ({coordinates})")
|
|
||||||
with open(gps_filename, "w+t") as fp:
|
|
||||||
json.dump(coordinates, fp)
|
|
||||||
else:
|
|
||||||
logging.warning("not saving GPS. Couldn't find location.")
|
|
||||||
|
|
||||||
def on_ui_setup(self, ui):
|
|
||||||
with ui._lock:
|
|
||||||
ui.add_element('gps', LabeledValue(color=BLACK, label='GPS', value='-', position=(ui.width() / 2 - 47, 0), label_font=fonts.Bold, text_font=fonts.Medium))
|
|
||||||
|
|
||||||
def on_unload(self, ui):
|
|
||||||
self.cleanup()
|
|
||||||
|
|
||||||
with ui._lock:
|
|
||||||
ui.remove_element('gps')
|
|
||||||
|
|
||||||
def on_ui_update(self, ui):
|
|
||||||
ui.set('gps', self.get_status())
|
|
||||||
@@ -18,10 +18,10 @@ class ohcapi(plugins.Plugin):
|
|||||||
self.ready = False
|
self.ready = False
|
||||||
self.lock = Lock()
|
self.lock = Lock()
|
||||||
try:
|
try:
|
||||||
self.report = StatusFile('/root/handshakes/.ohc_uploads', data_format='json')
|
self.report = StatusFile('/etc/pwnagotchi/handshakes/.ohc_uploads', data_format='json')
|
||||||
except JSONDecodeError:
|
except JSONDecodeError:
|
||||||
os.remove('/root/.ohc_newapi_uploads')
|
os.remove('/root/.ohc_newapi_uploads')
|
||||||
self.report = StatusFile('/root/handshakes/.ohc_uploads', data_format='json')
|
self.report = StatusFile('/etc/pwnagotchi/handshakes/.ohc_uploads', data_format='json')
|
||||||
self.skip = list()
|
self.skip = list()
|
||||||
self.last_run = 0 # Track last time periodic tasks were run
|
self.last_run = 0 # Track last time periodic tasks were run
|
||||||
self.internet_active = False # Track whether internet is currently available
|
self.internet_active = False # Track whether internet is currently available
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ class WpaSec(plugins.Plugin):
|
|||||||
self._init_db()
|
self._init_db()
|
||||||
|
|
||||||
def _init_db(self):
|
def _init_db(self):
|
||||||
db_conn = sqlite3.connect('/home/pi/.wpa_sec_db')
|
db_conn = sqlite3.connect('/etc/pwnagotchi/.wpa_sec_db')
|
||||||
db_conn.execute('pragma journal_mode=wal')
|
db_conn.execute('pragma journal_mode=wal')
|
||||||
with db_conn:
|
with db_conn:
|
||||||
db_conn.execute('''
|
db_conn.execute('''
|
||||||
@@ -72,7 +72,7 @@ class WpaSec(plugins.Plugin):
|
|||||||
if not remove_whitelisted([filename], config['main']['whitelist']):
|
if not remove_whitelisted([filename], config['main']['whitelist']):
|
||||||
return
|
return
|
||||||
|
|
||||||
db_conn = sqlite3.connect('/home/pi/.wpa_sec_db')
|
db_conn = sqlite3.connect('/etc/pwnagotchi/.wpa_sec_db')
|
||||||
with db_conn:
|
with db_conn:
|
||||||
db_conn.execute('''
|
db_conn.execute('''
|
||||||
INSERT INTO handshakes (path, status)
|
INSERT INTO handshakes (path, status)
|
||||||
@@ -93,7 +93,7 @@ class WpaSec(plugins.Plugin):
|
|||||||
display = agent.view()
|
display = agent.view()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
db_conn = sqlite3.connect('/home/pi/.wpa_sec_db')
|
db_conn = sqlite3.connect('/etc/pwnagotchi/.wpa_sec_db')
|
||||||
cursor = db_conn.cursor()
|
cursor = db_conn.cursor()
|
||||||
|
|
||||||
cursor.execute('SELECT path FROM handshakes WHERE status = ?', (self.Status.TOUPLOAD.value,))
|
cursor.execute('SELECT path FROM handshakes WHERE status = ?', (self.Status.TOUPLOAD.value,))
|
||||||
@@ -264,7 +264,7 @@ class WpaSec(plugins.Plugin):
|
|||||||
|
|
||||||
def on_ui_update(self, ui):
|
def on_ui_update(self, ui):
|
||||||
if 'show_pwd' in self.options and self.options['show_pwd'] and 'download_results' in self.options and self.options['download_results']:
|
if 'show_pwd' in self.options and self.options['show_pwd'] and 'download_results' in self.options and self.options['download_results']:
|
||||||
file_path = '/home/pi/handshakes/wpa-sec.cracked.potfile'
|
file_path = '/etc/pwnagotchi/handshakes/wpa-sec.cracked.potfile'
|
||||||
try:
|
try:
|
||||||
with open(file_path, 'r') as file:
|
with open(file_path, 'r') as file:
|
||||||
# Read all lines and extract the required fields
|
# Read all lines and extract the required fields
|
||||||
|
|||||||
Reference in New Issue
Block a user