From a5c2184335d5d0ebba2ff0508fc2b8b2fdabafab Mon Sep 17 00:00:00 2001 From: justin-p Date: Sun, 29 Sep 2019 22:36:59 +0200 Subject: [PATCH 01/54] nl locale --- .../pwnagotchi/locale/nl/LC_MESSAGES/voice.mo | Bin 0 -> 3884 bytes .../pwnagotchi/locale/nl/LC_MESSAGES/voice.po | 339 ++++++++++++++++++ 2 files changed, 339 insertions(+) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..42be23bca659f89af5964b38cdbfa7030df8cc38 GIT binary patch literal 3884 zcmbW3ON<;x8Gy@q0BImVcqCv5HJHS4yfdD)A+eVP@OwAjbyoIS@D2Du_zx&@9(+)#_rl}wQFyB1Mff4^Uxx3585H?D@HO~tD0(ivL#aog zgJQ?mpuG28_!#^#6uG~I5&SKDAN(^Exo^Q1{3n!skFzLtKLa(q4Nt=oik&}%V*k&e z?0X$*_(v%E)w^mrk3!jZ27U})h7ZFpLrhl_D0Uak`nTZqV@kaO-^2Rv3AV`lD?9^_ zVZ6v&hGPF!_%wV8o`7G6pM^hyPr%E%H^qqua_X-p_+fc&gFr(92~*p@CWco_!^Y= z-h`iq5+qDlPe93I7mEI?Q2d-W>)(T7$4{X6^*R(ezk&RzxA>Ac-;a}G&qGk^=Qt$H z;rbNcqEqrNF%!LV$-c!UF_%kXCU(dr^5v3vV0N&JFa>=e#8qsOi*$zgimehS%Kpf; z)ZEcd>XUp<@@eyt9EjZ#BTDPwl2{V*5c?K9%|}{PV)_&xiMhm0u2Xy@Hk7tf7uR%d zO+4?Yi$&r4&Xg`obm^nL+0c~x>azFglAc+e_)_m>)nq@)>`V_$78gS^wtLgG%1yf8 zQdg|0%Aw6l*AGIXy@~1Xt5wqk#)c@h<;g<#tRCdfqE}?hmvkQ^GMnnX=EuHvMKs8*ZRwYNmFtU}dgjtJD$E=M zOg1h$YSk_2wUZOQIm-+l^@pw%-7ZZYyzX>5YE2I;G7GOw>NBhBwdpJqA96eJxz%gh zOxTH-9=CD5hdcY#GPe_(&hJ?tnjHx$GAC7k7!9hd72Zx=SeM|WZeZ)h!o=a>j?L$q zn@0MMB>*7op-7Li&H)sXlQ1EXgq9kCo?|zukwzn4 z+_`c{a>Cm$PKzaqg;WhC8Z&aJXSv5aiZQxnd)^+PW{F$QIN<&3&bf=xC@Z8`J# zxM;OnYK!X1tn}z&Il`Z&=eLIZ4(>^L6=fuX{6J6UO+~&moCK|j_i=A-o3>Tk#sw2X z86I+cTY7|EwNky}<`-IOd+7bN2vX|S7X1mm)lqkLcX#i|*RFhp+g){ZQ;0~jG-(pE znfsCLm+iH<{Us7c2dwCBr`uU3I8&dO?TsRFar;u06zwg)qNB|h+qdkFlb!7=RQQTM z+g-lU?p|o0y`Yyrv(oLJ?w;*-qjgi1?XBEoMQTc)uV^V=m$f(bbEEp#^ov!2%1%b( zPt$oPA#YW$)Ay6l^LCb0Cb8`;YbGnwsf%8D?%cWM3(r1tZuxXP^t)cO$nkXvr*n-DddRty z(mt8a96uL6HijZGW(Jln5tU-P%@a}GtS&T@ES*>}F4jB#?XyCjzkN{fN%)ndYdCsmIh$<(*sHAz*}nLt~|xD0MWb zGyW~%d15EVjOnZ!Gc#$%3sr)(^~#|s(=1=Ni$iV0jUUqxfcRTWk`>Q2l#k`a>B-^<6WK95&-2|0#vGm+~#9 zHbtZqYM4b79Gb&_9aSmI_Y9#MtfEII5d9LmKqipQCFqQxRSG$bpk@Z~K>P{^Pi=T& zdwJ!?2aQ3yNTXTi5#>!=gcyXrXsN|a;*7TWVj^9YmT9IwvlT}h54Jhoq}QB{Ieu(* eFp*rCw$1xu&w!(+aQ44VrNy>pD3SAKEd2}c%N!{H literal 0 HcmV?d00001 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 new file mode 100644 index 00000000..3853be48 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.po @@ -0,0 +1,339 @@ +# pwnigotchi voice data +# Copyright (C) 2019 +# This file is distributed under the same license as the pwnagotchi package. +# FIRST AUTHOR justin-p@users.noreply.github.com, 2019. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-29 13:42+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" +"Language: english\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: voice.py:16 +msgid "ZzzzZZzzzzZzzz" +msgstr "ZzzzZZzzzzZzzz" + +#: voice.py:21 +msgid "" +"Hi, I'm Pwnagotchi!\n" +"Starting ..." +msgstr "" +"Hoi, Ik ben Pwnagotchi!\n" +"Opstarten ..." + +#: voice.py:22 +msgid "" +"New day, new hunt,\n" +"new pwns!" +msgstr "" +"Nieuwe dag, nieuwe jacht,\n" +"nieuwe pwns!" + +#: voice.py:23 +msgid "Hack the Planet!" +msgstr "Hack de Wereld!" + +#: voice.py:28 +msgid "AI ready." +msgstr "AI is klaar." + +#: voice.py:29 +msgid "" +"The neural network\n" +"is ready." +msgstr "" +"Het neuraal netwerk\n" +"is klaar voor gebruik." + +#: voice.py:39 +#, python-brace-format +msgid "" +"Hey, channel {channel} is\n" +"free! Your AP will\n" +"say thanks." +msgstr "" +"Hey, kanaal {channel} is\n" +"vrij! Je AP zal je\n" +"bedanken." + +#: voice.py:44 +msgid "I'm bored ..." +msgstr "Ik verveel mij ..." + +#: voice.py:45 +msgid "Let's go for a walk!" +msgstr "Laten we een rondje lopen!" + +#: voice.py:49 +msgid "" +"This is the best\n" +"day of my life!" +msgstr "" +"Dit is de beste\n" +"dag van mijn leven!" + +#: voice.py:53 +msgid "Shitty day :/" +msgstr "Kut dag :/" + +#: voice.py:58 +msgid "I'm extremely bored ..." +msgstr "Ik verveel me de pleuris ..." + +#: voice.py:59 +msgid "I'm very sad ..." +msgstr "Ik ben erg verdrietig ..." + +#: voice.py:60 +msgid "I'm sad" +msgstr "Ik ben verdrietig" + +#: voice.py:66 +msgid "I'm living the life!" +msgstr "Beter kan het leven niet worden!" + +#: voice.py:67 +msgid "I pwn therefore I am." +msgstr "Ik besta om de te pwnen." + +#: voice.py:68 +msgid "So many networks!!!" +msgstr "Zo veel netwerken!!!" + +#: voice.py:69 +msgid "" +"I'm having so much\n" +"fun!" +msgstr "Dit is zo leuk!" + + +#: voice.py:70 +msgid "" +"My crime is that of\n" +"curiosity ..." +msgstr "" +"Mijn enigiste misdrijf\n" +"is mijn nieuwsgierigheid ..." + +#: voice.py:75 +#, python-brace-format +msgid "" +"Hello\n" +"{name}!\n" +"Nice to meet you. {name}" +msgstr "" +"Hallo\n" +"{name}!\n" +"Leuk je te ontmoeten. {name}" + +#: voice.py:76 +#, python-brace-format +msgid "" +"Unit\n" +"{name}\n" +"is dichtbij! {name}" +msgstr "" +"" + +#: voice.py:81 +#, python-brace-format +msgid "" +"Uhm ...\n" +"goodbye\n" +"{name}" +msgstr "" +"Uhm ...\n" +"later\n" +"{name}" + +#: voice.py:82 +#, python-brace-format +msgid "" +"{name}\n" +"is gone ..." +msgstr "" +"{name}\n" +"is foetsie" + +#: voice.py:87 +#, python-brace-format +msgid "" +"Whoops ...\n" +"{name}\n" +"is gone." +msgstr "" +"Whoopsie ...\n" +"{name}\n" +"is foetsie" + +#: voice.py:88 +#, python-brace-format +msgid "" +"{name}\n" +"missed!" +msgstr "" +"{name}\n" +"gemissed!" + +#: voice.py:89 +msgid "Missed!" +msgstr "Gemissed!" + +#: voice.py:94 +msgid "" +"Nobody wants to\n" +"play with me ..." +msgstr "" +"Niemand wil met\n" +"mij spelen ..." + +#: voice.py:95 +msgid "I feel so alone ..." +msgstr "Zo alleen ..." + +#: voice.py:96 +msgid "Where's everybody?!" +msgstr "Waar is iedereen?!" + +#: voice.py:101 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Dutje doen voor {secs}s ..." + +#: voice.py:102 +msgid "Zzzzz" +msgstr "Zzzzz" + +#: voice.py:103 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "" + +#: voice.py:112 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Even {secs}s wachten ..." + +#: voice.py:114 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Rond kijken ({secs}s)" + +#: voice.py:121 +#, python-brace-format +msgid "" +"Hey\n" +"{what}\n" +"let's be friends!" +msgstr "" +"Hey\n" +"{what}\n" +"Laten we matties worden!" + +#: voice.py:122 +#, python-brace-format +msgid "" +"Associating to\n" +"{what}" +msgstr "" +"Associëren met\n" +"{what}" + +#: voice.py:123 +#, python-brace-format +msgid "" +"Yo\n" +"{what}!" +msgstr "" + + +#: voice.py:128 +#, python-brace-format +msgid "" +"Just decided that\n" +"{mac}\n" +"needs no WiFi!" +msgstr "Ik vind dat\n" +"{mac}\n" +"genoeg WiFi heeft gehad!" + +#: voice.py:129 +#, python-brace-format +msgid "" +"Deauthenticating\n" +"{mac}" +msgstr "" +"Deautoriseren\n" +"{mac}" + +#: voice.py:130 +#, python-brace-format +msgid "" +"Kickbanning\n" +"{mac}!" +msgstr "" +"Ik ga\n" +"{mac}\n" +"FF lekker kicken!" + +#: voice.py:135 +#, python-brace-format +msgid "" +"Cool, we got {num}\n" +"new handshake{plural}!" +msgstr "" +"Gaaf, we hebben {num}\n" +"nieuwe handshake{plural}!" + +#: voice.py:139 +msgid "" +"Ops, something\n" +"went wrong ...\n" +"Rebooting ..." +msgstr "" +"Ops, iets" +"ging fout ...\n" +"Rebooting ..." + +#: voice.py:143 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "{num} stations gekicked\n" + +#: voice.py:144 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "{num} nieuwe vrienden gemaakt\n" + +#: voice.py:145 +#, python-brace-format +msgid "{num} nieuwe handshakes\n" +msgstr "" + +#: voice.py:147 +msgid "Met 1 peer" +msgstr "Kwam 1 peer tegen" + +#: voice.py:149 +#, python-brace-format +msgid "Met {num} peers" +msgstr "Kwam {num} peers tegen" + +#: voice.py:154 +#, 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 "" +"Ik heb gepwned voor {duration} and heb {deauthed} clients gekicked! Ik heb ook " +"{associated} nieuwe frienden gevonden en heb {handshakes} handshakes gegeten! " +"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" \ No newline at end of file From 19d4dc8b07437ca5a3b29f498ca8fa3ac9c0cc6e Mon Sep 17 00:00:00 2001 From: justin-p Date: Sun, 29 Sep 2019 23:03:34 +0200 Subject: [PATCH 02/54] fixed length and typo --- .../pwnagotchi/locale/nl/LC_MESSAGES/voice.mo | Bin 3884 -> 3939 bytes .../pwnagotchi/locale/nl/LC_MESSAGES/voice.po | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo index 42be23bca659f89af5964b38cdbfa7030df8cc38..7d88419e29c37f8c9fe56292a864093d6da151be 100644 GIT binary patch delta 1101 zcmY+@F=!J}9LMqhnQN;tv28Rqts1XYQ#D!#DT-1wP$&)}6r>K@kQ0{@$IS4=$f~FL&?#|Nr-HKEIF;KW6-E zM(g9+$aTdt8^B*H_@RACn61KP%;Hbnf$hH8dOV04AI3JUVgc)@`R?F;e2M{n!?oDa z^QFDKExKBLoIL{ALB#RLe*xo3|>VAbPx63Bh2Az)VzzB#NXJ8 zNhWQv(5#D2Hv>JW2M1A+k79szEaELxpf6AvyhA;=gaJ0Ki~=a2<{3aecO1KL0@vUS z61&Y}hV|`c{Kq^Fd1g;A#dv~nl~Eh+!CusaBdE+KQJKu(PMpIn_ze4T0k>i2>L~C- zsP~SdDs~b>Wl*Q1iLPUS_pu#cVkdsUH~1B`&~u{Ogr89prYVauETGOp2^IJVYMxqr ze;IX_Zs1!bxio2!>RW41WU`WS{qProgp*T2M_3 zZFapV`)>NGsw(7b|Nm{f;~Ty*w-wv5k4xoMX1!b-57#)zt~wOWRj~(map}v|w(2w0 zLDZJ0sd73$oLBbfNN}c79-CcCoX8HHJ{w%9O`p0HRLixoscLz$GL>wUe7`vt4c8_r Z)8{My{X3X^>v`uIxm4C`^rydje*n8OW5WOd delta 1036 zcmY+@%S%*Y7{~GFIHRdKR+ec^O=Ed!oWvr!5VXjUXe}XaA|bPz5hN`lm=<=~n*=SQ zMT>%nU|PA$KOiJ%QP4#Sf-Z|dXw#za_c#ST%zHj(4rku?d4K23r^1s$<$YUrHmCu{ zCdPCUaS*@PaiBhCBARd!+wmKgFv&)&$1<+QA?(Ewbe^lYAMauj7jP~9MCYlmkH|$- zBF{+&7fLk`;X1w_#}#-HUEm7N;VpEbp@xVyJc~AR4gK8=cH$#+-WS-6Z*UcUM(16^ zF4m9VoOok_t9HH@i#UR1oI*N{2j~u-qW8^X5kH^}MC0;29q4_7xDgLyE1p1lk4d!g z%U);wxXH;8VxPqpzP}@HC;W-=Yo2%H?53aCJi2wiq 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 3853be48..a74cf4b2 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 @@ -311,12 +311,12 @@ msgstr "{num} stations gekicked\n" #: voice.py:144 #, python-brace-format msgid "Made {num} new friends\n" -msgstr "{num} nieuwe vrienden gemaakt\n" +msgstr "{num} nieuwe vrienden\n" #: voice.py:145 #, python-brace-format -msgid "{num} nieuwe handshakes\n" -msgstr "" +msgid "Got {num} handshakes\n" +msgstr "{num} nieuwe handshakes\n" #: voice.py:147 msgid "Met 1 peer" @@ -335,5 +335,5 @@ msgid "" "#pwnlog #pwnlife #hacktheplanet #skynet" msgstr "" "Ik heb gepwned voor {duration} and heb {deauthed} clients gekicked! Ik heb ook " -"{associated} nieuwe frienden gevonden en heb {handshakes} handshakes gegeten! " +"{associated} nieuwe vrienden gevonden en heb {handshakes} handshakes gegeten! " "#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet" \ No newline at end of file From b25092c97b2c1453d9defba3f3d5ffeef70d450f Mon Sep 17 00:00:00 2001 From: James Hooker Date: Mon, 30 Sep 2019 11:20:35 +0100 Subject: [PATCH 03/54] Include PaPiRus drivers in project --- .../scripts/pwnagotchi/ui/display.py | 6 +- .../scripts/pwnagotchi/ui/papirus/__init__.py | 0 .../scripts/pwnagotchi/ui/papirus/epd.py | 213 ++++++++++++++++++ .../scripts/pwnagotchi/ui/papirus/lm75b.py | 46 ++++ .../root/pwnagotchi/scripts/requirements.txt | 1 + 5 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/__init__.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index 4f9bb4a2..c530caae 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -123,11 +123,11 @@ class Display(View): self._display = InkyPHAT(self._display_color) self._display.set_border(InkyPHAT.BLACK) self._render_cb = self._inky_render - + elif self._is_papirus(): - from papirus import Papirus + from pwnagotchi.ui.papirus.epd import EPD os.environ['EPD_SIZE'] = '2.0' - self._display = Papirus() + self._display = EPD() self._display.clear() self._render_cb = self._papirus_render diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py new file mode 100644 index 00000000..923993bc --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/epd.py @@ -0,0 +1,213 @@ +#qCopyright 2013-2015 Pervasive Displays, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at: +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +# express or implied. See the License for the specific language +# governing permissions and limitations under the License. + + +from PIL import Image +from PIL import ImageOps +from pwnagotchi.ui.papirus.lm75b import LM75B +import re +import os +import sys + +if sys.version_info < (3,): + def b(x): + return x +else: + def b(x): + return x.encode('ISO-8859-1') + +class EPDError(Exception): + def __init__(self, value): + self.value = value + + def __str__(self): + return repr(self.value) + + +class EPD(object): + + """EPD E-Ink interface + +to use: + from EPD import EPD + + epd = EPD([path='/path/to/epd'], [auto=boolean], [rotation = 0|90|180|270]) + + image = Image.new('1', epd.size, 0) + # draw on image + epd.clear() # clear the panel + epd.display(image) # tranfer image data + epd.update() # refresh the panel image - not needed if auto=true +""" + + + PANEL_RE = re.compile('^([A-Za-z]+)\s+(\d+\.\d+)\s+(\d+)x(\d+)\s+COG\s+(\d+)\s+FILM\s+(\d+)\s*$', flags=0) + + def __init__(self, *args, **kwargs): + self._epd_path = '/dev/epd' + self._width = 200 + self._height = 96 + self._panel = 'EPD 2.0' + self._cog = 0 + self._film = 0 + self._auto = False + self._lm75b = LM75B() + self._rotation = 0 + self._uselm75b = True + + if len(args) > 0: + self._epd_path = args[0] + elif 'epd' in kwargs: + self._epd_path = kwargs['epd'] + + if ('auto' in kwargs) and kwargs['auto']: + self._auto = True + if ('rotation' in kwargs): + rot = kwargs['rotation'] + if rot in (0, 90, 180, 270): + self._rotation = rot + else: + raise EPDError('rotation can only be 0, 90, 180 or 270') + + with open(os.path.join(self._epd_path, 'version')) as f: + self._version = f.readline().rstrip('\n') + + with open(os.path.join(self._epd_path, 'panel')) as f: + line = f.readline().rstrip('\n') + m = self.PANEL_RE.match(line) + if m is None: + raise EPDError('invalid panel string') + self._panel = m.group(1) + ' ' + m.group(2) + self._width = int(m.group(3)) + self._height = int(m.group(4)) + self._cog = int(m.group(5)) + self._film = int(m.group(6)) + + if self._width < 1 or self._height < 1: + raise EPDError('invalid panel geometry') + if self._rotation in (90, 270): + self._width, self._height = self._height, self._width + + @property + def size(self): + return (self._width, self._height) + + @property + def width(self): + return self._width + + @property + def height(self): + return self._height + + @property + def panel(self): + return self._panel + + @property + def version(self): + return self._version + + @property + def cog(self): + return self._cog + + @property + def film(self): + return self._film + + @property + def auto(self): + return self._auto + + @auto.setter + def auto(self, flag): + if flag: + self._auto = True + else: + self._auto = False + + @property + def rotation(self): + return self._rotation + + @rotation.setter + def rotation(self, rot): + if rot not in (0, 90, 180, 270): + raise EPDError('rotation can only be 0, 90, 180 or 270') + if abs(self._rotation - rot) == 90 or abs(self._rotation - rot) == 270: + self._width, self._height = self._height, self._width + self._rotation = rot + + @property + def use_lm75b(self): + return self._uselm75b + + @use_lm75b.setter + def use_lm75b(self, flag): + if flag: + self._uselm75b = True + else: + self._uselm75b = False + + def error_status(self): + with open(os.path.join(self._epd_path, 'error'), 'r') as f: + return(f.readline().rstrip('\n')) + + def rotation_angle(self, rotation): + angles = { 90 : Image.ROTATE_90, 180 : Image.ROTATE_180, 270 : Image.ROTATE_270 } + return angles[rotation] + + def display(self, image): + + # attempt grayscale conversion, and then to single bit + # better to do this before calling this if the image is to + # be dispayed several times + if image.mode != "1": + image = ImageOps.grayscale(image).convert("1", dither=Image.FLOYDSTEINBERG) + + if image.mode != "1": + raise EPDError('only single bit images are supported') + + if image.size != self.size: + raise EPDError('image size mismatch') + + if self._rotation != 0: + image = image.transpose(self.rotation_angle(self._rotation)) + + with open(os.path.join(self._epd_path, 'LE', 'display_inverse'), 'r+b') as f: + f.write(image.tobytes()) + + if self.auto: + self.update() + + + def update(self): + self._command('U') + + def partial_update(self): + self._command('P') + + def fast_update(self): + self._command('F') + + def clear(self): + self._command('C') + + def _command(self, c): + if self._uselm75b: + with open(os.path.join(self._epd_path, 'temperature'), 'wb') as f: + f.write(b(repr(self._lm75b.getTempC()))) + with open(os.path.join(self._epd_path, 'command'), 'wb') as f: + f.write(b(c)) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py new file mode 100644 index 00000000..f3087f2b --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/papirus/lm75b.py @@ -0,0 +1,46 @@ +# Minimal support for LM75b temperature sensor on the Papirus HAT / Papirus Zero +# This module allows you to read the temperature. +# The OS-output (Over-temperature Shutdown) connected to GPIO xx (pin 11) is not supported +# by this module +# + +from __future__ import (print_function, division) + +import smbus + +LM75B_ADDRESS = 0x48 + +LM75B_TEMP_REGISTER = 0 +LM75B_CONF_REGISTER = 1 +LM75B_THYST_REGISTER = 2 +LM75B_TOS_REGISTER = 3 + +LM75B_CONF_NORMAL = 0 + +class LM75B(object): + def __init__(self, address=LM75B_ADDRESS, busnum=1): + self._address = address + self._bus = smbus.SMBus(busnum) + self._bus.write_byte_data(self._address, LM75B_CONF_REGISTER, LM75B_CONF_NORMAL) + + def getTempCFloat(self): + """Return temperature in degrees Celsius as float""" + raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF + raw = ((raw << 8) & 0xFF00) + (raw >> 8) + return (raw / 32.0) / 8.0 + + def getTempFFloat(self): + """Return temperature in degrees Fahrenheit as float""" + return (self.getTempCFloat() * (9.0 / 5.0)) + 32.0 + + def getTempC(self): + """Return temperature in degrees Celsius as integer, so it can be + used to write to /dev/epd/temperature""" + raw = self._bus.read_word_data(self._address, LM75B_TEMP_REGISTER) & 0xFFFF + raw = ((raw << 8) & 0xFF00) + (raw >> 8) + return (raw + 128) // 256 # round to nearest integer + +if __name__ == "__main__": + sens = LM75B() + print(sens.getTempC(), sens.getTempFFloat()) + diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt b/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt index 9b0d40d5..0a82ef71 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt +++ b/sdcard/rootfs/root/pwnagotchi/scripts/requirements.txt @@ -9,3 +9,4 @@ tweepy file_read_backwards numpy inky +smbus From 52ab525e9fc792c45919dd7f47644f46cd4398b1 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Mon, 30 Sep 2019 20:54:05 +0200 Subject: [PATCH 04/54] fixed bogus refresh policies that caused issues with waveshare displays --- sdcard/rootfs/root/pwnagotchi/config.yml | 2 - .../scripts/pwnagotchi/ui/display.py | 47 ++++++------------- .../pwnagotchi/ui/waveshare/v2/waveshare.py | 2 +- 3 files changed, 16 insertions(+), 35 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 1fb846e8..bc914a67 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -98,8 +98,6 @@ ui: type: 'waveshare_2' # Possible options red/yellow/black (black used for monocromatic displays) color: 'black' - # How often to do a full refresh 0 all the time, -1 never - refresh: 50 video: enabled: true address: '10.0.0.2' diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index c530caae..c9d72c47 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -1,7 +1,7 @@ import _thread from threading import Lock -import io +import shutil import core import os import pwnagotchi @@ -13,7 +13,6 @@ from http.server import BaseHTTPRequestHandler, HTTPServer class VideoHandler(BaseHTTPRequestHandler): _lock = Lock() - _buffer = None _index = """ %s @@ -36,36 +35,31 @@ class VideoHandler(BaseHTTPRequestHandler): @staticmethod def render(img): with VideoHandler._lock: - writer = io.BytesIO() - img.save(writer, format='PNG') - VideoHandler._buffer = writer.getvalue() + img.save("/root/pwnagotchi.png", format='PNG') def log_message(self, format, *args): return - def _w(self, data): - try: - self.wfile.write(data) - except: - pass - def do_GET(self): - if self._buffer is None: - self.send_response(404) - - elif self.path == '/': + if self.path == '/': self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() - self._w(bytes(self._index % (pwnagotchi.name(), 1000), "utf8")) + try: + self.wfile.write(bytes(self._index % (pwnagotchi.name(), 1000), "utf8")) + except: + pass elif self.path.startswith('/ui'): with self._lock: self.send_response(200) self.send_header('Content-type', 'image/png') - self.send_header('Content-length', '%d' % len(self._buffer)) self.end_headers() - self._w(self._buffer) + try: + with open("/root/pwnagotchi.png", 'rb') as fp: + shutil.copyfileobj(fp, self.wfile) + except: + pass else: self.send_response(404) @@ -80,8 +74,6 @@ class Display(View): self._video_address = config['ui']['display']['video']['address'] self._display_type = config['ui']['display']['type'] self._display_color = config['ui']['display']['color'] - self.full_refresh_count = 0 - self.full_refresh_trigger = config['ui']['display']['refresh'] self._render_cb = None self._display = None @@ -139,7 +131,7 @@ class Display(View): self._display.Clear(0xFF) self._display.init(self._display.lut_partial_update) self._render_cb = self._waveshare_render - + elif self._is_waveshare2(): from pwnagotchi.ui.waveshare.v2.waveshare import EPD # core.log("display module started") @@ -148,7 +140,7 @@ class Display(View): self._display.Clear(WHITE) self._display.init(self._display.PART_UPDATE) self._render_cb = self._waveshare_render - + else: core.log("unknown display type %s" % self._display_type) @@ -198,24 +190,15 @@ class Display(View): def _waveshare_render(self): buf = self._display.getbuffer(self.canvas) if self._is_waveshare1: - if self.full_refresh_trigger >= 0 and self.full_refresh_count == self.full_refresh_trigger: - self._display.Clear(0x00) self._display.display(buf) elif self._is_waveshare2: - if self.full_refresh_trigger >= 0 and self.full_refresh_count == self.full_refresh_trigger: - self._display.Clear(BLACK) self._display.displayPartial(buf) - self._display.sleep() - if self.full_refresh_trigger >= 0 and self.full_refresh_count == self.full_refresh_trigger: - self.full_refresh_count = 0 - elif self.full_refresh_trigger >= 0: - self.full_refresh_count += 1 def _on_view_rendered(self, img): # core.log("display::_on_view_rendered") VideoHandler.render(img) if self._enabled: - self.canvas = img if self._rotation == 0 else img.rotate(self._rotation) + self.canvas = (img if self._rotation == 0 else img.rotate(self._rotation)) if self._render_cb is not None: self._render_cb() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/waveshare.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/waveshare.py index 3286a3f5..6c3ed04a 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/waveshare.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v2/waveshare.py @@ -335,4 +335,4 @@ class EPD: self.send_data(0x01) delay_ms(100) - ### END OF FILE ### + ### END OF FILE ### \ No newline at end of file From b60383786288b147b5a9e0daeef0c76d7a81b07d Mon Sep 17 00:00:00 2001 From: Justin-p Date: Mon, 30 Sep 2019 20:58:48 +0200 Subject: [PATCH 05/54] size fixes --- .../pwnagotchi/locale/nl/LC_MESSAGES/voice.mo | Bin 3939 -> 3938 bytes .../pwnagotchi/locale/nl/LC_MESSAGES/voice.po | 28 +++++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo index 7d88419e29c37f8c9fe56292a864093d6da151be..e30eec4f495793f8aecbedeac227239e6a0e5434 100644 GIT binary patch delta 328 zcmXZXKWhR(5QpJ8L4vp5`3Ds>E2i)r3;2mk{KYyh z;v)Lq4)bVRB1NoX7WW+L=4RWSx*z0@ delta 326 zcmXZXF-SsD6vpxM0*SouJ}XSj^6|hD(ya!;*HF-)tBXrh5N=K`LZGAj1)E!H4I0}b zaByjH2q7Mdb4XK?*#Cmd`F-aMhjS+W)PMeSI)@_CRw4=PV}Osig9F^hPyE0iEa1B< zlErUKqt+rB%;O$jVhZbM_cYgi7q{r|@eCidbmV|AVvxr<`k3}ajnDy zIec2rhiDIpa2J2k?s55wC`F868SOzAxQ(^M%VHzibOJMuSE 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 a74cf4b2..6f57f6d7 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 @@ -26,7 +26,8 @@ msgid "" "Hi, I'm Pwnagotchi!\n" "Starting ..." msgstr "" -"Hoi, Ik ben Pwnagotchi!\n" +"Hoi, Ik ben\n" +"Pwnagotchi!\n" "Opstarten ..." #: voice.py:22 @@ -34,7 +35,8 @@ msgid "" "New day, new hunt,\n" "new pwns!" msgstr "" -"Nieuwe dag, nieuwe jacht,\n" +"Nieuwe dag,\n" +"nieuwe jacht,\n" "nieuwe pwns!" #: voice.py:23 @@ -50,7 +52,7 @@ msgid "" "The neural network\n" "is ready." msgstr "" -"Het neuraal netwerk\n" +"Neuraal netwerk\n" "is klaar voor gebruik." #: voice.py:39 @@ -86,11 +88,13 @@ msgstr "Kut dag :/" #: voice.py:58 msgid "I'm extremely bored ..." -msgstr "Ik verveel me de pleuris ..." +msgstr "Ik verveel me \n" +"de pleuris ..." #: voice.py:59 msgid "I'm very sad ..." -msgstr "Ik ben erg verdrietig ..." +msgstr "Ik ben erg\n" +"verdrietig ..." #: voice.py:60 msgid "I'm sad" @@ -98,7 +102,8 @@ msgstr "Ik ben verdrietig" #: voice.py:66 msgid "I'm living the life!" -msgstr "Beter kan het leven niet worden!" +msgstr "Beter kan het leven\n" +"niet worden!" #: voice.py:67 msgid "I pwn therefore I am." @@ -121,7 +126,8 @@ msgid "" "curiosity ..." msgstr "" "Mijn enigiste misdrijf\n" -"is mijn nieuwsgierigheid ..." +"is mijn \n" +"nieuwsgierigheid ..." #: voice.py:75 #, python-brace-format @@ -236,7 +242,8 @@ msgid "" msgstr "" "Hey\n" "{what}\n" -"Laten we matties worden!" +"Laten we matties\n" +"worden!" #: voice.py:122 #, python-brace-format @@ -263,7 +270,8 @@ msgid "" "needs no WiFi!" msgstr "Ik vind dat\n" "{mac}\n" -"genoeg WiFi heeft gehad!" +"genoeg WiFi\n" +"heeft gehad!" #: voice.py:129 #, python-brace-format @@ -299,7 +307,7 @@ msgid "" "went wrong ...\n" "Rebooting ..." msgstr "" -"Ops, iets" +"Oops, iets" "ging fout ...\n" "Rebooting ..." From 26abbf51d65e5c987474b6fe65adf1587c64e303 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Mon, 30 Sep 2019 21:22:01 +0200 Subject: [PATCH 06/54] more fixes --- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 2 +- .../pwnagotchi/scripts/pwnagotchi/agent.py | 2 +- .../pwnagotchi/scripts/pwnagotchi/ai/train.py | 43 ++++++++++--------- .../scripts/pwnagotchi/mesh/advertise.py | 39 ----------------- .../scripts/pwnagotchi/mesh/utils.py | 42 ++++++++++++++++++ .../scripts/pwnagotchi/ui/display.py | 12 +++--- 6 files changed, 72 insertions(+), 68 deletions(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index de44012a..dcb6c210 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -24,7 +24,7 @@ args = parser.parse_args() if args.do_clear: print("clearing the display ...") - from pwnagotchi.ui.waveshare import EPD + from pwnagotchi.ui.waveshare.v2.waveshare import EPD epd = EPD() epd.init(epd.FULL_UPDATE) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index f8f1c411..1fa5112b 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 core from bettercap.client import Client -from pwnagotchi.mesh.advertise import AsyncAdvertiser +from pwnagotchi.mesh.utils import AsyncAdvertiser from pwnagotchi.ai.train import AsyncTrainer RECOVERY_DATA_FILE = '/root/.pwnagotchi-recovery' diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py index 97e9a6df..917815dd 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py @@ -142,28 +142,29 @@ class AsyncTrainer(object): def _ai_worker(self): self._model = ai.load(self._config, self, self._epoch) - self.on_ai_ready() + if self._model: + self.on_ai_ready() - epochs_per_episode = self._config['ai']['epochs_per_episode'] + epochs_per_episode = self._config['ai']['epochs_per_episode'] - obs = None - while True: - self._model.env.render() - # enter in training mode? - if random.random() > self._config['ai']['laziness']: - core.log("[ai] learning for %d epochs ..." % epochs_per_episode) - try: - self.set_training(True, epochs_per_episode) - self._model.learn(total_timesteps=epochs_per_episode, callback=self.on_ai_training_step) - except Exception as e: - core.log("[ai] error while training: %s" % e) - finally: - self.set_training(False) + obs = None + while True: + self._model.env.render() + # enter in training mode? + if random.random() > self._config['ai']['laziness']: + core.log("[ai] learning for %d epochs ..." % epochs_per_episode) + try: + self.set_training(True, epochs_per_episode) + self._model.learn(total_timesteps=epochs_per_episode, callback=self.on_ai_training_step) + except Exception as e: + core.log("[ai] error while training: %s" % e) + finally: + self.set_training(False) + obs = self._model.env.reset() + # init the first time + elif obs is None: obs = self._model.env.reset() - # init the first time - elif obs is None: - obs = self._model.env.reset() - # run the inference - action, _ = self._model.predict(obs) - obs, _, _, _ = self._model.env.step(action) + # run the inference + action, _ = self._model.predict(obs) + obs, _, _, _ = self._model.env.step(action) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py index c5313ebb..9d5c788d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/advertise.py @@ -5,10 +5,8 @@ import threading from scapy.all import Dot11, Dot11FCS, Dot11Elt, RadioTap, sendp, sniff import core -import pwnagotchi import pwnagotchi.ui.faces as faces -from pwnagotchi.mesh import get_identity import pwnagotchi.mesh.wifi as wifi from pwnagotchi.mesh import new_session_id from pwnagotchi.mesh.peer import Peer @@ -181,40 +179,3 @@ class Advertiser(object): for ident in stale: del self._peers[ident] - - -class AsyncAdvertiser(object): - def __init__(self, config, view): - self._config = config - self._view = view - self._public_key, self._identity = get_identity(config) - self._advertiser = None - - def start_advertising(self): - _thread.start_new_thread(self._adv_worker, ()) - - def _adv_worker(self): - # this will take some time due to scapy being slow to be imported ... - from pwnagotchi.mesh.advertise import Advertiser - - self._advertiser = Advertiser( - self._config['main']['iface'], - pwnagotchi.name(), - pwnagotchi.version, - self._identity, - period=0.3, - data=self._config['personality']) - - self._advertiser.on_peer(self._on_new_unit, self._on_lost_unit) - - if self._config['personality']['advertise']: - self._advertiser.start() - self._view.on_state_change('face', self._advertiser.on_face_change) - else: - core.log("advertising is disabled") - - def _on_new_unit(self, peer): - self._view.on_new_peer(peer) - - def _on_lost_unit(self, peer): - self._view.on_lost_peer(peer) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py new file mode 100644 index 00000000..c99cd578 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py @@ -0,0 +1,42 @@ +import _thread + +import core +import pwnagotchi +from pwnagotchi.mesh import get_identity + + +class AsyncAdvertiser(object): + def __init__(self, config, view): + self._config = config + self._view = view + self._public_key, self._identity = get_identity(config) + self._advertiser = None + + def start_advertising(self): + _thread.start_new_thread(self._adv_worker, ()) + + def _adv_worker(self): + # this will take some time due to scapy being slow to be imported ... + from pwnagotchi.mesh.advertise import Advertiser + + self._advertiser = Advertiser( + self._config['main']['iface'], + pwnagotchi.name(), + pwnagotchi.version, + self._identity, + period=0.3, + data=self._config['personality']) + + self._advertiser.on_peer(self._on_new_unit, self._on_lost_unit) + + if self._config['personality']['advertise']: + self._advertiser.start() + self._view.on_state_change('face', self._advertiser.on_face_change) + else: + core.log("advertising is disabled") + + def _on_new_unit(self, peer): + self._view.on_new_peer(peer) + + def _on_lost_unit(self, peer): + self._view.on_lost_peer(peer) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index c9d72c47..4c693a69 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -111,12 +111,14 @@ class Display(View): def _init_display(self): if self._is_inky(): + core.log("initializing inky display") from inky import InkyPHAT self._display = InkyPHAT(self._display_color) self._display.set_border(InkyPHAT.BLACK) self._render_cb = self._inky_render elif self._is_papirus(): + core.log("initializing papirus display") from pwnagotchi.ui.papirus.epd import EPD os.environ['EPD_SIZE'] = '2.0' self._display = EPD() @@ -124,8 +126,8 @@ class Display(View): self._render_cb = self._papirus_render elif self._is_waveshare1(): + core.log("initializing waveshare v1 display") from pwnagotchi.ui.waveshare.v1.epd2in13 import EPD - # core.log("display module started") self._display = EPD() self._display.init(self._display.lut_full_update) self._display.Clear(0xFF) @@ -133,8 +135,8 @@ class Display(View): self._render_cb = self._waveshare_render elif self._is_waveshare2(): + core.log("initializing waveshare v2 display") from pwnagotchi.ui.waveshare.v2.waveshare import EPD - # core.log("display module started") self._display = EPD() self._display.init(self._display.FULL_UPDATE) self._display.Clear(WHITE) @@ -146,8 +148,6 @@ class Display(View): self.on_render(self._on_view_rendered) - core.log("display type '%s' initialized (color:%s)" % (self._display_type, self._display_color)) - def image(self): img = None if self.canvas is not None: @@ -189,9 +189,9 @@ class Display(View): def _waveshare_render(self): buf = self._display.getbuffer(self.canvas) - if self._is_waveshare1: + if self._is_waveshare1(): self._display.display(buf) - elif self._is_waveshare2: + elif self._is_waveshare2(): self._display.displayPartial(buf) def _on_view_rendered(self, img): From 0c98705ab7e41ac93432d004c8ea0dc57a8a0dbf Mon Sep 17 00:00:00 2001 From: Justin-p Date: Mon, 30 Sep 2019 21:47:49 +0200 Subject: [PATCH 07/54] update config and readme with new locale --- README.md | 1 + sdcard/rootfs/root/pwnagotchi/config.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f5687947..121a1f63 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,7 @@ Pwnagotchi is able to speak multiple languages!! Currently supported are: * **english** (default) * german +* dutch 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/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index bc914a67..fc9dcae3 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 + # currently implemented: en (default), de, nl lang: en # monitor interface to use iface: mon0 From 11501bed2f3b9a0f6fb923d92d96884ed31e9e1d Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Mon, 30 Sep 2019 21:59:33 +0200 Subject: [PATCH 08/54] macos connection share script --- README.md | 2 +- scripts/macos_connection_share.sh | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100755 scripts/macos_connection_share.sh diff --git a/README.md b/README.md index f5687947..da6fc3e5 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ usage: ./scripts/create_sibling.sh [OPTIONS] #### 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` 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. +If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/(linux|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. ### UI diff --git a/scripts/macos_connection_share.sh b/scripts/macos_connection_share.sh new file mode 100755 index 00000000..2528067b --- /dev/null +++ b/scripts/macos_connection_share.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +# name of the ethernet gadget interface on the host +USB_IFACE=${1:-en8} +# host interface to use for upstream connection +UPSTREAM_IFACE=${2:-en7} + +sysctl -w net.inet.ip.forwarding=1 +pfctl -e +echo "nat on ${UPSTREAM_IFACE} from ${USB_IFACE}:network to any -> (${UPSTREAM_IFACE})" | pfctl -f - From fd0a50cbf92cb5190205bb5033969e7a626ae1ab Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Mon, 30 Sep 2019 22:49:57 +0200 Subject: [PATCH 09/54] Fix too long text --- .../pwnagotchi/locale/de/LC_MESSAGES/voice.mo | Bin 3919 -> 3905 bytes .../pwnagotchi/locale/de/LC_MESSAGES/voice.po | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) 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 dcede010ed742768694a1053e34ad36b57502e97..e78a76aaf3c5ec299261cd9a855b3e47be7f7af1 100644 GIT binary patch delta 226 zcmXZWI|{-;6oui#fJGq22fon|Fkow8CDx+7t(8Uu!3C&b=QiAd2q~;A#0A)-Z~|qW^Si~7RxIw#ThXp)f zfY-kd?2uEQM5`{^djn5>)oI2ILR_JJXpaG&(0=5Od3<9HP3D&ym?gL4mq{FFIGG32 LXt{{u#9f;&nyVVV delta 240 zcmXZWuL{CY6vy$y+F;KAPKS&I!C(@!8fEwZ_RU>X1cR;_tYY>x1YuQ!L8}NpgJ9Jx z_?-%e`#HbM;ofs}F3zr|E!!e;FhnSMaa2%JA|FdC~+P2;n%&^{P{AcOz_ diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po index c85e2547..95393cb1 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/de/LC_MESSAGES/voice.po @@ -267,7 +267,7 @@ msgid "" "{mac}\n" "needs no WiFi!" msgstr "" -"Habe gerade entschieden,\n" +"Ich denke,\n" "dass {mac}\n" "kein WiFi brauch!" From 09f11badf287d9f2c7f2b5a0dc3743a4e2418609 Mon Sep 17 00:00:00 2001 From: Justin-p Date: Mon, 30 Sep 2019 22:51:19 +0200 Subject: [PATCH 10/54] Fix a copy paste error. Make Pwnagotchi a tad more polite --- .../pwnagotchi/locale/nl/LC_MESSAGES/voice.mo | Bin 3938 -> 4012 bytes .../pwnagotchi/locale/nl/LC_MESSAGES/voice.po | 41 +++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/nl/LC_MESSAGES/voice.mo index e30eec4f495793f8aecbedeac227239e6a0e5434..5c0ae61cdde5edeb86419385ed94aa40983fa559 100644 GIT binary patch delta 1374 zcmZA0OKeP09LMo9I@KE5q8=TO_KbS8XdBOXEC>tQR3n6hO*7S#x}DCQX6AMpMY`}v zY!Jgj#KKC1c%%y=Y{UYwu%N+$kg#K6VIda2zuOxLC%N-E_uM<@{Qv)R?&tbj4Wl1s z#xEIK8`lD^i!o!iMx29(qVW-&&i#2@iq}x{J;M$71ufQ> z8&iv0koiWm zYnUW~%diGlV+HG*ZFEu$bf8`wKt+BMEndSF_yiT`cT@(yQSVK!oOrJV6+jm*M2DL1 z1nT`OI1le&HNL=d);I6yD1(pDgCDqqZHQ6#X^giMwldm}+NMl&e+8A{T~tQTaXG%j z#TcJz%sOnwCD@Hh;1nvb5{}NGbCZrHdW@QA94&rDJ+B~&Bqs3{u0bsnXEyz>EpjI+ z!!+uw979#)0xIJhs7gFQif3L{QU6tRUNbNsC-c@)T!i)5j*9#+l9V}%s>EenhPSa1 z$5Da&!Un7*3*E0lRkjlqSU2*D89|PZIa5RZS=*e89$ZB#AMQ7VK}a=CtjSbbwMAUo ze|-&VE4dVuz7}P#!>Vj`7AA2;ACzgKucXwH+J9xP=oFE%v|MT`otm~l`=zF=)QHn? zu)~AfgsOrP;pl`-FUnqK`yW(#9xRKHvc8x>m52A^mzR#TY6jFQ8w)QO3gL47KtdV IP+t_p9}e2JZvX%Q delta 1287 zcmY+@UucbS9LMqB?AV_(+nB!_<~M&fY>pH~(pYTGpG1iZ(qTW_b9Tvw*8p6~Db{XV~EWZwJQ+}oWiv!q*7f^{lL{;z-b>AnnII(0rfqGP&b*TGx zVGVj%fya^DO@LMGZ_elcF@kLc#@xY4tQV55Dw>STu>louH>$F3R3*o8DW1j!cn??M z2V8{JW#frAqn_J_>ewO7&1EvcM1jtt#j7|4A7M4V#%K5ywb28z({p2}fEBbw6*i#G zLJKPKJ*YT6`QJxTXXzZS#Nl%KKby%b7V7Z})?y8PQs!%rBFui&J58YO%b_a0l3#y< zO5`1?vhS!kWmLt~EJd|^4Jx5#)LGh5N&o41I22HuDv&mz*l_59KSN1qsQSimHr_c+ zwV^g!$feh(4K=jUyl^&NeI0XkRUL}x{r@|b<$v&%g|A{U#<R{?K)j`xN(a@{Y`Qg0sxwYGji+7CL$fn5Xv62@Br5k*|=b(50S|->R zT_0SE9w|=6vsusifi3HAIpF+k-1ekwhqGB{dk?2wI%e9tZNJO(JD0R6FJWV`|CgMN za(i#m^<_MN^m$pLptQBsCS7;8%LL8kiRLYb<0-qs_Bxj#YNtz^aAh#vml_IJ{rqy9 zOL@NUI_k_eFOjw`?R9#7Hh5Ehqi{=KHaJyLR~U~cgPRpwi<0rI%S3~w%FV@xdR*4` WT=2NWR_EttFda|1p=jsdfWHA02&Ccw 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 6f57f6d7..1f6e8325 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 @@ -52,7 +52,7 @@ msgid "" "The neural network\n" "is ready." msgstr "" -"Neuraal netwerk\n" +"Neuronen netwerk\n" "is klaar voor gebruik." #: voice.py:39 @@ -68,7 +68,7 @@ msgstr "" #: voice.py:44 msgid "I'm bored ..." -msgstr "Ik verveel mij ..." +msgstr "Ik verveel me ..." #: voice.py:45 msgid "Let's go for a walk!" @@ -84,12 +84,12 @@ msgstr "" #: voice.py:53 msgid "Shitty day :/" -msgstr "Kut dag :/" +msgstr "Ruk dag :/" #: voice.py:58 msgid "I'm extremely bored ..." msgstr "Ik verveel me \n" -"de pleuris ..." +"kapot ..." #: voice.py:59 msgid "I'm very sad ..." @@ -107,7 +107,7 @@ msgstr "Beter kan het leven\n" #: voice.py:67 msgid "I pwn therefore I am." -msgstr "Ik besta om de te pwnen." +msgstr "Ik pwn daarom besta ik." #: voice.py:68 msgid "So many networks!!!" @@ -119,13 +119,12 @@ msgid "" "fun!" msgstr "Dit is zo leuk!" - #: voice.py:70 msgid "" "My crime is that of\n" "curiosity ..." msgstr "" -"Mijn enigiste misdrijf\n" +"Mijn enige misdrijf\n" "is mijn \n" "nieuwsgierigheid ..." @@ -145,9 +144,11 @@ msgstr "" msgid "" "Unit\n" "{name}\n" -"is dichtbij! {name}" +"is nearby! {name}" msgstr "" -"" +"Unit\n" +"{name}\n" +"is dichtbij! {name}" #: voice.py:81 #, python-brace-format @@ -157,7 +158,7 @@ msgid "" "{name}" msgstr "" "Uhm ...\n" -"later\n" +"tot ziens\n" "{name}" #: voice.py:82 @@ -167,7 +168,7 @@ msgid "" "is gone ..." msgstr "" "{name}\n" -"is foetsie" +"is weg" #: voice.py:87 #, python-brace-format @@ -178,7 +179,7 @@ msgid "" msgstr "" "Whoopsie ...\n" "{name}\n" -"is foetsie" +"is weg" #: voice.py:88 #, python-brace-format @@ -187,11 +188,11 @@ msgid "" "missed!" msgstr "" "{name}\n" -"gemissed!" +"gemist!" #: voice.py:89 msgid "Missed!" -msgstr "Gemissed!" +msgstr "Gemist!" #: voice.py:94 msgid "" @@ -242,7 +243,7 @@ msgid "" msgstr "" "Hey\n" "{what}\n" -"Laten we matties\n" +"Laten we vrienden\n" "worden!" #: voice.py:122 @@ -251,7 +252,7 @@ msgid "" "Associating to\n" "{what}" msgstr "" -"Associëren met\n" +"Verbinden met\n" "{what}" #: voice.py:123 @@ -279,7 +280,7 @@ msgid "" "Deauthenticating\n" "{mac}" msgstr "" -"Deautoriseren\n" +"De-autoriseren\n" "{mac}" #: voice.py:130 @@ -290,7 +291,7 @@ msgid "" msgstr "" "Ik ga\n" "{mac}\n" -"FF lekker kicken!" +"even kicken!" #: voice.py:135 #, python-brace-format @@ -328,12 +329,12 @@ msgstr "{num} nieuwe handshakes\n" #: voice.py:147 msgid "Met 1 peer" -msgstr "Kwam 1 peer tegen" +msgstr "1 peer ontmoet" #: voice.py:149 #, python-brace-format msgid "Met {num} peers" -msgstr "Kwam {num} peers tegen" +msgstr "{num} peers ontmoet" #: voice.py:154 #, python-brace-format From a15d06b5697a3957dbe0fd0265a0644c657c10cf Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Mon, 30 Sep 2019 23:28:42 +0200 Subject: [PATCH 11/54] Add some forgotten selfs --- .../root/pwnagotchi/scripts/pwnagotchi/voice.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py index 3ff9e0ef..45f5092d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py @@ -37,11 +37,11 @@ class Voice: '...']) - def on_free_channel(channel): + def on_free_channel(self, channel): return self._('Hey, channel {channel} is\nfree! Your AP will\nsay thanks.').format(channel=channel) - def on_bored(): + def on_bored(self): return random.choice([ \ self._('I\'m bored ...'), self._('Let\'s go for a walk!')]) @@ -98,7 +98,7 @@ class Voice: self._('Where\'s everybody?!')]) - def on_napping(self,secs): + def on_napping(self, secs): return random.choice([ \ self._('Napping for {secs}s ...').format(secs=secs), self._('Zzzzz'), @@ -109,14 +109,14 @@ class Voice: return random.choice(['...', '!']) - def on_waiting(self,secs): + def on_waiting(self, secs): return random.choice([ \ self._('Waiting for {secs}s ...').format(secs=secs), '...', self._('Looking around ({secs}s)').format(secs=secs)]) - def on_assoc(self,ap): + def on_assoc(self, ap): ssid, bssid = ap['hostname'], ap['mac'] what = ssid if ssid != '' and ssid != '' else bssid return random.choice([ \ @@ -132,7 +132,7 @@ class Voice: self._('Kickbanning\n{mac}!').format(mac=sta['mac'])]) - def on_handshakes(self,new_shakes): + def on_handshakes(self, new_shakes): s = 's' if new_shakes > 1 else '' return self._('Cool, we got {num}\nnew handshake{plural}!').format(num=new_shakes, plural=s) @@ -141,7 +141,7 @@ class Voice: return self._("Ops, something\nwent wrong ...\nRebooting ...") - def on_log(self,log): + def on_log(self, log): status = self._('Kicked {num} stations\n').format(num=log.deauthed) status += self._('Made {num} new friends\n').format(num=log.associated) status += self._('Got {num} handshakes\n').format(num=log.handshakes) @@ -152,7 +152,7 @@ class Voice: return status - def on_log_tweet(self,log): + def on_log_tweet(self, log): return self._('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').format( duration=log.duration_human, deauthed=log.deauthed, From 21730a82cbf6871347df384fd07ee947cb07a2e9 Mon Sep 17 00:00:00 2001 From: IncredInComp Date: Tue, 1 Oct 2019 00:05:04 -0700 Subject: [PATCH 12/54] Update create_sibling.sh added ../ to help new users to find the .img after creation. command tested to work to burn image, though I use sudo --- 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 5ae58ef4..c69ff848 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -283,4 +283,4 @@ fi setup_raspbian provision_raspbian -echo -ne "[+] Congratz, it's a boy (⌐■_■)!\n[+] One more step: dd if=$PWNI_OUTPUT of= bs=4M status=progress" +echo -ne "[+] Congratz, it's a boy (⌐■_■)!\n[+] One more step: dd if=../$PWNI_OUTPUT of= bs=4M status=progress" From 9620894b43c9758d8a10715f6df10db631f8305d Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Tue, 1 Oct 2019 11:29:11 +0200 Subject: [PATCH 13/54] fix: safer nn saving --- .../pwnagotchi/scripts/pwnagotchi/ai/train.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py index 917815dd..9bcefade 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py @@ -66,8 +66,8 @@ class Stats(object): def save(self): with self._lock: core.log("[ai] saving %s" % self.path) - with open(self.path, 'wt') as fp: - json.dump({ + + data = json.dumps({ 'born_at': self.born_at, 'epochs_lived': self.epochs_lived, 'epochs_trained': self.epochs_trained, @@ -75,7 +75,13 @@ class Stats(object): 'best': self.best_reward, 'worst': self.worst_reward } - }, fp) + }) + + temp = ".%s.tmp" % self.path + with open(temp, 'wt') as fp: + fp.write(data) + + os.replace(temp, self.path) class AsyncTrainer(object): @@ -103,7 +109,9 @@ class AsyncTrainer(object): def _save_ai(self): core.log("[ai] saving model to %s ..." % self._nn_path) - self._model.save(self._nn_path) + temp = "%.%s.tmp" % self._nn_path + self._model.save(temp) + os.replace(temp, self._nn_path) def on_ai_step(self): self._model.env.render() From 2bc485023a0ab6e3eb5de2314ab6bae680f29280 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Mon, 30 Sep 2019 11:21:15 +0200 Subject: [PATCH 14/54] Add pwnagotchi preview --- scripts/language.sh | 1 + scripts/preview.py | 157 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+) create mode 100755 scripts/preview.py diff --git a/scripts/language.sh b/scripts/language.sh index c56b7847..cf653f50 100755 --- a/scripts/language.sh +++ b/scripts/language.sh @@ -55,6 +55,7 @@ function update_lang() { msgmerge --update "$LOCALE_DIR/$1/LC_MESSAGES/voice.po" "$LOCALE_DIR/voice.pot" } + case "$1" in add) add_lang "$2" diff --git a/scripts/preview.py b/scripts/preview.py new file mode 100755 index 00000000..47afd7d3 --- /dev/null +++ b/scripts/preview.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 + +import sys +import os +import time +import argparse +import random +from http.server import HTTPServer +import shutil +import yaml +sys.path.insert(0, + os.path.join(os.path.dirname(os.path.realpath(__file__)), + '../sdcard/rootfs/root/pwnagotchi/scripts/')) + +from pwnagotchi.ui.view import View +from pwnagotchi.ui.display import Display, VideoHandler +import core + +class CustomDisplay(Display): + + def _http_serve(self): + if self._video_address is not None: + self._httpd = HTTPServer((self._video_address, self._video_port), + CustomVideoHandler) + core.log("ui available at http://%s:%d/" % (self._video_address, + self._video_port)) + self._httpd.serve_forever() + else: + core.log("could not get ip of usb0, video server not starting") + + + def _on_view_rendered(self, img): + CustomVideoHandler.render(img) + + if self._enabled: + self.canvas = (img if self._rotation == 0 else img.rotate(self._rotation)) + if self._render_cb is not None: + self._render_cb() + + +class CustomVideoHandler(VideoHandler): + + @staticmethod + def render(img): + with CustomVideoHandler._lock: + img.save("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), format='PNG') + + def do_GET(self): + if self.path == '/': + self.send_response(200) + self.send_header('Content-type', 'text/html') + self.end_headers() + try: + self.wfile.write( + bytes( + self._index % + ('localhost', 1000), "utf8")) + except BaseException: + pass + + elif self.path.startswith('/ui'): + with self._lock: + self.send_response(200) + self.send_header('Content-type', 'image/png') + self.end_headers() + try: + with open("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), 'rb') as fp: + shutil.copyfileobj(fp, self.wfile) + except BaseException: + pass + else: + self.send_response(404) + + +class DummyPeer: + @staticmethod + def name(): + return "beta" + + +def main(): + parser = argparse.ArgumentParser(description="This program emulates\ + the pwnagotchi display") + parser.add_argument('--display', help="Which display to use.", + default="waveshare_2") + parser.add_argument('--port', help="Which port to use", + default=8080) + parser.add_argument('--sleep', type=int, help="Time between emotions", + default=2) + parser.add_argument('--lang', help="Language to use", + default="en") + args = parser.parse_args() + + CONFIG = yaml.load(''' + main: + lang: {lang} + ui: + fps: 0.3 + display: + enabled: false + rotation: 180 + color: black + refresh: 30 + type: {display} + video: + enabled: true + address: "127.0.0.1" + port: {port} + '''.format(display=args.display, + port=args.port, + lang=args.lang), + Loader=yaml.FullLoader) + + DISPLAY = CustomDisplay(config=CONFIG, state={'name': '%s>' % 'preview'}) + + while True: + DISPLAY.on_starting() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_ai_ready() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_normal() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_new_peer(DummyPeer()) + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_lost_peer(DummyPeer()) + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_free_channel('6') + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.wait(args.sleep) + DISPLAY.update() + DISPLAY.on_bored() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_sad() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_motivated(1) + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_demotivated(-1) + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_excited() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_deauth({'mac': 'DE:AD:BE:EF:CA:FE'}) + DISPLAY.update() + + +if __name__ == '__main__': + SystemExit(main()) From c9996e358e88185c27a11d4b1c072a962b2f4be9 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Tue, 1 Oct 2019 12:28:34 +0200 Subject: [PATCH 15/54] Update Readme --- README.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 66eba585..2179f692 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ usage: ./scripts/create_sibling.sh [OPTIONS] #### Host Connection Share -If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/(linux|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. +If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/linux_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. ### UI @@ -98,7 +98,6 @@ Pwnagotchi is able to speak multiple languages!! Currently supported are: * **english** (default) * german -* dutch 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: @@ -121,6 +120,14 @@ If you changed the `voice.py`- File, the translations need an update. Do it like # DONE ``` +Now you can use the `preview.py`-script to preview the changes: + +```shell +./scripts/preview.py --lang it --display ws2 --port 8080 & +./scripts/preview.py --lang it --display inky --port 8081 & +# Now open http://localhost:8080 and http://localhost:8081 +``` + ### Random Info - `hostname` sets the unit name. From cbc47ba8c8e6ea50da98918c0f12874c4d8af9f2 Mon Sep 17 00:00:00 2001 From: 5h4d0wb0y <5h4d0wb0y@protonmail.com> Date: Tue, 1 Oct 2019 14:43:06 +0200 Subject: [PATCH 16/54] added IT locale support --- README.md | 1 + sdcard/rootfs/root/pwnagotchi/config.yml | 2 +- .../pwnagotchi/locale/it/LC_MESSAGES/voice.mo | Bin 0 -> 4132 bytes .../pwnagotchi/locale/it/LC_MESSAGES/voice.po | 347 ++++++++++++++++++ 4 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.mo create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po diff --git a/README.md b/README.md index 66eba585..03b90626 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ Pwnagotchi is able to speak multiple languages!! Currently supported are: * **english** (default) * german * dutch +* italian 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/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index fc9dcae3..8da7bc94 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 + # currently implemented: en (default), de, nl, it lang: en # monitor interface to use iface: mon0 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 new file mode 100644 index 0000000000000000000000000000000000000000..038f502396ed0fadd68d779b6667f52c931b8329 GIT binary patch literal 4132 zcma);O^h5z701gElhBX=0nA4XRAUpzcxOCo2e3DBV6%?x1+TNQH(1UARMTBEQ{JAg zNq@{TyV?^%2q_nkA|!-_B|ypn2`fi9MHU~o9FY(~BI1A|PC!n%@O#xWvug+_t?l_u z*HpiH@BLrZ+dn^e&x?v{k^3O{&31)!jJI$J9sbr6BPS@g};Jt zLRshbdz5+*{sD?VZ$NqP055$U9)e=`B#hui_yKqo@~66d#PBARc`v|_2dH^|1)hMf zL-F&0`x^fbLz&ls8m>WEKZl=!-+^N9r%>YkHT)!e6^b8kzz@MU;REnql1xbI5R`Zh zLm58_uO1+8P~Q7KA7byvZ~@+i67OqJ*82yPJVozQ>htg+D1KgmkHG|f4*mqn{NF&) z;Wa4!{1bi}9(;e3zoSs>pM(6Qu0omr4fuOlL8+Z{BuCcqQ1bo))bQuU8{%5L4>!P;__;hB_jdxT+38WC*nYLXL!TiGSkLQF-9{EVrz2 zTpqaE+!6~ChTMrh;=9zzySS%YO`YVs4$_)nRIi!u&zbzqBIw3F*$ZnkRBSn?pbluK#|iU0drUe$#)>7=ce%hD&# zR4(u9%11j}15@p)74NeJy=8UZS9&L}hr3a3xAef|X*n>Pc4w5;g~@hfb>5n~8rZyY zNiY)a3{A4DF3#TDd#8-lC6jDwX6yCLeAr>o!Zv zFHDO$>R#b2-iVFKf=+NPx0&9Ve%aNojCzH&vA*H!LNBlDEth3cX(l*e z^3AfXF1ZE0dTglIw{kYcgf7 zo01n(_?lcivQyfm+%1o*HIouhFtIPxNUf2GMLn{%2w$5S@>r@hSC%%7)!IZSg&SJR zDmbovFG}jd`O;OBAj=gq8qL*cR&2&eYHBFauz~8lS_oT->`}W{eAlNF{6-qte&mZM zR}By+y#4g3T%cHxY9QIzLPNb(c%q{iqpP;-{k&YS4P1pYET)%Es%r>r@(IgUTfW#V z<2Y6uR99|g=gx*B;+dWV8w0+F@T9!TDiTA!r-zeiMLs(ihE@CCr`?I2Zd>(i?$9x8 zRI!#@Q*$CIP>c;G7iq&)5 z+x%_s(^VdylaKI&OxWI5cUuU_oDL1AnywfArcJ8WYTEibTC;hUbf?{EFOt`hFRIpB z*>`E{$+};*HvE!~)}L-&wPPnUTj$vvOZrr2@oa0c)9Nhh#YdMqofDl?olbPwlvQh^ zFnO7o$`?!e3xh|~&Q`ZG(T|@xvv~IOsm|FG^RchgC9Ah{j*n3`Y4=gT?zR&@d;&vx zzczi_+OTH0B>R1~;~qbKdhzU+zIb}^L~2qqeg`&|w5v?!OdhSRu06FE@nX9Zt@ym6 zvRWIH5kXa)T_>qTmp>-wYEjziTwV2AXZGevY&~1Fp2`!SQkYBnOqVK9tIK*sbyjBH zSc=4HGixhP+T1Q^)9pGl^vzC;^4gEx-pR7BvmleSCb5uWBJ`E@!j^8jhxbmVX=ibn z9uc6eOsrO%*=sE8&LotZPMuDC?n@pj_jcVSbz^B|;++|~gtI7g7YrvRHyNkLyuaLe zDau^e7M>$D(^c*1F;VJ@JGXSdFx!rz6(3~xarHiBG@t74@$A_w1bGi%*lDw^vBufx>DkS^Fv5PN-2|&Py6a~#&rFG|K;+a%6{n4l z)ip-P5-&?+hOd&gV5}-!S=r|M&}YnRMuNMSWcJw8Z9GTjU7g1wzLjoCwlY*B+o9{A zADYd3QLM3H@`S_4Q9pSlw)PqkeJGSf5I|c!2nSg|#QRRVku;`v(u~B3(a7c|bR^uy zp;7JnmYZi<~ zv|Zbmn8^9X+7u~W+mjBC3-sM0s*|E~tIk=%K@9 zpN)*Z^O6Kbc(N&)Ha4v}NBKEC2+D@z+6C3GAc@y~C+^Y8c#`lFBBq@Mxuy*bqc!i3 zYoFPO`H94g$TT$h_bK$V=WBB1OB3M-aZ4ppq6G*|%^5aG9A9U>&5GUGG4xE$*6, 2019. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-10-01 14:15+0200\n" +"PO-Revision-Date: 2019-10-01 14:00+0200\n" +"Last-Translator: 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>\n" +"Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" +"Language: italian\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:18 +msgid "ZzzzZZzzzzZzzz" +msgstr "ZzzzZZzzzzZzzz" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:23 +msgid "" +"Hi, I'm Pwnagotchi!\n" +"Starting ..." +msgstr "" +"Ciao, sono Pwnagotchi!\n" +"Avviamento ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:24 +msgid "" +"New day, new hunt,\n" +"new pwns!" +msgstr "" +"Nuovo giorno, nuova caccia,\n" +"nuovi pwns!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:25 +msgid "Hack the Planet!" +msgstr "Hack il pianeta!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:30 +msgid "AI ready." +msgstr "IA pronta." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:31 +msgid "" +"The neural network\n" +"is ready." +msgstr "" +"La rete neurale\n" +"è pronta." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:41 +#, python-brace-format +msgid "" +"Hey, channel {channel} is\n" +"free! Your AP will\n" +"say thanks." +msgstr "" +"Hey, il canale {channel} è\n" +"libero! Il tuo AP\n" +"dirà grazie." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:46 +msgid "I'm bored ..." +msgstr "Sono annoiato ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:47 +msgid "Let's go for a walk!" +msgstr "Andiamo a fare una \npasseggiata!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:51 +msgid "" +"This is the best\n" +"day of my life!" +msgstr "" +"Questo è il migliore\n" +"giorno della mia vita!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:55 +msgid "Shitty day :/" +msgstr "Giorno di merda :/" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:60 +msgid "I'm extremely bored ..." +msgstr "" +"Sono estremamente\n" +"annoiato ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:61 +msgid "I'm very sad ..." +msgstr "Sono molto triste ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:62 +msgid "I'm sad" +msgstr "Sono triste" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:68 +msgid "I'm living the life!" +msgstr "Sto vivendo la vita!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:69 +msgid "I pwn therefore I am." +msgstr "Possiedo quindi sono." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:70 +msgid "So many networks!!!" +msgstr "Così tante reti!!!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:71 +msgid "" +"I'm having so much\n" +"fun!" +msgstr "" +"Mi sto divertendo\n" +"tanto!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:72 +msgid "" +"My crime is that of\n" +"curiosity ..." +msgstr "" +"La mia colpa è di\n" +"essere curioso ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:77 +#, python-brace-format +msgid "" +"Hello\n" +"{name}!\n" +"Nice to meet you. {name}" +msgstr "" +"Ciao\n" +"{name}!\n" +"Piacere di conoscerti. {name}" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:78 +#, python-brace-format +msgid "" +"Unit\n" +"{name}\n" +"is nearby! {name}" +msgstr "" +"L'Unità\n" +"{name}\n" +"è vicina! {name}" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:83 +#, python-brace-format +msgid "" +"Uhm ...\n" +"goodbye\n" +"{name}" +msgstr "" +"Uhm ...\n" +"addio\n" +"{name}" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:84 +#, python-brace-format +msgid "" +"{name}\n" +"is gone ..." +msgstr "" +"{name}\n" +"è andato ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:89 +#, python-brace-format +msgid "" +"Whoops ...\n" +"{name}\n" +"is gone." +msgstr "" +"Whoops ...\n" +"{name}\n" +"è andato." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:90 +#, python-brace-format +msgid "" +"{name}\n" +"missed!" +msgstr "" +"{name}\n" +"perso!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:91 +msgid "Missed!" +msgstr "Perso!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:96 +msgid "" +"Nobody wants to\n" +"play with me ..." +msgstr "" +"Nessuno vuole\n" +"giocare con me..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:97 +msgid "I feel so alone ..." +msgstr "Mi sento così solo ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:98 +msgid "Where's everybody?!" +msgstr "Dove sono tutti?!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:103 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Pisolino per {secs}i ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:104 +msgid "Zzzzz" +msgstr "Zzzzz" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:105 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "ZzzZzzz ({secs}i)" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:114 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "In attesa di {secs}i ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:116 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Guardando intorno ({secs}s)" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:123 +#, python-brace-format +msgid "" +"Hey\n" +"{what}\n" +"let's be friends!" +msgstr "" +"Hey\n" +"{what}\n" +"diventiamo amici!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:124 +#, python-brace-format +msgid "" +"Associating to\n" +"{what}" +msgstr "" +"Associarci a\n" +"{what}" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:125 +#, python-brace-format +msgid "" +"Yo\n" +"{what}!" +msgstr "" +"Yo\n" +"{what}!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:130 +#, python-brace-format +msgid "" +"Just decided that\n" +"{mac}\n" +"needs no WiFi!" +msgstr "" +"Ho appena deciso che\n" +"{mac}\n" +"non necessita di\n" +"WiFi!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:131 +#, python-brace-format +msgid "" +"Deauthenticating\n" +"{mac}" +msgstr "" +"Dissociarci da\n" +"{mac}" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:132 +#, python-brace-format +msgid "" +"Kickbanning\n" +"{mac}!" +msgstr "" +"Sto prendendo\n" +"a calci\n" +"{mac}!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:137 +#, python-brace-format +msgid "" +"Cool, we got {num}\n" +"new handshake{plural}!" +msgstr "" +"Bene, abbiamo {num}\n" +"nuovi handshake{plural}!" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:141 +msgid "" +"Ops, something\n" +"went wrong ...\n" +"Rebooting ..." +msgstr "" +"Ops, qualcosa\n" +"è andato storto ...\n" +"Riavvio ..." + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:145 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Calciate {num} stazioni\n" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:146 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "Fatti {num} nuovi amici\n" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:147 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Presi {num} handshakes\n" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:149 +msgid "Met 1 peer" +msgstr "Incontrato 1 peer" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:151 +#, python-brace-format +msgid "Met {num} peers" +msgstr "Incontrati {num} peers" + +#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:156 +#, 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 "" +"Ho lavorato per {duration} e preso a calci i clienti di {deauthed}! Ho anche " +"incontrato{associate} nuovi amici e ho mangiato {handshakes} handshakes! " +"#pwnagotchi#pwnlog #pwnlife #hacktheplanet #skynet" From 19c4b420724ce639987764bdacf4f8bdfc024a7f Mon Sep 17 00:00:00 2001 From: Panagiotis Vasilopoulos Date: Tue, 1 Oct 2019 16:26:14 +0000 Subject: [PATCH 17/54] Improved Greek translation files --- .../pwnagotchi/locale/gr/LC_MESSAGES/voice.mo | Bin 4750 -> 4763 bytes .../pwnagotchi/locale/gr/LC_MESSAGES/voice.po | 74 +++++++++--------- 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.mo index 434c3b8426a1ea2236573ce376eefaf58166c189..b2bf23d5864ca468cb0e46eddcc9738a6b8c708c 100644 GIT binary patch delta 1050 zcmYk)+e_177zglo2GV|;TZ#~Nd{?dm>fDw^&0OF`Q4x7j5OfivCJH)B6r(YAQm0^o z{V0P@QeJM_m{aDazpLn`p7*xHKM-}(O&38_-)EbVHy@w(@EqRXW}Q!*uV+lr8zv#t zb|D&s5bc@}2Vpn73VY!`Sb_)OXXt>xVKLNvkSkQ==W zcfdRF0!+Xb_#S%UPkXd7Nh?lW#KI8dLPf|g@d0+hU+@g{)mQfK!4Aapkk7q?T<|+Q z1{?649G`_eX&>APlh6eDkMB8i=54lGo5$Ve_DIhOpV!;scI!^_gPP!gUNT=ld9CeS zFccgPj0_F?WY19WR{x0fy1XurCTNkKNy?~kGN?c$T5}0{r6y>DRw$!)YF9c`itY6SQy2(G(8WAAoaZ}O zj#IAEo&?K0HWf6qjXNbZgP1Sl%sR@g;VIJPmYb>%LeFt)o!6TTJKLc*&c}7DEhXRAa2tM}$=Q^yC68U(KLFG*K10gGq ZQ#r1o{Ym^hFhJ$yr?!T){h!q#{sPLek?a5f delta 1027 zcmZXRT}YEr7{{OWWqaL+MuAb;Yqd zZ!Ab82x8OLoa=S7-9%UQoSPuJi=vAzqN}cg=>NQ16g1d==RBYP^WOvCJ>Rn_N92@) zNN*v@H==KtSm<@*a7x{6JQYh0UiJwT}0L3C2%Wv z8*Bh)z+K=g7exrO=o13F!Ec~6y4^&-z$WkmKwEN6%E8&xhH)f1f2F<#;o)oxs9>J0T>8R!gkg@^mP2m3?aBQ?Y``VJTHwNM?i zPX*Lxb(FIv0$Dw#-WkVCp648=c#Rh&h(5&`wm4y;u%P3Hsw)qc8N)-Jq3a{6ulz%; zj73Y17fsINxQ6bRn4B{Gem|Wb>g9wU)sw2n)pjk8;*1{U=XQ(5t1{Q_*VA@6-<6lJ z^*4%ijuWU%LCa$H zA6a=lWp5V~blgOJ8tI&^D`jBh64JI__+7NY;v~#S+Xffy;yFmQFd|WWT>6W*ZrvbT zt=RHNo~g&=dB$*Ws3$yPpnn{qF~LtfFMDh8*o=v(_=yRiAX!`bziQ~eKHK$D6xRRq Fs^8G~jJp5; diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po index 2d21d99f..26a2511d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/gr/LC_MESSAGES/voice.po @@ -1,18 +1,17 @@ # pwnigotchi voice data # Copyright (C) 2019 # This file is distributed under the same license as the pwnagotchi package. -# FIRST AUTHOR <33197631+dadav@users.noreply.github.com>, 2019. +# FIRST AUTHOR Perilis Fregkos , 2019. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-09-29 13:42+0200\n" -"PO-Revision-Date: 2019-09-29 14:00+0200\n" -"Last-Translator: dadav <33197631+dadav@users.noreply.github.com>\n" +"PO-Revision-Date: 2019-10-01 16:22+0000\n" +"Last-Translator: Panos Vasilopoulos \n" "Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" -"Language: greek\n" +"Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -39,7 +38,7 @@ msgstr "" #: voice.py:23 msgid "Hack the Planet!" -msgstr "Hackαρε τον Πλανήτη!" +msgstr "Hackαρε τον πλανήτη!" #: voice.py:28 msgid "AI ready." @@ -70,7 +69,7 @@ msgstr "Βαριέμαι ..." #: voice.py:45 msgid "Let's go for a walk!" -msgstr "Πάμε μια βόλτα!" +msgstr "Ας πάμε μια βόλτα!" #: voice.py:49 msgid "" @@ -86,7 +85,7 @@ msgstr "Σκατένια μέρα :/" #: voice.py:58 msgid "I'm extremely bored ..." -msgstr "Βαριέμαι υπερβολικά πολύ ..." +msgstr "Βαριέμαι πάρα πολύ ..." #: voice.py:59 msgid "I'm very sad ..." @@ -94,15 +93,15 @@ msgstr "Είμαι πολύ λυπημένο ..." #: voice.py:60 msgid "I'm sad" -msgstr "Είμαι λυπημένο ..." +msgstr "Είμαι λυπημένο" #: voice.py:66 msgid "I'm living the life!" -msgstr "Το ζω!" +msgstr "Ζω την ζωή μου!" #: voice.py:67 msgid "I pwn therefore I am." -msgstr "Pwnάρω άρα υπάρχω." +msgstr "Pwnάρω, άρα υπάρχω." #: voice.py:68 msgid "So many networks!!!" @@ -112,15 +111,15 @@ msgstr "Τόσα πολλά δίκτυα!!!" msgid "" "I'm having so much\n" "fun!" -msgstr "Έχει πολύ πλάκα!" +msgstr "Περνάω τέλεια!" #: voice.py:70 msgid "" "My crime is that of\n" "curiosity ..." msgstr "" -"Το μόνο μου έγκλημα\n" -"είναι η περιέργεια ..." +"Η περιέργεια είναι\n" +"το μόνο έγκλημά μου ..." #: voice.py:75 #, python-brace-format @@ -129,8 +128,7 @@ msgid "" "{name}!\n" "Nice to meet you. {name}" msgstr "" -"Γειά σου\n" -"{name}!\n" +"Γειά {name}!\n" "Χάρηκα για τη γνωριμία. {name}" #: voice.py:76 @@ -161,7 +159,7 @@ msgid "" "{name}\n" "is gone ..." msgstr "" -"{name}\n" +"Το {name}\n" "έφυγε ..." #: voice.py:87 @@ -171,9 +169,9 @@ msgid "" "{name}\n" "is gone." msgstr "" -"Ουπς ...\n" -"{name}\n" -"έφυγε." +"Ουπς ... \n" +"Εξαφανίστηκε το\n" +"{name}." #: voice.py:88 #, python-brace-format @@ -181,12 +179,12 @@ msgid "" "{name}\n" "missed!" msgstr "" -"{name}\n" -"χάθηκε!" +"Έχασα το\n" +"{name}!" #: voice.py:89 msgid "Missed!" -msgstr "Χάθηκε!" +msgstr "Το έχασα!" #: voice.py:94 msgid "" @@ -198,16 +196,16 @@ msgstr "" #: voice.py:95 msgid "I feel so alone ..." -msgstr "Νιώθω πολλή μοναξία ..." +msgstr "Νιώθω μοναχός μου ..." #: voice.py:96 msgid "Where's everybody?!" -msgstr "Μα, πού πήγαν όλοι;!" +msgstr "Μα, πού πήγαν όλοi;!" #: voice.py:101 #, python-brace-format msgid "Napping for {secs}s ..." -msgstr "Κοιμάμαι για {secs}s ..." +msgstr "Ξεκουράζομαι για {secs}s ..." #: voice.py:102 msgid "Zzzzz" @@ -226,7 +224,7 @@ msgstr "Περιμένω για {secs}s ..." #: voice.py:114 #, python-brace-format msgid "Looking around ({secs}s)" -msgstr "Ψάχνω τριγύρω ({secs}s)" +msgstr "Ψάχνω τριγύρω ({secs})" #: voice.py:121 #, python-brace-format @@ -235,8 +233,8 @@ msgid "" "{what}\n" "let's be friends!" msgstr "" -"Εε\n" -"{what}\n" +"Εε!\n" +"{what},\n" "ας γίνουμε φίλοι!" #: voice.py:122 @@ -245,7 +243,7 @@ msgid "" "Associating to\n" "{what}" msgstr "" -"Συσχετίζομαι με το\n" +"Συνδέομαι με το\n" "{what}" #: voice.py:123 @@ -254,7 +252,7 @@ msgid "" "Yo\n" "{what}!" msgstr "" -"Που'σε ρε τρελέ'\n" +"Που'σ ρε τρελέ\n" "{what}!" #: voice.py:128 @@ -274,7 +272,7 @@ msgid "" "Deauthenticating\n" "{mac}" msgstr "" -"Αποπιστοποίηση της\n" +"Πετάω έξω την\n" "{mac}" #: voice.py:130 @@ -283,7 +281,7 @@ msgid "" "Kickbanning\n" "{mac}!" msgstr "" -"Κλωτσομπούνι στη\n" +"Μπανάρω την\n" "{mac}!" #: voice.py:135 @@ -293,7 +291,7 @@ msgid "" "new handshake{plural}!" msgstr "" "Τέλεια δικέ μου, πήραμε {num}\n" -"νέες handshake{plural}!" +"νέες χειραψίες{plural}!" #: voice.py:139 msgid "" @@ -322,19 +320,19 @@ msgstr "Πήρα {num} χειραψίες\n" #: voice.py:147 msgid "Met 1 peer" -msgstr "Γνώρισα 1 συνάδελφο" +msgstr "Γνώρισα 1 φίλο" #: voice.py:149 #, python-brace-format msgid "Met {num} peers" -msgstr "Γνώρισα {num} συναδέλφους" +msgstr "Γνώρισα {num} φίλους" #: voice.py:154 #, 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" +"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi #pwnlog " +"#pwnlife #hacktheplanet #skynet" msgstr "" "Pwnαρα για {duration} και έριξα {deauthed} πελάτες! Επίσης γνώρισα " "{associated} νέους φίλους και καταβρόχθισα {handshakes} χειραψίες! #pwnagotchi " From 33f9917b903f0263ef81803f090b225ce3a57872 Mon Sep 17 00:00:00 2001 From: Panagiotis Vasilopoulos Date: Tue, 1 Oct 2019 16:41:43 +0000 Subject: [PATCH 18/54] Exception handlers in preview script --- scripts/preview.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/preview.py b/scripts/preview.py index 47afd7d3..16e4079e 100755 --- a/scripts/preview.py +++ b/scripts/preview.py @@ -43,7 +43,10 @@ class CustomVideoHandler(VideoHandler): @staticmethod def render(img): with CustomVideoHandler._lock: - img.save("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), format='PNG') + try: + img.save("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), format='PNG') + except BaseException: + core.log("could not write preview") def do_GET(self): if self.path == '/': @@ -67,7 +70,7 @@ class CustomVideoHandler(VideoHandler): with open("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), 'rb') as fp: shutil.copyfileobj(fp, self.wfile) except BaseException: - pass + core.log("could not open preview") else: self.send_response(404) From b502912d7ffe6c9c567ba1b2e256cb25e8f362a7 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Tue, 1 Oct 2019 18:56:27 +0200 Subject: [PATCH 19/54] fixed preview script --- scripts/preview.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/scripts/preview.py b/scripts/preview.py index 16e4079e..8ca53594 100755 --- a/scripts/preview.py +++ b/scripts/preview.py @@ -4,31 +4,30 @@ import sys import os import time import argparse -import random from http.server import HTTPServer import shutil import yaml + sys.path.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), '../sdcard/rootfs/root/pwnagotchi/scripts/')) -from pwnagotchi.ui.view import View from pwnagotchi.ui.display import Display, VideoHandler import core + class CustomDisplay(Display): def _http_serve(self): if self._video_address is not None: self._httpd = HTTPServer((self._video_address, self._video_port), - CustomVideoHandler) + CustomVideoHandler) core.log("ui available at http://%s:%d/" % (self._video_address, self._video_port)) self._httpd.serve_forever() else: core.log("could not get ip of usb0, video server not starting") - def _on_view_rendered(self, img): CustomVideoHandler.render(img) @@ -44,9 +43,9 @@ class CustomVideoHandler(VideoHandler): def render(img): with CustomVideoHandler._lock: try: - img.save("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), format='PNG') + img.save("/tmp/pwnagotchi-{rand}.png".format(rand=id(CustomVideoHandler)), format='PNG') except BaseException: - core.log("could not write preview") + core.log("could not write preview") def do_GET(self): if self.path == '/': @@ -107,12 +106,11 @@ def main(): type: {display} video: enabled: true - address: "127.0.0.1" + address: "0.0.0.0" port: {port} '''.format(display=args.display, port=args.port, - lang=args.lang), - Loader=yaml.FullLoader) + lang=args.lang)) DISPLAY = CustomDisplay(config=CONFIG, state={'name': '%s>' % 'preview'}) From 7739ed805e98d36fdc7258dcc224d522ca719dac Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Tue, 1 Oct 2019 19:38:09 +0200 Subject: [PATCH 20/54] fix --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py index 9bcefade..bd1130b7 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py @@ -109,7 +109,7 @@ class AsyncTrainer(object): def _save_ai(self): core.log("[ai] saving model to %s ..." % self._nn_path) - temp = "%.%s.tmp" % self._nn_path + temp = ".%s.tmp" % self._nn_path self._model.save(temp) os.replace(temp, self._nn_path) From cfd3f6dbc0c4b51e44d14f5c34a1308f7580b26b Mon Sep 17 00:00:00 2001 From: nicesocket <56041912+nicesocket@users.noreply.github.com> Date: Tue, 1 Oct 2019 19:38:52 +0200 Subject: [PATCH 21/54] Make sure to clear with the correct parameters for the configured display The former versions always used the V2-Controls which effectively destroys V1-Boards. --- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index dcb6c210..10e0490e 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -24,12 +24,36 @@ args = parser.parse_args() if args.do_clear: print("clearing the display ...") - from pwnagotchi.ui.waveshare.v2.waveshare import EPD - - epd = EPD() - epd.init(epd.FULL_UPDATE) - epd.Clear(0xff) - quit() + with open(args.config, 'rt') as fp: + config = yaml.safe_load(fp) + 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() with open(args.config, 'rt') as fp: config = yaml.safe_load(fp) From efc1997f02fc8c4e435fa201dbcd48dcecf47781 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Tue, 1 Oct 2019 20:16:23 +0200 Subject: [PATCH 22/54] antani --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b713ab32..a24bb052 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ Pwnagotchi is able to speak multiple languages!! Currently supported are: * **english** (default) * german * dutch +* greek * italian 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 8c840f9c82f6b620abee27e4fc026c3610da65cc Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Tue, 1 Oct 2019 20:18:09 +0200 Subject: [PATCH 23/54] fix --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py index bd1130b7..1312715c 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py @@ -77,7 +77,7 @@ class Stats(object): } }) - temp = ".%s.tmp" % self.path + temp = "%s.tmp" % self.path with open(temp, 'wt') as fp: fp.write(data) @@ -109,7 +109,7 @@ class AsyncTrainer(object): def _save_ai(self): core.log("[ai] saving model to %s ..." % self._nn_path) - temp = ".%s.tmp" % self._nn_path + temp = "%s.tmp" % self._nn_path self._model.save(temp) os.replace(temp, self._nn_path) From cb0100a878ccd665a1312131080940d586abd422 Mon Sep 17 00:00:00 2001 From: kovach <2214005+kovachwt@users.noreply.github.com> Date: Tue, 1 Oct 2019 10:13:31 +0100 Subject: [PATCH 24/54] add mk translation strings --- .../pwnagotchi/locale/mk/LC_MESSAGES/voice.mo | Bin 0 -> 4618 bytes .../pwnagotchi/locale/mk/LC_MESSAGES/voice.po | 341 ++++++++++++++++++ 2 files changed, 341 insertions(+) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.mo create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.po diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.mo b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/mk/LC_MESSAGES/voice.mo new file mode 100644 index 0000000000000000000000000000000000000000..21ab0c20eaa4ca6098488c3dd5d1a8ae344ae2e4 GIT binary patch literal 4618 zcmbW4Uyu}66~>#Gh_)tbj1U#|ju;8DGt81u!b&hmVpwI#1~#GK#p<28v(wp`?sd9{ zaoF0b>>{#SsnSwXK?;n7q|A#tEG(?-vQ&JrN*}!aU};(Ysj_@fe8_{9cYo)0&oXTC zWV1bA-`n?|`sAm(S8%$0{#OOp7*^k<-Y-xaYaypL!hi5fS&?Sf@1F?DE=;jp8$Uk3XfahN5Hqi z`@pq`j7!csQ2f~dO8-{yfi>us^&evLM*1t@7s2m=o4{X#p9OD$vhKYfaGX5&5Lf^Y zfrr5va2NPzQ1oB_L1GQ&LE(QC6#m}?MVIe`qT?kH)6Q?fkAr^z-vZwPCBA=09P#r( zNPiCO1I5lWSv$<|G${Ok1#Sla3Q9cI^0OOU4=V6Ea68xn9|M054uk&zCBC~z2I2P% z_$U~GkArW3!uQ``0lW*5MUQ?^`UgSbHwr@CIR%P8r$LG5FS7pMffBDjfuhTQLBe2j z0dPJoKiTyeP+}%_<&rpvE%8q-;UO_1gjRE?S*=8$ySTGbbGGvQ5Vu^y>66^TLGnVh zSKM+5AGx4peUoSLO)lhdC;_X@!=Pv_c}tqvi!`?S6+y|5e%qVY5~b>p7B=ttvi>iC zqSHIBJ%g&Dy>h$Y?1`eVFRzH5oMPQ*NMJs_F&h zsOpXD$%$IC;nk*c&J)^e##J4}e#shfC+l8m%6Y0g@AjO?b@q9sam8pgT=N1Q=bU}I zR%6k?tLv$pd%!PgNT|Bjv1*6S0!zyqhP5+hZcWFVA~mX2rQvJXh>doiDnTvKH8q(% zOesHdD-Er4>PXmZs6E4~<=1L%;e{+2{AE!A*5F+zLGWELHuSdnooAR*OQR z;0&sY#%2^MuNDScrF|2vKzwNEO4!h9PH`Wln8m^-MPV zTnooiguU8WCDQmZVdJbeM&oVb?R>2n#j31Jei?FvAx^V}+|uPp1))0Zf7Q=9Ux)oD z@x-}wK-wh^Nh+!+wyu&;`)xLig;oPkwY=JR&eN-OR(XS@7ZrI0kgft^($d4jj&N)MERciQkOTqQVm_R|wlAIU+a3x(2Rs9$;ET#swI)@0b7qnS6ZiS8UD3{AQBV<>grEz<@n6uV+5tf+cB%gAS|b-U_V7?wxdIxAb}*}x}`wot`dpuNUuJJ&7U!=7&m z+9d6f<*-x`m8>PVMT9TsoWs>HoQUiix9yElc?IW4cWcTyM~@%p?|4sKrFm3->SMl)%s)YK45)3z{+;>a&io@qwe69C?T>6JZYvhu{azI3M;cxb)x0=t45;z& zm{+Q*UE8+xKUyqq-;%al@#D>ig$n^Y$3(4N7$fk_(LyP#@5V+j*7U}7enfk9*6y|k zRDIkX8XS7^Hs}6A(cK#cF}aZ+X-_~aX7|}jF8RTiWM^zdI)1DfSMobj^T`ZLylk%6(Q{^b<)|^|;J7GjFTu;quN*bz zrQ}TatYOJB!c7QvL>75UUV#5qX5$~m8Q!Nv7*RtkCNn*UkePRxMz6WVEpFb(aTej? zvP#ZjPn>n_^sCZBJ)w@~J)}|f3{<9Jz|u>1oL9KIoSZ_mZcyZmGOx1Oq6jUdB~-Te zf_QqFwuF-KT@%VoruQaRriGQPWR@^-T6%cCVuQB~Uu)x{Sxja`P0^%hMEZ6%Igy;? zK9Q!&CFaki^O4xfb{S`-5E{vs%ff!9+xzYw%n@NxvFG#? zZx(QkwIzwnT<;->(2MkCNtRQn+!5bXDP(N#acF5s+GasVI)aa0lDe#-Bvee7z%#Y? zpj@4u|KD*5J+VEX%&KHoqC=+9ksX>ml8;MPCf1u5m$L)ZoW;xQ(qV3NPf&B_PF3tN zXoD`PYb%Z#`a#m0@v~AvvQC!lZ-@dIO=}CNoBazryJE%|rTj&)WG z-%k!=dV%F-|Cl$6?;Mj^UNz1vIOY|mF2k{t%$fy?@`t#e5+KywvPnxpN}l|8lOIzu zQj|AYRD84rkfzy-BCPBg=@uydrr!|Mpsj-Q;+#|f=50)DQ_6g<&rR!kTJj?;w(eGO z-Ufvd6LlzdDK9n-u>&7FVS%)l;-Y1@ChRjZtGt`Zv|WsRkYq@$u)|0cvIL=GENw{z zX1V64L{JJ_GFSH1G4wC)x{iir|zdGZNi&htD+&oZ0N zwD1?}l85P_j+?r6`vj5Q>?d+$boW}D#5T{^7MZpn+kkRYITa&uO*UA&J;*y&eciGW zmngu_%0@1hZ_=hF(hm^v#u~U}EBzW~sF;`f*>8XtD4I3dcXF_-Jj%nR*7xJffA)5zX K4x(>Q%Ks1h3, 2019. +# kovach <2214005+kovachwt@users.noreply.github.com>, 2019. +# +#, fuzzymsgid "" +msgstr "" +"Project-Id-Version: 0.0.1\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2019-09-29 13:42+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" +"Language: mk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: voice.py:16 +msgid "ZzzzZZzzzzZzzz" +msgstr "ДреееММмммМммм" + +#: voice.py:21 +msgid "" +"Hi, I'm Pwnagotchi!\n" +"Starting ..." +msgstr "" +"Здраво, јас сум Pwnagotchi!\n" +"Почнувам ..." + +#: voice.py:22 +msgid "" +"New day, new hunt,\n" +"new pwns!" +msgstr "" +"Нов ден, нов лов,\n" +"ќе си газиме!" + +#: voice.py:23 +msgid "Hack the Planet!" +msgstr "Хак д Планет!" + +#: voice.py:28 +msgid "AI ready." +msgstr "AI спремно." + +#: voice.py:29 +msgid "" +"The neural network\n" +"is ready." +msgstr "" +"Невронската мрежа\n" +"е спремна." + +#: voice.py:39 +#, python-brace-format +msgid "" +"Hey, channel {channel} is\n" +"free! Your AP will\n" +"say thanks." +msgstr "" +"Еј, каналот {channel} е\n" +"слободен! APто ќе ти\n" +"каже фала." + +#: voice.py:44 +msgid "I'm bored ..." +msgstr "Досаднооо ..." + +#: voice.py:45 +msgid "Let's go for a walk!" +msgstr "Ајде да шетнеме!" + +#: voice.py:49 +msgid "" +"This is the best\n" +"day of my life!" +msgstr "" +"Ова ми е најдобриот \n" +"ден во животот!" + +#: voice.py:53 +msgid "Shitty day :/" +msgstr "Срање ден :/" + +#: voice.py:58 +msgid "I'm extremely bored ..." +msgstr "Ултра досадно ..." + +#: voice.py:59 +msgid "I'm very sad ..." +msgstr "Многу тажно ..." + +#: voice.py:60 +msgid "I'm sad" +msgstr "Тажно" + +#: voice.py:66 +msgid "I'm living the life!" +msgstr "Ммхх животче!" + +#: voice.py:67 +msgid "I pwn therefore I am." +msgstr "Си газам значи постојам." + +#: voice.py:68 +msgid "So many networks!!!" +msgstr "Мммм колку мрежи!!!" + +#: voice.py:69 +msgid "" +"I'm having so much\n" +"fun!" +msgstr "Јухуу забавноо ее!" + +#: voice.py:70 +msgid "" +"My crime is that of\n" +"curiosity ..." +msgstr "" +"Виновен сум само за\n" +"љубопитност ..." + +#: voice.py:75 +#, python-brace-format +msgid "" +"Hello\n" +"{name}!\n" +"Nice to meet you. {name}" +msgstr "" +"Здраво\n" +"{name}!\n" +"Мило ми е. {name}" + +#: voice.py:76 +#, python-brace-format +msgid "" +"Unit\n" +"{name}\n" +"is nearby! {name}" +msgstr "" +"Опаа\n" +"{name}\n" +"е во близина! {name}" + +#: voice.py:81 +#, python-brace-format +msgid "" +"Uhm ...\n" +"goodbye\n" +"{name}" +msgstr "" +"Хмм ...\n" +"чао\n" +"{name}" + +#: voice.py:82 +#, python-brace-format +msgid "" +"{name}\n" +"is gone ..." +msgstr "" +"{name}\n" +"го снема ..." + +#: voice.py:87 +#, python-brace-format +msgid "" +"Whoops ...\n" +"{name}\n" +"is gone." +msgstr "" +"Уупс ...\n" +"{name}\n" +"го снема." + +#: voice.py:88 +#, python-brace-format +msgid "" +"{name}\n" +"missed!" +msgstr "" +"{name}\n" +"промаши!" + +#: voice.py:89 +msgid "Missed!" +msgstr "Промаши!" + +#: voice.py:94 +msgid "" +"Nobody wants to\n" +"play with me ..." +msgstr "" +"Никој не сака да\n" +"си игра со мене ..." + +#: voice.py:95 +msgid "I feel so alone ..." +msgstr "Толку сам ..." + +#: voice.py:96 +msgid "Where's everybody?!" +msgstr "Каде се сите?!" + +#: voice.py:101 +#, python-brace-format +msgid "Napping for {secs}s ..." +msgstr "Ќе дремнам {secs}с ..." + +#: voice.py:102 +msgid "Zzzzz" +msgstr "Дреммм" + +#: voice.py:103 +#, python-brace-format +msgid "ZzzZzzz ({secs}s)" +msgstr "Дремммм ({secs}с)" + +#: voice.py:112 +#, python-brace-format +msgid "Waiting for {secs}s ..." +msgstr "Чекам {secs}с ..." + +#: voice.py:114 +#, python-brace-format +msgid "Looking around ({secs}s)" +msgstr "Шарам наоколу ({secs}с)" + +#: voice.py:121 +#, python-brace-format +msgid "" +"Hey\n" +"{what}\n" +"let's be friends!" +msgstr "" +"Еј\n" +"{what}\n" +"ајде да се дружиме!" + +#: voice.py:122 +#, python-brace-format +msgid "" +"Associating to\n" +"{what}" +msgstr "" +"Се закачувам на\n" +"{what}" + +#: voice.py:123 +#, python-brace-format +msgid "" +"Yo\n" +"{what}!" +msgstr "" +"Јо\n" +"{what}!" + +#: voice.py:128 +#, python-brace-format +msgid "" +"Just decided that\n" +"{mac}\n" +"needs no WiFi!" +msgstr "" +"Знаеш што, на\n" +"{mac}\n" +"не му треба WiFi!" + +#: voice.py:129 +#, python-brace-format +msgid "" +"Deauthenticating\n" +"{mac}" +msgstr "" +"Го деавтентицирам\n" +"{mac}" + +#: voice.py:130 +#, python-brace-format +msgid "" +"Kickbanning\n" +"{mac}!" +msgstr "" +"Кикбан\n" +"{mac}!" + +#: voice.py:135 +#, python-brace-format +msgid "" +"Cool, we got {num}\n" +"new handshake{plural}!" +msgstr "" +"Кул, фативме {num}\n" +"нови ракувања!" + +#: voice.py:139 +msgid "" +"Ops, something\n" +"went wrong ...\n" +"Rebooting ..." +msgstr "" +"Упс, нешто не е\n" +"ко што треба ...\n" +"Рестартирам ..." + +#: voice.py:143 +#, python-brace-format +msgid "Kicked {num} stations\n" +msgstr "Избацив {num} станици" + +#: voice.py:144 +#, python-brace-format +msgid "Made {num} new friends\n" +msgstr "{num} нови другарчиња" + +#: voice.py:145 +#, python-brace-format +msgid "Got {num} handshakes\n" +msgstr "Фатив {num} ракувања" + +#: voice.py:147 +msgid "Met 1 peer" +msgstr "Запознав 1 пријател" + +#: voice.py:149 +#, python-brace-format +msgid "Met {num} peers" +msgstr "Запознав {num} пријатели" + +#: voice.py:154 +#, 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" From a004125bdecb7ea2b2e76a3f47437efb10ba38c8 Mon Sep 17 00:00:00 2001 From: dadav <33197631+dadav@users.noreply.github.com> Date: Tue, 1 Oct 2019 21:52:35 +0200 Subject: [PATCH 25/54] Add rest of emotions --- scripts/preview.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/preview.py b/scripts/preview.py index 8ca53594..261448ea 100755 --- a/scripts/preview.py +++ b/scripts/preview.py @@ -152,6 +152,19 @@ def main(): time.sleep(args.sleep) DISPLAY.on_deauth({'mac': 'DE:AD:BE:EF:CA:FE'}) DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_miss('test') + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_lonely() + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_handshakes(1) + DISPLAY.update() + time.sleep(args.sleep) + DISPLAY.on_rebooting() + DISPLAY.update() + time.sleep(args.sleep) if __name__ == '__main__': From 30744a8dd551925250fb77382f6bc33925fc2c9e Mon Sep 17 00:00:00 2001 From: strasharo Date: Tue, 1 Oct 2019 23:52:59 +0300 Subject: [PATCH 26/54] Fix for the segmentation fault in qemu Without this I'm getting a constant segmentation fault when running go under qemu on Fedora 30: + export GOPATH=/root/go + GOPATH=/root/go + go get -u github.com/bettercap/bettercap qemu: uncaught target signal 11 (Segmentation fault) - core dumped bin/bash: line 52: 23146 Segmentation fault (core dumped) go get -u github.com/bettercap/bettercap https://bugs.launchpad.net/qemu/+bug/1696773 --- 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 c69ff848..3c030c04 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -160,7 +160,7 @@ function provision_raspbian() { # install bettercap export GOPATH=/root/go - go get -u github.com/bettercap/bettercap + taskset -c 1 go get -u github.com/bettercap/bettercap mv "\$GOPATH/bin/bettercap" /usr/bin/bettercap # install bettercap caplets (cant run bettercap in chroot) From a495ffb13627fb1c6256f58f75a4dc1c7ebf7da2 Mon Sep 17 00:00:00 2001 From: Justin-p Date: Wed, 2 Oct 2019 00:29:14 +0200 Subject: [PATCH 27/54] Add update script --- README.md | 14 +++++++ scripts/update_pwnagotchi.sh | 77 ++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 scripts/update_pwnagotchi.sh diff --git a/README.md b/README.md index a24bb052..35f79ba6 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,20 @@ usage: ./scripts/create_sibling.sh [OPTIONS] If you connect to the unit via `usb0` (thus using the data port), you might want to use the `scripts/linux_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. +#### Update your pwnagotchi + +You can use the `scripts/update_pwnagotchi.sh` script to update to the most recent version of pwnagotchi. + +```shell +Usage: ./update_pwnagitchi.sh [-m | --master] [-c | --commit | --branch] [-bc | --backupconfig] [-rc | --restoreconfig] [-h | --help] + + -m, --master Update to the master branch. Used by default. + -c, --commit, --branch Update to the specific commit/branch. + -bc, --backupconfig Backup the current pwnagotchi config. + -rc, --restoreconfig Restore the current pwnagotchi config. -bc will be enabled. + -h, --help Shows this help. +``` + ### UI 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). diff --git a/scripts/update_pwnagotchi.sh b/scripts/update_pwnagotchi.sh new file mode 100644 index 00000000..c5cb7571 --- /dev/null +++ b/scripts/update_pwnagotchi.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# Default variables +folder="/tmp/pwnagotchi" +version="master" +commit=0 +backupconfig=0 +restoreconfig=0 + +# functions +function display_help { + echo "Usage: $0 [-m | --master] [-c | --commit | --branch] [-bc | --backupconfig] [-rc | --restoreconfig] [-h | --help]" >&2 + echo + echo " -m, --master Update to the master branch. Used by default." + echo " -c, --commit, --branch Update to the specific commit/branch." + echo " -bc, --backupconfig Backup the current pwnagotchi config." + echo " -rc, --restoreconfig Restore the current pwnagotchi config. -bc will be enabled." + echo " -h, --help Shows this help." + echo "" + echo + exit 1 +} +function test_root { +# Check if we are running as root. + if ! [ $(id -u) = 0 ]; then + echo " [!] This script must be run as root." + exit 3 + fi +} +function test_github { + wget -q --spider https://github.com/evilsocket/pwnagotchi/ + if [ $? -ne 0 ]; then + echo " [!] Cannot reach github. This script requires internet access, ensure connection sharing is working." + exit 4 + fi +} + +# Commandline arguments +while [[ "$#" -gt 0 ]]; do case $1 in + -m|--master) version="master"; shift;; + -c|--commit|---branch) commit="$2" version="other"; shift;; + -bc|--backupconfig) backupconfig=1; shift;; + -rc|--restoreconfig) backupconfig=1 restoreconfig=1; shift;; + -h|--help) display_help;; + *) echo "Unknown parameter passed: $1"; exit 2;; +esac; shift; done + +echo " [+] Checking prerequisites." +test_root +test_github + +# clean up old files, clone master, set checkout to commit if needed. +echo " [+] Cloning to $folder..." +rm $folder -rf +git clone https://github.com/evilsocket/pwnagotchi $folder -q +cd $folder +if [ $version == "other" ]; then + git checkout $commit -q +fi +echo " [+] Installing $(git log -1 --format="%h")" + +echo " [+] Updating..." +if [ $backupconfig -eq 1 ]; then + echo " [+] Creating backup of config.yml" + mv /root/pwnagotchi/config.yml ~/config.yml.bak -f +fi +rm /root/pwnagotchi -rf +rsync -aPq $folder/sdcard/rootfs/* / +cd /tmp +rm $folder -rf +if [ $restoreconfig -eq 1 ]; then + echo " [+] Restoring backup of config.yml" + mv ~/config.yml.bak /root/pwnagotchi/config.yml -f +fi + +echo " [+] Restarting pwnagotchi in auto mode. $( screen -X -S pwnagotchi quit)" +sudo -H -u root /usr/bin/screen -dmS pwnagotchi -c /root/pwnagotchi/data/screenrc.auto +echo " [+] Finished" \ No newline at end of file From cd5be9c4cdd6a7bd0f236707a6b5b20352fd98cc Mon Sep 17 00:00:00 2001 From: Justin-p Date: Wed, 2 Oct 2019 10:14:26 +0200 Subject: [PATCH 28/54] Add /boot. Redo help. Replaced --commit/--branch with --version. Added --url to easly switch to other fork for testing --- scripts/update_pwnagotchi.sh | 93 +++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/scripts/update_pwnagotchi.sh b/scripts/update_pwnagotchi.sh index c5cb7571..60107214 100644 --- a/scripts/update_pwnagotchi.sh +++ b/scripts/update_pwnagotchi.sh @@ -1,77 +1,82 @@ #!/bin/bash # Default variables -folder="/tmp/pwnagotchi" +git_folder="/tmp/pwnagotchi" +git_url="https://github.com/evilsocket/pwnagotchi/" version="master" -commit=0 backupconfig=0 restoreconfig=0 -# functions -function display_help { - echo "Usage: $0 [-m | --master] [-c | --commit | --branch] [-bc | --backupconfig] [-rc | --restoreconfig] [-h | --help]" >&2 - echo - echo " -m, --master Update to the master branch. Used by default." - echo " -c, --commit, --branch Update to the specific commit/branch." - echo " -bc, --backupconfig Backup the current pwnagotchi config." - echo " -rc, --restoreconfig Restore the current pwnagotchi config. -bc will be enabled." - echo " -h, --help Shows this help." - echo "" - echo - exit 1 +# Functions +function usage() { + cat < Date: Wed, 2 Oct 2019 10:40:16 +0200 Subject: [PATCH 29/54] updated arguments to getopts. Added -m for restart mode. Moved prerequisites checks. --- scripts/update_pwnagotchi.sh | 119 ++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 45 deletions(-) diff --git a/scripts/update_pwnagotchi.sh b/scripts/update_pwnagotchi.sh index 60107214..34e4eedf 100644 --- a/scripts/update_pwnagotchi.sh +++ b/scripts/update_pwnagotchi.sh @@ -1,82 +1,111 @@ #!/bin/bash # Default variables -git_folder="/tmp/pwnagotchi" -git_url="https://github.com/evilsocket/pwnagotchi/" -version="master" -backupconfig=0 -restoreconfig=0 +GIT_FOLDER="/tmp/pwnagotchi" +GIT_URL="https://github.com/evilsocket/pwnagotchi/" +VERSION="master" +SUPPORTED_RESTART_MODES=( 'auto' 'manual' ) +MODE="auto" +BACKUPCONFIG=0 +RESTORECONFIG=0 # Functions function usage() { - cat < Date: Wed, 2 Oct 2019 10:41:42 +0200 Subject: [PATCH 30/54] Updated README --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 35f79ba6..24f0cec0 100644 --- a/README.md +++ b/README.md @@ -85,13 +85,16 @@ If you connect to the unit via `usb0` (thus using the data port), you might want You can use the `scripts/update_pwnagotchi.sh` script to update to the most recent version of pwnagotchi. ```shell -Usage: ./update_pwnagitchi.sh [-m | --master] [-c | --commit | --branch] [-bc | --backupconfig] [-rc | --restoreconfig] [-h | --help] +usage: ./update_pwnagitchi.sh [OPTIONS] + + Options: + -v # Version to update to, can be a branch or commit. (default: master) + -u # Url to clone from. (default: https://github.com/evilsocket/pwnagotchi) + -m # Mode to restart to. (Supported: auto manual; default: auto) + -b # Backup the current pwnagotchi config. + -r # Restore the current pwnagotchi config. -b will be enabled. + -h # Shows this help. Shows this help. - -m, --master Update to the master branch. Used by default. - -c, --commit, --branch Update to the specific commit/branch. - -bc, --backupconfig Backup the current pwnagotchi config. - -rc, --restoreconfig Restore the current pwnagotchi config. -bc will be enabled. - -h, --help Shows this help. ``` ### UI From a4e2fe02b68f866e8d242b7d4669744cd2dff6d5 Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 11:33:07 +0200 Subject: [PATCH 31/54] Enable detection of bmaptool, and if present generate sparse files. This uses https://github.com/intel/bmap-tools to generate a .bmap file which can be copied around. The bmaptool allows storing sparse files onto for instance an SD card, thus avoiding having to transfer the full disk image every time one burns one. Thus saving lots of time (and SD card cycles). This also adds some instructions for then transfering and copying the sparse file. bmaptool: info: discovered bmap file '/Users/jeroen/berry.img.bmap' bmaptool: info: block map format version 2.0 bmaptool: info: 7324219 blocks of size 4096 (27.9 GiB), mapped 1539940 blocks (5.9 GiB or 21.0%) bmaptool: info: copying image 'berry.img' to file 'rdisk4' using bmap file 'berry.img.bmap' bmaptool: info: 100% copied bmaptool: info: synchronizing '/dev/rdisk4' bmaptool: info: copying time: 6m 49.7s, copying speed 14.7 MiB/sec versus copying the whole 30G which would take forever... --- .gitignore | 1 + scripts/create_sibling.sh | 63 +++++++++++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 1ed12070..7d065ae9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.img +*.img.bmap *.pcap __pycache__ _backups diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index c69ff848..e8e13968 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -5,14 +5,17 @@ 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 parted bmap-tools ) REPO_DIR="$(dirname "$(dirname "$(realpath "$0")")")" TMP_DIR="${REPO_DIR}/tmp" MNT_DIR="${TMP_DIR}/mnt" +THIS_DIR=$(pwd) PWNI_NAME="pwnagotchi" PWNI_OUTPUT="pwnagotchi.img" PWNI_SIZE="4" +OPT_SPARSE=0 OPT_PROVISION_ONLY=0 OPT_CHECK_DEPS_ONLY=0 OPT_IMAGE_PROVIDED=0 @@ -26,6 +29,18 @@ if [[ "$EUID" -ne 0 ]]; then fi function check_dependencies() { + if [ -f /etc/debian_version ]; + then + echo "[+] Checking Debian dependencies" + + for REQ in "${DEBREQUIREMENTS[@]}"; do + if ! dpkg -s "$REQ" >/dev/null 2>&1; then + echo "Dependency check failed for ${REQ}; use 'apt-get install ${REQ}' to install" + exit 1 + fi + done + fi + echo "[+] Checking dependencies" for REQ in "${REQUIREMENTS[@]}"; do if ! type "$REQ" >/dev/null 2>&1; then @@ -76,8 +91,31 @@ function provide_raspbian() { } function setup_raspbian(){ - echo "[+] Resize image" - dd if=/dev/zero bs=1G count="$PWNI_SIZE" >> "${TMP_DIR}/raspbian.img" + # Detect the ability to create sparse files + 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 + else + echo "[!] bmaptool not available, not creating a sparse image" + fi + fi + + # Note that we 'extend' the raspbian.img + if [ "${OPT_SPARSE}" -eq 1 ]; + then + # Resize sparse (so that we can use bmaptool later) + echo "[+] Resizing sparse image of ${PWNI_SIZE}GB (1000s)" + truncate -s ${PWNI_SIZE}GB "${TMP_DIR}/raspbian.img" + else + echo "[+] Resizing full image to ${PWNI_SIZE}G" + # Full disk-space using image (appends to raspbian image) + dd if=/dev/zero bs=1G count="${PWNI_SIZE}" >> "${TMP_DIR}/raspbian.img" + fi + echo "[+] Setup loop device" mkdir -p "${MNT_DIR}" LOOP_PATH="$(losetup --find --partscan --show "${TMP_DIR}/raspbian.img")" @@ -107,7 +145,7 @@ function provision_raspbian() { cd "${MNT_DIR}" sed -i'' 's/^\([^#]\)/#\1/g' etc/ld.so.preload # add comments echo "[+] Run chroot commands" - LANG=C chroot . bin/bash -x < # Provide the path of an already downloaded raspbian image -o # Name of the img-file (default: pwnagotchi.img) -s # Size which should be added to second partition (in Gigabyte) (default: 4) + -S # Create a sparse image and generate bmap file (default when bmaptool is available) -v # Version of raspbian (Supported: ${SUPPORTED_RASPBIAN_VERSIONS[*]}; default: latest) -p # Only run provisioning (assumes the image is already mounted) -d # Only run dependencies checks @@ -283,4 +326,14 @@ fi setup_raspbian provision_raspbian -echo -ne "[+] Congratz, it's a boy (⌐■_■)!\n[+] One more step: dd if=../$PWNI_OUTPUT of= bs=4M status=progress" +echo -e "[+] Congratz, it's a boy (⌐■_■)!" +echo -e "[+] One more step: dd if=../${PWNI_OUTPUT} of= bs=4M status=progress" + +if [ "${OPT_SPARSE}" -eq 1 ]; +then + echo -e "[t] To transfer use: rsync -vaS --progress $(whoami)@$(hostname -f):${THIS_DIR}/../${PWNI_OUTPUT} " + echo -e "[t] To burn with bmaptool: bmaptool copy ~/${PWNI_OUTPUT} /dev/" +fi + +# Helpful OSX reminder +echo -e "[t] Mac: use 'diskutil list' to figure out which device to burn to; 'diskutil unmountDisk' to unmount that disk'; then use /dev/rdiskX (note the 'r') for faster transfer" From 4aa2665dafa4449fcf00b7ef8fa9ed76da05a630 Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 11:53:18 +0200 Subject: [PATCH 32/54] Add -A option so that one can pass in the URL of a APT Proxy (eg apt-cacher-ng) so that rebuilding is much faster --- scripts/create_sibling.sh | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index c69ff848..33281f8a 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -17,6 +17,7 @@ OPT_PROVISION_ONLY=0 OPT_CHECK_DEPS_ONLY=0 OPT_IMAGE_PROVIDED=0 OPT_RASPBIAN_VERSION='latest' +OPT_APTPROXY="" SUPPORTED_RASPBIAN_VERSIONS=( 'latest' 'buster' 'stretch' ) @@ -111,6 +112,12 @@ function provision_raspbian() { set -eu export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + if [ ! -z "${OPT_APTPROXY}" ]; + then + echo "[+] Using Proxy ${OPT_APTPROXY}" + echo "Acquire::http { Proxy \"${OPT_APTPROXY}\"; }" >/etc/apt/apt.conf.d/99pwnagotchi_proxy + fi + uname -a apt-get -y update @@ -226,8 +233,11 @@ EOF exit 0 } -while getopts ":n:i:o:s:v:dph" o; do +while getopts "A:n:i:o:s:v:dph" o; do case "${o}" in + A) + OPT_APTPROXY="${OPTARG}" + ;; n) PWNI_NAME="${OPTARG}" ;; From 4c20314c907279a852e04cc37dd00efcf7525609 Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 11:57:25 +0200 Subject: [PATCH 33/54] Update dependencies, as travis needs bmap-tools now to perform CI --- .travis.yml | 2 +- scripts/create_sibling.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b1737097..8a41478a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ cache: - tmp/ before_script: - sudo apt-get -y update -- sudo apt-get -y install qemu-user-static binfmt-support qemu +- sudo apt-get -y install qemu-user-static binfmt-support qemu bmap-tools - sudo update-binfmts --display - unset GOROOT script: diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index e8e13968..f9b9bd05 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 parted bmap-tools ) +DEBREQUIREMENTS=( wget gzip git parted qemu-system-x86 qemu-user-static bmap-tools ) REPO_DIR="$(dirname "$(dirname "$(realpath "$0")")")" TMP_DIR="${REPO_DIR}/tmp" MNT_DIR="${TMP_DIR}/mnt" From 14f1e4bccb6b2293f87496d9e33475a186771bc0 Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 12:23:30 +0200 Subject: [PATCH 34/54] Enlarge the created disk to 8G, as it already fails during image creation with out of diskspace --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8a41478a..4928b9e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ before_script: - sudo update-binfmts --display - unset GOROOT script: -- sudo ./scripts/create_sibling.sh -n pwnagotchi -o pwnagotchi.img -s 4 +- sudo ./scripts/create_sibling.sh -n pwnagotchi -o pwnagotchi.img -s 8 - zip -s 2g pwnagotchi.zip pwnagotchi.img # TODO: deploy! From 816ee5771defa09f8d83120e82ddb8688498bb2c Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Wed, 2 Oct 2019 13:36:47 +0200 Subject: [PATCH 35/54] readme fix --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 24f0cec0..45644e4c 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,7 @@ Pwnagotchi is able to speak multiple languages!! Currently supported are: * german * dutch * greek +* macedonian * italian 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 96816d474c33d948d8b6cccec184f173352091f2 Mon Sep 17 00:00:00 2001 From: Alex Muthmann Date: Wed, 2 Oct 2019 14:49:39 +0200 Subject: [PATCH 36/54] Default to 8GB images Currently it's not possible to build images with 4GB, therefor 8GB should be default. --- 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 1cb446d5..f2d9c114 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -13,7 +13,7 @@ THIS_DIR=$(pwd) PWNI_NAME="pwnagotchi" PWNI_OUTPUT="pwnagotchi.img" -PWNI_SIZE="4" +PWNI_SIZE="8" OPT_SPARSE=0 OPT_PROVISION_ONLY=0 From 6515df2a9803fe63a192b3f81669c0980e6acc9a Mon Sep 17 00:00:00 2001 From: Alex Muthmann Date: Wed, 2 Oct 2019 14:50:02 +0200 Subject: [PATCH 37/54] Default to 8GB images --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4928b9e3..a62fa934 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ before_script: - sudo update-binfmts --display - unset GOROOT script: -- sudo ./scripts/create_sibling.sh -n pwnagotchi -o pwnagotchi.img -s 8 +- sudo ./scripts/create_sibling.sh -n pwnagotchi -o pwnagotchi.img - zip -s 2g pwnagotchi.zip pwnagotchi.img # TODO: deploy! From db5b9a3faeb3c25417a1e02e970c6267574ca856 Mon Sep 17 00:00:00 2001 From: darumaseye Date: Wed, 2 Oct 2019 17:24:41 +0200 Subject: [PATCH 38/54] Improved IT translation --- .../pwnagotchi/locale/it/LC_MESSAGES/voice.mo | Bin 4132 -> 3755 bytes .../pwnagotchi/locale/it/LC_MESSAGES/voice.po | 203 +++++++++--------- 2 files changed, 105 insertions(+), 98 deletions(-) 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 038f502396ed0fadd68d779b6667f52c931b8329..465dfc3dede76427c355ac24f24abaa7b52516fe 100644 GIT binary patch delta 1789 zcmZ9LPiP!f9LHbV{AnheMq{FFO_MjNHr=LdnxZIat=1%3#KfqGR1kcfo$fx|nOSFM zx7ZN2Af*>iPVL2m9x6yZh*Z!0KzE6ip#J9@~dBX(JcH0#f9DM5`~LUl)nO{va?Xb_n;)c z3irWpp(MNmW&fXWFYMjf5ul+6o`JjI2{?eu%d$>>^*a7e!85P~FG30URX%?Uihz4i ztSwO1LAV4(NC-vnMOc6toPeJ|5%>d?#J|Ep_y-in{)Vlec^P7M4&H{6sFx@rUEQ!105HC`>ob3+jl@Ymr8T4Q~AXlOu z;gQCZAyrFYxgHw6ZCepaL&*?vVs&@WqwTAZZ@Hp}d8ATtRSFQXQm_oU8g*QL81$aX z|8Z)Xcd=ir6e#HcSm`2)*LTBw<)uih-*&eF7Q$N}T|v0p-_OsiA=yLmom z(KeA_O%Q1lSkJn$cv#z-_DpE9XmF|++prRw^VXEwvE9{9G`)H*G?ggzs@8QDOl-Yu zV{l?G$`vcxk1LT*8Ucr@z78X6J}AtO*(9++(>lXmG%+l;c+!emx2%x1c8bo3NL zLXRUh#FjKR_>CT(fswJ^vF>3l0$MLYtUiWGBDi#^fvm!t{b(=&ri;_A)^SoMITOnzrD>m2UbVO`* zK;pWtTJf{XyWSdo8TFf=aj!mc%2vmIYO}uKL(fTT=rexJ>4ec`zg9Cku*PXxOpp+- zRRc+9%4OT_lf!}4LEH7%Sk|)g@c!YGN!?E|KbM$&G+cZ!;U=d^+$pW3P7|Tsx6+Q% WTF!rWwCl=OIF@)(P&b|SR{sKhjA6Y1 delta 2190 zcmZ{jO>7la6vuC&g)+58KCCE3?pQ?HK3-oDl@HNi2_FXV3A%uVay#$RUU+ZjIWw(&tU@v^7wf-)=oB0K} z5nhJk?{~Njc62DE;gfI`dWRO>1B;6u-mJgZtoecmyuxd^N^{&%!AvAD)4^5>PY042R%#D1r8L zHZ$mh@?8mPcnC@WAzTMvh2rl6C>ehR?}t~R1abqe;CywHhaR{Tok>ddLdmEP%K9)o z(uQc? z_yFv;P#io5ABLykdiW+R!i!K8`W1>2e?yVBlfo8YKa_yW(1#X^zt^A~d=^Te z7nh?yYN@NO7e7LLsXw5U;ug%C2|Wo~^+GC<_XEgP5{gNH64VBnU=K3nkO7%sMTR6p z6?65ZM60C!(kzP@tsAF?c@`DK?qi5_lAQ!3!D@z>C?_TvNg2f?OEKck6_xBaG5Q&j z0IilAz1%EmiHFS$sh`+J23Iz(vnU~Qib*3;=6_rE#p1)e_E^(MCv2Fyz@#o5_hxG* zm{a?rRL_Qu+MJ#+VI`R`r)}b?{U$iA`C6B&CbX%4X-)gbi~K{=I*47(YM1cRq&hn3 z1&!E6iA$$-u~@uxdC94^jmKwZ_|51|vxyCoxnw}e^tk-xFY@V3HrN^M9ML0Nca%y) zr7fkBchDs1=I3J*CRLM0@ecjy#MVk_YOFM^pV+c(WcwpqO52C-tYud_`?F6wKcC;7 zBvIf@95`*f*(u_hQ%~E_7PJ`~bEXzG^Yg++H0c(yoUKQrnU- zNl7ybou_sapA^RElLoOGq0wI5B#9j#=X*rm*D!H~evEKUE0DrMGwn4gp)`B8SyNMU z0bUQ>i9(O)y0!E1!qV*xEXRo|^GDhTjjlOEp{jMGuY5#$o+St(YIb!?SBJ!o5b8G8 z&6ak#kcVlgNRK;-ub?Fqe3^ih3wg6Gak@SgCRty1W#wpItJH+35!=-He)d-P;MSTO zud?5IO)t7)tLQI5Nez7U!bDAu@=T@TZZ}!h-qXMOK&X+yCMK^*e$QO?SkJ%-(m*#V kQB=p+kzWU2Zk$}d+bX*MzLKihrrsSNd77<7vKP(%0dSAbd;kCd diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po index da7383ae..f84e16c3 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po @@ -1,51 +1,50 @@ -# pwnigotchi voice data +# pwnaigotchi voice data # Copyright (C) 2019 # This file is distributed under the same license as the pwnagotchi package. -# 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>, 2019. +# FIRST AUTHOR 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>, 2019. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-10-01 14:15+0200\n" -"PO-Revision-Date: 2019-10-01 14:00+0200\n" -"Last-Translator: 5h4d0wb0y <28193209+5h4d0wb0y@users.noreply.github.com>\n" +"POT-Creation-Date: 2019-10-02 16:38+0000\n" +"PO-Revision-Date: 2019-10-02 17:20+0000\n" "Language-Team: pwnagotchi <33197631+dadav@users.noreply.github.com>\n" "Language: italian\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:18 +#: voice.py:18 msgid "ZzzzZZzzzzZzzz" -msgstr "ZzzzZZzzzzZzzz" +msgstr "" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:23 +#: voice.py:23 msgid "" "Hi, I'm Pwnagotchi!\n" "Starting ..." msgstr "" -"Ciao, sono Pwnagotchi!\n" -"Avviamento ..." +"Ciao!" +"Piacere Pwnagotchi!\n" +"Caricamento ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:24 +#: voice.py:24 msgid "" "New day, new hunt,\n" "new pwns!" msgstr "" -"Nuovo giorno, nuova caccia,\n" -"nuovi pwns!" +"Nuovo giorno...\n" +"nuovi handshakes!!!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:25 +#: voice.py:25 msgid "Hack the Planet!" -msgstr "Hack il pianeta!" +msgstr "" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:30 +#: voice.py:30 msgid "AI ready." msgstr "IA pronta." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:31 +#: voice.py:31 msgid "" "The neural network\n" "is ready." @@ -53,7 +52,7 @@ msgstr "" "La rete neurale\n" "è pronta." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:41 +#: voice.py:41 #, python-brace-format msgid "" "Hey, channel {channel} is\n" @@ -62,71 +61,72 @@ msgid "" msgstr "" "Hey, il canale {channel} è\n" "libero! Il tuo AP\n" -"dirà grazie." +"ringrazia." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:46 +#: voice.py:46 msgid "I'm bored ..." -msgstr "Sono annoiato ..." +msgstr "Che noia ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:47 +#: voice.py:47 msgid "Let's go for a walk!" -msgstr "Andiamo a fare una \npasseggiata!" +msgstr "" +"Andiamo a fare una\n" +"passeggiata!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:51 +#: voice.py:51 msgid "" "This is the best\n" "day of my life!" msgstr "" -"Questo è il migliore\n" -"giorno della mia vita!" +"Questo è il più bel\n" +"giorno della mia\n" +"vita!!!!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:55 +#: voice.py:55 msgid "Shitty day :/" msgstr "Giorno di merda :/" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:60 +#: voice.py:60 msgid "I'm extremely bored ..." msgstr "" "Sono estremamente\n" "annoiato ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:61 +#: voice.py:61 msgid "I'm very sad ..." -msgstr "Sono molto triste ..." +msgstr "Sono molto triste..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:62 +#: voice.py:62 msgid "I'm sad" msgstr "Sono triste" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:68 +#: voice.py:68 msgid "I'm living the life!" -msgstr "Sto vivendo la vita!" +msgstr "Mi sento vivo!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:69 +#: voice.py:69 msgid "I pwn therefore I am." -msgstr "Possiedo quindi sono." +msgstr "Pwn ergo sum." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:70 +#: voice.py:70 msgid "So many networks!!!" -msgstr "Così tante reti!!!" +msgstr "Qui è pieno di reti!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:71 +#: voice.py:71 msgid "" "I'm having so much\n" "fun!" msgstr "" "Mi sto divertendo\n" -"tanto!" +"tantissimo!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:72 +#: voice.py:72 msgid "" "My crime is that of\n" "curiosity ..." msgstr "" -"La mia colpa è di\n" -"essere curioso ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:77 +#: voice.py:77 #, python-brace-format msgid "" "Hello\n" @@ -135,9 +135,9 @@ msgid "" msgstr "" "Ciao\n" "{name}!\n" -"Piacere di conoscerti. {name}" +"E' un piacere. {name}" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:78 +#: voice.py:78 #, python-brace-format msgid "" "Unit\n" @@ -148,27 +148,28 @@ msgstr "" "{name}\n" "è vicina! {name}" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:83 +#: voice.py:83 #, python-brace-format msgid "" "Uhm ...\n" "goodbye\n" "{name}" msgstr "" -"Uhm ...\n" +"Uhm ..." "addio\n" -"{name}" +"{name}," +"mi mancherai..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:84 +#: voice.py:84 #, python-brace-format msgid "" "{name}\n" "is gone ..." msgstr "" "{name}\n" -"è andato ..." +"se n'è andato ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:89 +#: voice.py:89 #, python-brace-format msgid "" "Whoops ...\n" @@ -177,22 +178,24 @@ msgid "" msgstr "" "Whoops ...\n" "{name}\n" -"è andato." +"se n'è andato." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:90 +#: voice.py:90 #, python-brace-format msgid "" "{name}\n" "missed!" msgstr "" "{name}\n" -"perso!" +"è scomparso..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:91 +#: voice.py:91 msgid "Missed!" -msgstr "Perso!" +msgstr "" +"Ehi!\n" +"Dove sei andato!?" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:96 +#: voice.py:96 msgid "" "Nobody wants to\n" "play with me ..." @@ -200,39 +203,44 @@ msgstr "" "Nessuno vuole\n" "giocare con me..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:97 +#: voice.py:97 msgid "I feel so alone ..." -msgstr "Mi sento così solo ..." +msgstr "Mi sento così solo..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:98 +#: voice.py:98 msgid "Where's everybody?!" msgstr "Dove sono tutti?!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:103 +#: voice.py:103 #, python-brace-format msgid "Napping for {secs}s ..." -msgstr "Pisolino per {secs}i ..." +msgstr "" +"Schiaccio un \n" +"pisolino per {secs}s ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:104 +#: voice.py:104 msgid "Zzzzz" -msgstr "Zzzzz" +msgstr "" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:105 +#: voice.py:105 #, python-brace-format msgid "ZzzZzzz ({secs}s)" -msgstr "ZzzZzzz ({secs}i)" +msgstr "" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:114 +#: voice.py:114 #, python-brace-format msgid "Waiting for {secs}s ..." -msgstr "In attesa di {secs}i ..." +msgstr "Aspetto {secs}s ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:116 +#: voice.py:116 #, python-brace-format msgid "Looking around ({secs}s)" -msgstr "Guardando intorno ({secs}s)" +msgstr "" +"Do uno sguardo" +"qui intorno..." +"({secs}s)" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:123 +#: voice.py:123 #, python-brace-format msgid "" "Hey\n" @@ -241,18 +249,19 @@ msgid "" msgstr "" "Hey\n" "{what}\n" -"diventiamo amici!" +"Diventiamo amici!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:124 +#: voice.py:124 #, python-brace-format msgid "" "Associating to\n" "{what}" msgstr "" -"Associarci a\n" +"Collegamento con\n" "{what}" +"in corso..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:125 +#: voice.py:125 #, python-brace-format msgid "" "Yo\n" @@ -261,7 +270,7 @@ msgstr "" "Yo\n" "{what}!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:130 +#: voice.py:130 #, python-brace-format msgid "" "Just decided that\n" @@ -273,16 +282,14 @@ msgstr "" "non necessita di\n" "WiFi!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:131 +#: voice.py:131 #, python-brace-format msgid "" "Deauthenticating\n" "{mac}" msgstr "" -"Dissociarci da\n" -"{mac}" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:132 +#: voice.py:132 #, python-brace-format msgid "" "Kickbanning\n" @@ -292,16 +299,16 @@ msgstr "" "a calci\n" "{mac}!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:137 +#: voice.py:137 #, python-brace-format msgid "" "Cool, we got {num}\n" "new handshake{plural}!" msgstr "" "Bene, abbiamo {num}\n" -"nuovi handshake{plural}!" +"handshake{plural} in più!" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:141 +#: voice.py:141 msgid "" "Ops, something\n" "went wrong ...\n" @@ -311,37 +318,37 @@ msgstr "" "è andato storto ...\n" "Riavvio ..." -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:145 +#: voice.py:145 #, python-brace-format msgid "Kicked {num} stations\n" -msgstr "Calciate {num} stazioni\n" +msgstr "{num} stazioni pestate\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:146 +#: voice.py:146 #, python-brace-format msgid "Made {num} new friends\n" -msgstr "Fatti {num} nuovi amici\n" +msgstr "{num} nuovi amici\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:147 +#: voice.py:147 #, python-brace-format msgid "Got {num} handshakes\n" -msgstr "Presi {num} handshakes\n" +msgstr "{num} handshakes presi\n" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:149 +#: voice.py:149 msgid "Met 1 peer" -msgstr "Incontrato 1 peer" +msgstr "1 peer incontrato" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:151 +#: voice.py:151 #, python-brace-format msgid "Met {num} peers" -msgstr "Incontrati {num} peers" +msgstr "{num} peers incontrati" -#: /home/sh4d0wb0y/Projects/GitHub/pwnagotchi/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py:156 +#: voice.py:156 #, 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 "" -"Ho lavorato per {duration} e preso a calci i clienti di {deauthed}! Ho anche " -"incontrato{associate} nuovi amici e ho mangiato {handshakes} handshakes! " -"#pwnagotchi#pwnlog #pwnlife #hacktheplanet #skynet" +"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" From 610bd46572ee9aaeef397580c19ceff131dc3ea4 Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Wed, 2 Oct 2019 16:40:58 +0100 Subject: [PATCH 39/54] initial packer/ansible base builder --- .travis.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index a62fa934..b7167a64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,28 @@ dist: bionic -language: generic +language: go +go: + - 1.x + env: global: - LANG=C - LC_ALL=C + before_cache: - mountpoint -q $TRAVIS_BUILD_DIR/tmp/mnt && sudo umount -R $TRAVIS_BUILD_DIR/tmp/mnt - sudo find $TRAVIS_BUILD_DIR/tmp/ -name '*.img' -delete + cache: apt: true directories: - tmp/ + before_script: - sudo apt-get -y update -- sudo apt-get -y install qemu-user-static binfmt-support qemu bmap-tools +- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx - sudo update-binfmts --display -- unset GOROOT + script: -- sudo ./scripts/create_sibling.sh -n pwnagotchi -o pwnagotchi.img -- zip -s 2g pwnagotchi.zip pwnagotchi.img +- sudo make -e PWN_HOSTNAME="pwnagotchi" VERSION="$TRAVIS_TAG" # TODO: deploy! From a3e149420b5984e1b1deba8151d10e230eda631a Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Wed, 2 Oct 2019 16:42:28 +0100 Subject: [PATCH 40/54] initial packer/ansible base builder --- Makefile | 22 +++ builder/pwnagotchi.json | 26 ++++ builder/pwnagotchi.yml | 289 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 337 insertions(+) create mode 100644 Makefile create mode 100644 builder/pwnagotchi.json create mode 100644 builder/pwnagotchi.yml diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..e71c5b8f --- /dev/null +++ b/Makefile @@ -0,0 +1,22 @@ +PWN_HOSTNAME="pwnagotchi" +PWN_VERSION="master" + +all: install image clean + +install: + @curl https://releases.hashicorp.com/packer/1.3.5/packer_1.3.5_linux_amd64.zip -o /tmp/packer.zip + @unzip /tmp/packer.zip -d /tmp + @mv /tmp/packer /usr/bin/packer + @git clone https://github.com/solo-io/packer-builder-arm-image /tmp/packer-builder-arm-image + @cd /tmp/packer-builder-arm-image && go build + @cp /tmp/packer-builder-arm-image/packer-builder-arm-image /usr/bin + +image: + @cd builder && sudo packer build pwnagotchi.json + @mv builder/output-pwnagotchi/image pwnagotchi-raspbian-lite-$(PWN_VERSION).img + @zip pwnagotchi-raspbian-lite-$(PWN_VERSION).zip pwnagotchi-raspbian-lite-$(PWN_VERSION).img + +clean: + @rm -rf /tmp/packer-builder-arm-image + @rm -f pwnagotchi-raspbian-lite.img + @rm -rf builder/output-pwnagotchi builder/packer_cache diff --git a/builder/pwnagotchi.json b/builder/pwnagotchi.json new file mode 100644 index 00000000..c78629eb --- /dev/null +++ b/builder/pwnagotchi.json @@ -0,0 +1,26 @@ +{ + "variables": { + "home": "{{env `HOME`}}" + }, + "builders": [{ + "name": "pwnagotchi", + "type": "arm-image", + "iso_url" : "https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-07-12/2019-07-10-raspbian-buster-lite.zip", + "iso_checksum_type":"sha256", + "iso_checksum":"9e5cf24ce483bb96e7736ea75ca422e3560e7b455eee63dd28f66fa1825db70e", + "last_partition_extra_size" : 3221225472 + }], + "provisioners": [ + { + "type": "shell", + "inline": [ + "apt-get -y update", + "apt-get install -y ansible" + ] + }, + { + "type":"ansible-local", + "playbook_file": "pwnagotchi.yml" + } + ] +} diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml new file mode 100644 index 00000000..06720028 --- /dev/null +++ b/builder/pwnagotchi.yml @@ -0,0 +1,289 @@ +--- +- hosts: + - 127.0.0.1 + become: yes + vars: + pwn_hostname: "pwnagotchi" + pwn_version: "master" + + tasks: + + - name: selected hostname + debug: + msg: "{{ pwn_hostname }}" + + - name: build version + debug: + msg: "{{ pwn_version }}" + + - name: change hostname + hostname: + name: "{{pwn_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' + state: present + + - name: Add re4son-kernel repo key + apt_key: + url: https://re4son-kernel.com/keys/http/archive-key.asc + state: present + + - name: Add re4son-kernel repository + apt_repository: + repo: deb http://http.re4son-kernel.com/re4son/ kali-pi main + state: present + + - name: update apt package cache + apt: + update_cache: yes + + - name: upgrade apt distro + apt: + upgrade: dist + + - name: install packages + apt: + name: "{{ packages }}" + state: present + vars: + packages: + - vim + - screen + - golang + - git + - build-essential + - python3-pip + - 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 + + - 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 + - bluetooth.service + - triggerhappy.service + + - name: enable dphys-swapfile service + systemd: + name: dphys-swapfile.service + state: started + enabled: yes + + - name: build bettercap + command: go get -u github.com/bettercap/bettercap + environment: + GOPATH: /root/go + + - name: install bettercap + copy: + src: /root/go/bin/bettercap + dest: /usr/bin/bettercap + mode: 0755 + + - name: clone bettercap caplets + git: + repo: https://github.com/bettercap/caplets.git + dest: /tmp/caplets + + - name: install bettercap caplets + make: + chdir: /tmp/caplets + target: install + + - name: clone pwnagotchi repository + git: + repo: https://github.com/evilsocket/pwnagotchi.git + dest: /tmp/pwnagotchi + + - name: copy pwnagotchi files to final destination + copy: + src: /tmp/pwnagotchi/sdcard/rootfs/root/pwnagotchi/ + dest: /root/pwnagotchi/ + mode: preserve + + - name: remove pwnagotchi files from temporary repository + file: + 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 + mode: 0755 + content: | + #!/usr/bin/env bash + while true + do + top -b -n1 | awk '/Cpu\(s\)/ { printf("%d %", $2 + $4 + 0.5) }' + sleep 3 + done + + - name: create memusage script + copy: + dest: /usr/bin/memusage + mode: 0755 + content: | + #!/usr/bin/env + free -m | awk '/Mem/ { printf( "%d %", $3 / $2 * 100 + 0.5 ) }' + + - name: create monstart script + copy: + dest: /usr/bin/monstart + mode: 0755 + content: | + #!/usr/bin/env bash + iw phy phy0 interface add mon0 type monitor && ifconfig mon0 up + + - name: create monstop script + copy: + dest: /usr/bin/monstop + mode: 0755 + content: | + #!/usr/bin/env bash + ifconfig mon0 down && iw dev mon0 del + + - name: configure rc.local + blockinfile: + path: /etc/rc.local + insertbefore: "exit 0" + block: | + if ! /opt/vc/bin/tvservice -s | grep HDMI; then + /opt/vc/bin/tvservice -o + fi + /root/pwnagotchi/scripts/startup.sh & + + - name: configure usb interface + blockinfile: + path: /etc/network/interfaces.d/usb0.cfg + create: yes + block: | + allow-hotplug usb0 + iface usb0 inet static + address 10.0.0.2 + netmask 255.255.255.0 + network 10.0.0.0 + broadcast 10.0.0.255 + gateway 10.0.0.1 + + - name: configure eth0 interface (pi2/3/4) + blockinfile: + path: /etc/network/interfaces.d/eth0.cfg + create: yes + block: | + allow-hotplug eth0 + iface eth0 inet dhcp + + - name: enable ssh on boot + file: + path: /boot/ssh + state: touch + + - name: adjust /boot/config.txt + lineinfile: + dest: /boot/config.txt + insertafter: EOF + line: '{{ item }}' + with_items: + - "dtoverlay=dwc2" + - "dtparam=spi=on" + - "dtoverlay=spi1-3cs" + - "dtoverlay=pi3-disable-bt" + - "dtparam=audio=off" + + - name: change root partition + replace: + dest: /boot/cmdline.txt + backup: no + regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+" + replace: "root=/dev/mmcblk0p2" + + - name: configure /boot/cmdline.txt + lineinfile: + path: /boot/cmdline.txt + backrefs: True + state: present + backup: no + regexp: '(.*)$' + line: '\1 modules-load=dwc2,g_ether' + + - name: configure ssh + lineinfile: + dest: /etc/ssh/sshd_config + backup: no + regexp: '#?PermitRootLogin (.*)$' + line: 'PermitRootLogin yes' + + - name: configure motd + copy: + dest: /etc/motd + content: "(◕‿‿◕) {{pwn_hostname}} (pwnagotchi-{{pwn_version}})" + + - name: clean apt cache + apt: + autoclean: yes + + - name: remove dependencies that are no longer required + apt: + autoremove: yes + + - 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 From f7ef846d679b48af9d68175ae487aa24d604747f Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Wed, 2 Oct 2019 16:46:22 +0100 Subject: [PATCH 41/54] try adding golang to apt --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b7167a64..98f2dd24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ cache: before_script: - sudo apt-get -y update -- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx +- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx golang - sudo update-binfmts --display script: From 88fcd399ac93125f4df497645bf550f3950aea95 Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Wed, 2 Oct 2019 16:51:13 +0100 Subject: [PATCH 42/54] add go get --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e71c5b8f..b81990b2 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ install: @unzip /tmp/packer.zip -d /tmp @mv /tmp/packer /usr/bin/packer @git clone https://github.com/solo-io/packer-builder-arm-image /tmp/packer-builder-arm-image - @cd /tmp/packer-builder-arm-image && go build + @cd /tmp/packer-builder-arm-image && go get -d ./... && go build @cp /tmp/packer-builder-arm-image/packer-builder-arm-image /usr/bin image: From 4664790cc508dc4061785e54673a7391e7bd022d Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Wed, 2 Oct 2019 17:01:58 +0100 Subject: [PATCH 43/54] remove golang from apt --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 98f2dd24..b7167a64 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ cache: before_script: - sudo apt-get -y update -- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx golang +- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx - sudo update-binfmts --display script: From 894e8de2900ff7c38998bb056d7e9f5d3f560d98 Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Wed, 2 Oct 2019 17:11:31 +0100 Subject: [PATCH 44/54] try with generic image --- .travis.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index b7167a64..0366e05d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ dist: bionic -language: go -go: - - 1.x +language: generic env: global: @@ -19,7 +17,7 @@ cache: before_script: - sudo apt-get -y update -- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx +- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx golang - sudo update-binfmts --display script: From 911c0478ba7e7bed6f268445ad1ca3e56e212cb2 Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 18:15:52 +0200 Subject: [PATCH 45/54] Fix initial non-existent/empty log issue Fixes bug where on initial session there is no file, and thus no lines are read and one thus gets a index out of bounds error as lines is empty... --- sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py index d66008de..edf66ede 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/log.py @@ -160,6 +160,9 @@ class SessionParser(object): break lines.reverse() + if len(lines) == 0: + lines.append("Initial Session"); + self.last_session = lines self.last_session_id = hashlib.md5(lines[0].encode()).hexdigest() self.last_saved_session_id = self._get_last_saved_session_id() From e8f126b4085002f8f30ce80c3105d6123b6e4fde Mon Sep 17 00:00:00 2001 From: Cassiano Aquino Date: Wed, 2 Oct 2019 17:21:41 +0100 Subject: [PATCH 46/54] Revert "initial packer/ansible base builder" --- .travis.yml | 11 +- Makefile | 22 --- builder/pwnagotchi.json | 26 ---- builder/pwnagotchi.yml | 289 ---------------------------------------- 4 files changed, 4 insertions(+), 344 deletions(-) delete mode 100644 Makefile delete mode 100644 builder/pwnagotchi.json delete mode 100644 builder/pwnagotchi.yml diff --git a/.travis.yml b/.travis.yml index 0366e05d..a62fa934 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,26 +1,23 @@ dist: bionic language: generic - env: global: - LANG=C - LC_ALL=C - before_cache: - mountpoint -q $TRAVIS_BUILD_DIR/tmp/mnt && sudo umount -R $TRAVIS_BUILD_DIR/tmp/mnt - sudo find $TRAVIS_BUILD_DIR/tmp/ -name '*.img' -delete - cache: apt: true directories: - tmp/ - before_script: - sudo apt-get -y update -- sudo apt-get -y install qemu-user-static binfmt-support qemu kpartx golang +- sudo apt-get -y install qemu-user-static binfmt-support qemu bmap-tools - sudo update-binfmts --display - +- unset GOROOT script: -- sudo make -e PWN_HOSTNAME="pwnagotchi" VERSION="$TRAVIS_TAG" +- sudo ./scripts/create_sibling.sh -n pwnagotchi -o pwnagotchi.img +- zip -s 2g pwnagotchi.zip pwnagotchi.img # TODO: deploy! diff --git a/Makefile b/Makefile deleted file mode 100644 index b81990b2..00000000 --- a/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -PWN_HOSTNAME="pwnagotchi" -PWN_VERSION="master" - -all: install image clean - -install: - @curl https://releases.hashicorp.com/packer/1.3.5/packer_1.3.5_linux_amd64.zip -o /tmp/packer.zip - @unzip /tmp/packer.zip -d /tmp - @mv /tmp/packer /usr/bin/packer - @git clone https://github.com/solo-io/packer-builder-arm-image /tmp/packer-builder-arm-image - @cd /tmp/packer-builder-arm-image && go get -d ./... && go build - @cp /tmp/packer-builder-arm-image/packer-builder-arm-image /usr/bin - -image: - @cd builder && sudo packer build pwnagotchi.json - @mv builder/output-pwnagotchi/image pwnagotchi-raspbian-lite-$(PWN_VERSION).img - @zip pwnagotchi-raspbian-lite-$(PWN_VERSION).zip pwnagotchi-raspbian-lite-$(PWN_VERSION).img - -clean: - @rm -rf /tmp/packer-builder-arm-image - @rm -f pwnagotchi-raspbian-lite.img - @rm -rf builder/output-pwnagotchi builder/packer_cache diff --git a/builder/pwnagotchi.json b/builder/pwnagotchi.json deleted file mode 100644 index c78629eb..00000000 --- a/builder/pwnagotchi.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "variables": { - "home": "{{env `HOME`}}" - }, - "builders": [{ - "name": "pwnagotchi", - "type": "arm-image", - "iso_url" : "https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-07-12/2019-07-10-raspbian-buster-lite.zip", - "iso_checksum_type":"sha256", - "iso_checksum":"9e5cf24ce483bb96e7736ea75ca422e3560e7b455eee63dd28f66fa1825db70e", - "last_partition_extra_size" : 3221225472 - }], - "provisioners": [ - { - "type": "shell", - "inline": [ - "apt-get -y update", - "apt-get install -y ansible" - ] - }, - { - "type":"ansible-local", - "playbook_file": "pwnagotchi.yml" - } - ] -} diff --git a/builder/pwnagotchi.yml b/builder/pwnagotchi.yml deleted file mode 100644 index 06720028..00000000 --- a/builder/pwnagotchi.yml +++ /dev/null @@ -1,289 +0,0 @@ ---- -- hosts: - - 127.0.0.1 - become: yes - vars: - pwn_hostname: "pwnagotchi" - pwn_version: "master" - - tasks: - - - name: selected hostname - debug: - msg: "{{ pwn_hostname }}" - - - name: build version - debug: - msg: "{{ pwn_version }}" - - - name: change hostname - hostname: - name: "{{pwn_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' - state: present - - - name: Add re4son-kernel repo key - apt_key: - url: https://re4son-kernel.com/keys/http/archive-key.asc - state: present - - - name: Add re4son-kernel repository - apt_repository: - repo: deb http://http.re4son-kernel.com/re4son/ kali-pi main - state: present - - - name: update apt package cache - apt: - update_cache: yes - - - name: upgrade apt distro - apt: - upgrade: dist - - - name: install packages - apt: - name: "{{ packages }}" - state: present - vars: - packages: - - vim - - screen - - golang - - git - - build-essential - - python3-pip - - 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 - - - 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 - - bluetooth.service - - triggerhappy.service - - - name: enable dphys-swapfile service - systemd: - name: dphys-swapfile.service - state: started - enabled: yes - - - name: build bettercap - command: go get -u github.com/bettercap/bettercap - environment: - GOPATH: /root/go - - - name: install bettercap - copy: - src: /root/go/bin/bettercap - dest: /usr/bin/bettercap - mode: 0755 - - - name: clone bettercap caplets - git: - repo: https://github.com/bettercap/caplets.git - dest: /tmp/caplets - - - name: install bettercap caplets - make: - chdir: /tmp/caplets - target: install - - - name: clone pwnagotchi repository - git: - repo: https://github.com/evilsocket/pwnagotchi.git - dest: /tmp/pwnagotchi - - - name: copy pwnagotchi files to final destination - copy: - src: /tmp/pwnagotchi/sdcard/rootfs/root/pwnagotchi/ - dest: /root/pwnagotchi/ - mode: preserve - - - name: remove pwnagotchi files from temporary repository - file: - 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 - mode: 0755 - content: | - #!/usr/bin/env bash - while true - do - top -b -n1 | awk '/Cpu\(s\)/ { printf("%d %", $2 + $4 + 0.5) }' - sleep 3 - done - - - name: create memusage script - copy: - dest: /usr/bin/memusage - mode: 0755 - content: | - #!/usr/bin/env - free -m | awk '/Mem/ { printf( "%d %", $3 / $2 * 100 + 0.5 ) }' - - - name: create monstart script - copy: - dest: /usr/bin/monstart - mode: 0755 - content: | - #!/usr/bin/env bash - iw phy phy0 interface add mon0 type monitor && ifconfig mon0 up - - - name: create monstop script - copy: - dest: /usr/bin/monstop - mode: 0755 - content: | - #!/usr/bin/env bash - ifconfig mon0 down && iw dev mon0 del - - - name: configure rc.local - blockinfile: - path: /etc/rc.local - insertbefore: "exit 0" - block: | - if ! /opt/vc/bin/tvservice -s | grep HDMI; then - /opt/vc/bin/tvservice -o - fi - /root/pwnagotchi/scripts/startup.sh & - - - name: configure usb interface - blockinfile: - path: /etc/network/interfaces.d/usb0.cfg - create: yes - block: | - allow-hotplug usb0 - iface usb0 inet static - address 10.0.0.2 - netmask 255.255.255.0 - network 10.0.0.0 - broadcast 10.0.0.255 - gateway 10.0.0.1 - - - name: configure eth0 interface (pi2/3/4) - blockinfile: - path: /etc/network/interfaces.d/eth0.cfg - create: yes - block: | - allow-hotplug eth0 - iface eth0 inet dhcp - - - name: enable ssh on boot - file: - path: /boot/ssh - state: touch - - - name: adjust /boot/config.txt - lineinfile: - dest: /boot/config.txt - insertafter: EOF - line: '{{ item }}' - with_items: - - "dtoverlay=dwc2" - - "dtparam=spi=on" - - "dtoverlay=spi1-3cs" - - "dtoverlay=pi3-disable-bt" - - "dtparam=audio=off" - - - name: change root partition - replace: - dest: /boot/cmdline.txt - backup: no - regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+" - replace: "root=/dev/mmcblk0p2" - - - name: configure /boot/cmdline.txt - lineinfile: - path: /boot/cmdline.txt - backrefs: True - state: present - backup: no - regexp: '(.*)$' - line: '\1 modules-load=dwc2,g_ether' - - - name: configure ssh - lineinfile: - dest: /etc/ssh/sshd_config - backup: no - regexp: '#?PermitRootLogin (.*)$' - line: 'PermitRootLogin yes' - - - name: configure motd - copy: - dest: /etc/motd - content: "(◕‿‿◕) {{pwn_hostname}} (pwnagotchi-{{pwn_version}})" - - - name: clean apt cache - apt: - autoclean: yes - - - name: remove dependencies that are no longer required - apt: - autoremove: yes - - - 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 From 58edfd2a4b3b6586b55a56e2be52c6c89c6cbd06 Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 18:25:18 +0200 Subject: [PATCH 47/54] The -S option does not exist, as it is automatically detected (OPT_SPARSE) --- scripts/create_sibling.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/create_sibling.sh b/scripts/create_sibling.sh index f2d9c114..55b784f4 100755 --- a/scripts/create_sibling.sh +++ b/scripts/create_sibling.sh @@ -265,7 +265,6 @@ usage: $0 [OPTIONS] -i # Provide the path of an already downloaded raspbian image -o # Name of the img-file (default: pwnagotchi.img) -s # Size which should be added to second partition (in Gigabyte) (default: 4) - -S # Create a sparse image and generate bmap file (default when bmaptool is available) -v # Version of raspbian (Supported: ${SUPPORTED_RASPBIAN_VERSIONS[*]}; default: latest) -p # Only run provisioning (assumes the image is already mounted) -d # Only run dependencies checks From db48b7aa5268ae534f3ce3f0f7e37d728406952f Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 18:39:15 +0200 Subject: [PATCH 48/54] Update waveshare v1 driver to "4.00" aka "2019.07.31" from: https://github.com/waveshare/e-Paper/tree/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd --- .../pwnagotchi/ui/waveshare/v1/epd2in13.py | 443 +++++++++--------- .../pwnagotchi/ui/waveshare/v1/epdconfig.py | 157 +++++-- 2 files changed, 344 insertions(+), 256 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py index 5805086e..b6de9dad 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epd2in13.py @@ -1,218 +1,225 @@ -# //***************************************************************************** -# * | File : epd2in13.py -# * | Author : Waveshare team -# * | Function : Electronic paper driver -# * | Info : -# *---------------- -# * | This version: V3.1 -# * | Date : 2019-03-20 -# * | Info : python3 demo -# * fix: TurnOnDisplay() -# ******************************************************************************// -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documnetation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and//or sell -# copies of the Software, and to permit persons to whom the Software is -# furished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# - - -from . import epdconfig -from PIL import Image -import RPi.GPIO as GPIO -# import numpy as np - -# Display resolution -EPD_WIDTH = 122 -EPD_HEIGHT = 250 - -class EPD: - def __init__(self): - self.reset_pin = epdconfig.RST_PIN - self.dc_pin = epdconfig.DC_PIN - self.busy_pin = epdconfig.BUSY_PIN - self.width = EPD_WIDTH - self.height = EPD_HEIGHT - lut_full_update = [ - 0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 - ] - - lut_partial_update = [ - 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - ] - - # Hardware reset - def reset(self): - epdconfig.digital_write(self.reset_pin, GPIO.HIGH) - epdconfig.delay_ms(200) - epdconfig.digital_write(self.reset_pin, GPIO.LOW) # module reset - epdconfig.delay_ms(200) - epdconfig.digital_write(self.reset_pin, GPIO.HIGH) - epdconfig.delay_ms(200) - - def send_command(self, command): - epdconfig.digital_write(self.dc_pin, GPIO.LOW) - epdconfig.spi_writebyte([command]) - - def send_data(self, data): - epdconfig.digital_write(self.dc_pin, GPIO.HIGH) - epdconfig.spi_writebyte([data]) - - def wait_until_idle(self): - # print("busy") - while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy - epdconfig.delay_ms(100) - # print("free busy") - - def TurnOnDisplay(self): - self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2 - self.send_data(0xC4) - self.send_command(0x20) # MASTER_ACTIVATION - self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE - self.wait_until_idle() - - def init(self, lut): - if (epdconfig.module_init() != 0): - return -1 - # EPD hardware init start - self.reset() - self.send_command(0x01) # DRIVER_OUTPUT_CONTROL - self.send_data((EPD_HEIGHT - 1) & 0xFF) - self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF) - self.send_data(0x00) # GD = 0 SM = 0 TB = 0 - - self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL - self.send_data(0xD7) - self.send_data(0xD6) - self.send_data(0x9D) - - self.send_command(0x2C) # WRITE_VCOM_REGISTER - self.send_data(0xA8) # VCOM 7C - - self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD - self.send_data(0x1A) # 4 dummy lines per gate - - self.send_command(0x3B) # SET_GATE_TIME - self.send_data(0x08) # 2us per line - - self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL - self.send_data(0x03) - - self.send_command(0X11) # DATA_ENTRY_MODE_SETTING - self.send_data(0x03) # X increment; Y increment - - # WRITE_LUT_REGISTER - self.send_command(0x32) - for count in range(30): - self.send_data(lut[count]) - - return 0 - -## - # @brief: specify the memory area for data R//W - ## - def SetWindows(self, x_start, y_start, x_end, y_end): - self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION - self.send_data((x_start >> 3) & 0xFF) - self.send_data((x_end >> 3) & 0xFF) - self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION - self.send_data(y_start & 0xFF) - self.send_data((y_start >> 8) & 0xFF) - self.send_data(y_end & 0xFF) - self.send_data((y_end >> 8) & 0xFF) - -## - # @brief: specify the start point for data R//W - ## - def SetCursor(self, x, y): - self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER - # x point must be the multiple of 8 or the last 3 bits will be ignored - self.send_data((x >> 3) & 0xFF) - self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER - self.send_data(y & 0xFF) - self.send_data((y >> 8) & 0xFF) - self.wait_until_idle() - - def getbuffer(self, image): - if self.width%8 == 0: - linewidth = self.width//8 - else: - linewidth = self.width//8 + 1 - - buf = [0xFF] * (linewidth * self.height) - image_monocolor = image.convert('1') - imwidth, imheight = image_monocolor.size - pixels = image_monocolor.load() - - if(imwidth == self.width and imheight == self.height): - # print("Vertical") - for y in range(imheight): - for x in range(imwidth): - if pixels[x, y] == 0: - # x = imwidth - x - buf[x // 8 + y * linewidth] &= ~(0x80 >> (x % 8)) - elif(imwidth == self.height and imheight == self.width): - # print("Horizontal") - for y in range(imheight): - for x in range(imwidth): - newx = y - newy = self.height - x - 1 - if pixels[x, y] == 0: - # newy = imwidth - newy - 1 - buf[newx // 8 + newy*linewidth] &= ~(0x80 >> (y % 8)) - return buf - - - def display(self, image): - if self.width%8 == 0: - linewidth = self.width//8 - else: - linewidth = self.width//8 + 1 - - self.SetWindows(0, 0, EPD_WIDTH, EPD_HEIGHT); - for j in range(0, self.height): - self.SetCursor(0, j); - self.send_command(0x24); - for i in range(0, linewidth): - self.send_data(image[i + j * linewidth]) - self.TurnOnDisplay() - - def Clear(self, color): - if self.width%8 == 0: - linewidth = self.width//8 - else: - linewidth = self.width//8 + 1 - - self.SetWindows(0, 0, EPD_WIDTH, EPD_HEIGHT); - for j in range(0, self.height): - self.SetCursor(0, j); - self.send_command(0x24); - for i in range(0, linewidth): - self.send_data(color) - self.TurnOnDisplay() - - def sleep(self): - self.send_command(0x10) #enter deep sleep - # self.send_data(0x01) - epdconfig.delay_ms(100) - -### END OF FILE ### - +# ***************************************************************************** +# * | File : epd2in13.py +# * | Author : Waveshare team +# * | Function : Electronic paper driver +# * | Info : +# *---------------- +# * | This version: V4.0 +# * | Date : 2019-06-20 +# # | Info : python demo +# ----------------------------------------------------------------------------- +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documnetation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + + +import logging +from . import epdconfig +import numpy as np + +# Display resolution +EPD_WIDTH = 122 +EPD_HEIGHT = 250 + +class EPD: + def __init__(self): + self.reset_pin = epdconfig.RST_PIN + self.dc_pin = epdconfig.DC_PIN + self.busy_pin = epdconfig.BUSY_PIN + self.cs_pin = epdconfig.CS_PIN + self.width = EPD_WIDTH + self.height = EPD_HEIGHT + + lut_full_update = [ + 0x22, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x11, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + + lut_partial_update = [ + 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + ] + + # Hardware reset + def reset(self): + epdconfig.digital_write(self.cs_pin, 0) + epdconfig.digital_write(self.reset_pin, 1) + epdconfig.delay_ms(200) + epdconfig.digital_write(self.reset_pin, 0) + epdconfig.delay_ms(10) + epdconfig.digital_write(self.reset_pin, 1) + epdconfig.delay_ms(200) + epdconfig.digital_write(self.cs_pin, 1) + + def send_command(self, command): + epdconfig.digital_write(self.cs_pin, 0) + epdconfig.digital_write(self.dc_pin, 0) + epdconfig.spi_writebyte([command]) + epdconfig.digital_write(self.cs_pin, 1) + + def send_data(self, data): + epdconfig.digital_write(self.cs_pin, 0) + epdconfig.digital_write(self.dc_pin, 1) + epdconfig.spi_writebyte([data]) + epdconfig.digital_write(self.cs_pin, 1) + + def ReadBusy(self): + while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy + epdconfig.delay_ms(100) + + def TurnOnDisplay(self): + self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2 + self.send_data(0xC4) + self.send_command(0x20) # MASTER_ACTIVATION + self.send_command(0xFF) # TERMINATE_FRAME_READ_WRITE + + logging.debug("e-Paper busy") + self.ReadBusy() + logging.debug("e-Paper busy release") + + def init(self, lut): + if (epdconfig.module_init() != 0): + return -1 + # EPD hardware init start + self.reset() + self.send_command(0x01) # DRIVER_OUTPUT_CONTROL + self.send_data((EPD_HEIGHT - 1) & 0xFF) + self.send_data(((EPD_HEIGHT - 1) >> 8) & 0xFF) + self.send_data(0x00) # GD = 0 SM = 0 TB = 0 + + self.send_command(0x0C) # BOOSTER_SOFT_START_CONTROL + self.send_data(0xD7) + self.send_data(0xD6) + self.send_data(0x9D) + + self.send_command(0x2C) # WRITE_VCOM_REGISTER + self.send_data(0xA8) # VCOM 7C + + self.send_command(0x3A) # SET_DUMMY_LINE_PERIOD + self.send_data(0x1A) # 4 dummy lines per gate + + self.send_command(0x3B) # SET_GATE_TIME + self.send_data(0x08) # 2us per line + + self.send_command(0X3C) # BORDER_WAVEFORM_CONTROL + self.send_data(0x03) + + self.send_command(0X11) # DATA_ENTRY_MODE_SETTING + self.send_data(0x03) # X increment; Y increment + + # WRITE_LUT_REGISTER + self.send_command(0x32) + for count in range(30): + self.send_data(lut[count]) + + return 0 + +## + # @brief: specify the memory area for data R/W + ## + def SetWindows(self, x_start, y_start, x_end, y_end): + self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION + self.send_data((x_start >> 3) & 0xFF) + self.send_data((x_end >> 3) & 0xFF) + self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION + self.send_data(y_start & 0xFF) + self.send_data((y_start >> 8) & 0xFF) + self.send_data(y_end & 0xFF) + self.send_data((y_end >> 8) & 0xFF) + +## + # @brief: specify the start point for data R/W + ## + def SetCursor(self, x, y): + self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER + # x point must be the multiple of 8 or the last 3 bits will be ignored + self.send_data((x >> 3) & 0xFF) + self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER + self.send_data(y & 0xFF) + self.send_data((y >> 8) & 0xFF) + self.ReadBusy() + + def getbuffer(self, image): + if self.width%8 == 0: + linewidth = int(self.width/8) + else: + linewidth = int(self.width/8) + 1 + + buf = [0xFF] * (linewidth * self.height) + image_monocolor = image.convert('1') + imwidth, imheight = image_monocolor.size + pixels = image_monocolor.load() + + if(imwidth == self.width and imheight == self.height): + for y in range(imheight): + for x in range(imwidth): + if pixels[x, y] == 0: + # x = imwidth - x + buf[int(x / 8) + y * linewidth] &= ~(0x80 >> (x % 8)) + elif(imwidth == self.height and imheight == self.width): + for y in range(imheight): + for x in range(imwidth): + newx = y + newy = self.height - x - 1 + if pixels[x, y] == 0: + # newy = imwidth - newy - 1 + buf[int(newx / 8) + newy*linewidth] &= ~(0x80 >> (y % 8)) + return buf + + + def display(self, image): + if self.width%8 == 0: + linewidth = int(self.width/8) + else: + linewidth = int(self.width/8) + 1 + + self.SetWindows(0, 0, self.width, self.height); + for j in range(0, self.height): + self.SetCursor(0, j); + self.send_command(0x24); + for i in range(0, linewidth): + self.send_data(image[i + j * linewidth]) + self.TurnOnDisplay() + + def Clear(self, color): + if self.width%8 == 0: + linewidth = int(self.width/8) + else: + linewidth = int(self.width/8) + 1 + + self.SetWindows(0, 0, self.width, self.height); + for j in range(0, self.height): + self.SetCursor(0, j); + self.send_command(0x24); + for i in range(0, linewidth): + self.send_data(color) + self.TurnOnDisplay() + + def sleep(self): + self.send_command(0x10) #enter deep sleep + self.send_data(0x01) + epdconfig.delay_ms(100) + + epdconfig.module_exit() + +### END OF FILE ### + diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py index 78ff6479..76d8ca9d 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/waveshare/v1/epdconfig.py @@ -1,19 +1,13 @@ # /***************************************************************************** -# * | File : EPD_1in54.py +# * | File : epdconfig.py # * | Author : Waveshare team # * | Function : Hardware underlying interface # * | Info : # *---------------- -# * | This version: V2.0 -# * | Date : 2018-11-01 +# * | This version: V1.0 +# * | Date : 2019-06-21 # * | Info : -# * 1.Remove: -# digital_write(self, pin, value) -# digital_read(self, pin) -# delay_ms(self, delaytime) -# set_lut(self, lut) -# self.lut = self.lut_full_update -# ******************************************************************************/ +# ****************************************************************************** # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documnetation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights @@ -33,41 +27,128 @@ # THE SOFTWARE. # - -import spidev -import RPi.GPIO as GPIO +import os +import logging +import sys import time -# Pin definition -RST_PIN = 17 -DC_PIN = 25 -CS_PIN = 8 -BUSY_PIN = 24 -# SPI device, bus = 0, device = 0 -SPI = spidev.SpiDev(0, 0) +class RaspberryPi: + # Pin definition + RST_PIN = 17 + DC_PIN = 25 + CS_PIN = 8 + BUSY_PIN = 24 -def digital_write(pin, value): - GPIO.output(pin, value) + def __init__(self): + import spidev + import RPi.GPIO -def digital_read(pin): - return GPIO.input(BUSY_PIN) + self.GPIO = RPi.GPIO -def delay_ms(delaytime): - time.sleep(delaytime / 1000.0) + # SPI device, bus = 0, device = 0 + self.SPI = spidev.SpiDev(0, 0) -def spi_writebyte(data): - SPI.writebytes(data) + def digital_write(self, pin, value): + self.GPIO.output(pin, value) + + def digital_read(self, pin): + return self.GPIO.input(self.BUSY_PIN) + + def delay_ms(self, delaytime): + time.sleep(delaytime / 1000.0) + + def spi_writebyte(self, data): + self.SPI.writebytes(data) + + def module_init(self): + self.GPIO.setmode(self.GPIO.BCM) + self.GPIO.setwarnings(False) + self.GPIO.setup(self.RST_PIN, self.GPIO.OUT) + self.GPIO.setup(self.DC_PIN, self.GPIO.OUT) + self.GPIO.setup(self.CS_PIN, self.GPIO.OUT) + self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN) + self.SPI.max_speed_hz = 4000000 + self.SPI.mode = 0b00 + return 0 + + def module_exit(self): + logging.debug("spi end") + self.SPI.close() + + logging.debug("close 5V, Module enters 0 power consumption ...") + self.GPIO.output(self.RST_PIN, 0) + self.GPIO.output(self.DC_PIN, 0) + + self.GPIO.cleanup() + + +class JetsonNano: + # Pin definition + RST_PIN = 17 + DC_PIN = 25 + CS_PIN = 8 + BUSY_PIN = 24 + + def __init__(self): + import ctypes + find_dirs = [ + os.path.dirname(os.path.realpath(__file__)), + '/usr/local/lib', + '/usr/lib', + ] + self.SPI = None + for find_dir in find_dirs: + so_filename = os.path.join(find_dir, 'sysfs_software_spi.so') + if os.path.exists(so_filename): + self.SPI = ctypes.cdll.LoadLibrary(so_filename) + break + if self.SPI is None: + raise RuntimeError('Cannot find sysfs_software_spi.so') + + import Jetson.GPIO + self.GPIO = Jetson.GPIO + + def digital_write(self, pin, value): + self.GPIO.output(pin, value) + + def digital_read(self, pin): + return self.GPIO.input(self.BUSY_PIN) + + def delay_ms(self, delaytime): + time.sleep(delaytime / 1000.0) + + def spi_writebyte(self, data): + self.SPI.SYSFS_software_spi_transfer(data[0]) + + def module_init(self): + self.GPIO.setmode(self.GPIO.BCM) + self.GPIO.setwarnings(False) + self.GPIO.setup(self.RST_PIN, self.GPIO.OUT) + self.GPIO.setup(self.DC_PIN, self.GPIO.OUT) + self.GPIO.setup(self.CS_PIN, self.GPIO.OUT) + self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN) + self.SPI.SYSFS_software_spi_begin() + return 0 + + def module_exit(self): + logging.debug("spi end") + self.SPI.SYSFS_software_spi_end() + + logging.debug("close 5V, Module enters 0 power consumption ...") + self.GPIO.output(self.RST_PIN, 0) + self.GPIO.output(self.DC_PIN, 0) + + self.GPIO.cleanup() + + +if os.path.exists('/sys/bus/platform/drivers/gpiomem-bcm2835'): + implementation = RaspberryPi() +else: + implementation = JetsonNano() + +for func in [x for x in dir(implementation) if not x.startswith('_')]: + setattr(sys.modules[__name__], func, getattr(implementation, func)) -def module_init(): - GPIO.setmode(GPIO.BCM) - GPIO.setwarnings(False) - GPIO.setup(RST_PIN, GPIO.OUT) - GPIO.setup(DC_PIN, GPIO.OUT) - GPIO.setup(CS_PIN, GPIO.OUT) - GPIO.setup(BUSY_PIN, GPIO.IN) - SPI.max_speed_hz = 2000000 - SPI.mode = 0b00 - return 0; ### END OF FILE ### From 47042f0946b5d1987aacdbfebe10992bde280eb8 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Wed, 2 Oct 2019 19:01:07 +0200 Subject: [PATCH 49/54] new: implemented plugin system (closes #54) --- README.md | 6 + sdcard/rootfs/root/pwnagotchi/config.yml | 4 +- sdcard/rootfs/root/pwnagotchi/scripts/main.py | 77 +++++---- .../pwnagotchi/scripts/pwnagotchi/agent.py | 24 ++- .../pwnagotchi/scripts/pwnagotchi/ai/epoch.py | 4 +- .../pwnagotchi/scripts/pwnagotchi/ai/train.py | 30 +++- .../scripts/pwnagotchi/mesh/utils.py | 4 +- .../scripts/pwnagotchi/plugins/__init__.py | 45 +++++ .../pwnagotchi/plugins/default/example.py | 162 ++++++++++++++++++ .../pwnagotchi/plugins/default/ups_lite.py | 65 +++++++ .../scripts/pwnagotchi/ui/display.py | 4 +- .../pwnagotchi/scripts/pwnagotchi/ui/state.py | 3 + .../pwnagotchi/scripts/pwnagotchi/ui/view.py | 17 +- 13 files changed, 397 insertions(+), 48 deletions(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py diff --git a/README.md b/README.md index 45644e4c..b0331f89 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,12 @@ Now you can use the `preview.py`-script to preview the changes: # Now open http://localhost:8080 and http://localhost:8081 ``` +### 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) for a list of default +plugins and all the callbacks that you can define for your own customizations. + ### Random Info - `hostname` sets the unit name. diff --git a/sdcard/rootfs/root/pwnagotchi/config.yml b/sdcard/rootfs/root/pwnagotchi/config.yml index 8da7bc94..7cf1c6f7 100644 --- a/sdcard/rootfs/root/pwnagotchi/config.yml +++ b/sdcard/rootfs/root/pwnagotchi/config.yml @@ -2,6 +2,8 @@ main: # currently implemented: en (default), de, nl, it lang: en + # custom plugins path, if null only default plugins with be loaded + plugins: null # monitor interface to use iface: mon0 # command to run to bring the mon interface up in case it's not up already @@ -21,7 +23,7 @@ main: ai: # if false, only the default 'personality' will be used - enabled: true + enabled: false path: /root/brain.nn # 1.0 - laziness = probability of start training laziness: 0.1 diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/main.py b/sdcard/rootfs/root/pwnagotchi/scripts/main.py index 10e0490e..09f6ec30 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/main.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/main.py @@ -5,7 +5,7 @@ import time import traceback import core -import pwnagotchi +import pwnagotchi, pwnagotchi.plugins as plugins from pwnagotchi.log import SessionParser from pwnagotchi.voice import Voice @@ -25,39 +25,49 @@ args = parser.parse_args() if args.do_clear: print("clearing the display ...") with open(args.config, 'rt') as fp: - config = yaml.safe_load(fp) - 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() + config = yaml.safe_load(fp) + 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() with open(args.config, 'rt') as fp: config = yaml.safe_load(fp) +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.on('loaded') + display = Display(config=config, state={'name': '%s>' % pwnagotchi.name()}) agent = Agent(view=display, config=config) @@ -65,6 +75,9 @@ core.log("%s@%s (v%s)" % (pwnagotchi.name(), agent._identity, pwnagotchi.version # for key, value in config['personality'].items(): # core.log(" %s: %s" % (key, value)) +for _, plugin in plugins.loaded.items(): + core.log("plugin '%s' v%s loaded from %s" % (plugin.__name__, plugin.__version__, plugin.__file__)) + if args.do_manual: core.log("entering manual mode ...") @@ -112,13 +125,15 @@ core.logfile = config['main']['log'] agent.start_ai() agent.setup_events() -agent.set_ready() +agent.set_starting() agent.start_monitor_mode() agent.start_event_polling() # print initial stats agent.next_epoch() +agent.set_ready() + while True: try: # recon on all channels diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index 1fa5112b..bf9ecca2 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -8,6 +8,7 @@ import _thread import core +import pwnagotchi.plugins as plugins from bettercap.client import Client from pwnagotchi.mesh.utils import AsyncAdvertiser from pwnagotchi.ai.train import AsyncTrainer @@ -47,29 +48,35 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): def supported_channels(self): return self._supported_channels - def on_ai_ready(self): - self._view.on_ai_ready() + def set_starting(self): + self._view.on_starting() def set_ready(self): - self._view.on_starting() + plugins.on('ready', self) def set_free_channel(self, channel): self._view.on_free_channel(channel) + plugins.on('free_channel', self, channel) def set_bored(self): self._view.on_bored() + plugins.on('bored', self) def set_sad(self): self._view.on_sad() + plugins.on('sad', self) def set_excited(self): self._view.on_excited() + plugins.on('excited', self) def set_lonely(self): self._view.on_lonely() + plugins.on('lonely', self) def set_rebooting(self): self._view.on_rebooting() + plugins.on('rebooting', self) def setup_events(self): core.log("connecting to %s ..." % self.url) @@ -128,6 +135,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): self.start_advertising() def wait_for(self, t, sleeping=True): + plugins.on('sleep' if sleeping else 'wait', self, t) self._view.wait(t, sleeping) self._epoch.track(sleep=True, inc=t) @@ -179,6 +187,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): def set_access_points(self, aps): self._access_points = aps + plugins.on('wifi_update', self, aps) self._epoch.observe(aps, self._advertiser.peers() if self._advertiser is not None else ()) return self._access_points @@ -338,6 +347,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): if apsta is None: core.log("!!! captured new handshake: %s !!!" % key) self._last_pwnd = ap_mac + plugins.on('handshake', self, ap_mac, sta_mac) else: (ap, sta) = apsta self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap[ @@ -346,6 +356,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): ap['channel'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'])) + plugins.on('handshake', self, ap, sta) except Exception as e: core.log("error: %s" % e) @@ -419,6 +430,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): except Exception as e: self._on_error(ap['mac'], e) + plugins.on('association', self, ap) if throttle > 0: time.sleep(throttle) self._view.on_normal() @@ -439,6 +451,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): except Exception as e: self._on_error(sta['mac'], e) + plugins.on('deauthentication', self, ap, sta) if throttle > 0: time.sleep(throttle) self._view.on_normal() @@ -470,6 +483,9 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): self._current_channel = channel self._epoch.track(hop=True) self._view.set('channel', '%d' % channel) + + plugins.on('channel_hop', self, channel) + except Exception as e: core.log("error: %s" % e) @@ -509,6 +525,8 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): core.log("%d epochs with activity -> excited" % self._epoch.active_for) self.set_excited() + plugins.on('epoch', self, self._epoch.epoch - 1, self._epoch.data()) + if self._epoch.blind_for >= self._config['main']['mon_max_blind_epochs']: core.log("%d epochs without visible access points -> rebooting ..." % self._epoch.blind_for) self._reboot() diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py index bdd8c2e1..8508eb97 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/epoch.py @@ -7,6 +7,7 @@ import pwnagotchi.mesh.wifi as wifi from pwnagotchi.ai.reward import RewardFunction + class Epoch(object): def __init__(self, config): self.epoch = 0 @@ -92,7 +93,8 @@ class Epoch(object): try: peers_per_chan[peer.last_channel - 1] += 1.0 except IndexError as e: - core.log("got peer data on channel %d, we can store %d channels" % (peer.last_channel, wifi.NumChannels)) + core.log( + "got peer data on channel %d, we can store %d channels" % (peer.last_channel, wifi.NumChannels)) # normalize aps_per_chan = [e / num_aps for e in aps_per_chan] diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py index 1312715c..34140dd8 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ai/train.py @@ -7,6 +7,7 @@ import json import core +import pwnagotchi.plugins as plugins import pwnagotchi.ai as ai from pwnagotchi.ai.epoch import Epoch @@ -68,14 +69,14 @@ class Stats(object): core.log("[ai] saving %s" % self.path) data = json.dumps({ - 'born_at': self.born_at, - 'epochs_lived': self.epochs_lived, - 'epochs_trained': self.epochs_trained, - 'rewards': { - 'best': self.best_reward, - 'worst': self.worst_reward - } - }) + 'born_at': self.born_at, + 'epochs_lived': self.epochs_lived, + 'epochs_trained': self.epochs_trained, + 'rewards': { + 'best': self.best_reward, + 'worst': self.worst_reward + } + }) temp = "%s.tmp" % self.path with open(temp, 'wt') as fp: @@ -98,6 +99,11 @@ class AsyncTrainer(object): self._is_training = training self._training_epochs = for_epochs + if training: + plugins.on('ai_training_start', self, for_epochs) + else: + plugins.on('ai_training_end', self) + def is_training(self): return self._is_training @@ -123,8 +129,10 @@ class AsyncTrainer(object): def on_ai_training_step(self, _locals, _globals): self._model.env.render() + plugins.on('ai_training_step', self, _locals, _globals) def on_ai_policy(self, new_params): + plugins.on('ai_policy', self, new_params) core.log("[ai] setting new policy:") for name, value in new_params.items(): if name in self._config['personality']: @@ -139,13 +147,19 @@ class AsyncTrainer(object): self.run('set wifi.sta.ttl %d' % self._config['personality']['sta_ttl']) self.run('set wifi.rssi.min %d' % self._config['personality']['min_rssi']) + def on_ai_ready(self): + self._view.on_ai_ready() + plugins.on('ai_ready', self) + def on_ai_best_reward(self, r): core.log("[ai] best reward so far: %s" % r) self._view.on_motivated(r) + plugins.on('ai_best_reward', self, r) def on_ai_worst_reward(self, r): core.log("[ai] worst reward so far: %s" % r) self._view.on_demotivated(r) + plugins.on('ai_worst_reward', self, r) def _ai_worker(self): self._model = ai.load(self._config, self, self._epoch) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py index c99cd578..8c84b942 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/mesh/utils.py @@ -1,7 +1,7 @@ import _thread import core -import pwnagotchi +import pwnagotchi, pwnagotchi.plugins as plugins from pwnagotchi.mesh import get_identity @@ -37,6 +37,8 @@ class AsyncAdvertiser(object): def _on_new_unit(self, peer): self._view.on_new_peer(peer) + plugins.on('peer_detected', self, peer) def _on_lost_unit(self, peer): self._view.on_lost_peer(peer) + plugins.on('peer_lost', self, peer) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py new file mode 100644 index 00000000..6f84a901 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/__init__.py @@ -0,0 +1,45 @@ +import os +import glob +import importlib, importlib.util + +# import core + +default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default") +loaded = {} + + +def dummy_callback(): + pass + + +def on(event_name, *args, **kwargs): + global loaded + cb_name = 'on_%s' % event_name + for _, plugin in loaded.items(): + if cb_name in plugin.__dict__: + # print("calling %s %s(%s)" %(cb_name, args, kwargs)) + plugin.__dict__[cb_name](*args, **kwargs) + + +def load_from_file(filename): + plugin_name = os.path.basename(filename.replace(".py", "")) + spec = importlib.util.spec_from_file_location(plugin_name, filename) + instance = importlib.util.module_from_spec(spec) + spec.loader.exec_module(instance) + return plugin_name, instance + + +def load_from_path(path): + 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__: + # print("plugin %s is not enabled" % name) + pass + else: + loaded[name] = plugin + + return 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 new file mode 100644 index 00000000..60efbd28 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py @@ -0,0 +1,162 @@ +__author__ = 'evilsocket@gmail.com' +__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. + +from pwnagotchi.ui.components import LabeledValue +from pwnagotchi.ui.view import BLACK +import pwnagotchi.ui.fonts as fonts +import core + + +# called when the plugin is loaded +def on_loaded(): + core.log("WARNING: plugin %s should be disabled!" % __name__) + + +# called to setup the ui elements +def on_ui_setup(ui): + # add custom UI elements + ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 - 25, 0), + label_font=fonts.Bold, text_font=fonts.Medium)) + + +# called when the ui is updated +def on_ui_update(ui): + # update those elements + some_voltage = 0.1 + some_capacity = 100.0 + + ui.set('ups', "%4.2fV/%2i%%" % (some_voltage, some_capacity)) + + +# called when the hardware display setup is done, display is an hardware specific object +def on_display_setup(display): + pass + + +# called when everything is ready and the main loop is about to start +def on_ready(agent): + core.log("unit is ready") + # you can run custom bettercap commands if you want + # agent.run('ble.recon on') + # or set a custom state + # agent.set_bored() + + +# called when the AI finished loading +def on_ai_ready(agent): + pass + + +# called when the AI finds a new set of parameters +def on_ai_policy(agent, policy): + pass + + +# called when the AI starts training for a given number of epochs +def on_ai_training_start(agent, epochs): + pass + + +# called after the AI completed a training epoch +def on_ai_training_step(agent, _locals, _globals): + pass + + +# called when the AI has done training +def on_ai_training_end(agent): + pass + + +# called when the AI got the best reward so far +def on_ai_best_reward(agent, reward): + pass + + +# called when the AI got the best reward so far +def on_ai_worst_reward(agent, reward): + pass + + +# called when a non overlapping wifi channel is found to be free +def on_free_channel(agent, channel): + pass + + +# called when the status is set to bored +def on_bored(agent): + pass + + +# called when the status is set to sad +def on_sad(agent): + pass + + +# called when the status is set to excited +def on_excited(agent): + pass + + +# called when the status is set to lonely +def on_lonely(agent): + pass + + +# called when the agent is rebooting the board +def on_rebooting(agent): + pass + + +# called when the agent is waiting for t seconds +def on_wait(agent, t): + pass + + +# called when the agent is sleeping for t seconds +def on_sleep(agent, t): + pass + + +# called when the agent refreshed its access points list +def on_wifi_update(agent, access_points): + pass + + +# called when the agent is sending an association frame +def on_association(agent, access_point): + pass + + +# callend when the agent is deauthenticating a client station from an AP +def on_deauthentication(agent, access_point, client_station): + pass + + +# callend when the agent is tuning on a specific channel +def on_channel_hop(agent, channel): + pass + + +# called when a new handshake is captured, access_point and client_station are json objects +# if the agent could match the BSSIDs to the current list, otherwise they are just the strings of the BSSIDs +def on_handshake(agent, access_point, client_station): + pass + + +# called when an epoch is over (where an epoch is a single loop of the main algorithm) +def on_epoch(agent, epoch, epoch_data): + pass + + +# called when a new peer is detected +def on_peer_detected(agent, peer): + pass + + +# called when a known peer is lost +def on_peer_lost(agent, peer): + pass 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 new file mode 100644 index 00000000..7ddcecdd --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/ups_lite.py @@ -0,0 +1,65 @@ +# Based on UPS Lite v1.1 from https://github.com/xenDE +# +# funtions for get UPS status - needs enable "i2c" in raspi-config +# +# https://github.com/linshuqin329/UPS-Lite +# +# For Raspberry Pi Zero Ups Power Expansion Board with Integrated Serial Port S3U4 +# https://www.ebay.de/itm/For-Raspberry-Pi-Zero-Ups-Power-Expansion-Board-with-Integrated-Serial-Port-S3U4/323873804310 +# https://www.aliexpress.com/item/32888533624.html +__author__ = 'evilsocket@gmail.com' +__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 pwnagotchi.ui.components import LabeledValue +from pwnagotchi.ui.view import BLACK +import pwnagotchi.ui.fonts as fonts + + +# TODO: add enable switch in config.yml an cleanup all to the best place +class UPS: + def __init__(self): + # only import when the module is loaded and enabled + import smbus + # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1) + self._bus = smbus.SMBus(1) + + def voltage(self): + try: + address = 0x36 + read = self._bus.read_word_data(address, 2) + swapped = struct.unpack("H", read))[0] + return swapped * 1.25 / 1000 / 16 + except: + return 0.0 + + def capacity(self): + try: + address = 0x36 + read = self._bus.read_word_data(address, 4) + swapped = struct.unpack("H", read))[0] + return swapped / 256 + except: + return 0.0 + + +ups = None + + +def on_loaded(): + global ups + ups = UPS() + + +def on_ui_setup(ui): + ui.add_element('ups', LabeledValue(color=BLACK, label='UPS', value='0%/0V', position=(ui.width() / 2 - 25, 0), + label_font=fonts.Bold, text_font=fonts.Medium)) + + +def on_ui_update(ui): + ui.set('ups', "%4.2fV/%2i%%" % (ups.voltage(), ups.capacity())) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py index 4c693a69..657aefbb 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/display.py @@ -4,7 +4,7 @@ from threading import Lock import shutil import core import os -import pwnagotchi +import pwnagotchi, pwnagotchi.plugins as plugins from pwnagotchi.ui.view import WHITE, View @@ -146,6 +146,8 @@ class Display(View): else: core.log("unknown display type %s" % self._display_type) + plugins.on('display_setup', self._display) + self.on_render(self._on_view_rendered) def image(self): diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py index 71b7d4ee..c5b66be3 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/state.py @@ -7,6 +7,9 @@ class State(object): self._lock = Lock() self._listeners = {} + def add_element(self, key, elem): + self._state[key] = elem + def add_listener(self, key, cb): with self._lock: self._listeners[key] = cb diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/ui/view.py index 19e79999..3ae90895 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 from PIL import Image, ImageDraw import core -import pwnagotchi +import pwnagotchi.plugins as plugins from pwnagotchi.voice import Voice import pwnagotchi.ui.fonts as fonts @@ -41,7 +41,7 @@ def setup_display_specifics(config): name_pos = (int(width / 2) - 15, int(height * .15)) status_pos = (int(width / 2) - 15, int(height * .30)) - elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1', + elif config['ui']['display']['type'] in ('ws_1', 'ws1', 'waveshare_1', 'waveshare1', 'ws_2', 'ws2', 'waveshare_2', 'waveshare2'): fonts.setup(10, 9, 10, 35) @@ -105,8 +105,19 @@ class View(object): for key, value in state.items(): self._state.set(key, value) + plugins.on('ui_setup', self) + _thread.start_new_thread(self._refresh_handler, ()) + def add_element(self, key, elem): + self._state.add_element(key, elem) + + def width(self): + return self._width + + def height(self): + return self._height + def on_state_change(self, key, cb): self._state.add_listener(key, cb) @@ -294,6 +305,8 @@ class View(object): self._canvas = Image.new('1', (self._width, self._height), WHITE) drawer = ImageDraw.Draw(self._canvas) + plugins.on('ui_update', self) + for key, lv in self._state.items(): lv.draw(self._canvas, drawer) From 5ced9c6ecdb23d95b5e4ab099ba3216d7ddcfae6 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Wed, 2 Oct 2019 19:02:11 +0200 Subject: [PATCH 50/54] fixed readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b0331f89..5e4567ae 100644 --- a/README.md +++ b/README.md @@ -151,7 +151,7 @@ Now you can use the `preview.py`-script to preview the changes: ### 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) for a list of default +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. ### Random Info From b948627bd5e7a83ddd68c66a56c0b8c105563d08 Mon Sep 17 00:00:00 2001 From: Jeroen Massar Date: Wed, 2 Oct 2019 19:03:50 +0200 Subject: [PATCH 51/54] Fix CRLF line endings... Before: ``` bash: ./update_pwnagotchi.sh: /bin/bash^M: bad interpreter: No such file or directory ``` Thus: ``` scripts/update_pwnagotchi.sh: Bourne-Again shell script text executable, ASCII text, with CRLF line terminators dos2unix: converting file scripts/update_pwnagotchi.sh to Unix format... scripts/update_pwnagotchi.sh: Bourne-Again shell script text executable, ASCII text ``` Now it works :) --- scripts/update_pwnagotchi.sh | 220 +++++++++++++++++------------------ 1 file changed, 110 insertions(+), 110 deletions(-) diff --git a/scripts/update_pwnagotchi.sh b/scripts/update_pwnagotchi.sh index 34e4eedf..0039e7bc 100644 --- a/scripts/update_pwnagotchi.sh +++ b/scripts/update_pwnagotchi.sh @@ -1,111 +1,111 @@ -#!/bin/bash -# Default variables -GIT_FOLDER="/tmp/pwnagotchi" -GIT_URL="https://github.com/evilsocket/pwnagotchi/" -VERSION="master" -SUPPORTED_RESTART_MODES=( 'auto' 'manual' ) -MODE="auto" -BACKUPCONFIG=0 -RESTORECONFIG=0 - -# Functions -function usage() { - cat < Date: Wed, 2 Oct 2019 19:09:24 +0200 Subject: [PATCH 52/54] Improved IT translation --- .../pwnagotchi/locale/it/LC_MESSAGES/voice.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po index f84e16c3..3dabc3de 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/locale/it/LC_MESSAGES/voice.po @@ -24,7 +24,7 @@ msgid "" "Hi, I'm Pwnagotchi!\n" "Starting ..." msgstr "" -"Ciao!" +"Ciao!\n" "Piacere Pwnagotchi!\n" "Caricamento ..." @@ -155,9 +155,9 @@ msgid "" "goodbye\n" "{name}" msgstr "" -"Uhm ..." +"Uhm ...\n" "addio\n" -"{name}," +"{name},\n" "mi mancherai..." #: voice.py:84 @@ -236,8 +236,8 @@ msgstr "Aspetto {secs}s ..." #, python-brace-format msgid "Looking around ({secs}s)" msgstr "" -"Do uno sguardo" -"qui intorno..." +"Do uno sguardo\n" +"qui intorno...\n" "({secs}s)" #: voice.py:123 @@ -258,7 +258,7 @@ msgid "" "{what}" msgstr "" "Collegamento con\n" -"{what}" +"{what}\n" "in corso..." #: voice.py:125 From 5725d8b23956e4a20d8bb25f30b76ec4063539a8 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Wed, 2 Oct 2019 19:41:50 +0200 Subject: [PATCH 53/54] new: gps coordinates are saved along with handshakes if gps is connected (related to #55) --- .../pwnagotchi/scripts/pwnagotchi/agent.py | 8 +++- .../pwnagotchi/plugins/default/example.py | 2 +- .../scripts/pwnagotchi/plugins/default/gps.py | 47 +++++++++++++++++++ 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py index bf9ecca2..739d6ed4 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/agent.py @@ -45,6 +45,9 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): pass return False + def config(self): + return self._config + def supported_channels(self): return self._supported_channels @@ -336,6 +339,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): try: for h in [e for e in self.events() if e['tag'] == 'wifi.client.handshake']: + filename = h['data']['file'] sta_mac = h['data']['station'] ap_mac = h['data']['ap'] key = "%s -> %s" % (sta_mac, ap_mac) @@ -347,7 +351,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): if apsta is None: core.log("!!! captured new handshake: %s !!!" % key) self._last_pwnd = ap_mac - plugins.on('handshake', self, ap_mac, sta_mac) + plugins.on('handshake', self, filename, ap_mac, sta_mac) else: (ap, sta) = apsta self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap[ @@ -356,7 +360,7 @@ class Agent(Client, AsyncAdvertiser, AsyncTrainer): ap['channel'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'])) - plugins.on('handshake', self, ap, sta) + plugins.on('handshake', self, filename, ap, sta) except Exception as e: core.log("error: %s" % e) 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 60efbd28..4a63275e 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/example.py @@ -143,7 +143,7 @@ def on_channel_hop(agent, channel): # called when a new handshake is captured, access_point and client_station are json objects # if the agent could match the BSSIDs to the current list, otherwise they are just the strings of the BSSIDs -def on_handshake(agent, access_point, client_station): +def on_handshake(agent, filename, access_point, client_station): 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 new file mode 100644 index 00000000..c3c53a98 --- /dev/null +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/plugins/default/gps.py @@ -0,0 +1,47 @@ +__author__ = 'evilsocket@gmail.com' +__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 core +import json +import os + +device = '/dev/ttyUSB0' +speed = 19200 +running = False + + +def on_loaded(): + core.log("GPS plugin loaded for %s" % device) + + +def on_ready(agent): + global running + + if os.path.exists(device): + core.log("enabling GPS bettercap's module for %s" % device) + try: + agent.run('gps off') + except: + pass + + agent.run('set gps.device %s' % device) + agent.run('set gps.speed %d' % speed) + agent.run('gps on') + running = True + else: + core.log("no GPS detected") + + +def on_handshake(agent, filename, access_point, client_station): + if running: + info = agent.session() + gps = info['gps'] + gps_filename = filename.replace('.pcap', '.gps.json') + + core.log("saving GPS to %s (%s)" % (gps_filename, gps)) + with open(gps_filename, 'w+t') as fp: + json.dump(gps, fp) From cf1558eb29792f17fa4b62af01e2fe60a0ec13e2 Mon Sep 17 00:00:00 2001 From: Simone Margaritelli Date: Wed, 2 Oct 2019 19:58:01 +0200 Subject: [PATCH 54/54] fix: keep led on to understand when the unit is still alive --- .../rootfs/root/pwnagotchi/scripts/blink.sh | 5 --- .../pwnagotchi/scripts/pwnagotchi/voice.py | 35 ++++--------------- 2 files changed, 7 insertions(+), 33 deletions(-) diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh b/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh index 48673dc2..e7f475eb 100755 --- a/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh +++ b/sdcard/rootfs/root/pwnagotchi/scripts/blink.sh @@ -10,8 +10,3 @@ done echo 0 >/sys/class/leds/led0/brightness sleep 0.3 - -# Powersave options -# Disable power LED ~30ma -echo none >/sys/class/leds/led0/trigger -echo 1 >/sys/class/leds/led0/brightness diff --git a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py index 45f5092d..53460ed0 100644 --- a/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py +++ b/sdcard/rootfs/root/pwnagotchi/scripts/pwnagotchi/voice.py @@ -17,44 +17,36 @@ class Voice: def default(self): return self._('ZzzzZZzzzzZzzz') - def on_starting(self): return random.choice([ \ self._('Hi, I\'m Pwnagotchi!\nStarting ...'), self._('New day, new hunt,\nnew pwns!'), self._('Hack the Planet!')]) - def on_ai_ready(self): return random.choice([ self._('AI ready.'), self._('The neural network\nis ready.')]) - def on_normal(self): return random.choice([ \ '', '...']) - def on_free_channel(self, channel): return self._('Hey, channel {channel} is\nfree! Your AP will\nsay thanks.').format(channel=channel) - def on_bored(self): return random.choice([ \ self._('I\'m bored ...'), self._('Let\'s go for a walk!')]) - def on_motivated(self, reward): return self._('This is the best\nday of my life!') - def on_demotivated(self, reward): return self._('Shitty day :/') - def on_sad(self): return random.choice([ \ self._('I\'m extremely bored ...'), @@ -62,7 +54,6 @@ class Voice: self._('I\'m sad'), '...']) - def on_excited(self): return random.choice([ \ self._('I\'m living the life!'), @@ -71,51 +62,43 @@ class Voice: self._('I\'m having so much\nfun!'), self._('My crime is that of\ncuriosity ...')]) - def on_new_peer(self, peer): return random.choice([ \ self._('Hello\n{name}!\nNice to meet you. {name}').format(name=peer.name()), self._('Unit\n{name}\nis nearby! {name}').format(name=peer.name())]) - def on_lost_peer(self, peer): return random.choice([ \ self._('Uhm ...\ngoodbye\n{name}').format(name=peer.name()), self._('{name}\nis gone ...').format(name=peer.name())]) - def on_miss(self, who): return random.choice([ \ self._('Whoops ...\n{name}\nis gone.').format(name=who), self._('{name}\nmissed!').format(name=who), self._('Missed!')]) - def on_lonely(self): return random.choice([ \ self._('Nobody wants to\nplay with me ...'), self._('I feel so alone ...'), self._('Where\'s everybody?!')]) - def on_napping(self, secs): return random.choice([ \ self._('Napping for {secs}s ...').format(secs=secs), self._('Zzzzz'), self._('ZzzZzzz ({secs}s)').format(secs=secs)]) - def on_awakening(self): return random.choice(['...', '!']) - def on_waiting(self, secs): return random.choice([ \ self._('Waiting for {secs}s ...').format(secs=secs), '...', self._('Looking around ({secs}s)').format(secs=secs)]) - def on_assoc(self, ap): ssid, bssid = ap['hostname'], ap['mac'] what = ssid if ssid != '' and ssid != '' else bssid @@ -124,23 +107,19 @@ class Voice: self._('Associating to\n{what}').format(what=what), self._('Yo\n{what}!').format(what=what)]) - - def on_deauth(self,sta): + def on_deauth(self, sta): return random.choice([ \ self._('Just decided that\n{mac}\nneeds no WiFi!').format(mac=sta['mac']), self._('Deauthenticating\n{mac}').format(mac=sta['mac']), self._('Kickbanning\n{mac}!').format(mac=sta['mac'])]) - def on_handshakes(self, new_shakes): s = 's' if new_shakes > 1 else '' return self._('Cool, we got {num}\nnew handshake{plural}!').format(num=new_shakes, plural=s) - def on_rebooting(self): return self._("Ops, something\nwent wrong ...\nRebooting ...") - def on_log(self, log): status = self._('Kicked {num} stations\n').format(num=log.deauthed) status += self._('Made {num} new friends\n').format(num=log.associated) @@ -151,10 +130,10 @@ class Voice: status += self._('Met {num} peers').format(num=log.peers) return status - def on_log_tweet(self, log): - return self._('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').format( - duration=log.duration_human, - deauthed=log.deauthed, - associated=log.associated, - handshakes=log.handshakes) + return self._( + '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').format( + duration=log.duration_human, + deauthed=log.deauthed, + associated=log.associated, + handshakes=log.handshakes)