diff --git a/.idea/misc.xml b/.idea/misc.xml
index d95f6c4d..6178365c 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/.idea/pwnagotchi.iml b/.idea/pwnagotchi.iml
index b258c893..7e680cfc 100644
--- a/.idea/pwnagotchi.iml
+++ b/.idea/pwnagotchi.iml
@@ -4,7 +4,7 @@
-
+
diff --git a/Makefile b/Makefile
index 5d0491cb..c6679b65 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,21 @@
-PACKER_VERSION=1.9.4
-PWN_HOSTNAME=pwnagotchi
-PWN_VERSION:=$(shell cut -d"'" -f2 < pwnagotchi/_version.py)
+PACKER_VERSION := 1.9.4
+PWN_HOSTNAME := pwnagotchi
+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 build machine while updating the permanent hostname of the build image.
@@ -19,9 +34,8 @@ langs:
./scripts/language.sh compile $$(basename $$lang); \
done
-install:
-PACKER := ~/packer
-PACKER_URL := https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_amd64.zip
+PACKER := /tmp/pwnagotchi/packer
+PACKER_URL := https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_$(GOARCH).zip
$(PACKER):
mkdir -p $(@D)
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.
$(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
- sudo chown -R $$USER:$$USER ../builder/output-pwnagotchi
+ sudo chown -R $$USER:$$USER builder/output-pwnagotchi
mv builder/output-pwnagotchi/image $@
# If any of these files are updated, rebuild the checksums.
@@ -57,6 +71,7 @@ image: $(PWN_RELEASE).zip
clean:
- python3 setup.py clean --all
- rm -rf dist pwnagotchi.egg-info
- - rm -rf $(PACKER)
- - rm -rf $(PWN_RELEASE).*
+ - rm -f $(PACKER)
+ - rm -f $(PWN_RELEASE).*
- sudo rm -rf builder/output-pwnagotchi builder/packer_cache
+
diff --git a/builder/data/etc/dphys-swapfile b/builder/data/etc/dphys-swapfile
new file mode 100644
index 00000000..1c908a10
--- /dev/null
+++ b/builder/data/etc/dphys-swapfile
@@ -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
\ No newline at end of file
diff --git a/builder/data/usr/bin/pwnlib b/builder/data/usr/bin/pwnlib
index e439e097..2046ac55 100755
--- a/builder/data/usr/bin/pwnlib
+++ b/builder/data/usr/bin/pwnlib
@@ -39,12 +39,17 @@ start_monitor_interface() {
rfkill unblock all
ifconfig wlan0 up
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
stop_monitor_interface() {
- airmon-ng stop wlan0mon
+ ifconfig wlan0mon down && iw dev wlan0mon del
ifconfig wlan0 up
}
diff --git a/builder/pwnagotchi.json b/builder/pwnagotchi.json
index c051a4d5..76a18d5f 100644
--- a/builder/pwnagotchi.json
+++ b/builder/pwnagotchi.json
@@ -15,8 +15,7 @@
"type": "shell",
"inline": [
"uname -a",
- "dpkg-architecture",
- "mkdir -p /usr/local/src/pwnagotchi"
+ "dpkg-architecture"
]
},
{
diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml
index fcdabbe5..ec8366c2 100644
--- a/builder/pwnagotchi.yml
+++ b/builder/pwnagotchi.yml
@@ -204,7 +204,6 @@
git:
repo: https://github.com/DrSchottky/nexmon.git
dest: /usr/local/src/nexmon
-# version: bfb3fe90c881498d7ee245b38f16722c1de26fa1
register: nexmongit
- name: make firmware
@@ -234,11 +233,17 @@
replace: "KERNEL_RELEASE"
- 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:
executable: /bin/bash
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)
replace:
dest: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/Makefile
@@ -260,11 +265,31 @@
replace: "KERNEL_RELEASE"
- 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:
executable: /bin/bash
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)
replace:
dest: /usr/local/src/nexmon/patches/bcm43455c0/7_45_206/nexmon/Makefile
@@ -286,15 +311,20 @@
replace: "KERNEL_RELEASE"
- 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:
executable: /bin/bash
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)
copy:
- src: /lib/modules/6.1.21-v8+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko
- dest: /lib/modules/6.1.21-v8+/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.orig
+ 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.xz.orig
- name: copy modified driver (everyone but RPiZW)
copy:
@@ -379,24 +409,31 @@
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
when: golang.changed
- - name: download pwngrid
+ - name: download pwngrid 1.10.4
git:
repo: https://github.com/jayofelony/pwngrid.git
- dest: /usr/local/src/
+ dest: /usr/local/src/pwngrid
register: pwngrid
- - name: install pwngrid
- shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && make && sudo make install"
+ - name: install pwngrid 1.10.4
+ shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && sudo make && sudo make install"
args:
executables: /bin/bash
chdir: /usr/local/src/pwngrid
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
- 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:
executable: /bin/bash
- register: bettercap
+ chdir: /usr/local/src/bettercap
+ when: bettercap.changed
- name: clone bettercap caplets
git:
@@ -519,10 +556,10 @@
echo "- sudo pwnagotchi --check-update, to see if there is a new version available"
echo
echo "If you want to know if I'm running, you can use"
- echo "systemctl status pwnagotchi"
+ echo "sudo systemctl status pwnagotchi"
echo
echo "You can restart me using"
- echo "systemctl restart pwnagotchi"
+ echo "sudo systemctl restart pwnagotchi"
echo
echo "You learn more about me at https://pwnagotchi.ai/"
when: hostname.changed
diff --git a/pwnagotchi/_version.py b/pwnagotchi/_version.py
index cb9dc8a9..9a0e3da6 100644
--- a/pwnagotchi/_version.py
+++ b/pwnagotchi/_version.py
@@ -1 +1 @@
-__version__ = '2.4.2'
+__version__ = '2.4.3'
diff --git a/pwnagotchi/bettercap.py b/pwnagotchi/bettercap.py
index 243e00a6..695c20ce 100644
--- a/pwnagotchi/bettercap.py
+++ b/pwnagotchi/bettercap.py
@@ -70,7 +70,8 @@ class Client(object):
while True:
logging.info("[bettercap] creating new websocket...")
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
while True:
try:
@@ -78,27 +79,26 @@ class Client(object):
try:
await consumer(msg)
except Exception as ex:
- logging.debug("error while parsing event (%s)", ex)
+ logging.debug("[bettercap] error while parsing event (%s)", ex)
except websockets.ConnectionClosedError:
try:
pong = await ws.ping()
await asyncio.wait_for(pong, timeout=ping_timeout)
- logging.warning('ping OK, keeping connection alive...')
+ logging.warning('[bettercap] ping OK, keeping connection alive...')
continue
except:
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)
break
except ConnectionRefusedError:
sleep_time = min_sleep + max_sleep*random.random()
- logging.warning('nobody seems to be listening at the bettercap endpoint...')
- logging.warning('retrying connection in {} sec'.format(sleep_time))
+ logging.warning('[bettercap] nobody seems to be listening at the bettercap endpoint...')
+ logging.warning('[bettercap] retrying connection in {} sec'.format(sleep_time))
await asyncio.sleep(sleep_time)
continue
except OSError:
- sleep_time = min_sleep + max_sleep*random.random()
- logging.warning('connection to the bettercap endpoint failed...')
+ logging.warning('[bettercap] connection to the bettercap endpoint failed...')
pwnagotchi.reboot()
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})
except requests.exceptions.ConnectionError as e:
sleep_time = min_sleep + max_sleep*random.random()
- logging.warning("can't run my request... connection to the bettercap endpoint failed...")
- logging.warning('retrying run in {} sec'.format(sleep_time))
+ logging.warning("[bettercap] can't run my request... connection to the bettercap endpoint failed...")
+ logging.warning('[bettercap] retrying run in {} sec'.format(sleep_time))
sleep(sleep_time)
else:
break
diff --git a/pwnagotchi/defaults.toml b/pwnagotchi/defaults.toml
index 6988ef77..ea8fc151 100644
--- a/pwnagotchi/defaults.toml
+++ b/pwnagotchi/defaults.toml
@@ -2,8 +2,8 @@ main.name = "pwnagotchi"
main.lang = "en"
main.confd = "/etc/pwnagotchi/conf.d/"
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/PwnPeter/pwnagotchi-plugins/archive/master.zip",
"https://github.com/tisboyo/pwnagotchi-pisugar2-plugin/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.sync_rtc_on_boot = false
-main.plugins.internet-connection.enabled = true
-
main.plugins.grid.enabled = true
main.plugins.grid.report = true
main.plugins.grid.exclude = [
@@ -59,13 +57,6 @@ main.plugins.gps.enabled = false
main.plugins.gps.speed = 19200
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.onlinehashcrack.enabled = false
diff --git a/pwnagotchi/grid.py b/pwnagotchi/grid.py
index 78edb804..dab0034f 100644
--- a/pwnagotchi/grid.py
+++ b/pwnagotchi/grid.py
@@ -60,7 +60,7 @@ def closest_peer():
return all[0] if len(all) else None
-def update_data(last_session):
+def update_data(last_session, plugin_data):
brain = {}
try:
with open('/root/brain.json') as fp:
@@ -84,7 +84,8 @@ def update_data(last_session):
'uname': subprocess.getoutput("uname -a"),
'brain': brain,
'version': pwnagotchi.__version__,
- 'build': "Pwnagotchi-Torch by Jayofelony"
+ 'build': "Pwnagotchi-Torch by Jayofelony",
+ 'plugins': plugin_data
}
logging.debug("updating grid data: %s" % data)
diff --git a/pwnagotchi/log.py b/pwnagotchi/log.py
index 00cc13b8..5cf120e9 100644
--- a/pwnagotchi/log.py
+++ b/pwnagotchi/log.py
@@ -17,8 +17,8 @@ LAST_SESSION_FILE = '/root/.pwnagotchi-last-session'
class LastSession(object):
EPOCH_TOKEN = '[epoch '
- EPOCH_PARSER = re.compile(r'^.+\[epoch (\d+)\] (.+)')
- EPOCH_DATA_PARSER = re.compile(r'([a-z_]+)=([^\s]+)')
+ EPOCH_PARSER = re.compile(r'^.+\[epoch (\d+)] (.+)')
+ EPOCH_DATA_PARSER = re.compile(r'([a-z_]+)=(\S+)')
TRAINING_TOKEN = ' training epoch '
START_TOKEN = 'connecting to http'
DEAUTH_TOKEN = 'deauthing '
@@ -46,7 +46,7 @@ class LastSession(object):
self.max_reward = -1000
self.avg_reward = 0
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
def _get_last_saved_session_id(self):
@@ -197,7 +197,7 @@ class LastSession(object):
lines.reverse()
if len(lines) == 0:
- lines.append("Initial Session");
+ lines.append("Initial Session")
ui.on_reading_logs()
diff --git a/pwnagotchi/plugins/__init__.py b/pwnagotchi/plugins/__init__.py
index 57e86976..c5d2efd7 100644
--- a/pwnagotchi/plugins/__init__.py
+++ b/pwnagotchi/plugins/__init__.py
@@ -1,10 +1,11 @@
-import os
-import glob
import _thread
-import threading
-import importlib, importlib.util
+import glob
+import importlib
+import importlib.util
import logging
-
+import os
+import threading
+import pwnagotchi.grid
default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default")
loaded = {}
@@ -43,7 +44,7 @@ def toggle_plugin(name, enable=True):
global loaded, database
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]['enabled'] = enable
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' in options and options['enabled']]
+ pwnagotchi.grid.update_data(None, enabled)
+
# load default plugins
load_from_path(default_path, enabled=enabled)
diff --git a/pwnagotchi/plugins/default/bluetoothsniffer.py b/pwnagotchi/plugins/default/bluetoothsniffer.py
deleted file mode 100644
index 3657f063..00000000
--- a/pwnagotchi/plugins/default/bluetoothsniffer.py
+++ /dev/null
@@ -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
\ No newline at end of file
diff --git a/pwnagotchi/plugins/default/bt-tether.py b/pwnagotchi/plugins/default/bt-tether.py
index fa7c867f..547c6473 100644
--- a/pwnagotchi/plugins/default/bt-tether.py
+++ b/pwnagotchi/plugins/default/bt-tether.py
@@ -473,7 +473,7 @@ class BTTether(plugins.Plugin):
devices_to_try = 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():
if device.connected():
@@ -579,7 +579,7 @@ class BTTether(plugins.Plugin):
def on_ui_setup(self, ui):
with ui._lock:
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))
def on_ui_update(self, ui):
diff --git a/pwnagotchi/plugins/default/grid.py b/pwnagotchi/plugins/default/grid.py
index acf80927..79259a3a 100644
--- a/pwnagotchi/plugins/default/grid.py
+++ b/pwnagotchi/plugins/default/grid.py
@@ -5,6 +5,7 @@ import glob
import re
import pwnagotchi.grid as grid
+import pwnagotchi.plugins
import pwnagotchi.plugins as plugins
from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap
from threading import Lock
@@ -129,7 +130,7 @@ class Grid(plugins.Plugin):
with self.lock:
try:
- grid.update_data(agent.last_session)
+ grid.update_data(agent.last_session, None)
except Exception as e:
logging.error("error connecting to the pwngrid-peer service: %s" % e)
logging.debug(e, exc_info=True)
diff --git a/pwnagotchi/plugins/default/watchdog.py b/pwnagotchi/plugins/default/watchdog.py
deleted file mode 100644
index 8ebb6b8e..00000000
--- a/pwnagotchi/plugins/default/watchdog.py
+++ /dev/null
@@ -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)
diff --git a/pwnagotchi/utils.py b/pwnagotchi/utils.py
index 19084572..f8f38677 100644
--- a/pwnagotchi/utils.py
+++ b/pwnagotchi/utils.py
@@ -58,8 +58,7 @@ class DottedTomlEncoder(TomlEncoder):
if not retstr.endswith('\n\n'):
retstr += '\n'
else:
- retstr += (pre + qsection + " = " +
- str(self.dump_value(value)) + '\n')
+ retstr += (pre + qsection + " = " + str(self.dump_value(value)) + '\n')
return retstr, self._dict()