mirror of
https://github.com/jayofelony/pwnagotchi.git
synced 2025-07-01 18:37:27 -04:00
Merge branch 'pwnagotchi-torch-testing' into pwnagotchi-torch-64
This commit is contained in:
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -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
2
.idea/pwnagotchi.iml
generated
@ -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">
|
||||||
|
35
Makefile
35
Makefile
@ -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
|
||||||
|
|
||||||
|
26
builder/data/etc/dphys-swapfile
Normal file
26
builder/data/etc/dphys-swapfile
Normal 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
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
"type": "shell",
|
"type": "shell",
|
||||||
"inline": [
|
"inline": [
|
||||||
"uname -a",
|
"uname -a",
|
||||||
"dpkg-architecture",
|
"dpkg-architecture"
|
||||||
"mkdir -p /usr/local/src/pwnagotchi"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = '2.4.2'
|
__version__ = '2.4.3'
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
|
@ -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()
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user