Merge branch 'pwnagotchi-torch-testing' into pwnagotchi-torch-64

This commit is contained in:
Jeroen Oudshoorn
2023-09-24 00:43:50 +02:00
18 changed files with 145 additions and 281 deletions

2
.idea/misc.xml generated
View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (pwnagotchi)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (pwnagotchi)" project-jdk-type="Python SDK" />
</project> </project>

2
.idea/pwnagotchi.iml generated
View File

@ -4,7 +4,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" /> <excludeFolder url="file://$MODULE_DIR$/venv" />
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.11 (pwnagotchi)" jdkType="Python SDK" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="PyDocumentationSettings"> <component name="PyDocumentationSettings">

View File

@ -1,6 +1,21 @@
PACKER_VERSION=1.9.4 PACKER_VERSION := 1.9.4
PWN_HOSTNAME=pwnagotchi PWN_HOSTNAME := pwnagotchi
PWN_VERSION:=$(shell cut -d"'" -f2 < pwnagotchi/_version.py) PWN_VERSION := $(shell cut -d"'" -f2 < pwnagotchi/_version.py)
PWN_RELEASE := pwnagotchi-raspios-lite-$(PWN_VERSION)
MACHINE_TYPE := $(shell uname -m)
ifneq (,$(filter x86_64,$(MACHINE_TYPE)))
GOARCH := amd64
else ifneq (,$(filter i686,$(MACHINE_TYPE)))
GOARCH := 386
else ifneq (,$(filter arm64% aarch64%,$(MACHINE_TYPE)))
GOARCH := arm64
else ifneq (,$(filter arm%,$(MACHINE_TYPE)))
GOARCH := arm
else
GOARCH := amd64
$(warning Unable to detect CPU arch from machine type $(MACHINE_TYPE), assuming $(GOARCH))
endif
# The Ansible part of the build can inadvertently change the active hostname of # The Ansible part of the build can inadvertently change the active hostname of
# the build machine while updating the permanent hostname of the build image. # the build machine while updating the permanent hostname of the build image.
@ -19,9 +34,8 @@ langs:
./scripts/language.sh compile $$(basename $$lang); \ ./scripts/language.sh compile $$(basename $$lang); \
done done
install: PACKER := /tmp/pwnagotchi/packer
PACKER := ~/packer PACKER_URL := https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_$(GOARCH).zip
PACKER_URL := https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_amd64.zip
$(PACKER): $(PACKER):
mkdir -p $(@D) mkdir -p $(@D)
curl -L "$(PACKER_URL)" -o $(PACKER).zip curl -L "$(PACKER_URL)" -o $(PACKER).zip
@ -38,9 +52,9 @@ $(PWN_RELEASE).img: | $(PACKER)
# If the packer or ansible files are updated, rebuild the image. # If the packer or ansible files are updated, rebuild the image.
$(PWN_RELEASE).img: $(SDIST) builder/pwnagotchi.json builder/pwnagotchi.yml $(shell find builder/data -type f) $(PWN_RELEASE).img: $(SDIST) builder/pwnagotchi.json builder/pwnagotchi.yml $(shell find builder/data -type f)
$(PACKER) plugins install github.com/solo-io/arm-image sudo $(PACKER) plugins install github.com/solo-io/arm-image
cd builder && sudo $(UNSHARE) $(PACKER) build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" pwnagotchi.json cd builder && sudo $(UNSHARE) $(PACKER) build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" pwnagotchi.json
sudo chown -R $$USER:$$USER ../builder/output-pwnagotchi sudo chown -R $$USER:$$USER builder/output-pwnagotchi
mv builder/output-pwnagotchi/image $@ mv builder/output-pwnagotchi/image $@
# If any of these files are updated, rebuild the checksums. # If any of these files are updated, rebuild the checksums.
@ -57,6 +71,7 @@ image: $(PWN_RELEASE).zip
clean: clean:
- python3 setup.py clean --all - python3 setup.py clean --all
- rm -rf dist pwnagotchi.egg-info - rm -rf dist pwnagotchi.egg-info
- rm -rf $(PACKER) - rm -f $(PACKER)
- rm -rf $(PWN_RELEASE).* - rm -f $(PWN_RELEASE).*
- sudo rm -rf builder/output-pwnagotchi builder/packer_cache - sudo rm -rf builder/output-pwnagotchi builder/packer_cache

View File

@ -0,0 +1,26 @@
# /etc/dphys-swapfile - user settings for dphys-swapfile package
# author Neil Franklin, last modification 2010.05.05
# copyright ETH Zuerich Physics Departement
# use under either modified/non-advertising BSD or GPL license
# this file is sourced with . so full normal sh syntax applies
# the default settings are added as commented out CONF_*=* lines
# where we want the swapfile to be, this is the default
#CONF_SWAPFILE=/var/swap
# set size to absolute value, leaving empty (default) then uses computed value
# you most likely don't want this, unless you have an special disk situation
CONF_SWAPSIZE=2048
# set size to computed value, this times RAM size, dynamically adapts,
# guarantees that there is enough swap without wasting disk space on excess
#CONF_SWAPFACTOR=2
# restrict size (computed and absolute!) to maximally this limit
# can be set to empty for no limit, but beware of filled partitions!
# this is/was a (outdated?) 32bit kernel limit (in MBytes), do not overrun it
# but is also sensible on 64bit to prevent filling /var or even / partition
#CONF_MAXSWAP=2048

View File

@ -39,12 +39,17 @@ start_monitor_interface() {
rfkill unblock all rfkill unblock all
ifconfig wlan0 up ifconfig wlan0 up
iw dev wlan0 set power_save off iw dev wlan0 set power_save off
airmon-ng start wlan0 airmon-ng check kill
iw phy "$(iw phy | head -1 | cut -d" " -f2)" interface add wlan0mon type monitor && ifconfig wlan0mon up
# If wlan0 is NOT taken down after bringing up mon0, then when switching to AUTO you will get:
# error 400: error while initializing wlan0mon to channel 1: iw: out=command failed: Device or resource busy (-16) err=exit status 240
ifconfig wlan0 down
} }
# stops mon0 # stops mon0
stop_monitor_interface() { stop_monitor_interface() {
airmon-ng stop wlan0mon ifconfig wlan0mon down && iw dev wlan0mon del
ifconfig wlan0 up ifconfig wlan0 up
} }

View File

@ -15,8 +15,7 @@
"type": "shell", "type": "shell",
"inline": [ "inline": [
"uname -a", "uname -a",
"dpkg-architecture", "dpkg-architecture"
"mkdir -p /usr/local/src/pwnagotchi"
] ]
}, },
{ {

View File

@ -204,7 +204,6 @@
git: git:
repo: https://github.com/DrSchottky/nexmon.git repo: https://github.com/DrSchottky/nexmon.git
dest: /usr/local/src/nexmon dest: /usr/local/src/nexmon
# version: bfb3fe90c881498d7ee245b38f16722c1de26fa1
register: nexmongit register: nexmongit
- name: make firmware - name: make firmware
@ -234,11 +233,17 @@
replace: "KERNEL_RELEASE" replace: "KERNEL_RELEASE"
- name: make firmware patch (bcm43436b0) - name: make firmware patch (bcm43436b0)
shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43436b0/9_88_4_65/nexmon/ && make && make install-firmware" shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43436b0/9_88_4_65/nexmon/ && make"
args: args:
executable: /bin/bash executable: /bin/bash
chdir: /usr/local/src/nexmon/ chdir: /usr/local/src/nexmon/
- name: install new firmware (bcm43436b0)
copy:
src: /usr/local/src/nexmon/patches/bcm43436b0/9_88_4_65/nexmon/brcmfmac43436-sdio.bin
dest: /lib/firmware/brcm/brcmfmac43436-sdio.bin
- name: choose the right kernel version (bcm43430a1) - name: choose the right kernel version (bcm43430a1)
replace: replace:
dest: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/Makefile dest: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/Makefile
@ -260,11 +265,31 @@
replace: "KERNEL_RELEASE" replace: "KERNEL_RELEASE"
- name: make firmware patch (bcm43430a1) - name: make firmware patch (bcm43430a1)
shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/ && make && make install-firmware" shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/ && make"
args: args:
executable: /bin/bash executable: /bin/bash
chdir: /usr/local/src/nexmon/ chdir: /usr/local/src/nexmon/
- name: install new firmware (bcm43430a1)
copy:
src: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/brcmfmac43430-sdio.bin
dest: /lib/firmware/brcm/brcmfmac43430-sdio.bin
- name: Delete the firmware blob to avoid it crashing
file:
state: absent
path: /lib/firmware/brcm/brcmfmac43430-sdio.clm_blob
- name: Delete the RPiZW firmware blob to avoid it crashing
file:
state: absent
path: /lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.clm_blob
- name: Delete the RPi3 firmware blob to avoid it crashing
file:
state: absent
path: /lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.clm_blob
- name: choose the right kernel version (bcm43455c0) - name: choose the right kernel version (bcm43455c0)
replace: replace:
dest: /usr/local/src/nexmon/patches/bcm43455c0/7_45_206/nexmon/Makefile dest: /usr/local/src/nexmon/patches/bcm43455c0/7_45_206/nexmon/Makefile
@ -286,15 +311,20 @@
replace: "KERNEL_RELEASE" replace: "KERNEL_RELEASE"
- name: make firmware patch (bcm43455c0) - name: make firmware patch (bcm43455c0)
shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43455c0/7_45_206/nexmon/ && make && make install-firmware" shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43455c0/7_45_206/nexmon/ && make"
args: args:
executable: /bin/bash executable: /bin/bash
chdir: /usr/local/src/nexmon/ chdir: /usr/local/src/nexmon/
- name: install new firmware (bcm43455c0)
copy:
src: /usr/local/src/nexmon/patches/bcm43455c0/7_45_206/nexmon/brcmfmac43455-sdio.bin
dest: /lib/firmware/brcm/brcmfmac43455-sdio.bin
- name: copy modified driver (everyone but RPiZW) - name: copy modified driver (everyone but RPiZW)
copy: copy:
src: /lib/modules/6.1.21-v8+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko src: /lib/modules/6.1.21-v8+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz
dest: /lib/modules/6.1.21-v8+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.orig dest: /lib/modules/6.1.21-v8+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig
- name: copy modified driver (everyone but RPiZW) - name: copy modified driver (everyone but RPiZW)
copy: copy:
@ -379,24 +409,31 @@
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
when: golang.changed when: golang.changed
- name: download pwngrid - name: download pwngrid 1.10.4
git: git:
repo: https://github.com/jayofelony/pwngrid.git repo: https://github.com/jayofelony/pwngrid.git
dest: /usr/local/src/ dest: /usr/local/src/pwngrid
register: pwngrid register: pwngrid
- name: install pwngrid - name: install pwngrid 1.10.4
shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && make && sudo make install" shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && sudo make && sudo make install"
args: args:
executables: /bin/bash executables: /bin/bash
chdir: /usr/local/src/pwngrid chdir: /usr/local/src/pwngrid
when: pwngrid.changed when: pwngrid.changed
- name: download bettercap v2.32.1
git:
repo: https://github.com/jayofelony/bettercap.git
dest: /usr/local/src/bettercap
register: bettercap
- name: Install bettercap v2.32.1 - name: Install bettercap v2.32.1
shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go env -w GO111MODULE=off && go get github.com/jayofelony/bettercap && cd $GOPATH/src/github.com/jayofelony/bettercap && make build && make install" shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && sudo make && sudo make install"
args: args:
executable: /bin/bash executable: /bin/bash
register: bettercap chdir: /usr/local/src/bettercap
when: bettercap.changed
- name: clone bettercap caplets - name: clone bettercap caplets
git: git:
@ -519,10 +556,10 @@
echo "- sudo pwnagotchi --check-update, to see if there is a new version available" echo "- sudo pwnagotchi --check-update, to see if there is a new version available"
echo echo
echo "If you want to know if I'm running, you can use" echo "If you want to know if I'm running, you can use"
echo "systemctl status pwnagotchi" echo "sudo systemctl status pwnagotchi"
echo echo
echo "You can restart me using" echo "You can restart me using"
echo "systemctl restart pwnagotchi" echo "sudo systemctl restart pwnagotchi"
echo echo
echo "You learn more about me at https://pwnagotchi.ai/" echo "You learn more about me at https://pwnagotchi.ai/"
when: hostname.changed when: hostname.changed

View File

@ -1 +1 @@
__version__ = '2.4.2' __version__ = '2.4.3'

View File

@ -70,7 +70,8 @@ class Client(object):
while True: while True:
logging.info("[bettercap] creating new websocket...") logging.info("[bettercap] creating new websocket...")
try: try:
async with websockets.connect(s, ping_interval=ping_interval, ping_timeout=ping_timeout, max_queue=max_queue) as ws: async with websockets.connect(s, ping_interval=ping_interval, ping_timeout=ping_timeout,
max_queue=max_queue) as ws:
# listener loop # listener loop
while True: while True:
try: try:
@ -78,27 +79,26 @@ class Client(object):
try: try:
await consumer(msg) await consumer(msg)
except Exception as ex: except Exception as ex:
logging.debug("error while parsing event (%s)", ex) logging.debug("[bettercap] error while parsing event (%s)", ex)
except websockets.ConnectionClosedError: except websockets.ConnectionClosedError:
try: try:
pong = await ws.ping() pong = await ws.ping()
await asyncio.wait_for(pong, timeout=ping_timeout) await asyncio.wait_for(pong, timeout=ping_timeout)
logging.warning('ping OK, keeping connection alive...') logging.warning('[bettercap] ping OK, keeping connection alive...')
continue continue
except: except:
sleep_time = min_sleep + max_sleep*random.random() sleep_time = min_sleep + max_sleep*random.random()
logging.warning('ping error - retrying connection in {} sec'.format(sleep_time)) logging.warning('[bettercap] ping error - retrying connection in {} sec'.format(sleep_time))
await asyncio.sleep(sleep_time) await asyncio.sleep(sleep_time)
break break
except ConnectionRefusedError: except ConnectionRefusedError:
sleep_time = min_sleep + max_sleep*random.random() sleep_time = min_sleep + max_sleep*random.random()
logging.warning('nobody seems to be listening at the bettercap endpoint...') logging.warning('[bettercap] nobody seems to be listening at the bettercap endpoint...')
logging.warning('retrying connection in {} sec'.format(sleep_time)) logging.warning('[bettercap] retrying connection in {} sec'.format(sleep_time))
await asyncio.sleep(sleep_time) await asyncio.sleep(sleep_time)
continue continue
except OSError: except OSError:
sleep_time = min_sleep + max_sleep*random.random() logging.warning('[bettercap] connection to the bettercap endpoint failed...')
logging.warning('connection to the bettercap endpoint failed...')
pwnagotchi.reboot() pwnagotchi.reboot()
def run(self, command, verbose_errors=True): def run(self, command, verbose_errors=True):
@ -107,8 +107,8 @@ class Client(object):
r = requests.post("%s/session" % self.url, auth=self.auth, json={'cmd': command}) r = requests.post("%s/session" % self.url, auth=self.auth, json={'cmd': command})
except requests.exceptions.ConnectionError as e: except requests.exceptions.ConnectionError as e:
sleep_time = min_sleep + max_sleep*random.random() sleep_time = min_sleep + max_sleep*random.random()
logging.warning("can't run my request... connection to the bettercap endpoint failed...") logging.warning("[bettercap] can't run my request... connection to the bettercap endpoint failed...")
logging.warning('retrying run in {} sec'.format(sleep_time)) logging.warning('[bettercap] retrying run in {} sec'.format(sleep_time))
sleep(sleep_time) sleep(sleep_time)
else: else:
break break

View File

@ -2,8 +2,8 @@ main.name = "pwnagotchi"
main.lang = "en" main.lang = "en"
main.confd = "/etc/pwnagotchi/conf.d/" main.confd = "/etc/pwnagotchi/conf.d/"
main.custom_plugin_repos = [ main.custom_plugin_repos = [
"https://github.com/jayofelony/pwnagotchi-torch-plugins/archive/master.zip",
"https://github.com/evilsocket/pwnagotchi-plugins-contrib/archive/master.zip", "https://github.com/evilsocket/pwnagotchi-plugins-contrib/archive/master.zip",
"https://github.com/PwnPeter/pwnagotchi-plugins/archive/master.zip",
"https://github.com/tisboyo/pwnagotchi-pisugar2-plugin/archive/master.zip", "https://github.com/tisboyo/pwnagotchi-pisugar2-plugin/archive/master.zip",
"https://github.com/nullm0ose/pwnagotchi-plugin-pisugar3/archive/master.zip" "https://github.com/nullm0ose/pwnagotchi-plugin-pisugar3/archive/master.zip"
] ]
@ -40,8 +40,6 @@ main.plugins.pisugar2.enabled = false
main.plugins.pisugar2.shutdown = 5 main.plugins.pisugar2.shutdown = 5
main.plugins.pisugar2.sync_rtc_on_boot = false main.plugins.pisugar2.sync_rtc_on_boot = false
main.plugins.internet-connection.enabled = true
main.plugins.grid.enabled = true main.plugins.grid.enabled = true
main.plugins.grid.report = true main.plugins.grid.report = true
main.plugins.grid.exclude = [ main.plugins.grid.exclude = [
@ -59,13 +57,6 @@ main.plugins.gps.enabled = false
main.plugins.gps.speed = 19200 main.plugins.gps.speed = 19200
main.plugins.gps.device = "/dev/ttyUSB0" main.plugins.gps.device = "/dev/ttyUSB0"
main.plugins.bluetoothsniffer.enabled = false
main.plugins.bluetoothsniffer.timer = 45 # On how may seconds to scan for bluetooth devices
main.plugins.bluetoothsniffer.devices_file = "/root/handshakes/bluetooth_devices.json" # Path to the JSON file with bluetooth devices
main.plugins.bluetoothsniffer.count_interval = 86400 # On how may seconds to update count bluetooth devices
main.plugins.bluetoothsniffer.bt_x_coord = 160
main.plugins.bluetoothsniffer.bt_y_coord = 66
main.plugins.webgpsmap.enabled = false main.plugins.webgpsmap.enabled = false
main.plugins.onlinehashcrack.enabled = false main.plugins.onlinehashcrack.enabled = false

View File

@ -60,7 +60,7 @@ def closest_peer():
return all[0] if len(all) else None return all[0] if len(all) else None
def update_data(last_session): def update_data(last_session, plugin_data):
brain = {} brain = {}
try: try:
with open('/root/brain.json') as fp: with open('/root/brain.json') as fp:
@ -84,7 +84,8 @@ def update_data(last_session):
'uname': subprocess.getoutput("uname -a"), 'uname': subprocess.getoutput("uname -a"),
'brain': brain, 'brain': brain,
'version': pwnagotchi.__version__, 'version': pwnagotchi.__version__,
'build': "Pwnagotchi-Torch by Jayofelony" 'build': "Pwnagotchi-Torch by Jayofelony",
'plugins': plugin_data
} }
logging.debug("updating grid data: %s" % data) logging.debug("updating grid data: %s" % data)

View File

@ -17,8 +17,8 @@ LAST_SESSION_FILE = '/root/.pwnagotchi-last-session'
class LastSession(object): class LastSession(object):
EPOCH_TOKEN = '[epoch ' EPOCH_TOKEN = '[epoch '
EPOCH_PARSER = re.compile(r'^.+\[epoch (\d+)\] (.+)') EPOCH_PARSER = re.compile(r'^.+\[epoch (\d+)] (.+)')
EPOCH_DATA_PARSER = re.compile(r'([a-z_]+)=([^\s]+)') EPOCH_DATA_PARSER = re.compile(r'([a-z_]+)=(\S+)')
TRAINING_TOKEN = ' training epoch ' TRAINING_TOKEN = ' training epoch '
START_TOKEN = 'connecting to http' START_TOKEN = 'connecting to http'
DEAUTH_TOKEN = 'deauthing ' DEAUTH_TOKEN = 'deauthing '
@ -46,7 +46,7 @@ class LastSession(object):
self.max_reward = -1000 self.max_reward = -1000
self.avg_reward = 0 self.avg_reward = 0
self._peer_parser = re.compile( self._peer_parser = re.compile(
'detected unit (.+)@(.+) \(v.+\) on channel \d+ \(([\d\-]+) dBm\) \[sid:(.+) pwnd_tot:(\d+) uptime:(\d+)\]') 'detected unit (.+)@(.+) \(v.+\) on channel \d+ \(([\d\-]+) dBm\) \[sid:(.+) pwnd_tot:(\d+) uptime:(\d+)]')
self.parsed = False self.parsed = False
def _get_last_saved_session_id(self): def _get_last_saved_session_id(self):
@ -197,7 +197,7 @@ class LastSession(object):
lines.reverse() lines.reverse()
if len(lines) == 0: if len(lines) == 0:
lines.append("Initial Session"); lines.append("Initial Session")
ui.on_reading_logs() ui.on_reading_logs()

View File

@ -1,10 +1,11 @@
import os
import glob
import _thread import _thread
import threading import glob
import importlib, importlib.util import importlib
import importlib.util
import logging import logging
import os
import threading
import pwnagotchi.grid
default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default") default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default")
loaded = {} loaded = {}
@ -43,7 +44,7 @@ def toggle_plugin(name, enable=True):
global loaded, database global loaded, database
if pwnagotchi.config: if pwnagotchi.config:
if not name in pwnagotchi.config['main']['plugins']: if name not in pwnagotchi.config['main']['plugins']:
pwnagotchi.config['main']['plugins'][name] = dict() pwnagotchi.config['main']['plugins'][name] = dict()
pwnagotchi.config['main']['plugins'][name]['enabled'] = enable pwnagotchi.config['main']['plugins'][name]['enabled'] = enable
save_config(pwnagotchi.config, '/etc/pwnagotchi/config.toml') save_config(pwnagotchi.config, '/etc/pwnagotchi/config.toml')
@ -130,6 +131,8 @@ def load(config):
enabled = [name for name, options in config['main']['plugins'].items() if enabled = [name for name, options in config['main']['plugins'].items() if
'enabled' in options and options['enabled']] 'enabled' in options and options['enabled']]
pwnagotchi.grid.update_data(None, enabled)
# load default plugins # load default plugins
load_from_path(default_path, enabled=enabled) load_from_path(default_path, enabled=enabled)

View File

@ -1,177 +0,0 @@
import logging
import os
import subprocess
import json
import time
import pwnagotchi.plugins as plugins
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.components import LabeledValue
from pwnagotchi.ui.view import BLACK
from datetime import datetime
class BluetoothSniffer(plugins.Plugin):
__author__ = 'diytechtinker'
__version__ = '0.1.3'
__license__ = 'GPL3'
__description__ = 'A plugin that sniffs Bluetooth devices and saves their MAC addresses, name and counts to a JSON file'
def __init__(self):
# Defining the instance variables
self.options = {
'timer': 45,
'devices_file': '/root/handshakes/bluetooth_devices.json',
'count_interval': 86400,
'bt_x_coord': 160,
'bt_y_coord': 66
}
self.data = {}
self.last_scan_time = 0
def on_loaded(self):
logging.info("[BtS] bluetoothsniffer plugin loaded.")
logging.info("[BtS] Bluetooth devices file location: %s", self.options['devices_file'])
# Creating the device file path if it does not exist
if not os.path.exists(os.path.dirname(self.options['devices_file'])):
os.makedirs(os.path.dirname(self.options['devices_file']))
# Creating the device file if it does not exist
if not os.path.exists(self.options['devices_file']):
with open(self.options['devices_file'], 'w') as f:
json.dump({}, f)
# Loading the data from the device file
with open(self.options['devices_file'], 'r') as f:
self.data = json.load(f)
def on_ui_setup(self, ui):
with ui._lock:
ui.add_element('BtS', LabeledValue(color=BLACK,
label='BT SNFD',
value=" ",
position=(int(self.options["bt_x_coord"]),
int(self.options["bt_y_coord"])),
label_font=fonts.Small,
text_font=fonts.Small))
def on_unload(self, ui):
with ui._lock:
ui.remove_element('BtS')
def on_ui_update(self, ui):
current_time = time.time()
# Checking the time elapsed since last scan
if current_time - self.last_scan_time >= self.options['timer']:
self.last_scan_time = current_time
# logging.info("[BtS] Bluetooth sniffed: %s", str(self.bt_sniff_info()))
ui.set('BtS', str(self.bt_sniff_info()))
self.scan(ui)
# Method for scanning the nearby bluetooth devices
def scan(self, display):
logging.info("[BtS] Scanning for bluetooths...")
current_time = time.time()
changed = False
# Running the system command hcitool to scan nearby bluetooth devices
cmd_inq = "hcitool inq --flush"
try:
inq_output = subprocess.check_output(cmd_inq.split())
except subprocess.CalledProcessError as e:
logging.error("[BtS] Error running command: %s", e)
for line in inq_output.splitlines()[1:]:
fields = line.split()
mac_address = fields[0].decode()
for i in range(len(fields)):
if fields[i].decode() == "class:" and i+1 < len(fields):
device_class = fields[i+1].decode()
logging.info("[BtS] Found bluetooth %s", mac_address)
# Update the count, first_seen, and last_seen time of the device
if mac_address in self.data and len(self.data) > 0:
if 'Unknown' == self.data[mac_address]['name']:
name = self.get_device_name(mac_address)
self.data[mac_address]['name'] = name
self.data[mac_address]['new_info'] = 2
logging.info("[BtS] Updated bluetooth name: %s", name)
changed = True
if 'Unknown' == self.data[mac_address]['manufacturer']:
manufacturer = self.get_device_manufacturer(mac_address)
self.data[mac_address]['manufacturer'] = manufacturer
self.data[mac_address]['new_info'] = 2
logging.info("[BtS] Updated bluetooth manufacturer: %s", manufacturer)
changed = True
if device_class != self.data[mac_address]['class']:
self.data[mac_address]['class'] = device_class
self.data[mac_address]['new_info'] = 2
logging.info("[BtS] Updated bluetooth class: %s", device_class)
changed = True
last_seen_time = int(datetime.strptime(self.data[mac_address]['last_seen'], '%H:%M:%S %d-%m-%Y').timestamp())
if current_time - last_seen_time >= self.options['count_interval']:
self.data[mac_address]['count'] += 1
self.data[mac_address]['last_seen'] = time.strftime('%H:%M:%S %d-%m-%Y', time.localtime(current_time))
self.data[mac_address]['new_info'] = 2
logging.info("[BtS] Updated bluetooth count.")
changed = True
else:
name = self.get_device_name(mac_address)
manufacturer = self.get_device_manufacturer(mac_address)
self.data[mac_address] = {'name': name, 'count': 1, 'class': device_class, 'manufacturer': manufacturer, 'first_seen': time.strftime('%H:%M:%S %d-%m-%Y', time.localtime(current_time)), 'last_seen': time.strftime('%H:%M:%S %d-%m-%Y', time.localtime(current_time)), 'new_info': True}
logging.info("[BtS] Added new bluetooth device %s with MAC: %s", name, mac_address)
changed = True
# Save the updated devices to the JSON file
if changed:
with open(self.options['devices_file'], 'w') as f:
logging.info("[BtS] Saving bluetooths %s into json.", name)
json.dump(self.data, f)
display.set('status', 'Bluetooth sniffed and stored!')
display.update(force=True)
# Method to get the device name
def get_device_name(self, mac_address):
logging.info("[BtS] Trying to get name for %s", mac_address)
name = 'Unknown'
hcitool_process = subprocess.Popen(["hcitool", "name", mac_address], stdout=subprocess.PIPE)
output, error = hcitool_process.communicate()
if output.decode().strip() != '':
name = output.decode().strip()
logging.info("[BtS] Got name %s for %s", name, mac_address)
return name
# Method to get the device manufacturer
def get_device_manufacturer(self, mac_address):
manufacturer = 'Unknown'
cmd_info = f"hcitool info {mac_address} | grep 'Manufacturer:' | cut -d ' ' -f 2-"
try:
logging.info("[BtS] Trying to get manufacturer for %s", mac_address)
start_time = time.time()
process = subprocess.Popen(cmd_info, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
while process.poll() is None:
time.sleep(0.1)
if time.time() - start_time > 7:
logging.info("[BtS] Timeout while trying to get manufacturer for %s", mac_address)
process.kill()
return manufacturer
output, error = process.communicate(timeout=1)
if output.decode().strip() != '':
manufacturer = output.decode().strip()
logging.info("[BtS] Got manufacturer %s for %s", manufacturer, mac_address)
except Exception as e:
logging.info("[BtS] Error while trying to get manufacturer for %s: %s", mac_address, str(e))
return manufacturer
def bt_sniff_info(self):
num_devices = len(self.data)
if num_devices > 0:
num_unknown = sum(1 for device in self.data.values() if device['name'] == 'Unknown' or device['manufacturer'] == 'Unknown')
num_known = num_devices - num_unknown
return_text = "%s|%s" % (num_devices, num_known)
else:
return_text = "0|0"
return return_text

View File

@ -473,7 +473,7 @@ class BTTether(plugins.Plugin):
devices_to_try = list() devices_to_try = list()
connected_priorities = list() connected_priorities = list()
any_device_connected = False # if this is true, last status on screen should be C any_device_connected = False # if this is true, last status on screen should be C
for _, device in self.devices.items(): for _, device in self.devices.items():
if device.connected(): if device.connected():
@ -579,7 +579,7 @@ class BTTether(plugins.Plugin):
def on_ui_setup(self, ui): def on_ui_setup(self, ui):
with ui._lock: with ui._lock:
ui.add_element('bluetooth', LabeledValue(color=BLACK, label='BT', value='-', ui.add_element('bluetooth', LabeledValue(color=BLACK, label='BT', value='-',
position=(ui.width() / 2 - 10, 0), position=(ui.width() / 2 - 5, 0),
label_font=fonts.Bold, text_font=fonts.Medium)) label_font=fonts.Bold, text_font=fonts.Medium))
def on_ui_update(self, ui): def on_ui_update(self, ui):

View File

@ -5,6 +5,7 @@ import glob
import re import re
import pwnagotchi.grid as grid import pwnagotchi.grid as grid
import pwnagotchi.plugins
import pwnagotchi.plugins as plugins import pwnagotchi.plugins as plugins
from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap
from threading import Lock from threading import Lock
@ -129,7 +130,7 @@ class Grid(plugins.Plugin):
with self.lock: with self.lock:
try: try:
grid.update_data(agent.last_session) grid.update_data(agent.last_session, None)
except Exception as e: except Exception as e:
logging.error("error connecting to the pwngrid-peer service: %s" % e) logging.error("error connecting to the pwngrid-peer service: %s" % e)
logging.debug(e, exc_info=True) logging.debug(e, exc_info=True)

View File

@ -1,36 +0,0 @@
import os
import logging
import re
import subprocess
from io import TextIOWrapper
from pwnagotchi import plugins
class Watchdog(plugins.Plugin):
__author__ = '33197631+dadav@users.noreply.github.com'
__version__ = '0.1.0'
__license__ = 'GPL3'
__description__ = 'Restart pwnagotchi when blindbug is detected.'
def __init__(self):
self.options = dict()
self.pattern = re.compile(r'brcmf_cfg80211_nexmon_set_channel.*?Set Channel failed')
def on_loaded(self):
"""
Gets called when the plugin gets loaded
"""
logging.info("Watchdog plugin loaded.")
def on_epoch(self, agent, epoch, epoch_data):
# get last 10 lines
last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl','-n10','-k', '--since', '-5m'],
stdout=subprocess.PIPE).stdout))[-10:])
if len(self.pattern.findall(last_lines)) >= 5:
display = agent.view()
display.set('status', 'Blind-Bug detected. Restarting.')
display.update(force=True)
logging.info('[WATCHDOG] Blind-Bug detected. Restarting.')
mode = 'MANU' if agent.mode == 'manual' else 'AUTO'
import pwnagotchi
pwnagotchi.reboot(mode=mode)

View File

@ -58,8 +58,7 @@ class DottedTomlEncoder(TomlEncoder):
if not retstr.endswith('\n\n'): if not retstr.endswith('\n\n'):
retstr += '\n' retstr += '\n'
else: else:
retstr += (pre + qsection + " = " + retstr += (pre + qsection + " = " + str(self.dump_value(value)) + '\n')
str(self.dump_value(value)) + '\n')
return retstr, self._dict() return retstr, self._dict()