Merge branch 'master' into master

This commit is contained in:
evilsocket 2019-10-06 15:35:56 +02:00 committed by GitHub
commit 7bba0b5286
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
94 changed files with 362 additions and 1805 deletions

5
.gitignore vendored
View File

@ -2,6 +2,7 @@
*.img.bmap *.img.bmap
*.pcap *.pcap
*.po~ *.po~
preview.png
__pycache__ __pycache__
_backups _backups
_emulation _emulation
@ -10,3 +11,7 @@ config.laptop.yml
.idea .idea
packer_cache packer_cache
output-pwnagotchi output-pwnagotchi
.DS_Store
build
dist
pwnagotchi.egg-info

8
MANIFEST.in Normal file
View File

@ -0,0 +1,8 @@
exclude *.pyc .DS_Store .gitignore MANIFEST.in
include setup.py
include distribute_setup.py
include README.md
include LICENSE
recursive-include bin *
recursive-include pwnagotchi *.py
recursive-include pwnagotchi *.yml

View File

@ -4,8 +4,10 @@
<p align="center"> <p align="center">
<a href="https://github.com/evilsocket/pwnagotchi/releases/latest"><img alt="Release" src="https://img.shields.io/github/release/evilsocket/pwnagotchi.svg?style=flat-square"></a> <a href="https://github.com/evilsocket/pwnagotchi/releases/latest"><img alt="Release" src="https://img.shields.io/github/release/evilsocket/pwnagotchi.svg?style=flat-square"></a>
<a href="https://github.com/evilsocket/pwnagotchi/blob/master/LICENSE.md"><img alt="Software License" src="https://img.shields.io/badge/license-GPL3-brightgreen.svg?style=flat-square"></a> <a href="https://github.com/evilsocket/pwnagotchi/blob/master/LICENSE.md"><img alt="Software License" src="https://img.shields.io/badge/license-GPL3-brightgreen.svg?style=flat-square"></a>
<a href="https://github.com/evilsocket/pwnagotchi/graphs/contributors"><img alt="Contributors" src="https://img.shields.io/github/contributors/evilsocket/pwnagotchi"/></a>
<a href="https://travis-ci.org/evilsocket/pwnagotchi"><img alt="Travis" src="https://img.shields.io/travis/evilsocket/pwnagotchi/master.svg?style=flat-square"></a> <a href="https://travis-ci.org/evilsocket/pwnagotchi"><img alt="Travis" src="https://img.shields.io/travis/evilsocket/pwnagotchi/master.svg?style=flat-square"></a>
<a href="https://pwnagotchi.herokuapp.com/"><img alt="Slack" src="https://pwnagotchi.herokuapp.com/badge.svg"></a> <a href="https://pwnagotchi.herokuapp.com/"><img alt="Slack" src="https://pwnagotchi.herokuapp.com/badge.svg"></a>
<a href="https://twitter.com/intent/follow?screen_name=pwnagotchi"><img src="https://img.shields.io/twitter/follow/pwnagotchi?style=social&logo=twitter" alt="follow on Twitter"></a>
</p> </p>
</p> </p>

106
bin/pwnagotchi Executable file
View File

@ -0,0 +1,106 @@
#!/usr/bin/python3
if __name__ == '__main__':
import argparse
import time
import os
import logging
import pwnagotchi
import pwnagotchi.utils as utils
import pwnagotchi.plugins as plugins
from pwnagotchi.log import SessionParser
from pwnagotchi.agent import Agent
from pwnagotchi.ui.display import Display
parser = argparse.ArgumentParser()
parser.add_argument('-C', '--config', action='store', dest='config',
default=os.path.join(os.path.abspath(os.path.dirname(pwnagotchi.__file__)), '/defaults.yml'),
help='Main configuration file.')
parser.add_argument('-U', '--user-config', action='store', dest='user_config', default='/etc/pwnagotchi/config.yml',
help='If this file exists, configuration will be merged and this will override default values.')
parser.add_argument('--manual', dest="do_manual", action="store_true", default=False, help="Manual mode.")
parser.add_argument('--clear', dest="do_clear", action="store_true", default=False,
help="Clear the ePaper display and exit.")
parser.add_argument('--debug', dest="debug", action="store_true", default=False,
help="Enable debug logs.")
args = parser.parse_args()
config = utils.load_config(args)
utils.setup_logging(args, config)
plugins.load(config)
display = Display(config=config, state={'name': '%s>' % pwnagotchi.name()})
agent = Agent(view=display, config=config)
logging.info("%s@%s (v%s)" % (pwnagotchi.name(), agent._identity, pwnagotchi.version))
for _, plugin in plugins.loaded.items():
logging.debug("plugin '%s' v%s loaded from %s" % (plugin.__name__, plugin.__version__, plugin.__file__))
if args.do_clear:
logging.info("clearing the display ...")
display.clear()
elif args.do_manual:
logging.info("entering manual mode ...")
log = SessionParser(config)
logging.info(
"the last session lasted %s (%d completed epochs, trained for %d), average reward:%s (min:%s max:%s)" % (
log.duration_human,
log.epochs,
log.train_epochs,
log.avg_reward,
log.min_reward,
log.max_reward))
while True:
display.on_manual_mode(log)
time.sleep(1)
if Agent.is_connected():
plugins.on('internet_available', display, config, log)
else:
logging.info("entering auto mode ...")
agent.start()
while True:
try:
# recon on all channels
agent.recon()
# get nearby access points grouped by channel
channels = agent.get_access_points_by_channel()
# check for free channels to use
agent.check_channels(channels)
# for each channel
for ch, aps in channels:
agent.set_channel(ch)
if not agent.is_stale() and agent.any_activity():
logging.info("%d access points on channel %d" % (len(aps), ch))
# for each ap on this channel
for ap in aps:
# send an association frame in order to get for a PMKID
agent.associate(ap)
# deauth all client stations in order to get a full handshake
for sta in ap['clients']:
agent.deauth(ap, sta)
# An interesting effect of this:
#
# From Pwnagotchi's perspective, the more new access points
# and / or client stations nearby, the longer one epoch of
# its relative time will take ... basically, in Pwnagotchi's universe,
# WiFi electromagnetic fields affect time like gravitational fields
# affect ours ... neat ^_^
agent.next_epoch()
except Exception as e:
logging.exception("main loop exception")

View File

@ -16,7 +16,6 @@
services: services:
enable: enable:
- dphys-swapfile.service - dphys-swapfile.service
- getty@ttyGS0.service
disable: disable:
- apt-daily.timer - apt-daily.timer
- apt-daily.service - apt-daily.service
@ -245,6 +244,37 @@
#!/usr/bin/env bash #!/usr/bin/env bash
free -m | awk '/Mem/ { printf( "%d %", $3 / $2 * 100 + 0.5 ) }' free -m | awk '/Mem/ { printf( "%d %", $3 / $2 * 100 + 0.5 ) }'
- name: create bootblink script
copy:
dest: /usr/bin/bootblink
mode: 0755
content: |
#!/usr/bin/env bash
for i in $(seq 1 "$1");
do
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
echo 1 >/sys/class/leds/led0/brightness
sleep 0.3
done
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
- name: create pwnagotchi-launcher script
copy:
dest: /usr/bin/pwnagotchi-launcher
mode: 0755
content: |
#!/usr/bin/env bash
# blink 10 times to signal ready state
/usr/bin/bootblink 10 &
# start a detached screen session with bettercap
if ifconfig | grep usb0 | grep RUNNING; then
/usr/bin/pwnagotchi --manual
else
/usr/bin/pwnagotchi
fi
- name: create monstart script - name: create monstart script
copy: copy:
dest: /usr/bin/monstart dest: /usr/bin/monstart
@ -261,6 +291,22 @@
#!/usr/bin/env bash #!/usr/bin/env bash
ifconfig mon0 down && iw dev mon0 del ifconfig mon0 down && iw dev mon0 del
- name: create hdmion script
copy:
dest: /usr/bin/hdmion
mode: 0755
content: |
#!/usr/bin/env bash
sudo /opt/vc/bin/tvservice -p
- name: create hdmioff script
copy:
dest: /usr/bin/hdmioff
mode: 0755
content: |
#!/usr/bin/env bash
sudo /opt/vc/bin/tvservice -o
- name: configure rc.local - name: configure rc.local
blockinfile: blockinfile:
path: /etc/rc.local path: /etc/rc.local
@ -271,6 +317,13 @@
fi fi
/root/pwnagotchi/scripts/startup.sh & /root/pwnagotchi/scripts/startup.sh &
- name: create /etc/pwnagotchi/config.yml
blockinfile:
path: /etc/pwnagotchi/config.yml
create: yes
block: |
# put here your custom configuration overrides
- name: configure lo interface - name: configure lo interface
blockinfile: blockinfile:
path: /etc/network/interfaces.d/lo-cfg path: /etc/network/interfaces.d/lo-cfg
@ -335,7 +388,7 @@
state: present state: present
backup: no backup: no
regexp: '(.*)$' regexp: '(.*)$'
line: '\1 modules-load=dwc2,g_cdc' line: '\1 modules-load=dwc2,g_ether'
- name: configure ssh - name: configure ssh
lineinfile: lineinfile:

View File

@ -26,7 +26,7 @@ usage: ./scripts/create_sibling.sh [OPTIONS]
`GLib-ERROR **: 20:50:46.361: getauxval () failed: No such file or directory` `GLib-ERROR **: 20:50:46.361: getauxval () failed: No such file or directory`
- Affected DEB & Versions: QEMU <= 2.11 - Affected DEB & Versions: QEMU <= 2.11
- Fix: Upgrade QEMU to >= 3.1 - Fix: Upgrade QEMU to >= 3.1
- Bug Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=923289 - Bug Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=923289
@ -55,7 +55,6 @@ If you changed the `voice.py`- File, the translations need an update. Do it like
Now you can use the `preview.py`-script to preview the changes: Now you can use the `preview.py`-script to preview the changes:
```shell ```shell
./scripts/preview.py --lang it --display ws2 --port 8080 & ./scripts/preview.py --lang it --display ws1 ws2 inky --output preview.png
./scripts/preview.py --lang it --display inky --port 8081 & # Now open preview.png
# Now open http://localhost:8080 and http://localhost:8081
``` ```

View File

@ -1,6 +1,6 @@
import subprocess import subprocess
version = '1.0.0plz3' version = '1.0.0plz4'
_name = None _name = None

View File

@ -153,8 +153,8 @@ bettercap:
scheme: http scheme: http
hostname: localhost hostname: localhost
port: 8081 port: 8081
username: user username: pwnagotchi
password: pass password: pwnagotchi
# folder where bettercap stores the WPA handshakes, given that # folder where bettercap stores the WPA handshakes, given that
# wifi.handshakes.aggregate will be set to false and individual # wifi.handshakes.aggregate will be set to false and individual
# pcap files will be created in order to minimize the chances # pcap files will be created in order to minimize the chances

View File

@ -33,11 +33,11 @@ msgid "AI ready."
msgstr "ΤΝ έτοιμη." msgstr "ΤΝ έτοιμη."
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "Το νευρωνικό δίκτυοείναι έτοιμο." msgstr "Το νευρωνικό δίκτυο είναι έτοιμο."
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "Ε, το κανάλι {channel} είναιελεύθερο! Το AP σου θαείναι ευγνώμων." msgstr "Ε, το κανάλι {channel} είναιελεύθερο! Το AP σου θα είναι ευγνώμων."
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "Βαριέμαι ..." msgstr "Βαριέμαι ..."

View File

@ -25,20 +25,20 @@ msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "Bonjour, je suis Pwnagotchi! Démarrage ..." msgstr "Bonjour, je suis Pwnagotchi! Démarrage ..."
msgid "New day, new hunt, new pwns!" msgid "New day, new hunt, new pwns!"
msgstr "Nouvelle journée, nouvelle chasse, nouveau pwns!" msgstr "Nouveau jour, nouvelle chasse, nouveaux pwns !"
msgid "Hack the Planet!" msgid "Hack the Planet!"
msgstr "Hack la planète!" msgstr "Hack la planète!"
msgid "AI ready." msgid "AI ready."
msgstr "IA prête." msgstr "L'IA est prête."
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "Le réseau neuronal est prêt." msgstr "Le réseau neuronal est prêt."
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "Hey, le channel {channel} est libre! Ton AP va dis merci." msgstr "Hey, le channel {channel} est libre! Ton point d'accès va te remercier."
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "Je m'ennuie ..." msgstr "Je m'ennuie ..."
@ -68,17 +68,17 @@ msgid "I pwn therefore I am."
msgstr "Je pwn donc je suis." msgstr "Je pwn donc je suis."
msgid "So many networks!!!" msgid "So many networks!!!"
msgstr "Autant de réseaux!!!" msgstr "Tellement de réseaux!!!"
msgid "I'm having so much fun!" msgid "I'm having so much fun!"
msgstr "Je m'amuse tellement!" msgstr "Je m'amuse tellement!"
msgid "My crime is that of curiosity ..." msgid "My crime is that of curiosity ..."
msgstr "Mon crime est celui de la curiosité ..." msgstr "Mon crime, c'est la curiosité ..."
#, python-brace-format #, python-brace-format
msgid "Hello {name}! Nice to meet you. {name}" msgid "Hello {name}! Nice to meet you. {name}"
msgstr "Bonjour {name}! Ravis de te rencontrer. {name}" msgstr "Bonjour {name}! Ravi de te rencontrer. {name}"
#, python-brace-format #, python-brace-format
msgid "Unit {name} is nearby! {name}" msgid "Unit {name} is nearby! {name}"
@ -145,7 +145,7 @@ msgstr ""
#, python-brace-format #, python-brace-format
msgid "Just decided that {mac} needs no WiFi!" msgid "Just decided that {mac} needs no WiFi!"
msgstr "Décidé à l'instant que {mac} n'a pas besoin de WiFi!" msgstr "Je viens de décider que {mac} n'a pas besoin de WiFi!"
#, python-brace-format #, python-brace-format
msgid "Deauthenticating {mac}" msgid "Deauthenticating {mac}"
@ -153,11 +153,11 @@ msgstr "Désauthentification de {mac}"
#, python-brace-format #, python-brace-format
msgid "Kickbanning {mac}!" msgid "Kickbanning {mac}!"
msgstr "" msgstr "Je kick et je bannis {mac}!"
#, python-brace-format #, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!" msgid "Cool, we got {num} new handshake{plural}!"
msgstr "Cool, nous avons {num} nouveaux handshake{plural}!" msgstr "Cool, on a {num} nouveaux handshake{plural}!"
msgid "Ops, something went wrong ... Rebooting ..." msgid "Ops, something went wrong ... Rebooting ..."
msgstr "Oups, quelque chose s'est mal passé ... Redémarrage ..." msgstr "Oups, quelque chose s'est mal passé ... Redémarrage ..."
@ -188,7 +188,7 @@ msgid ""
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgstr "" msgstr ""
"J'ai pwn durant {duration} et kick {deauthed} clients! J'ai aussi rencontré " "J'ai pwn durant {duration} et kick {deauthed} clients! J'ai aussi rencontré "
"{associated} nouveaux amis and mangé {handshakes} handshakes! #pwnagotchi " "{associated} nouveaux amis et dévoré {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgid "hours" msgid "hours"

View File

@ -152,7 +152,7 @@ class Advertiser(object):
if self._is_broadcasted_advertisement(dot11): if self._is_broadcasted_advertisement(dot11):
try: try:
dot11elt = p.getlayer(Dot11Elt) dot11elt = p.getlayer(Dot11Elt)
if dot11elt.ID == wifi.Dot11ElemID_Identity: if dot11elt.ID == wifi.Dot11ElemID_Whisper:
self._parse_identity(p[RadioTap], dot11, dot11elt) self._parse_identity(p[RadioTap], dot11, dot11elt)
else: else:

View File

@ -1,6 +1,6 @@
SignatureAddress = 'de:ad:be:ef:de:ad' SignatureAddress = 'de:ad:be:ef:de:ad'
BroadcastAddress = 'ff:ff:ff:ff:ff:ff' BroadcastAddress = 'ff:ff:ff:ff:ff:ff'
Dot11ElemID_Identity = 222 Dot11ElemID_Whisper = 222
NumChannels = 140 NumChannels = 140
def freq_to_channel(freq): def freq_to_channel(freq):
@ -30,7 +30,7 @@ def encapsulate(payload, addr_from, addr_to=BroadcastAddress):
while data_left > 0: while data_left > 0:
sz = min(chunk_size, data_left) sz = min(chunk_size, data_left)
chunk = payload[data_off: data_off + sz] chunk = payload[data_off: data_off + sz]
frame /= Dot11Elt(ID=Dot11ElemID_Identity, info=chunk, len=sz) frame /= Dot11Elt(ID=Dot11ElemID_Whisper, info=chunk, len=sz)
data_off += sz data_off += sz
data_left -= sz data_left -= sz

15
requirements.txt Normal file
View File

@ -0,0 +1,15 @@
crypto==1.4.1
requests==2.21.0
PyYAML==5.1
scapy==2.4.3
gym==0.14.0
stable-baselines==2.7.0
tensorflow==1.13.1
tensorflow-estimator==1.14.0
tweepy==3.6.0
file-read-backwards==2.0.0
numpy==1.17.2
inky==0.0.5
smbus2==0.3.0
Pillow==5.4.1
spidev==3.4

View File

@ -94,9 +94,8 @@ function provide_raspbian() {
function setup_raspbian(){ function setup_raspbian(){
# Detect the ability to create sparse files # Detect the ability to create sparse files
if [ "${OPT_SPARSE}" -eq 0 ]; then if [ "${OPT_SPARSE}" -eq 0 ]; then
if [ which bmaptool -eq 0 ]; then if ! type "bmaptool" > /dev/null; then
echo "[!] bmaptool not available, not creating a sparse image" echo "[!] bmaptool not available, not creating a sparse image"
else else
echo "[+] Defaulting to sparse image generation as bmaptool is available" echo "[+] Defaulting to sparse image generation as bmaptool is available"
OPT_SPARSE=1 OPT_SPARSE=1

View File

@ -1,77 +1,35 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import sys import sys
import os import os
import time
import argparse import argparse
from http.server import HTTPServer
import shutil
import logging
import yaml import yaml
sys.path.insert(0, sys.path.insert(0,
os.path.join(os.path.dirname(os.path.realpath(__file__)), os.path.join(os.path.dirname(os.path.realpath(__file__)),
'../sdcard/rootfs/root/pwnagotchi/scripts/')) '../'))
from pwnagotchi.ui.display import Display, VideoHandler from pwnagotchi.ui.display import Display, VideoHandler
from PIL import Image
class CustomDisplay(Display): class CustomDisplay(Display):
def __init__(self, config, state):
self.last_image = None
super(CustomDisplay, self).__init__(config, state)
def _http_serve(self): def _http_serve(self):
if self._video_address is not None: # do nothing
self._httpd = HTTPServer((self._video_address, self._video_port), pass
CustomVideoHandler)
logging.info("ui available at http://%s:%d/" % (self._video_address,
self._video_port))
self._httpd.serve_forever()
else:
logging.info("could not get ip of usb0, video server not starting")
def _on_view_rendered(self, img): def _on_view_rendered(self, img):
CustomVideoHandler.render(img) self.last_image = img
if self._enabled: def get_image(self):
self.canvas = (img if self._rotation == 0 else img.rotate(self._rotation)) """
if self._render_cb is not None: Return the saved image
self._render_cb() """
return self.last_image
class CustomVideoHandler(VideoHandler):
@staticmethod
def render(img):
with CustomVideoHandler._lock:
try:
img.save("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), format='PNG')
except BaseException:
logging.exception("could not write preview")
def do_GET(self):
if self.path == '/':
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
try:
self.wfile.write(
bytes(
self._index %
('localhost', 1000), "utf8"))
except BaseException:
pass
elif self.path.startswith('/ui'):
with self._lock:
self.send_response(200)
self.send_header('Content-type', 'image/png')
self.end_headers()
try:
with open("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), 'rb') as fp:
shutil.copyfileobj(fp, self.wfile)
except BaseException:
logging.exception("could not open preview")
else:
self.send_response(404)
class DummyPeer: class DummyPeer:
@ -80,20 +38,44 @@ class DummyPeer:
return "beta" return "beta"
def append_images(images, horizontal=True, xmargin=0, ymargin=0):
w, h = zip(*(i.size for i in images))
if horizontal:
t_w = sum(w)
t_h = max(h)
else:
t_w = max(w)
t_h = sum(h)
result = Image.new('RGB', (t_w, t_h))
x_offset = 0
y_offset = 0
for im in images:
result.paste(im, (x_offset, y_offset))
if horizontal:
x_offset += im.size[0] + xmargin
else:
y_offset += im.size[1] + ymargin
return result
def main(): def main():
parser = argparse.ArgumentParser(description="This program emulates\ parser = argparse.ArgumentParser(description="This program emulates\
the pwnagotchi display") the pwnagotchi display")
parser.add_argument('--display', help="Which display to use.", parser.add_argument('--displays', help="Which displays to use.", nargs="+",
default="waveshare_2") default="waveshare_2")
parser.add_argument('--port', help="Which port to use",
default=8080)
parser.add_argument('--sleep', type=int, help="Time between emotions",
default=2)
parser.add_argument('--lang', help="Language to use", parser.add_argument('--lang', help="Language to use",
default="en") default="en")
parser.add_argument('--output', help="Path to output image (PNG)", default="preview.png")
parser.add_argument('--xmargin', type=int, default=5)
parser.add_argument('--ymargin', type=int, default=5)
args = parser.parse_args() args = parser.parse_args()
CONFIG = yaml.load(''' config_template = '''
main: main:
lang: {lang} lang: {lang}
ui: ui:
@ -107,64 +89,79 @@ def main():
video: video:
enabled: true enabled: true
address: "0.0.0.0" address: "0.0.0.0"
port: {port} port: 8080
'''.format(display=args.display, '''
port=args.port,
lang=args.lang))
DISPLAY = CustomDisplay(config=CONFIG, state={'name': '%s>' % 'preview'}) list_of_displays = list()
for display_type in args.displays:
config = yaml.safe_load(config_template.format(display=display_type,
lang=args.lang))
display = CustomDisplay(config=config, state={'name': f"{display_type}>"})
list_of_displays.append(display)
while True: columns = list()
DISPLAY.on_starting()
DISPLAY.update() for display in list_of_displays:
time.sleep(args.sleep) emotions = list()
DISPLAY.on_ai_ready() # Starting
DISPLAY.update() display.on_starting()
time.sleep(args.sleep) display.update()
DISPLAY.on_normal() emotions.append(display.get_image())
DISPLAY.update() display.on_ai_ready()
time.sleep(args.sleep) display.update()
DISPLAY.on_new_peer(DummyPeer()) emotions.append(display.get_image())
DISPLAY.update() display.on_normal()
time.sleep(args.sleep) display.update()
DISPLAY.on_lost_peer(DummyPeer()) emotions.append(display.get_image())
DISPLAY.update() display.on_new_peer(DummyPeer())
time.sleep(args.sleep) display.update()
DISPLAY.on_free_channel('6') emotions.append(display.get_image())
DISPLAY.update() display.on_lost_peer(DummyPeer())
time.sleep(args.sleep) display.update()
DISPLAY.wait(args.sleep) emotions.append(display.get_image())
DISPLAY.update() display.on_free_channel('6')
DISPLAY.on_bored() display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.wait(2)
DISPLAY.on_sad() display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_bored()
DISPLAY.on_motivated(1) display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_sad()
DISPLAY.on_demotivated(-1) display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_motivated(1)
DISPLAY.on_excited() display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_demotivated(-1)
DISPLAY.on_deauth({'mac': 'DE:AD:BE:EF:CA:FE'}) display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_excited()
DISPLAY.on_miss('test') display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_deauth({'mac': 'DE:AD:BE:EF:CA:FE'})
DISPLAY.on_lonely() display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_miss('test')
DISPLAY.on_handshakes(1) display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_lonely()
DISPLAY.on_rebooting() display.update()
DISPLAY.update() emotions.append(display.get_image())
time.sleep(args.sleep) display.on_handshakes(1)
display.update()
emotions.append(display.get_image())
display.on_rebooting()
display.update()
emotions.append(display.get_image())
# append them all together (vertical)
columns.append(append_images(emotions, horizontal=False, xmargin=args.xmargin, ymargin=args.ymargin))
# append columns side by side
final_image = append_images(columns, horizontal=True, xmargin=args.xmargin, ymargin=args.ymargin)
final_image.save(args.output, 'PNG')
if __name__ == '__main__': if __name__ == '__main__':

6
scripts/pypi_upload.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/bash
rm -rf build dist ergo_nn.egg-info &&
python3 setup.py sdist bdist_wheel &&
clear &&
twine upload dist/*

View File

@ -1 +0,0 @@
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2,g_ether

File diff suppressed because it is too large Load Diff

View File

View File

@ -1 +0,0 @@
alpha

View File

@ -1,6 +0,0 @@
127.0.0.1 localhost alpha alpha.local
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

View File

@ -1 +0,0 @@
(◕‿‿◕) alpha (pwnagotchi)

View File

@ -1,17 +0,0 @@
auto lo
iface lo inet loopback
allow-hotplug wlan0
iface wlan0 inet static
allow-hotplug eth0
iface eth0 inet dhcp
allow-hotplug usb0
iface usb0 inet static
address 10.0.0.2
netmask 255.255.255.0
network 10.0.0.0
broadcast 10.0.0.255
gateway 10.0.0.1

View File

@ -1,19 +0,0 @@
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
# Powersave (Disable HDMI) ~30ma
sleep 10
if ! /opt/vc/bin/tvservice -s | grep HDMI; then
/opt/vc/bin/tvservice -o
fi
/root/pwnagotchi/scripts/startup.sh &
exit 0

View File

@ -1,121 +0,0 @@
# $OpenBSD: sshd_config,v 1.103 2018/04/09 20:41:22 tj Exp $
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# This sshd was compiled with PATH=/usr/bin:/bin:/usr/sbin:/sbin
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
#Port 22
#AddressFamily any
#ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
#PubkeyAuthentication yes
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
#AuthorizedPrincipalsFile none
#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody
# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no
# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
ChallengeResponseAuthentication no
# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no
# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes
#GSSAPIStrictAcceptorCheck yes
#GSSAPIKeyExchange no
# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication. Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
UsePAM yes
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
X11Forwarding yes
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
PrintMotd no
#PrintLastLog yes
#TCPKeepAlive yes
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none
# no default banner path
#Banner none
# Allow client to pass locale environment variables
AcceptEnv LANG LC_*
# override default of no subsystems
Subsystem sftp /usr/lib/openssh/sftp-server
# Example of overriding settings on a per-user basis
#Match User anoncvs
# X11Forwarding no
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,49 +0,0 @@
defutf8 on
shell -${SHELL}
defscrollback 1024
startup_message off
altscreen on
autodetach on
zombie kr
activity "activity in %n (%t)"
bell_msg "bell in %n (%t)"
vbell on
vbell_msg "WTF DUDE ??!!"
vbellwait 1
# set terminal emulator to xterm mode
term xterm
# Make the output buffer large for (fast) xterms.
termcapinfo xterm* ti@:te@
# tell screen how to set colors
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
# allow bold colors
attrcolor b ".I"
# erase background with current bg color
defbce "on"
# ctrl + { left, right }
bindkey ^[[1;5D prev
bindkey ^[[1;5C next
bindkey ^[[5D prev
bindkey ^[[5C next
bindkey ^[b prev
bindkey ^[f next
bindkey ^[[D prev
bindkey ^[[C next
screen -t shell
screen -t auto-mode /bin/bash -c "/root/pwnagotchi/scripts/main.py"
screen -t bettercap /usr/bin/bettercap -caplet http-ui -eval "!/usr/bin/monstart; set wifi.interface mon0"
select log
backtick 1 0 0 cpuusage
backtick 2 5 5 memusage
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][cpu %1`][mem %2`][%{B} %m-%d %{W}%c %{g}]'

View File

@ -1,49 +0,0 @@
defutf8 on
shell -${SHELL}
defscrollback 1024
startup_message off
altscreen on
autodetach on
zombie kr
activity "activity in %n (%t)"
bell_msg "bell in %n (%t)"
vbell on
vbell_msg "WTF DUDE ??!!"
vbellwait 1
# set terminal emulator to xterm mode
term xterm
# Make the output buffer large for (fast) xterms.
termcapinfo xterm* ti@:te@
# tell screen how to set colors
termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
# allow bold colors
attrcolor b ".I"
# erase background with current bg color
defbce "on"
# ctrl + { left, right }
bindkey ^[[1;5D prev
bindkey ^[[1;5C next
bindkey ^[[5D prev
bindkey ^[[5C next
bindkey ^[b prev
bindkey ^[f next
bindkey ^[[D prev
bindkey ^[[C next
screen -t shell
screen -t manual-mode /bin/bash -c "/root/pwnagotchi/scripts/main.py --manual"
screen -t bettercap /usr/bin/bettercap -caplet http-ui -eval "!/usr/bin/monstart; set wifi.interface mon0"
select log
backtick 1 0 0 cpuusage
backtick 2 5 5 memusage
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][cpu %1`][mem %2`][%{B} %m-%d %{W}%c %{g}]'

View File

@ -1,12 +0,0 @@
#!/usr/bin/env bash
for i in $(seq 1 "$1");
do
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
echo 1 >/sys/class/leds/led0/brightness
sleep 0.3
done
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3

View File

@ -1,103 +0,0 @@
#!/usr/bin/python3
import argparse
import time
import logging
import pwnagotchi
import pwnagotchi.utils as utils
import pwnagotchi.plugins as plugins
from pwnagotchi.log import SessionParser
from pwnagotchi.agent import Agent
from pwnagotchi.ui.display import Display
parser = argparse.ArgumentParser()
parser.add_argument('-C', '--config', action='store', dest='config', default='/root/pwnagotchi/config.yml',
help='Main configuration file.')
parser.add_argument('-U', '--user-config', action='store', dest='user_config', default='/root/custom.yml',
help='If this file exists, configuration will be merged and this will override default values.')
parser.add_argument('--manual', dest="do_manual", action="store_true", default=False, help="Manual mode.")
parser.add_argument('--clear', dest="do_clear", action="store_true", default=False,
help="Clear the ePaper display and exit.")
parser.add_argument('--debug', dest="debug", action="store_true", default=False,
help="Enable debug logs.")
args = parser.parse_args()
config = utils.load_config(args)
utils.setup_logging(args, config)
plugins.load(config)
display = Display(config=config, state={'name': '%s>' % pwnagotchi.name()})
agent = Agent(view=display, config=config)
logging.info("%s@%s (v%s)" % (pwnagotchi.name(), agent._identity, pwnagotchi.version))
for _, plugin in plugins.loaded.items():
logging.debug("plugin '%s' v%s loaded from %s" % (plugin.__name__, plugin.__version__, plugin.__file__))
if args.do_clear:
logging.info("clearing the display ...")
display.clear()
elif args.do_manual:
logging.info("entering manual mode ...")
log = SessionParser(config)
logging.info(
"the last session lasted %s (%d completed epochs, trained for %d), average reward:%s (min:%s max:%s)" % (
log.duration_human,
log.epochs,
log.train_epochs,
log.avg_reward,
log.min_reward,
log.max_reward))
while True:
display.on_manual_mode(log)
time.sleep(1)
if Agent.is_connected():
plugins.on('internet_available', display, config, log)
else:
logging.info("entering auto mode ...")
agent.start()
while True:
try:
# recon on all channels
agent.recon()
# get nearby access points grouped by channel
channels = agent.get_access_points_by_channel()
# check for free channels to use
agent.check_channels(channels)
# for each channel
for ch, aps in channels:
agent.set_channel(ch)
if not agent.is_stale() and agent.any_activity():
logging.info("%d access points on channel %d" % (len(aps), ch))
# for each ap on this channel
for ap in aps:
# send an association frame in order to get for a PMKID
agent.associate(ap)
# deauth all client stations in order to get a full handshake
for sta in ap['clients']:
agent.deauth(ap, sta)
# An interesting effect of this:
#
# From Pwnagotchi's perspective, the more new access points
# and / or client stations nearby, the longer one epoch of
# its relative time will take ... basically, in Pwnagotchi's universe,
# WiFi electromagnetic fields affect time like gravitational fields
# affect ours ... neat ^_^
agent.next_epoch()
except Exception as e:
logging.exception("main loop exception")

View File

@ -1,13 +0,0 @@
Crypto
requests
pyyaml
scapy
gym
stable-baselines
tensorflow
tweepy
file_read_backwards
numpy
inky
smbus
pillow

View File

@ -1,11 +0,0 @@
#!/usr/bin/env bash
# blink 10 times to signal ready state
/root/pwnagotchi/scripts/blink.sh 10 &
# start a detached screen session with bettercap
if ifconfig | grep usb0 | grep RUNNING; then
sudo -H -u root /usr/bin/screen -dmS pwnagotchi -c /root/pwnagotchi/data/screenrc.manual
else
sudo -H -u root /usr/bin/screen -dmS pwnagotchi -c /root/pwnagotchi/data/screenrc.auto
fi

View File

@ -1,51 +0,0 @@
#!/usr/bin/gawk -f
#-------------------------------------------------------------------------------
# ~/bin/cpustat : display cpu utilization
#
# usage : normally used as a GNU/screen backtick
#
# notes : 1. Works on the assumption that /proc/stat's first line
# : has the total "jiffies" since boot up used by the
# : different types of tasks in the system. See the
# : filesystems/proc.txt document in kernel source tree
# :
# : 2. Displays a total CPU% (user+system+nice) as well as
# : user CPU% system CPU% and nice CPU%
#-------------------------------------------------------------------------------
BEGIN {
file = "/proc/stat"
while (getline < file) { # read first line
# extract jiffies:
user=$2-user_saved; # . user
nice=$3-nice_saved; # . nice user
syst=$4-syst_saved; # . system
idle=$5-idle_saved; # . idle
wait=$6-wait_saved; # . iowait
irqs=$7-irqs_saved; # . irq
sirq=$8-sirq_saved; # . softirq
cact=user+syst+nice; # what counts
ctot=user+nice+syst+idle+wait+irqs+sirq; # total activity
tcpu=cact/ctot*100; # total % cpu utilization
ucpu=user/ctot*100; # user % cpu utilization
scpu=syst/ctot*100; # system % cpu utilization
ncpu=nice/ctot*100; # nice % cpu utilization
printf "%.1f %%\n",tcpu
user_saved=$2; # save the current jiffies
nice_saved=$3; # values for the next loop
syst_saved=$4;
idle_saved=$5;
wait_saved=$6;
irqs_saved=$7;
sirq_saved=$8;
close(file) # re-read file
system("sleep 3")
}
}

View File

@ -1 +0,0 @@
free -m | grep Mem | awk {'printf( "%.1f %", $3 / $2 * 100 )'}

View File

@ -1,2 +0,0 @@
#!/bin/bash
iw phy phy0 interface add mon0 type monitor && ifconfig mon0 up

View File

@ -1,2 +0,0 @@
#!/bin/bash
ifconfig mon0 down && iw dev mon0 del

28
setup.py Normal file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env python3
from setuptools import setup, find_packages
import pwnagotchi
required = []
with open('requirements.txt') as fp:
for line in fp:
line = line.strip()
if line != "":
required.append(line)
setup(name='pwnagotchi',
version=pwnagotchi.version,
description='(⌐■_■) - Deep Reinforcement Learning instrumenting bettercap for WiFI pwning.',
author='evilsocket && the dev team',
author_email='evilsocket@gmail.com',
url='https://pwnagotchi.ai/',
license='GPL',
install_requires=required,
scripts=['bin/pwnagotchi'],
package_data={'pwnagotchi': ('pwnagotchi/defaults.yml',)},
packages=find_packages(),
classifiers=[
'Programming Language :: Python :: 3',
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: GNU General Public License (GPL)',
'Environment :: Console',
])