mirror of
https://github.com/jayofelony/pwnagotchi.git
synced 2025-07-01 18:37:27 -04:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
92cd5d3fdb | |||
99caa7a973 | |||
a94e7eef02 | |||
1cefae55d1 | |||
c5ee1df855 | |||
d142840307 | |||
e558146e28 | |||
11a3330153 | |||
53b2dd8628 | |||
6381f9443b | |||
fa7e87b974 | |||
cca2ff2da4 | |||
78415b3137 | |||
34284aa1bc | |||
56ebb60662 | |||
84f6624844 | |||
3bcbb0ce9a | |||
e01e457992 | |||
86991304a5 | |||
4f62759d6d | |||
7b7ba02aad | |||
7040be2d30 | |||
d0617ccfaf | |||
a0b5078b64 | |||
54c1ffd63c |
@ -1 +0,0 @@
|
||||
hcxtools
|
@ -60,6 +60,7 @@ def pwnagotchi_cli():
|
||||
channels = agent.get_access_points_by_channel()
|
||||
# for each channel
|
||||
for ch, aps in channels:
|
||||
time.sleep(0.2) # This is to make sure it doesn't error (https://github.com/seemoo-lab/nexmon/issues/596)
|
||||
agent.set_channel(ch)
|
||||
|
||||
if not agent.is_stale() and agent.any_activity():
|
||||
|
@ -30,4 +30,4 @@ echo
|
||||
echo " You can restart me using"
|
||||
echo " pwnkill"
|
||||
echo
|
||||
echo " You can learn more about me at https://pwnagotchi.ai/"
|
||||
echo " You can learn more about me at https://pwnagotchi.org/"
|
||||
|
@ -9,15 +9,6 @@ if is_crypted_mode; then
|
||||
done
|
||||
fi
|
||||
|
||||
# check if wifi driver is bugged
|
||||
if ! check_brcm; then
|
||||
if ! reload_brcm; then
|
||||
echo "Could not reload wifi driver. Reboot"
|
||||
reboot
|
||||
fi
|
||||
sleep 10
|
||||
fi
|
||||
|
||||
# start mon0
|
||||
start_monitor_interface
|
||||
|
||||
|
@ -13,14 +13,6 @@ blink_led() {
|
||||
sleep 0.3
|
||||
}
|
||||
|
||||
# check if brcm is stuck
|
||||
check_brcm() {
|
||||
if [[ "$(journalctl -n10 -k --since -5m | grep -c 'brcmf_cfg80211_nexmon_set_channel.*Set Channel failed')" -ge 5 ]]; then
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# reload mod
|
||||
reload_brcm() {
|
||||
if ! modprobe -r brcmfmac; then
|
||||
|
@ -74,6 +74,10 @@ build {
|
||||
inline = ["chmod +x /usr/bin/*"]
|
||||
}
|
||||
|
||||
provisioner "shell" {
|
||||
inline = ["dpkg --add-architecture armhf"]
|
||||
}
|
||||
|
||||
provisioner "file" {
|
||||
destination = "/etc/systemd/system/"
|
||||
sources = [
|
||||
@ -91,7 +95,11 @@ build {
|
||||
inline = ["chmod +x /etc/update-motd.d/*"]
|
||||
}
|
||||
provisioner "shell" {
|
||||
inline = ["apt-get -y --allow-releaseinfo-change update", "apt-get -y dist-upgrade", "apt-get install -y --no-install-recommends ansible"]
|
||||
inline = [
|
||||
"apt-get -y --allow-releaseinfo-change update",
|
||||
"apt-get -y dist-upgrade",
|
||||
"apt-get install -y --no-install-recommends ansible"
|
||||
]
|
||||
}
|
||||
provisioner "ansible-local" {
|
||||
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
|
||||
|
@ -6,8 +6,8 @@
|
||||
vars:
|
||||
kernel:
|
||||
min: "6.1"
|
||||
full: "6.1.0-rpi7-rpi-v8"
|
||||
full_pi5: "6.1.0-rpi7-rpi-2712"
|
||||
full: "6.1.0-rpi8-rpi-v8"
|
||||
full_pi5: "6.1.0-rpi8-rpi-2712"
|
||||
pwnagotchi:
|
||||
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
|
||||
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}"
|
||||
@ -79,6 +79,11 @@
|
||||
- curl
|
||||
- dkms
|
||||
- fbi
|
||||
- firmware-atheros
|
||||
- firmware-brcm80211
|
||||
- firmware-libertas
|
||||
- firmware-misc-nonfree
|
||||
- firmware-realtek
|
||||
- flex
|
||||
- fonts-dejavu
|
||||
- fonts-dejavu-core
|
||||
@ -97,9 +102,9 @@
|
||||
- libbz2-dev
|
||||
- libc-ares-dev
|
||||
- libc6-dev
|
||||
- libc6:armhf
|
||||
- libcap-dev
|
||||
- libcurl-ocaml-dev
|
||||
- libssl-ocaml-dev
|
||||
- libdbus-1-dev
|
||||
- libdbus-glib-1-dev
|
||||
- libeigen3-dev
|
||||
@ -112,7 +117,10 @@
|
||||
- libgmp3-dev
|
||||
- libgstreamer1.0-0
|
||||
- libhdf5-dev
|
||||
- libisl23:armhf
|
||||
- liblapack-dev
|
||||
- libmpc3:armhf
|
||||
- libmpfr6:armhf
|
||||
- libncursesw5-dev
|
||||
- libnetfilter-queue-dev
|
||||
- libopenblas-dev
|
||||
@ -126,34 +134,31 @@
|
||||
- libraspberrypi0
|
||||
- libsqlite3-dev
|
||||
- libssl-dev
|
||||
- libssl-ocaml-dev
|
||||
- libstdc++6:armhf
|
||||
- libswscale5
|
||||
- libtiff6
|
||||
- libtool
|
||||
- libusb-1.0-0-dev
|
||||
- lsof
|
||||
- make
|
||||
- python3-yaml
|
||||
- python3-dbus
|
||||
- python3-flask
|
||||
- python3-flask-cors
|
||||
- python3-flaskext.wtf
|
||||
- python3-gast
|
||||
- python3-pil
|
||||
- python3-pip
|
||||
- python3-pycryptodome
|
||||
- python3-requests
|
||||
- python3-scapy
|
||||
- python3-setuptools
|
||||
- python3-smbus
|
||||
- python3-smbus2
|
||||
- python3-spidev
|
||||
- python3-tweepy
|
||||
- python3-werkzeug
|
||||
- firmware-atheros
|
||||
- firmware-brcm80211
|
||||
- firmware-libertas
|
||||
- firmware-misc-nonfree
|
||||
- firmware-realtek
|
||||
- python3-pip
|
||||
- python3-setuptools
|
||||
- python3-smbus
|
||||
- python3-yaml
|
||||
- qpdf
|
||||
- raspberrypi-kernel-headers
|
||||
- rsync
|
||||
@ -291,9 +296,21 @@
|
||||
path: /usr/local/src/hcxtools
|
||||
|
||||
# Install nexmon to fix wireless scanning (takes 2.5G of space)
|
||||
- name: symlink 1
|
||||
file:
|
||||
src: "/usr/lib/arm-linux-gnueabihf/libisl.so.23.2.0"
|
||||
dest: "/usr/lib/arm-linux-gnueabihf/libisl.so.10"
|
||||
state: link
|
||||
|
||||
- name: symlink 2
|
||||
file:
|
||||
src: "/usr/lib/arm-linux-gnueabihf/libmpfr.so.6.2.0"
|
||||
dest: "/usr/lib/arm-linux-gnueabihf/libmpfr.so.4"
|
||||
state: link
|
||||
|
||||
- name: clone nexmon repository
|
||||
git:
|
||||
repo: https://github.com/DrSchottky/nexmon.git
|
||||
repo: https://github.com/seemoo-lab/nexmon.git
|
||||
dest: /usr/local/src/nexmon
|
||||
|
||||
# FIRST WE BUILD DRIVER FOR RPi5
|
||||
@ -346,7 +363,7 @@
|
||||
|
||||
- name: clone nexmon repository
|
||||
git:
|
||||
repo: https://github.com/DrSchottky/nexmon.git
|
||||
repo: https://github.com/seemoo-lab/nexmon.git
|
||||
dest: /usr/local/src/nexmon
|
||||
|
||||
- name: make firmware, RPi4
|
||||
|
@ -1 +1 @@
|
||||
__version__ = '2.8.0'
|
||||
__version__ = '2.8.1'
|
||||
|
@ -21,11 +21,12 @@ RECOVERY_DATA_FILE = '/root/.pwnagotchi-recovery'
|
||||
|
||||
class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
|
||||
def __init__(self, view, config, keypair):
|
||||
Client.__init__(self, config['bettercap']['hostname'],
|
||||
config['bettercap']['scheme'],
|
||||
config['bettercap']['port'],
|
||||
config['bettercap']['username'],
|
||||
config['bettercap']['password'])
|
||||
Client.__init__(self,
|
||||
"127.0.0.1" if "hostname" not in config['bettercap'] else config['bettercap']['hostname'],
|
||||
"http" if "scheme" not in config['bettercap'] else config['bettercap']['scheme'],
|
||||
8081 if "port" not in config['bettercap'] else config['bettercap']['port'],
|
||||
"pwnagotchi" if "username" not in config['bettercap'] else config['bettercap']['username'],
|
||||
"pwnagotchi" if "password" not in config['bettercap'] else config['bettercap']['password'])
|
||||
Automata.__init__(self, config, view)
|
||||
AsyncAdvertiser.__init__(self, config, view, keypair)
|
||||
AsyncTrainer.__init__(self, config)
|
||||
@ -362,7 +363,8 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
|
||||
plugins.on('handshake', self, filename, ap_mac, sta_mac)
|
||||
else:
|
||||
(ap, sta) = ap_and_station
|
||||
self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap['hostname'] != '<hidden>' else ap_mac
|
||||
self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap[
|
||||
'hostname'] != '<hidden>' else ap_mac
|
||||
logging.warning(
|
||||
"!!! captured new handshake on channel %d, %d dBm: %s (%s) -> %s [%s (%s)] !!!",
|
||||
ap['channel'], ap['rssi'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'])
|
||||
|
@ -198,11 +198,6 @@ ui.display.enabled = false
|
||||
ui.display.rotation = 180
|
||||
ui.display.type = "waveshare_4"
|
||||
|
||||
bettercap.scheme = "http"
|
||||
bettercap.hostname = "localhost"
|
||||
bettercap.port = 8081
|
||||
bettercap.username = "pwnagotchi"
|
||||
bettercap.password = "pwnagotchi"
|
||||
bettercap.handshakes = "/root/handshakes"
|
||||
bettercap.silence = [
|
||||
"ble.device.new",
|
||||
|
@ -27,10 +27,9 @@ class FixServices(plugins.Plugin):
|
||||
|
||||
def __init__(self):
|
||||
self.options = dict()
|
||||
self.pattern = re.compile(r'brcmf_cfg80211_nexmon_set_channel.*?Set Channel failed')
|
||||
self.pattern2 = re.compile(r'wifi error while hopping to channel')
|
||||
self.pattern3 = re.compile(r'Firmware has halted or crashed')
|
||||
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
|
||||
self.pattern1 = re.compile(r'wifi error while hopping to channel')
|
||||
self.pattern2 = re.compile(r'Firmware has halted or crashed')
|
||||
self.pattern3 = re.compile(r'error 400: could not find interface wlan0mon')
|
||||
self.isReloadingMon = False
|
||||
self.connection = None
|
||||
self.LASTTRY = 0
|
||||
@ -46,23 +45,11 @@ class FixServices(plugins.Plugin):
|
||||
last_lines = self.get_last_lines('journalctl', ['-n10', '-k'], 10)
|
||||
try:
|
||||
cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True)
|
||||
logging.info("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output))
|
||||
logging.debug("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output))
|
||||
if ",UP," in str(cmd_output):
|
||||
logging.info("wlan0mon is up.")
|
||||
|
||||
if len(self.pattern.findall(last_lines)) >= 3:
|
||||
if hasattr(agent, 'view'):
|
||||
display = agent.view()
|
||||
display.set('status', 'Blind-Bug detected. Restarting.')
|
||||
display.update(force=True)
|
||||
logging.info('[Fix_Services] Blind-Bug detected. Restarting.')
|
||||
try:
|
||||
self._tryTurningItOffAndOnAgain(agent)
|
||||
except Exception as err:
|
||||
logging.warning("[Fix_Services turnOffAndOn] %s" % repr(err))
|
||||
|
||||
else:
|
||||
logging.info("[Fix_Services] Logs look good!")
|
||||
logging.info("[Fix_Services] Logs look good!")
|
||||
|
||||
except Exception as err:
|
||||
logging.error("[Fix_Services ip link show wlan0mon]: %s" % repr(err))
|
||||
@ -121,21 +108,8 @@ class FixServices(plugins.Plugin):
|
||||
logging.debug("[Fix_Services]**** checking")
|
||||
|
||||
# Look for pattern 1
|
||||
if len(self.pattern.findall(last_lines)) >= 3:
|
||||
logging.info("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
|
||||
if hasattr(agent, 'view'):
|
||||
display = agent.view()
|
||||
display.set('status', 'Blind-Bug detected. Restarting.')
|
||||
display.update(force=True)
|
||||
logging.info('[Fix_Services] Blind-Bug detected. Restarting.')
|
||||
try:
|
||||
self._tryTurningItOffAndOnAgain(agent)
|
||||
except Exception as err:
|
||||
logging.warning("[Fix_Services] TTOAOA: %s" % repr(err))
|
||||
|
||||
# Look for pattern 2
|
||||
elif len(self.pattern2.findall(other_last_lines)) >= 5:
|
||||
logging.info("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
|
||||
if len(self.pattern1.findall(other_last_lines)) >= 5:
|
||||
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
|
||||
if hasattr(agent, 'view'):
|
||||
display = agent.view()
|
||||
display.set('status', 'Wifi channel stuck. Restarting recon.')
|
||||
@ -157,8 +131,8 @@ class FixServices(plugins.Plugin):
|
||||
except Exception as err:
|
||||
logging.error("[Fix_Services wifi.recon flip] %s" % repr(err))
|
||||
|
||||
# Look for pattern 3
|
||||
elif len(self.pattern3.findall(other_last_lines)) >= 1:
|
||||
# Look for pattern 2
|
||||
elif len(self.pattern2.findall(other_last_lines)) >= 1:
|
||||
logging.info("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.")
|
||||
if hasattr(agent, 'view'):
|
||||
display = agent.view()
|
||||
@ -167,12 +141,12 @@ class FixServices(plugins.Plugin):
|
||||
try:
|
||||
# Run the monstart command to restart wlan0mon
|
||||
cmd_output = subprocess.check_output("monstart", shell=True)
|
||||
logging.info("[Fix_Services monstart]: %s" % repr(cmd_output))
|
||||
logging.debug("[Fix_Services monstart]: %s" % repr(cmd_output))
|
||||
except Exception as err:
|
||||
logging.error("[Fix_Services monstart]: %s" % repr(err))
|
||||
|
||||
# Look for pattern 4
|
||||
elif len(self.pattern4.findall(other_other_last_lines)) >= 3:
|
||||
# Look for pattern 3
|
||||
elif len(self.pattern3.findall(other_other_last_lines)) >= 3:
|
||||
logging.info("[Fix_Services] wlan0 is down!")
|
||||
if hasattr(agent, 'view'):
|
||||
display = agent.view()
|
||||
@ -181,7 +155,7 @@ class FixServices(plugins.Plugin):
|
||||
try:
|
||||
# Run the monstart command to restart wlan0mon
|
||||
cmd_output = subprocess.check_output("monstart", shell=True)
|
||||
logging.info("[Fix_Services monstart]: %s" % repr(cmd_output))
|
||||
logging.debug("[Fix_Services monstart]: %s" % repr(cmd_output))
|
||||
except Exception as err:
|
||||
logging.error("[Fix_Services monstart]: %s" % repr(err))
|
||||
|
||||
@ -237,7 +211,7 @@ class FixServices(plugins.Plugin):
|
||||
# is it up?
|
||||
try:
|
||||
cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True)
|
||||
logging.info("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output))
|
||||
logging.debug("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output))
|
||||
if ",UP," in str(cmd_output):
|
||||
logging.info("wlan0mon is up. Skip reset?")
|
||||
# not reliable, so don't skip just yet
|
||||
@ -309,11 +283,9 @@ class FixServices(plugins.Plugin):
|
||||
# stop looping and get back to recon
|
||||
break
|
||||
else:
|
||||
logging.info(
|
||||
"[Fix_Services set wifi.interfaceface wlan0mon] failed? %s" % repr(result))
|
||||
logging.debug("[Fix_Services set wifi.interfaceface wlan0mon] failed? %s" % repr(result))
|
||||
except Exception as err:
|
||||
logging.info(
|
||||
"[Fix_Services set wifi.interface wlan0mon] except: %s" % repr(err))
|
||||
logging.debug("[Fix_Services set wifi.interface wlan0mon] except: %s" % repr(err))
|
||||
except Exception as cerr: #
|
||||
if not display:
|
||||
print("failed loading wlan0mon attempt #%s: %s" % (tries, repr(cerr)))
|
||||
@ -362,7 +334,7 @@ class FixServices(plugins.Plugin):
|
||||
"face": faces.HAPPY})
|
||||
else:
|
||||
print("I can see again")
|
||||
logging.info("[Fix_Services] wifi.recon on")
|
||||
logging.debug("[Fix_Services] wifi.recon on")
|
||||
self.LASTTRY = time.time() + 120 # 2-minute pause until next time.
|
||||
else:
|
||||
logging.error("[Fix_Services] wifi.recon did not start up")
|
||||
@ -378,7 +350,7 @@ class FixServices(plugins.Plugin):
|
||||
try:
|
||||
logging.info("[Fix_Services] unloaded")
|
||||
except Exception as err:
|
||||
logging.info("[Fix_Services] unload err %s " % repr(err))
|
||||
logging.error("[Fix_Services] unload err %s " % repr(err))
|
||||
pass
|
||||
|
||||
|
||||
|
@ -153,8 +153,7 @@ class View(object):
|
||||
self.set('uptime', last_session.duration)
|
||||
self.set('channel', '-')
|
||||
self.set('aps', "%d" % last_session.associated)
|
||||
self.set('shakes', '%d (%s)' % (last_session.handshakes, \
|
||||
utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
|
||||
self.set('shakes', '%d (%s)' % (last_session.handshakes, utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
|
||||
self.set_closest_peer(last_session.last_peer, last_session.peers)
|
||||
self.update()
|
||||
|
||||
|
7
setup.py
7
setup.py
@ -30,13 +30,6 @@ def install_file(source_filename, dest_filename):
|
||||
|
||||
|
||||
def install_system_files():
|
||||
f = open("apt_packages.txt", "r")
|
||||
for x in f:
|
||||
if x == "":
|
||||
continue
|
||||
os.system(f"apt-get install {x}")
|
||||
f.close()
|
||||
|
||||
setup_path = os.path.dirname(__file__)
|
||||
data_path = os.path.join(setup_path, "builder/data")
|
||||
|
||||
|
Reference in New Issue
Block a user