Compare commits

..

234 Commits

Author SHA1 Message Date
6cdc892264 Merge pull request #363 from wpa-2/patch-2
Update defaults.toml
2025-03-08 07:28:12 +01:00
531f5f3c45 Update defaults.toml
Signed-off-by: wpa-2 <9049886+wpa-2@users.noreply.github.com>
2025-03-07 21:08:41 +00:00
fb7ef7b1dd Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-11-17 21:56:42 +01:00
28ff1429ac Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-11-17 21:52:58 +01:00
68941abc08 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-11-17 21:00:28 +01:00
a7379d18e6 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-11-17 20:42:34 +01:00
f9318ef27a Merge remote-tracking branch 'origin/master' 2024-11-17 20:07:59 +01:00
cedb3d35ff Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-11-17 20:07:55 +01:00
4861a0c08b Merge pull request #211 from SeanDuggan/master
Icelandic Translations for IS Locale
2024-10-02 19:25:34 +02:00
766463280d Updated missing charset line
Signed-off-by: SeanDuggan <duggse01@risk.regn.net>
2024-10-01 16:48:39 +01:00
29e278da57 Icelandic Translations
Signed-off-by: SeanDuggan <duggse01@risk.regn.net>
2024-09-30 22:16:06 +01:00
7e6d198c9b Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-09-19 07:37:15 +02:00
4029b2ffa0 Merge pull request #203 from Sniffleupagus/usr1-save-recovery
add mode parameter to agent._restart, and call agent._restart from US…
2024-09-08 21:04:46 +02:00
32d244ec6f add mode parameter to agent._restart, and call agent._restart from USR1 handler instead of pwnagotchi.restart() 2024-09-08 19:25:09 +01:00
Rai
79e141320c Merge pull request #202 from quymdh/dev-q
Update: agent.py, train.py
2024-08-31 04:37:15 +10:00
330110843c Fix:
- Pwnagochi service is not running
 - Handshake not being captured
2024-08-30 16:19:43 +00:00
dc5b297a82 Merge pull request #197 from keganpowers34/patch-1
Update waveshare3in7.py
2024-08-26 21:43:22 +02:00
e8f23d654c Update waveshare3in7.py
fix return outside of function error 

Signed-off-by: keganpowers34 <42286354+keganpowers34@users.noreply.github.com>
2024-08-26 12:04:39 -06:00
Rai
aedbf6bbfb Update README.md
Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-08-26 23:26:40 +10:00
0b3fc98f1c Merge pull request #196 from EatPrilosec/fixbuild
Fix build
2024-08-25 22:13:21 +02:00
7edaa9040e remove unnecessary action input
Signed-off-by: EatPrilosec <ae3nerdgod@gmail.com>
2024-08-25 07:02:37 -04:00
6b6f5923ee Compensate for ../../../<output file>.img
i assume this is for local builds, because it outputs the file outside of runner workdir entirely. compensated by making extra directory levels

Signed-off-by: EatPrilosec <ae3nerdgod@gmail.com>
2024-08-25 05:29:56 -04:00
d6bd65333e Employ matrix build strategy
- workaround for binfmt error
- speeds up builds
- allows for easier board additions

Signed-off-by: EatPrilosec <ae3nerdgod@gmail.com>
2024-08-24 22:44:46 -04:00
f81f1cedfc fix build
libraspberrypi-bin seems to be provided by raspi-utils now

Signed-off-by: EatPrilosec <ae3nerdgod@gmail.com>
2024-08-24 12:05:59 -04:00
f6fa4ef39e fix build
libraspberrypi-bin seems to be provided by raspi-utils now

Signed-off-by: EatPrilosec <ae3nerdgod@gmail.com>
2024-08-24 12:05:09 -04:00
e2ac10babb Merge pull request #195 from mendoitarou/master
Update Japanese (JA) Language
2024-08-23 20:54:10 +02:00
bff310ea3e Add files via upload
Signed-off-by: mendoitarou_ <42207304+mendoitarou@users.noreply.github.com>
2024-08-23 21:01:31 +09:00
a53130321f Update voice.po
Signed-off-by: mendoitarou_ <42207304+mendoitarou@users.noreply.github.com>
2024-08-23 20:39:56 +09:00
730cdad7cd Delete pwnagotchi/locale/ja/LC_MESSAGES/voice.mo
Signed-off-by: mendoitarou_ <42207304+mendoitarou@users.noreply.github.com>
2024-08-23 20:39:22 +09:00
85746046e1 Merge pull request #192 from wlmh110/master
waveshare e-lnk 2.13 V3/V4 update
2024-08-21 18:31:45 +02:00
fbe8211a10 waveshare e-lnk 2.13 V3/V4 update
Optimize the initialization function to resolve the issue of noise in the first few frames caused by the lack of buffer initialization.

Signed-off-by: 铲屎将军 <37292630+wlmh110@users.noreply.github.com>
2024-08-21 22:43:47 +08:00
Rai
ea4f495ab8 Merge pull request #167 from Sniffleupagus/patch-3
Add new configuration option "ui.cursor" to enable or disable blinking cursor
2024-08-19 02:26:24 +10:00
afb840212d Added ui.cursor to defaults.toml
Signed-off-by: Sniffleupagus <129890632+Sniffleupagus@users.noreply.github.com>
2024-08-18 12:16:14 -04:00
82b64baaed Fixed default value to maintain original behavior (True)
Signed-off-by: Sniffleupagus <129890632+Sniffleupagus@users.noreply.github.com>
2024-08-18 12:15:03 -04:00
244d3c03f9 Change 'showcursor' to 'curso
Signed-off-by: Sniffleupagus <129890632+Sniffleupagus@users.noreply.github.com>
2024-08-18 12:06:45 -04:00
Rai
c440a73824 Update README.md
changes a few url

Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-08-17 21:57:02 +10:00
Rai
48b3d6dcb5 Update waveshare3in7.py
adds fixes for #185 

Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-08-13 23:21:13 +10:00
Rai
b9531c60a2 adds v3 and v4 to waveshare 2in3 is any
Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-08-13 23:07:40 +10:00
Rai
27aac52e1f missed a thread
Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-08-11 02:57:44 +10:00
77998cd214 Merge pull request #182 from rai68/log-changes
Log changes
2024-08-07 19:45:35 +02:00
Rai
03c33e1be3 Merge branch 'master' into log-changes
Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-08-07 00:58:01 +10:00
4f63af63a8 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-31 00:33:52 +02:00
6ceb27f837 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-30 22:51:03 +02:00
5d5cde5409 Revert "Update build"
This reverts commit 2630068c7b.
2024-07-28 17:22:45 +02:00
2630068c7b Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-28 17:21:28 +02:00
Rai
de940d0e77 Merge branch 'jayofelony:master' into log-changes 2024-07-28 20:27:09 +10:00
0f36a10567 Update __init__.py 2024-07-28 17:46:53 +10:00
65a93812ef Merge remote-tracking branch 'origin/master' 2024-07-26 23:29:05 +02:00
022ebccf30 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-26 23:28:59 +02:00
Rai
e5812e86c1 fixes an indent in 1in44 lcd waveshare
Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-07-13 19:05:12 +10:00
1ee940c798 adds daemonise and plugin as threads 2024-07-09 07:35:53 +10:00
e3f0da6193 small fixes 2024-07-09 04:57:52 +10:00
f9efbb56cd Update defaults.toml 2024-07-09 04:24:43 +10:00
89a589af72 changes to logging and threading 2024-07-09 04:22:18 +10:00
a100933678 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-02 15:10:17 +02:00
3584f3f551 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-02 15:04:51 +02:00
3fdcebc90c Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-02 15:04:33 +02:00
e33bec1d31 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-02 15:03:06 +02:00
de0a09e39d Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-01 20:15:45 +02:00
dbb83b4825 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-01 16:05:45 +02:00
956c083985 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-01 16:00:09 +02:00
62c324730c Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-01 13:17:12 +02:00
8dc6f78610 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-01 13:16:44 +02:00
0542c002d0 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-01 13:16:28 +02:00
702d463194 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-07-01 07:51:18 +02:00
087fd9cf09 Revert
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-30 20:07:53 +02:00
28335419f6 MLS is offline
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-30 20:07:41 +02:00
db444588dd Wiki
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-16 17:07:58 +02:00
de08804b7f pycharm files
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:04:42 +02:00
9d6a7e9441 Same files added to create a package
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:04:17 +02:00
14480346fe Change how spi is called.
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:03:56 +02:00
7b6ad4e99a More pythonic
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:03:36 +02:00
313edb1524 Duplicate display file
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:03:23 +02:00
820f2cef59 Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:02:58 +02:00
c76d9f4909 Try to get a fix for device is busy while changing channels.
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:02:47 +02:00
69ff6cd03c Add pisugar 3 plugin to default plugins
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:02:23 +02:00
09f6281666 Remove bt helper
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:02:07 +02:00
2f1c216387 Add inky phat v2
Change import for v1

Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:01:52 +02:00
87d8beb9be Change bettercap version check for oPwngrid
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:01:17 +02:00
e63be1ffd8 Add extra check for fix_services.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:00:53 +02:00
d5755103a0 Remove pisugar2 settings
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 20:00:30 +02:00
2014c22262 Fix couple displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 19:59:51 +02:00
5295692da9 Added display inky phat v2
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-15 19:58:54 +02:00
b7eb86d55c Update view.py 2024-06-13 05:45:42 +10:00
81c3581138 Merge pull request #149
Move BT status position in view
2024-06-12 21:00:40 +02:00
7d8b66e1cb Update displayhatmini.py 2024-06-13 04:18:57 +10:00
689d39c450 more changes 2024-06-13 03:37:51 +10:00
8eccd71c6b changes to ui 2024-06-13 02:55:05 +10:00
Rai
caf73700fd Merge branch 'jayofelony:master' into master 2024-06-12 20:40:08 +10:00
e9c12dde94 Add new configuration option "ui.showcursor" to enable or disable blinking cursor by name
When ui.fps is not zero, the default UI adds a blinking cursor next to the pwnagotchi name, as a verification that the display is updating. This proposed change adds a configuration option "ui.showcursor" to allow users to disable the cursor. If ui.showcursor is set to "true" in config.toml, the cursor will show, if set "false" in config, the cursor will not be shown. Default behavior if ui.showcursor is not set is maintained (cursor will show). If ui.fps is set to 0, the cursor will not be shown regardless of the ui.showcursor setting.

(tested on a single pwny with showcursor unset, false, and true, multiple times)

Signed-off-by: Sniffleupagus <129890632+Sniffleupagus@users.noreply.github.com>
2024-06-11 10:00:32 -07:00
3f40c0b7b3 Switch to bettercap lite
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-06 14:36:33 +02:00
318e3480ce Remove clear on exit, invokes an extra restart at boot
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-06 13:43:59 +02:00
1614d1f94d Updated fix_services.py
Updated pwnagotchi

Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-06 13:41:19 +02:00
4e1f08f6a8 Updated partnership with PiSugar team.
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-05 10:55:21 +02:00
cbc601e38b Updated displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-05 10:50:15 +02:00
20bae7adaa Version 2.9.2
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-03 21:49:57 +02:00
ed62ac0b84 Version 2.9.2
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-03 20:06:32 +02:00
f0ecee0555 Merge remote-tracking branch 'origin/master' 2024-06-02 12:47:58 +02:00
8e99ae419d Version 2.9.2
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-06-02 12:47:51 +02:00
88957059ef Merge pull request #148 from energydrinksjunkie/master
added serbian language
2024-05-01 23:27:45 +02:00
c42e8d0f5d Move BT status position in view
This moves the position of BT status a little to the left to make enough space for battery plugin status.

When a battery plugin is used along with bt-tether, BT status can overwrite the first character of the battery plugin status.

Signed-off-by: Ayman Bagabas <ayman.bagabas@gmail.com>
2024-05-01 16:26:11 -04:00
5b5718c186 added serbian language 2024-05-01 22:22:01 +02:00
70f0dcb891 Merge pull request #144 from jfhenriques/master
Fix condition error in view.py when using invert=true
2024-04-26 19:06:09 +02:00
8f02c36d63 Merge branch 'jayofelony:master' into master 2024-04-26 16:16:11 +01:00
9941f093e9 Fix issue with FilledRect when using ui.invert=true 2024-04-26 16:14:05 +01:00
de07226be1 Update _version.py 2024-04-26 17:03:16 +02:00
6603e01005 Update pwnlib 2024-04-26 17:02:51 +02:00
e2fa3ca138 Update pwnlib 2024-04-26 17:02:33 +02:00
357ffc67e5 Update _version.py
Signed-off-by: Jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-26 09:19:13 +02:00
ea8fb5e533 Merge pull request #139 from RKouchoo/master
Fix 3.7 orientation
2024-04-26 06:37:39 +02:00
31afd6d0ba Merge pull request #138 from kszabi1/fix-ui-components-draw
Fix [#137 issue]: Incorrect use of assignment operator (=) instead of comparison operator (==) in draw method
2024-04-26 06:37:28 +02:00
b38274e652 Fix 3.7 orientation 2024-04-26 13:21:55 +10:00
518e8c219c Fix incorrect use of assignment operator (=) instead of comparison operator (==) in draw method of ui/components.py 2024-04-26 01:34:26 +02:00
4e07fbf1aa Update raspberrypi32.yml
Signed-off-by: Jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-25 20:30:45 +02:00
b3e81a95c8 Update raspberrypi32.yml
Signed-off-by: Jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-25 20:06:54 +02:00
050966215b Merge pull request #132
I2C oled support for SSD1306 chipsed oled screens
2024-04-22 08:41:34 +02:00
fef442edbb I2C oled driver mods by NurseJackass
I2C oled config can be added in the config.toml
Default is 128x64 display on i2c address 0x3C

ui.display.type = "i2coled"
ui.display.i2c_addr = 0x3C
ui.display.width = 128
ui.display.height = 64
2024-04-18 17:39:53 +02:00
1064936503 Small changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-15 15:23:47 +02:00
a762a7f763 Merge remote-tracking branch 'origin/master' 2024-04-15 15:23:41 +02:00
8fd0e358a9 Small changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-15 15:23:34 +02:00
9a941c1d46 Merge branch 'jayofelony:master' into master 2024-04-04 15:46:29 +02:00
ead5a3baac Merge pull request #121 from rai68/patch-2
Update components.py
2024-04-03 21:58:17 +02:00
ac2973889d Update FUNDING.yml 2024-04-03 21:14:22 +02:00
Rai
8991dd6811 Update components.py
this allows plugins / ui elements of bitmap to be inverted for plugins etc

Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-04-04 03:04:31 +10:00
415e5cd551 Small changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-03 09:39:38 +02:00
47705ba1a2 Update config.txt at creation of image file, no more overwriting at auto-update.
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-03 09:39:10 +02:00
7c7bbc770b Merge branch 'jayofelony:master' into master 2024-04-02 17:54:00 +02:00
ab83de4905 separate I2C Oled display
Separate files for ggeneric I2C Oled display with SSD1306 driver
128x64 resolution is tested, 128x32 and 96x16 resolutions is not tested yet
2024-04-02 17:46:11 +02:00
8f7741cd9e Remove unused imports
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-04-01 17:30:51 +02:00
835886e6f6 Merge pull request #114
Update Traditional Chinese (TW) Language
2024-04-01 17:29:58 +02:00
6b2039a8e6 Merge pull request #116
Fix Waveshare V2 Position
2024-04-01 17:29:28 +02:00
d53d0c7841 Merge pull request #117
Fix range of lines about the displays
2024-04-01 17:29:10 +02:00
6c40998b51 Merge pull request #118
Fix typo in ansible script
2024-04-01 17:28:18 +02:00
a71a90ba3d Delete config.py 2024-04-01 01:37:47 +02:00
b03f6f747b Generic I2C Oled support , waveshare oled/lcd vertical layout
work in progress for the triple screen project
2024-03-31 23:55:15 +02:00
a8ba88c9cc Fix typo in ansible script
Signed-off-by: Morten Winther Olsson <18525061+olwimo@users.noreply.github.com>
2024-03-30 08:04:55 +01:00
f597bd6d29 Fix range of lines about the displays
Signed-off-by: Benoît Allard <benoit.allard@gmx.de>
2024-03-29 15:08:07 +01:00
a3f103ac06 Fix Waveshare V2 Position
The current location "178, 84" does not correctly display the temperature symbol (Cellsius, Kelvin, etc.). I fix the code whit the correct position.

Signed-off-by: Andrea Draghetti <drego85@draghetti.it>
2024-03-29 08:57:45 +01:00
e0a068e51d Upload tw voice.mo
Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com>
2024-03-27 18:46:42 +08:00
dc1b3c7635 Delete tw voice.mo
Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com>
2024-03-27 18:45:59 +08:00
3657859a73 Update tw voice.po
Signed-off-by: alan67160 <20385640+alan67160@users.noreply.github.com>
2024-03-27 18:45:21 +08:00
33ff5a0bf8 Fix ui.invert
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-27 07:37:59 +01:00
666f65c640 Merge pull request #110
Update Portuguese (Brazil) Language
2024-03-27 07:36:24 +01:00
84d45a0d45 Version 2.9.0
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-27 07:20:45 +01:00
06a4491008 Update 32bit to use latest pwngrid/bettercap
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-27 07:17:35 +01:00
5485f83ca6 Update Portuguese (Brazil) Language 2024-03-26 14:06:55 -03:00
Rai
8a242a707b Update LCD_2inch4.py
Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-03-27 02:06:05 +10:00
Rai
8a3eacb5d2 Update LCD_2inch4.py
Signed-off-by: Rai <58925163+rai68@users.noreply.github.com>
2024-03-27 02:05:24 +10:00
ab541458fa add extra check for fix_services
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 12:15:00 +01:00
ac345c2ee7 make_latest: true
generate_release_notes: true

Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 07:58:06 +01:00
468cfd9f4f prerelease: false
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 07:55:06 +01:00
d6bc5c0e66 Reboot after auto-update
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 00:07:15 +01:00
4905eb6b26 Optimize display imports
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-26 00:05:50 +01:00
697a7778b1 Fix fix_services.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 23:29:10 +01:00
9287283ee7 Added 11 waveshare lcd displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 22:53:07 +01:00
8013109ef7 Refactoring displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 22:52:42 +01:00
f140fe1a2d Update setup.py to look for empty apt_packages.txt
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 11:58:46 +01:00
8fe503c67d No new apt-packages needed
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-25 08:11:39 +01:00
d81013412e Update several displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 15:18:58 +01:00
3c701822bd Update donation method
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:58:26 +01:00
2f5ddb492a Small typo's
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:58:07 +01:00
9e3324221d Fix adafruit 2.13inch display
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:57:40 +01:00
b069b82984 Version 2.8.9
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:57:20 +01:00
cb7d965271 Update MOTD
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-24 12:57:08 +01:00
7abf9ff8da Update faces.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:49:46 +01:00
18fb956251 Update setup.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:46:32 +01:00
afb1d11cd8 Added Adafruit 2in13_V3 display
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-23 09:24:52 +01:00
627be80e6c add system wide aliases, if you were to use custom users
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:49 +01:00
c4c4d6c417 in case you use an unsupported display it will default to dummy display, displaying nothing
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:27 +01:00
8dcae13ce9 add commented dtoverlay=disable-wifi
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 19:09:00 +01:00
1352e99774 Fix wrong imports
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 18:34:49 +01:00
2182d7c29d Update Frysian Language
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 09:56:47 +01:00
703c05a93b Full SSID again
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 09:06:04 +01:00
697cc5d88b Add DummyDisplay
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:56 +01:00
4b04f9b7a5 Install OS packages from auto-update
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:22 +01:00
c7b94a0707 Version 2.8.8 starts here
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-22 08:37:01 +01:00
5116bac2a7 Multiple changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-20 22:32:04 +01:00
51625e61f9 Multiple changes
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-20 22:25:36 +01:00
bf9a0a96c1 Update raspberrypi64.yml 2024-03-20 21:17:20 +01:00
bd03f07aa8 Update raspberrypi32.yml 2024-03-20 21:16:50 +01:00
3f13df8f20 Merge pull request #104
Update defaults.toml
2024-03-20 07:20:19 +01:00
ce0275f2ae Update defaults.toml
Removed main.filter since it's no longer referenced in agent.py as of this commit 1a55afd74a (diff-0548f0a21e1984ecf3c32d6cd9c17e6a62f4f139c001360935890f649b745cc7)

Signed-off-by: seelenamt <dandrewe@gmail.com>
2024-03-19 10:51:59 -05:00
b971f18f75 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:19:54 +01:00
ea9d11d018 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:19:00 +01:00
8a572f1b70 Update Sponsor links
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 13:16:14 +01:00
0c4f2a5093 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 09:25:17 +01:00
7edd752664 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-19 07:56:06 +01:00
cc550aa236 small change
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 15:05:00 +01:00
ff033d41d3 Revert "fallback to older 32bit image"
This reverts commit b33af167d4.
2024-03-18 14:56:59 +01:00
6d0a0d8d5f fallback to older 32bit image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 13:04:19 +01:00
b33af167d4 fallback to older 32bit image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 12:03:20 +01:00
9053762e71 2.8.7.2
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 11:59:32 +01:00
26fef7dd99 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	builder/data/64bit/raspberrypi64.yml
2024-03-18 11:58:33 +01:00
5dd17291f7 Fix a lot of stuff
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-18 11:58:22 +01:00
bac79f3465 Update _version.py 2024-03-17 21:17:08 +01:00
bb8dfe0244 Update raspberrypi64.yml 2024-03-17 21:16:25 +01:00
1b16975031 Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:24:57 +01:00
dd2b559ebc Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:22:35 +01:00
93ba2a7f79 Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:20:02 +01:00
dd18072002 Update workflow
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 09:18:31 +01:00
1eafbb841f Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 01:10:56 +01:00
aa817288ea Update Raspios image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 00:50:17 +01:00
43285eb2c0 Update Raspios image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 00:47:49 +01:00
4b29476c2f Update Raspios image
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 00:46:09 +01:00
1a8ff930d9 Update nexmon
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-17 00:34:54 +01:00
8a65afdc8f Update nexmon
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-16 10:52:56 +01:00
6fcd1b0e23 Fix displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-15 15:50:43 +01:00
e0b0f5d800 Fix displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-15 15:07:55 +01:00
2243079bf6 Fix displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-15 15:07:15 +01:00
e10eb31ed1 Fix displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-15 13:41:27 +01:00
1c8114e444 Merge remote-tracking branch 'origin/master' 2024-03-15 10:00:01 +01:00
91638a151f Fix displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-15 09:59:55 +01:00
d4adaabcbd Merge pull request #93
Screen support
2024-03-13 23:03:44 +01:00
006cdb0fe3 Add 2 waveshare displays
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-13 22:41:18 +01:00
29386fb945 Update build to kernel 6.6.20
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-13 21:49:12 +01:00
4b4646d604 Added 2 waveshare diplays:
5.79 inch
5.79b inch

Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-13 21:49:00 +01:00
3fae6ec312 Screen support
Screen support for the following displays:
Adafruit pitft (2,4" and 2,8" tested)
Adafruit tft bonnet
Pimoroni pirate audio
Waveshare OLED/LCD hat
2024-03-13 16:31:49 +01:00
09a82aa0b4 revert pcapng
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-13 07:59:37 +01:00
541865a2eb Merge pull request #92 from jayofelony/dev
Dev
2024-03-13 07:57:37 +01:00
928de2769d Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-13 07:55:53 +01:00
6987840da2 Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	Makefile
#	pwnagotchi/plugins/default/hashie.py
2024-03-07 21:37:27 +01:00
58de15ce2d Update Makefile
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-06 16:55:04 +01:00
b5ea3da619 Update Makefile
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-06 15:23:40 +01:00
6c68d4608f Fix gps plugin
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-06 15:23:30 +01:00
14a727954b Update Makefile and build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-05 21:48:33 +01:00
aeada2ee6e Fix waveshare2in7_V2.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-05 21:48:16 +01:00
ebb8fef3fc Update build
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-05 19:54:47 +01:00
e531288369 Added WeAct 2.9 inch display
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-05 19:54:33 +01:00
2015b56c5d Fix waveshare3in52.py
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-05 19:54:10 +01:00
2497475057 Added WeAct 2.9 inch display
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-05 19:54:01 +01:00
0bdbbc23fd Version 2.8.7
Signed-off-by: jayofelony <oudshoorn.jeroen@gmail.com>
2024-03-05 19:53:35 +01:00
0585fe75fe update 2024-02-09 13:14:10 +01:00
a7634a2b4a update Makefile 2024-02-09 13:01:47 +01:00
ca4feb895e Revert "Revert "Testing pcapng fileformat""
This reverts commit 0e274af5a0.
2024-02-08 22:51:57 +01:00
393 changed files with 10724 additions and 4765 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,3 +1,3 @@
# These are supported funding model platforms # These are supported funding model platforms
github: jayofelony github: jayofelony

View File

@ -2,71 +2,54 @@ name: Publish
on: on:
workflow_dispatch: workflow_dispatch:
inputs:
version:
description: 'Version number'
required: true
jobs: jobs:
build: build:
name: ${{ matrix.name }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
matrix:
include:
- name: "Raspberry Pi 32-bit"
id: "32bit"
- name: "Raspberry Pi 64-bit"
id: "64bit"
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
path: publish/build
- name: Extract version from file - name: Extract version from file
id: get_version id: get_version
run: | run: |
VERSION=$(cut -d "'" -f2 < pwnagotchi/_version.py) VERSION=$(cut -d "'" -f2 < publish/build/pwnagotchi/_version.py)
echo "VERSION=$VERSION" >> $GITHUB_ENV echo "VERSION=$VERSION" >> $GITHUB_ENV
- name: Get latest tag
uses: actions-ecosystem/action-get-latest-tag@v1
id: get-latest-tag
- name: Set LAST_VERSION as an environment variable
run: echo "LAST_VERSION=${{ steps.get-latest-tag.outputs.tag }}" >> $GITHUB_ENV
- name: Generate release notes
id: generate_release_notes
run: |
COMMITS=$(git log --merges --pretty=format:"* %s" $LAST_VERSION--$VERSION | sed 's/$/\\n/g')
CONTRIBUTORS=$(git shortlog -sn $LAST_VERSION--$VERSION | awk '{print "* @" $2}' | sed 's/$/\\n/g')
RELEASE_BODY="**Full Changelog**: https://github.com/jayofelony/pwnagotchi/compare/$LAST_VERSION...$VERSION"
echo "RELEASE_BODY=$RELEASE_BODY" >> $GITHUB_ENV
- name: Install qemu dependencies - name: Install qemu dependencies
run: sudo apt update && sudo apt install qemu-user-static qemu-utils xz-utils -y run: sudo apt update && sudo apt install qemu-user-static qemu-utils xz-utils -y
- name: Build img file - name: Build ${{ matrix.name }} img file
run: ls -la .; pwd; make all run: cd publish/build; ls -la .; pwd; make packer; make ${{ matrix.id }}
- name: Transfer 32bit.img to docker and give permissions - name: Change name of .img.xz to add version
run: sudo chown runner:docker "pwnagotchi-32bit.img" run: |
sudo chown runner:docker "pwnagotchi-${{ matrix.id }}.img"
- name: Transfer 64bit.img to docker and give permissions mv "pwnagotchi-${{ matrix.id }}.img" "pwnagotchi-${{ env.VERSION }}-${{ matrix.id }}.img"
run: sudo chown runner:docker "pwnagotchi-64bit.img"
- name: PiShrink - name: PiShrink
run: | run: |
wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
chmod +x pishrink.sh chmod +x pishrink.sh
sudo mv pishrink.sh /usr/local/bin sudo mv pishrink.sh /usr/local/bin
find /home/runner/work/ -type f -name "*.img" -exec sudo pishrink.sh -aZ {} \; sudo pishrink.sh -aZ "pwnagotchi-${{ env.VERSION }}-${{ matrix.id }}.img"
- name: Change name of 32.img.xz to add version
run: mv "pwnagotchi-32bit.img.xz" "pwnagotchi-$VERSION-32bit.img.xz"
- name: Change name of 64.img.xz to add version
run: mv "pwnagotchi-64bit.img.xz" "pwnagotchi-$VERSION-64bit.img.xz"
- name: Release - name: Release
uses: softprops/action-gh-release@v1 uses: softprops/action-gh-release@v2
with: with:
prerelease: true prerelease: false
make_latest: true
tag_name: v${{ env.VERSION }} tag_name: v${{ env.VERSION }}
name: Pwnagotchi v${{ env.VERSION }} name: Pwnagotchi v${{ env.VERSION }}
files: | files: pwnagotchi-${{ env.VERSION }}-${{ matrix.id }}.img.xz
pwnagotchi-${{ env.VERSION }}-32bit.img.xz generate_release_notes: true
pwnagotchi-${{ env.VERSION }}-64bit.img.xz
body: ${{ env.RELEASE_BODY }}

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.pyc

19
.idea/deployment.xml generated
View File

@ -1,23 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="PublishConfigData" serverName="pwnagotchi" filePermissions="493" folderPermissions="493" remoteFilesAllowedToDisappearOnAutoupload="false" confirmBeforeUploading="false"> <component name="PublishConfigData" filePermissions="493" folderPermissions="493" remoteFilesAllowedToDisappearOnAutoupload="false" confirmBeforeUploading="false">
<option name="confirmBeforeUploading" value="false" /> <option name="confirmBeforeUploading" value="false" />
<serverData>
<paths name="pwnagotchi">
<serverdata>
<mappings>
<mapping deploy="/usr/local/lib/python3.11/dist-packages/pwnagotchi" local="$PROJECT_DIR$/pwnagotchi" web="/" />
<mapping deploy="/usr/local/bin" local="$PROJECT_DIR$/bin" />
<mapping local="" />
</mappings>
<excludedPaths>
<excludedPath local="true" path="$PROJECT_DIR$/venv" />
<excludedPath local="true" path="$PROJECT_DIR$/pwnagotchi.egg-info" />
<excludedPath local="true" path="$PROJECT_DIR$/dist" />
<excludedPath local="true" path="$PROJECT_DIR$/builder/packer-builder-arm" />
</excludedPaths>
</serverdata>
</paths>
</serverData>
</component> </component>
</project> </project>

2
.idea/misc.xml generated
View File

@ -3,7 +3,7 @@
<component name="Black"> <component name="Black">
<option name="sdkName" value="Python 3.11 (pwnagotchi)" /> <option name="sdkName" value="Python 3.11 (pwnagotchi)" />
</component> </component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (pwnagotchi)" project-jdk-type="Python SDK" />
<component name="PythonCompatibilityInspectionAdvertiser"> <component name="PythonCompatibilityInspectionAdvertiser">
<option name="version" value="3" /> <option name="version" value="3" />
</component> </component>

2
.idea/pwnagotchi.iml generated
View File

@ -4,7 +4,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/venv" /> <excludeFolder url="file://$MODULE_DIR$/venv" />
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.10" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.12 (pwnagotchi)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="PyDocumentationSettings"> <component name="PyDocumentationSettings">

10
.idea/sshConfigs.xml generated Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SshConfigs">
<configs>
<sshConfig authType="PASSWORD" connectionConfig="{&quot;serverAliveInterval&quot;:300}" id="8b69df7d-cec5-421f-8edf-53ed6233f6b6" port="22" customName="pwnagotchi" nameFormat="CUSTOM" useOpenSSHConfig="true">
<option name="customName" value="pwnagotchi" />
</sshConfig>
</configs>
</component>
</project>

14
.idea/webServers.xml generated Normal file
View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WebServers">
<option name="servers">
<webServer id="cf2a1148-a103-4472-a782-7debdc6dabf9" name="pwnagotchi">
<fileTransfer accessType="SFTP" port="22" sshConfigId="8b69df7d-cec5-421f-8edf-53ed6233f6b6" sshConfig="pwnagotchi">
<advancedOptions>
<advancedOptions dataProtectionLevel="Private" passiveMode="true" shareSSLContext="true" />
</advancedOptions>
</fileTransfer>
</webServer>
</option>
</component>
</project>

View File

@ -1,4 +1,4 @@
PACKER_VERSION := 1.10.1 PACKER_VERSION := 1.11.0
PWN_HOSTNAME := pwnagotchi PWN_HOSTNAME := pwnagotchi
PWN_VERSION := $(shell cut -d"'" -f2 < pwnagotchi/_version.py) PWN_VERSION := $(shell cut -d"'" -f2 < pwnagotchi/_version.py)
@ -26,7 +26,7 @@ UNSHARE := $(UNSHARE) --uts
endif endif
# sudo apt-get install qemu-user-static qemu-utils # sudo apt-get install qemu-user-static qemu-utils
all: clean packer image all: packer image
update_langs: update_langs:
@for lang in pwnagotchi/locale/*/; do\ @for lang in pwnagotchi/locale/*/; do\
@ -40,21 +40,23 @@ compile_langs:
./scripts/language.sh compile $$(basename $$lang); \ ./scripts/language.sh compile $$(basename $$lang); \
done done
packer: clean packer:
curl https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_amd64.zip -o /tmp/packer.zip curl https://releases.hashicorp.com/packer/$(PACKER_VERSION)/packer_$(PACKER_VERSION)_linux_amd64.zip -o /tmp/packer.zip
unzip /tmp/packer.zip -d /tmp unzip -o /tmp/packer.zip -d /tmp
sudo mv /tmp/packer /usr/bin/packer sudo mv /tmp/packer /usr/bin/packer
image: clean packer image: packer
export LC_ALL=en_GB.UTF-8
cd builder && sudo /usr/bin/packer init combined.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" combined.json.pkr.hcl cd builder && sudo /usr/bin/packer init combined.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" combined.json.pkr.hcl
bullseye: clean packer 32bit: packer
cd builder && sudo /usr/bin/packer init data/32bit/raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/32bit/raspberrypi32.json.pkr.hcl export LC_ALL=en_GB.UTF-8
sudo pishrink -vaZ pwnagotchi-32bit.img cd builder && sudo /usr/bin/packer init raspberrypi32.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi32.json.pkr.hcl
bookworm: clean packer 64bit: packer
cd builder && sudo /usr/bin/packer init data/64bit/raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" data/64bit/raspberrypi64.json.pkr.hcl export LC_ALL=en_GB.UTF-8
sudo pishrink -vaZ pwnagotchi-64bit.img cd builder && sudo /usr/bin/packer init raspberrypi64.json.pkr.hcl && sudo $(UNSHARE) /usr/bin/packer build -var "pwn_hostname=$(PWN_HOSTNAME)" -var "pwn_version=$(PWN_VERSION)" raspberrypi64.json.pkr.hcl
clean: clean:
- rm -rf /tmp/packer* - rm -rf /tmp/packer*
- rm -rf /tmp/LICENSE.txt

View File

@ -3,11 +3,15 @@ This is the main source for all forks:
- RPiZeroW (32bit) - RPiZeroW (32bit)
- RPiZero2W, RPi3, RPi4, RPi5 (64bit) - RPiZero2W, RPi3, RPi4, RPi5 (64bit)
**For installation docs check out the [wiki](https://github.com/jayofelony/pwnagotchi/wiki)!**
[GH Sponsor](https://github.com/sponsors/jayofelony) [GH Sponsor](https://github.com/sponsors/jayofelony)
**Proudly partnering with [PiSugar](https://www.pisugar.com)!!**
--- ---
[Pwnagotchi](https://pwnagotchi.ai/) is an [A2C](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752)-based "AI" leveraging [bettercap](https://www.bettercap.org/) that learns from its surrounding Wi-Fi environment to maximize the crackable WPA key material it captures (either passively, or by performing authentication and association attacks). This material is collected as PCAP files containing any form of handshake supported by [hashcat](https://hashcat.net/hashcat/), including [PMKIDs](https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/), [Pwnagotchi](https://pwnagotchi.org/) is an [A2C](https://hackernoon.com/intuitive-rl-intro-to-advantage-actor-critic-a2c-4ff545978752)-based "AI" leveraging [bettercap](https://www.bettercap.org/) that learns from its surrounding Wi-Fi environment to maximize the crackable WPA key material it captures (either passively, or by performing authentication and association attacks). This material is collected as PCAP files containing any form of handshake supported by [hashcat](https://hashcat.net/hashcat/), including [PMKIDs](https://www.evilsocket.net/2019/02/13/Pwning-WiFi-networks-with-bettercap-and-the-PMKID-client-less-attack/),
full and half WPA handshakes. full and half WPA handshakes.
![ui](https://i.imgur.com/X68GXrn.png) ![ui](https://i.imgur.com/X68GXrn.png)
@ -22,18 +26,17 @@ Multiple units within close physical proximity can "talk" to each other, adverti
## Documentation ## Documentation
https://www.pwnagotchi.ai https://github.com/jayofelony/pwnagotchi/wiki
https://www.pwnagotchi.org
## Links ## Links
| &nbsp; | Official Links | | &nbsp; | Official Links |
|-----------|-------------------------------------------------------------| |-----------|-------------------------------------------------------------|
| Website | [pwnagotchi.ai](https://pwnagotchi.ai/) | | Website | [pwnagotchi.org](https://pwnagotchi.org/) |
| Forum | [community.pwnagotchi.ai](https://community.pwnagotchi.ai/) | | Forum | [discord.gg](https://discord.gg/PGgnzFbz4M) |
| Slack | [pwnagotchi.slack.com](https://invite.pwnagotchi.ai/) |
| Subreddit | [r/pwnagotchi](https://www.reddit.com/r/pwnagotchi/) | | Subreddit | [r/pwnagotchi](https://www.reddit.com/r/pwnagotchi/) |
| Twitter | [@pwnagotchi](https://twitter.com/pwnagotchi) |
## License ## License
`pwnagotchi` is made with ♥ by [@evilsocket](https://twitter.com/evilsocket) and the [amazing dev team](https://github.com/evilsocket/pwnagotchi/graphs/contributors). It is released under the GPL3 license. `pwnagotchi` created by [@evilsocket](https://twitter.com/evilsocket) and updated by [us](https://github.com/jayofelony/pwnagotchi/graphs/contributors). It is released under the GPL3 license.

View File

@ -19,85 +19,83 @@ from pwnagotchi import fs
from pwnagotchi.utils import DottedTomlEncoder, parse_version as version_to_tuple from pwnagotchi.utils import DottedTomlEncoder, parse_version as version_to_tuple
def do_clear(display): def pwnagotchi_cli():
logging.info("clearing the display ...") def do_clear(display):
display.clear() logging.info("clearing the display ...")
sys.exit(0) display.clear()
sys.exit(0)
def do_manual_mode(agent):
logging.info("entering manual mode ...")
def do_manual_mode(agent): agent.mode = 'manual'
logging.info("entering manual mode ...") agent.last_session.parse(agent.view(), args.skip_session)
if not args.skip_session:
agent.mode = 'manual' logging.info(
agent.last_session.parse(agent.view(), args.skip_session) "the last session lasted %s (%d completed epochs, trained for %d), average reward:%s (min:%s max:%s)" % (
if not args.skip_session: agent.last_session.duration_human,
logging.info( agent.last_session.epochs,
"the last session lasted %s (%d completed epochs, trained for %d), average reward:%s (min:%s max:%s)" % ( agent.last_session.train_epochs,
agent.last_session.duration_human, agent.last_session.avg_reward,
agent.last_session.epochs, agent.last_session.min_reward,
agent.last_session.train_epochs, agent.last_session.max_reward))
agent.last_session.avg_reward,
agent.last_session.min_reward,
agent.last_session.max_reward))
while True:
display.on_manual_mode(agent.last_session)
time.sleep(5)
if grid.is_connected():
plugins.on('internet_available', agent)
def do_auto_mode(agent):
logging.info("entering auto mode ...")
agent.mode = 'auto'
agent.start()
while True:
try:
# recon on all channels
agent.recon()
# get nearby access points grouped by channel
channels = agent.get_access_points_by_channel()
# for each channel
for ch, aps in channels:
agent.set_channel(ch)
if not agent.is_stale() and agent.any_activity():
logging.info("%d access points on channel %d" % (len(aps), ch))
# for each ap on this channel
for ap in aps:
# send an association frame in order to get for a PMKID
agent.associate(ap)
# deauth all client stations in order to get a full handshake
for sta in ap['clients']:
agent.deauth(ap, sta)
time.sleep(1) # delay to not trigger nexmon firmware bugs
# An interesting effect of this:
#
# From Pwnagotchi's perspective, the more new access points
# and / or client stations nearby, the longer one epoch of
# its relative time will take ... basically, in Pwnagotchi's universe,
# Wi-Fi electromagnetic fields affect time like gravitational fields
# affect ours ... neat ^_^
agent.next_epoch()
while True:
display.on_manual_mode(agent.last_session)
time.sleep(5)
if grid.is_connected(): if grid.is_connected():
plugins.on('internet_available', agent) plugins.on('internet_available', agent)
except Exception as e: def do_auto_mode(agent):
if str(e).find("wifi.interface not set") > 0: logging.info("entering auto mode ...")
logging.exception("main loop exception due to unavailable wifi device, likely programmatically disabled (%s)", e)
logging.info("sleeping 60 seconds then advancing to next epoch to allow for cleanup code to trigger") agent.mode = 'auto'
time.sleep(60) agent.start()
while True:
try:
# recon on all channels
agent.recon()
# get nearby access points grouped by channel
channels = agent.get_access_points_by_channel()
# for each channel
for ch, aps in channels:
time.sleep(1)
agent.set_channel(ch)
if not agent.is_stale() and agent.any_activity():
logging.info("%d access points on channel %d" % (len(aps), ch))
# for each ap on this channel
for ap in aps:
# send an association frame in order to get for a PMKID
agent.associate(ap)
# deauth all client stations in order to get a full handshake
for sta in ap['clients']:
agent.deauth(ap, sta)
time.sleep(1) # delay to not trigger nexmon firmware bugs
# An interesting effect of this:
#
# From Pwnagotchi's perspective, the more new access points
# and / or client stations nearby, the longer one epoch of
# its relative time will take ... basically, in Pwnagotchi's universe,
# Wi-Fi electromagnetic fields affect time like gravitational fields
# affect ours ... neat ^_^
agent.next_epoch() agent.next_epoch()
else:
logging.exception("main loop exception (%s)", e)
if grid.is_connected():
plugins.on('internet_available', agent)
except Exception as e:
if str(e).find("wifi.interface not set") > 0:
logging.exception("main loop exception due to unavailable wifi device, likely programmatically disabled (%s)", e)
logging.info("sleeping 60 seconds then advancing to next epoch to allow for cleanup code to trigger")
time.sleep(60)
agent.next_epoch()
else:
logging.exception("main loop exception (%s)", e)
if __name__ == '__main__':
def add_parsers(parser): def add_parsers(parser):
""" """
Adds the plugins and google subcommands Adds the plugins and google subcommands
@ -169,21 +167,23 @@ if __name__ == '__main__':
allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE) allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
return all(allowed.match(x) for x in hostname.split(".")) return all(allowed.match(x) for x in hostname.split("."))
pwn_restore = input("Do you want to restore the previous configuration? [Y/N]\n") pwn_restore = input("Do you want to restore the previous configuration?\n\n"
"[Y/N]: ")
if pwn_restore in ('y', 'yes'): if pwn_restore in ('y', 'yes'):
os.system("cp -f /etc/pwnagotchi/config.toml.bak /etc/pwnagotchi/config.toml") os.system("cp -f /etc/pwnagotchi/config.toml.bak /etc/pwnagotchi/config.toml")
print("Your previous configuration is restored, and I will restart in 5 seconds.") print("Your previous configuration is restored, and I will restart in 5 seconds.")
time.sleep(5) time.sleep(5)
os.system("service pwnagotchi restart") os.system("service pwnagotchi restart")
else: else:
pwn_check = input("This will create a new configuration file and overwrite your current backup, are you sure? [Y/N]\n") pwn_check = input("This will create a new configuration file and overwrite your current backup, are you sure?\n\n"
"[Y/N]: ")
if pwn_check.lower() in ('y', 'yes'): if pwn_check.lower() in ('y', 'yes'):
os.system("mv -f /etc/pwnagotchi/config.toml /etc/pwnagotchi/config.toml.bak") os.system("mv -f /etc/pwnagotchi/config.toml /etc/pwnagotchi/config.toml.bak")
with open("/etc/pwnagotchi/config.toml", "a+") as f: with open("/etc/pwnagotchi/config.toml", "a+") as f:
f.write("# Do not edit this file if you do not know what you are doing!!!\n\n") f.write("# Do not edit this file if you do not know what you are doing!!!\n\n")
# Set pwnagotchi name # Set pwnagotchi name
print("Welcome to the interactive installation of your personal Pwnagotchi configuration!\n" print("Welcome to the interactive installation of your personal Pwnagotchi configuration!\n"
"My name is Jayofelony, how may I call you?\n") "My name is Jayofelony, how may I call you?\n\n")
pwn_name = input("Pwnagotchi name (no spaces): ") pwn_name = input("Pwnagotchi name (no spaces): ")
if pwn_name == "": if pwn_name == "":
pwn_name = "Pwnagotchi" pwn_name = "Pwnagotchi"
@ -212,32 +212,39 @@ if __name__ == '__main__':
f.write(f"\t\"{bssid}\",\n") f.write(f"\t\"{bssid}\",\n")
f.write("]\n") f.write("]\n")
# set bluetooth tether # set bluetooth tether
pwn_bluetooth = input("Do you want to enable BT-Tether? [Y/N] ") pwn_bluetooth = input("Do you want to enable BT-Tether?\n\n"
"[Y/N] ")
if pwn_bluetooth.lower() in ('y', 'yes'): if pwn_bluetooth.lower() in ('y', 'yes'):
f.write("main.plugins.bt-tether.enabled = true\n\n") f.write("main.plugins.bt-tether.enabled = true\n\n")
pwn_bluetooth_device = input("What device do you use? Android or iOS? ") pwn_bluetooth_device = input("What device do you use? Android or iOS?\n\n"
"Device: ")
if pwn_bluetooth_device.lower() == "android": if pwn_bluetooth_device.lower() == "android":
f.write("main.plugins.bt-tether.devices.android-phone.enabled = true\n") f.write("main.plugins.bt-tether.devices.android-phone.enabled = true\n")
pwn_bluetooth_mac = input("What is the bluetooth MAC of your device? ") pwn_bluetooth_mac = input("What is the bluetooth MAC of your device?\n\n"
"MAC: ")
if pwn_bluetooth_mac != "": if pwn_bluetooth_mac != "":
f.write(f"main.plugins.bt-tether.devices.android-phone.mac = \"{pwn_bluetooth_mac}\"\n") f.write(f"main.plugins.bt-tether.devices.android-phone.mac = \"{pwn_bluetooth_mac}\"\n")
elif pwn_bluetooth_device.lower() == "ios": elif pwn_bluetooth_device.lower() == "ios":
f.write("main.plugins.bt-tether.devices.ios-phone.enabled = true\n") f.write("main.plugins.bt-tether.devices.ios-phone.enabled = true\n")
pwn_bluetooth_mac = input("What is the bluetooth MAC of your device? ") pwn_bluetooth_mac = input("What is the bluetooth MAC of your device?\n\n"
"MAC: ")
if pwn_bluetooth_mac != "": if pwn_bluetooth_mac != "":
f.write(f"main.plugins.bt-tether.devices.ios-phone.mac = \"{pwn_bluetooth_mac}\"\n") f.write(f"main.plugins.bt-tether.devices.ios-phone.mac = \"{pwn_bluetooth_mac}\"\n")
# set up display settings # set up display settings
pwn_display_enabled = input("Do you use a display? [Y/N] ") pwn_display_enabled = input("Do you want to enable a display?\n\n"
"[Y/N]: ")
if pwn_display_enabled.lower() in ('y', 'yes'): if pwn_display_enabled.lower() in ('y', 'yes'):
f.write("ui.display.enabled = true\n") f.write("ui.display.enabled = true\n")
pwn_display_type = input("What display do you use?\n\n" pwn_display_type = input("What display do you use?\n\n"
"Be sure to check for the correct display type @ \n" "Be sure to check for the correct display type @ \n"
"https://github.com/jayofelony/pwnagotchi/blob/master/pwnagotchi/utils.py#L240-L431\n") "https://github.com/jayofelony/pwnagotchi/blob/master/pwnagotchi/utils.py#L240-L501\n\n"
"Display type: ")
if pwn_display_type != "": if pwn_display_type != "":
f.write(f"ui.display.type = \"{pwn_display_type}\"\n") f.write(f"ui.display.type = \"{pwn_display_type}\"\n")
pwn_display_invert = input("Do you want to invert the display colors? [Y/N]\n\n" pwn_display_invert = input("Do you want to invert the display colors?\n"
"N = Black background\n" "N = Black background\n"
"Y = White background\n") "Y = White background\n\n"
"[Y/N]: ")
if pwn_display_invert.lower() in ('y', 'yes'): if pwn_display_invert.lower() in ('y', 'yes'):
f.write("ui.invert = true\n") f.write("ui.invert = true\n")
f.close() f.close()
@ -257,8 +264,7 @@ if __name__ == '__main__':
sys.exit(0) sys.exit(0)
if args.donate: if args.donate:
print("Donations can made @ \n " print("Donations can be made @ \n "
"https://www.patreon.com/pwnagotchi_torch \n "
"https://github.com/sponsors/jayofelony \n\n" "https://github.com/sponsors/jayofelony \n\n"
"But only if you really want to!") "But only if you really want to!")
sys.exit(0) sys.exit(0)
@ -271,8 +277,7 @@ if __name__ == '__main__':
local = version_to_tuple(pwnagotchi.__version__) local = version_to_tuple(pwnagotchi.__version__)
remote = version_to_tuple(latest_ver) remote = version_to_tuple(latest_ver)
if remote > local: if remote > local:
user_input = input("There is a new version available! Update from v%s to v%s?\n[Y/N] " user_input = input("There is a new version available! Update from v%s to v%s?\n[Y/N] " % (pwnagotchi.__version__, latest_ver))
% (pwnagotchi.__version__, latest_ver))
# input validation # input validation
if user_input.lower() in ('y', 'yes'): if user_input.lower() in ('y', 'yes'):
if os.path.exists('/root/.auto-update'): if os.path.exists('/root/.auto-update'):
@ -318,7 +323,7 @@ if __name__ == '__main__':
def usr1_handler(*unused): def usr1_handler(*unused):
logging.info('Received USR1 singal. Restart process ...') logging.info('Received USR1 singal. Restart process ...')
restart("MANU" if args.do_manual else "AUTO") agent._restart("MANU" if args.do_manual else "AUTO")
signal.signal(signal.SIGUSR1, usr1_handler) signal.signal(signal.SIGUSR1, usr1_handler)
@ -326,3 +331,7 @@ if __name__ == '__main__':
do_manual_mode(agent) do_manual_mode(agent)
else: else:
do_auto_mode(agent) do_auto_mode(agent)
if __name__ == '__main__':
pwnagotchi_cli()

View File

@ -1,8 +1,8 @@
packer { packer {
required_plugins { required_plugins {
arm = { arm-image = {
version = "1.0.0" source = "github.com/solo-io/arm-image"
source = "github.com/cdecoux/builder-arm" version = ">= 0.0.1"
} }
ansible = { ansible = {
source = "github.com/hashicorp/ansible" source = "github.com/hashicorp/ansible"
@ -19,64 +19,26 @@ variable "pwn_version" {
type = string type = string
} }
source "arm" "rpi64-pwnagotchi" { source "arm-image" "rpi64-pwnagotchi" {
file_checksum_url = "https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-11/2023-12-11-raspios-bookworm-arm64-lite.img.xz.sha256" image_type = "raspberrypi"
file_urls = ["https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-11/2023-12-11-raspios-bookworm-arm64-lite.img.xz"] iso_url = "https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz"
file_checksum_type = "sha256" iso_checksum = "sha256:43d150e7901583919e4eb1f0fa83fe0363af2d1e9777a5bb707d696d535e2599"
file_target_extension = "xz" output_filename = "../../../pwnagotchi-64bit.img"
file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] qemu_binary = "qemu-aarch64-static"
image_path = "../pwnagotchi-64bit.img" target_image_size = 19969908736
qemu_binary_source_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P" image_mounts = ["/boot/firmware","/"]
qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P"
image_build_method = "resize"
image_size = "9G"
image_type = "dos"
image_partitions {
name = "boot"
type = "c"
start_sector = "8192"
filesystem = "fat"
size = "256M"
mountpoint = "/boot/firmware"
}
image_partitions {
name = "root"
type = "83"
start_sector = "532480"
filesystem = "ext4"
size = "0"
mountpoint = "/"
}
} }
source "arm" "rpi32-pwnagotchi" { source "arm-image" "rpi32-pwnagotchi" {
file_checksum_url = "https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-12-06/2023-12-05-raspios-bullseye-armhf-lite.img.xz.sha256" image_type = "raspberrypi"
file_urls = ["https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-12-06/2023-12-05-raspios-bullseye-armhf-lite.img.xz"] iso_url = "https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-07-04/2024-07-04-raspios-bookworm-armhf-lite.img.xz"
file_checksum_type = "sha256" iso_checksum = "sha256:df9c192d66d35e1ce67acde33a5b5f2b81ff02d2b986ea52f1f6ea211d646a1b"
file_target_extension = "xz" output_filename = "../../../pwnagotchi-32bit.img"
file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] qemu_binary = "qemu-arm-static"
image_path = "../pwnagotchi-32bit.img" qemu_args = ["-cpu", "arm1176"]
qemu_binary_source_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" image_arch = "arm"
qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" target_image_size = 19969908736
image_build_method = "resize" image_mounts = ["/boot/firmware","/"]
image_size = "9G"
image_type = "dos"
image_partitions {
name = "boot"
type = "c"
start_sector = "8192"
filesystem = "fat"
size = "256M"
mountpoint = "/boot"
}
image_partitions {
name = "root"
type = "83"
start_sector = "532480"
filesystem = "ext4"
size = "0"
mountpoint = "/"
}
} }
# a build block invokes sources and runs provisioning steps on them. The # a build block invokes sources and runs provisioning steps on them. The
@ -84,7 +46,7 @@ source "arm" "rpi32-pwnagotchi" {
# https://www.packer.io/docs/from-1.5/blocks/build # https://www.packer.io/docs/from-1.5/blocks/build
build { build {
name = "Raspberry Pi 64 Pwnagotchi" name = "Raspberry Pi 64 Pwnagotchi"
sources = ["source.arm.rpi64-pwnagotchi"] sources = ["source.arm-image.rpi64-pwnagotchi"]
provisioner "file" { provisioner "file" {
destination = "/usr/bin/" destination = "/usr/bin/"
@ -101,6 +63,13 @@ build {
provisioner "shell" { provisioner "shell" {
inline = ["chmod +x /usr/bin/*"] inline = ["chmod +x /usr/bin/*"]
} }
provisioner "shell" {
inline = ["mkdir -p /usr/local/src/pwnagotchi"]
}
provisioner "file" {
destination = "/usr/local/src/pwnagotchi/"
source = "../"
}
provisioner "file" { provisioner "file" {
destination = "/etc/systemd/system/" destination = "/etc/systemd/system/"
@ -123,13 +92,13 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_file = "data/64bit/raspberrypi64.yml" playbook_file = "raspberrypi64.yml"
} }
} }
build { build {
name = "Raspberry Pi 32 Pwnagotchi" name = "Raspberry Pi 32 Pwnagotchi"
sources = ["source.arm.rpi32-pwnagotchi"] sources = ["source.arm-image.rpi32-pwnagotchi"]
provisioner "file" { provisioner "file" {
destination = "/usr/bin/" destination = "/usr/bin/"
sources = [ sources = [
@ -142,10 +111,16 @@ build {
"data/32bit/usr/bin/pwnlib", "data/32bit/usr/bin/pwnlib",
] ]
} }
provisioner "shell" {
inline = ["mkdir -p /usr/local/src/pwnagotchi"]
}
provisioner "file" {
destination = "/usr/local/src/pwnagotchi/"
source = "../"
}
provisioner "shell" { provisioner "shell" {
inline = ["chmod +x /usr/bin/*"] inline = ["chmod +x /usr/bin/*"]
} }
provisioner "file" { provisioner "file" {
destination = "/etc/systemd/system/" destination = "/etc/systemd/system/"
sources = [ sources = [
@ -167,7 +142,6 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_dir = "data/32bit/extras/" playbook_file = "raspberrypi32.yml"
playbook_file = "data/32bit/raspberrypi32.yml"
} }
} }

View File

@ -1,36 +0,0 @@
_show_complete()
{
local cur opts node_names all_options opt_line
all_options="
pwnagotchi -h --help -C --config -U --user-config --manual --skip-session --clear --debug --version --print-config --check-update --donate {plugins,google}
pwnagotchi plugins -h --help {list,install,enable,disable,uninstall,update,upgrade}
pwnagotchi plugins list -i --installed -h --help
pwnagotchi plugins install -h --help
pwnagotchi plugins uninstall -h --help
pwnagotchi plugins enable -h --help
pwnagotchi plugins disable -h --help
pwnagotchi plugins update -h --help
pwnagotchi plugins upgrade -h --help
pwnagotchi google -h --help {login,refresh}
pwnagotchi google login -h --help
pwnagotchi google refresh -h --help
"
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
# shellcheck disable=SC2124
cmd="${COMP_WORDS[@]:0:${#COMP_WORDS[@]}-1}"
opt_line="$(grep -m1 "$cmd" <<<"$all_options")"
if [[ ${cur} == -* ]] ; then
opts="$(echo "$opt_line" | tr ' ' '\n' | awk '/^ *-/{gsub("[^a-zA-Z0-9-]","",$1);print $1}')"
# shellcheck disable=SC2207
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
fi
# shellcheck disable=SC2086
opts="$(echo $opt_line | grep -Po '{\K[^}]+' | tr ',' '\n')"
# shellcheck disable=SC2207
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
}
complete -F _show_complete pwnagotchi

View File

@ -1,62 +0,0 @@
# A sample configuration for dhcpcd.
# See dhcpcd.conf(5) for details.
# Allow users of this group to interact with dhcpcd via the control socket.
#controlgroup wheel
# Inform the DHCP server of our hostname for DDNS.
hostname
# Use the hardware address of the interface for the Client ID.
clientid
# or
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
# Some non-RFC compliant DHCP servers do not reply with this set.
# In this case, comment out duid and enable clientid above.
#duid
# Persist interface configuration when dhcpcd exits.
persistent
# Rapid commit support.
# Safe to enable by default because it requires the equivalent option set
# on the server to actually work.
option rapid_commit
# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu
# Most distributions have NTP support.
#option ntp_servers
# A ServerID is required by RFC2131.
require dhcp_server_identifier
# Generate SLAAC address using the Hardware Address of the interface
#slaac hwaddr
# OR generate Stable Private IPv6 Addresses based from the DUID
slaac private
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# !! DO NOT EDIT THESE LINES BELOW PLEASE !!
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# static IP configuration:
denyinterfaces wlan0
interface eth0
static domain_name_servers=8.8.8.8 1.1.1.1
metric 201
interface usb0
static ip_address=10.0.0.2/24
static routers=10.0.0.1
static domain_name_servers=10.0.0.1 8.8.8.8 1.1.1.1
metric 202
interface bnep0
static domain_name_servers=8.8.8.8 1.1.1.1
metric 203

View File

@ -1,6 +0,0 @@
[Unit]
After=hciuart.service bluetooth.service
Before=
[Service]
ExecStartPre=/bin/sleep 5

View File

@ -1,33 +0,0 @@
#!/bin/sh
_hostname=$(hostname)
_version=$(cut -d"'" -f2 < /usr/local/lib/python3.9/dist-packages/pwnagotchi/_version.py)
echo
echo "(◕‿‿◕) $_hostname"
echo
echo " Hi! I'm a pwnagotchi $_version, please take good care of me!"
echo " Here are some basic things you need to know to raise me properly!"
echo
echo " If you want to change my configuration, use /etc/pwnagotchi/config.toml"
echo " All plugin config files are located in /etc/pwnagotchi/conf.d/"
echo " Read the readme if you want to use gdrivesync plugin!!"
echo
echo " All the configuration options can be found on /etc/pwnagotchi/default.toml,"
echo " but don't change this file because I will recreate it every time I'm restarted!"
echo
echo " I use oPwnGrid as my main API, you can check stats at https://opwngrid.xyz"
echo
echo " I'm managed by systemd. Here are some basic commands."
echo
echo " If you want to know what I'm doing, you can check my logs with the command"
echo " - pwnlog"
echo " - sudo pwnagotchi --version, to check the current version"
echo " - sudo pwnagotchi --donate, to see how you can donate to this project"
echo " - sudo pwnagotchi --check-update, to see if there is a new version available"
echo
echo " If you want to know if I'm running, you can use"
echo " sudo systemctl status pwnagotchi"
echo
echo " You can restart me using"
echo " pwnkill"
echo
echo " You learn more about me at https://pwnagotchi.ai/"

View File

@ -1,40 +0,0 @@
# Install nexmon to fix wireless scanning (takes 2.5G of space)
- name: clone nexmon repository
git:
repo: https://github.com/DrSchottky/nexmon.git
dest: /usr/local/src/nexmon
- name: make firmware
shell: "source ./setup_env.sh && make"
args:
executable: /bin/bash
chdir: /usr/local/src/nexmon/
- name: "make firmware patch ({{ item.name }})"
shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/{{ item.patch }}/nexmon/ && make"
args:
executable: /bin/bash
chdir: /usr/local/src/nexmon/
environment:
QEMU_UNAME: "{{ item.kernel }}"
ARCHFLAGS: "{{ item.arch_flags }}"
- name: "install new firmware ({{ item.name }})"
copy:
src: "/usr/local/src/nexmon/patches/{{ item.patch }}/nexmon/{{ item.firmware }}"
dest: "/usr/lib/firmware/brcm/{{ item.firmware }}"
follow: true
environment:
QEMU_UNAME: "{{ item.kernel }}"
ARCHFLAGS: "{{ item.arch_flags }}"
- name: backup original driver
command: "mv /usr/lib/modules/{{ item.kernel }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ item.kernel }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig"
- name: copy modified driver
copy:
src: "/usr/local/src/nexmon/patches/driver/brcmfmac_6.1.y-nexmon/brcmfmac.ko"
dest: "/usr/lib/modules/{{ item.kernel }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko"
- name : load brcmfmac drivers
command: "/sbin/depmod -a {{ item.kernel }}"

View File

@ -1,28 +0,0 @@
#!/usr/bin/env bash
source /usr/bin/pwnlib
# we need to decrypt something
if is_crypted_mode; then
while ! is_decrypted; do
echo "Waiting for decryption..."
sleep 1
done
fi
# check if wifi driver is bugged
if ! check_brcm; then
if ! reload_brcm; then
echo "Could not reload wifi driver. Reboot"
reboot
fi
sleep 10
fi
# start wlan0mon
start_monitor_interface
if is_auto_mode_no_delete; then
/usr/local/bin/bettercap -no-colors -caplet pwnagotchi-auto -iface wlan0mon
else
/usr/local/bin/bettercap -no-colors -caplet pwnagotchi-manual -iface wlan0mon
fi

View File

@ -1,149 +0,0 @@
#!/usr/bin/env python3
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import parse_qsl
_HTML_FORM_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
<title>Decryption</title>
<style>
body {{ text-align: center; padding: 150px; }}
h1 {{ font-size: 50px; }}
body {{ font: 20px Helvetica, sans-serif; color: #333; }}
article {{ display: block; text-align: center; width: 650px; margin: 0 auto;}}
input {{
padding: 12px 20px;
margin: 8px 0;
box-sizing: border-box;
border: 1px solid #ccc;
}}
input[type=password] {{
width: 75%;
font-size: 24px;
}}
input[type=submit] {{
cursor: pointer;
width: 75%;
}}
input[type=submit]:hover {{
background-color: #d9d9d9;
}}
</style>
</head>
<body>
<article>
<h1>Decryption</h1>
<p>Some of your files are encrypted.</p>
<p>Please provide the decryption password.</p>
<div>
<form action="/set-password" method="POST">
{password_fields}
<input type="submit" value="Submit">
</form>
</div>
</article>
</body>
</html>
"""
POST_RESPONSE = """
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
/* Center the loader */
#loader {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 150px;
height: 150px;
margin: -75px 0 0 -75px;
border: 16px solid #f3f3f3;
border-radius: 50%;
border-top: 16px solid #3498db;
width: 120px;
height: 120px;
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
#myDiv {
display: none;
text-align: center;
}
</style>
<script type="text/javascript">
function checkPwnagotchi() {
var target = 'http://' + document.location.hostname + ':8080/';
var xhr = new XMLHttpRequest();
xhr.open('GET', target);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200 || xhr.status == 401) {
window.location.replace(target);
}else{
setTimeout(checkPwnagotchi, 1000);
}
}
};
xhr.send();
}
setTimeout(checkPwnagotchi, 1000);
</script>
</head>
<body style="margin:0;">
<div id="loader"></div>
</body>
</html>
"""
HTML_FORM = None
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(HTML_FORM.encode())
def do_POST(self):
content_length = int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
for mapping, password in parse_qsl(body.decode('UTF-8')):
with open('/tmp/.pwnagotchi-secret-{}'.format(mapping), 'wt') as pwfile:
pwfile.write(password)
self.send_response(200)
self.end_headers()
self.wfile.write(POST_RESPONSE.encode())
with open('/root/.pwnagotchi-crypted') as crypted_file:
mappings = [line.split()[0] for line in crypted_file.readlines()]
fields = ''.join(['<label for="{m}">Passphrase for {m}:</label>\n<input type="password" id="{m}" name="{m}" value=""><br>'.format(m=m)
for m in mappings])
HTML_FORM = _HTML_FORM_TEMPLATE.format(password_fields=fields)
httpd = HTTPServer(('0.0.0.0', 80), SimpleHTTPRequestHandler)
httpd.serve_forever()

View File

@ -1,26 +0,0 @@
# /etc/dphys-swapfile - user settings for dphys-swapfile package
# author Neil Franklin, last modification 2010.05.05
# copyright ETH Zuerich Physics Departement
# use under either modified/non-advertising BSD or GPL license
# this file is sourced with . so full normal sh syntax applies
# the default settings are added as commented out CONF_*=* lines
# where we want the swapfile to be, this is the default
#CONF_SWAPFILE=/var/swap
# set size to absolute value, leaving empty (default) then uses computed value
# you most likely don't want this, unless you have an special disk situation
CONF_SWAPSIZE=2048
# set size to computed value, this times RAM size, dynamically adapts,
# guarantees that there is enough swap without wasting disk space on excess
#CONF_SWAPFACTOR=2
# restrict size (computed and absolute!) to maximally this limit
# can be set to empty for no limit, but beware of filled partitions!
# this is/was a (outdated?) 32bit kernel limit (in MBytes), do not overrun it
# but is also sensible on 64bit to prevent filling /var or even / partition
#CONF_MAXSWAP=2048

View File

@ -1,13 +0,0 @@
[Unit]
Description=bettercap api.rest service.
Documentation=https://bettercap.org
Wants=network.target
[Service]
Type=simple
ExecStart=/usr/bin/bettercap-launcher
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@ -1,20 +0,0 @@
[Unit]
Description=Bluetooth service
Documentation=man:bluetoothd(8)
ConditionPathIsDirectory=/sys/class/bluetooth
[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=sap,a2dp
NotifyAccess=main
#WatchdogSec=10
#Restart=on-failure
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
LimitNPROC=1
ProtectHome=true
ProtectSystem=full
[Install]
WantedBy=bluetooth.target
Alias=dbus-org.bluez.service

View File

@ -1,20 +0,0 @@
[Unit]
Description=pwnagotchi Deep Reinforcement Learning instrumenting bettercap for WiFI pwning.
Documentation=https://pwnagotchi.org
Wants=network.target
After=pwngrid-peer.service
[Service]
Type=simple
WorkingDirectory=~
ExecStart=/usr/bin/pwnagotchi-launcher
ExecStopPost=/usr/bin/bash -c "if egrep -qi 'personality.clear_on_exit[ =]*true' /etc/pwnagotchi/config.toml ; then /usr/local/bin/pwnagotchi --clear; fi"
Restart=always
RestartSec=30
TasksMax=infinity
LimitNPROC=infinity
StandardOutput=null
StandardError=null
[Install]
WantedBy=multi-user.target

View File

@ -1,16 +0,0 @@
[Unit]
Description=pwngrid peer service.
Documentation=https://pwnagotchi.ai
Wants=network.target
After=bettercap.service
[Service]
Environment=LD_PRELOAD=/usr/local/lib/libpcap.so.1
Environment=LD_LIBRARY_PATH=/usr/local/lib
Type=simple
ExecStart=/usr/local/bin/pwngrid -keys /etc/pwnagotchi -peers /root/peers -address 127.0.0.1:8666 -client-token /root/.api-enrollment.json -wait -log /etc/pwnagotchi/log/pwngrid-peer.log -iface wlan0mon
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@ -1,15 +0,0 @@
client_config_backend: file
client_config_file: /root/client_secrets.json
client_config:
client_id: <YOUR CLIENT ID>
client_secret: <YOUR CLIENT SECRET>
save_credentials: True
save_credentials_backend: file
save_credentials_file: /root/credentials.json
get_refresh_token: True
oauth_scope:
- https://www.googleapis.com/auth/drive
- https://www.googleapis.com/auth/drive.install

View File

@ -1,2 +0,0 @@
#!/usr/bin/env bash
sudo /usr/bin/tvservice -o

View File

@ -1,2 +0,0 @@
#!/usr/bin/env bash
sudo /usr/bin/tvservice -p

View File

@ -1,3 +0,0 @@
#!/usr/bin/env bash
source /usr/bin/pwnlib
start_monitor_interface

View File

@ -1,3 +0,0 @@
#!/usr/bin/env bash
source /usr/bin/pwnlib
stop_monitor_interface

View File

@ -1,16 +0,0 @@
#!/usr/bin/env bash
source /usr/bin/pwnlib
# we need to decrypt something
if is_crypted_mode; then
while ! is_decrypted; do
echo "Waiting for decryption..."
sleep 1
done
fi
if is_auto_mode; then
/usr/local/bin/pwnagotchi
else
/usr/local/bin/pwnagotchi --manual
fi

View File

@ -1,191 +0,0 @@
#!/usr/bin/env bash
# well ... it blinks the led
blink_led() {
# shellcheck disable=SC2034
for i in $(seq 1 "$1"); do
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
echo 1 >/sys/class/leds/led0/brightness
sleep 0.3
done
echo 0 >/sys/class/leds/led0/brightness
sleep 0.3
}
# reload mod
reload_brcm() {
if ! modprobe -r brcmfmac; then
return 1
fi
sleep 1
if ! modprobe brcmfmac; then
return 1
fi
sleep 2
iw dev wlan0 set power_save off
return 0
}
# starts mon0
start_monitor_interface() {
rfkill unblock all
ifconfig wlan0 up
sleep 3
iw dev wlan0 set power_save off
iw phy "$(iw phy | head -1 | cut -d" " -f2)" interface add wlan0mon type monitor
sleep 2
rfkill unblock all
ifconfig wlan0 down
ifconfig wlan0mon up
iw dev wlan0mon set power_save off
}
# stops mon0
stop_monitor_interface() {
ifconfig wlan0mon down && iw dev wlan0mon del
reload_brcm
ifconfig wlan0 up
}
# returns 0 if the specified network interface is up
is_interface_up() {
if grep -qi 'up' /sys/class/net/"$1"/operstate; then
return 0
fi
return 1
}
# returns 0 if conditions for AUTO mode are met
is_auto_mode() {
# check override file first
if [ -f /root/.pwnagotchi-manual ]; then
# remove the override file if found
rm -rf /root/.pwnagotchi-manual
return 1
fi
# check override file first
if [ -f /root/.pwnagotchi-auto ]; then
# remove the override file if found
rm -rf /root/.pwnagotchi-auto
return 0
fi
# if usb0 is up, we're in MANU
if is_interface_up usb0; then
return 1
fi
# if eth0 is up (for other boards), we're in MANU
if is_interface_up eth0; then
return 0
fi
# no override, but none of the interfaces is up -> AUTO
return 0
}
# returns 0 if conditions for AUTO mode are met
is_auto_mode_no_delete() {
# check override file first
if [ -f /root/.pwnagotchi-manual ]; then
return 1
fi
# check override file first
if [ -f /root/.pwnagotchi-auto ]; then
return 0
fi
# if usb0 is up, we're in MANU
if is_interface_up usb0; then
return 1
fi
# if eth0 is up (for other boards), we're in MANU
if is_interface_up eth0; then
return 0
fi
# no override, but none of the interfaces is up -> AUTO
return 0
}
# check if we need to decrypt something
is_crypted_mode() {
if [ -f /root/.pwnagotchi-crypted ]; then
return 0
fi
return 1
}
# decryption loop
is_decrypted() {
while read -r mapping container mount; do
# mapping = name the device or file will be mapped to
# container = the luks encrypted device or file
# mount = the mountpoint
# fail if not mounted
if ! mountpoint -q "$mount" >/dev/null 2>&1; then
if [ -f /tmp/.pwnagotchi-secret-"$mapping" ]; then
</tmp/.pwnagotchi-secret-"$mapping" read -r SECRET
if ! test -b /dev/disk/by-id/dm-uuid-*"$(cryptsetup luksUUID "$container" | tr -d -)"*; then
if echo -n "$SECRET" | cryptsetup luksOpen -d- "$container" "$mapping" >/dev/null 2>&1; then
echo "Container decrypted!"
fi
fi
if mount /dev/mapper/"$mapping" "$mount" >/dev/null 2>&1; then
echo "Mounted /dev/mapper/$mapping to $mount"
continue
fi
fi
if ! ip -4 addr show wlan0 | grep inet >/dev/null 2>&1; then
>/dev/null 2>&1 ip addr add 192.168.0.10/24 dev wlan0
fi
if ! pgrep -f decryption-webserver >/dev/null 2>&1; then
>/dev/null 2>&1 decryption-webserver &
fi
if ! pgrep wpa_supplicant >/dev/null 2>&1; then
>/tmp/wpa_supplicant.conf cat <<EOF
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
ap_scan=2
network={
ssid="DECRYPT-ME"
mode=2
key_mgmt=WPA-PSK
psk="pwnagotchi"
frequency=2437
}
EOF
>/dev/null 2>&1 wpa_supplicant -u -s -O -D nl80211 -i wlan0 -c /tmp/wpa_supplicant.conf &
fi
if ! pgrep dnsmasq >/dev/null 2>&1; then
>/dev/null 2>&1 dnsmasq -k -p 53 -h -O "6,192.168.0.10" -A "/#/192.168.0.10" -i wlan0 -K -F 192.168.0.50,192.168.0.60,255.255.255.0,24h &
fi
return 1
fi
done </root/.pwnagotchi-crypted
# overwrite passwords
python3 -c 'print("A"*4096)' | tee /tmp/.pwnagotchi-secret-* >/dev/null
# delete
rm /tmp/.pwnagotchi-secret-*
sync # flush
pkill wpa_supplicant
pkill dnsmasq
pid="$(pgrep -f "decryption-webserver")"
[[ -n "$pid" ]] && kill "$pid"
return 0
}

View File

@ -0,0 +1,6 @@
# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.
i2c-dev

16
builder/data/etc/rc.local Normal file
View File

@ -0,0 +1,16 @@
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
timedatectl set-ntp true
exit 0

View File

@ -1,6 +1,6 @@
[Unit] [Unit]
Description=pwnagotchi Deep Reinforcement Learning instrumenting bettercap for WiFI pwning. Description=pwnagotchi Deep Reinforcement Learning instrumenting bettercap for WiFI pwning.
Documentation=https://pwnagotchi.ai Documentation=https://pwnagotchi.org
Wants=network.target Wants=network.target
After=pwngrid-peer.service After=pwngrid-peer.service

View File

@ -2,7 +2,7 @@
_hostname=$(hostname) _hostname=$(hostname)
_version=$(cut -d"'" -f2 < /usr/local/lib/python3.11/dist-packages/pwnagotchi/_version.py) _version=$(cut -d"'" -f2 < /usr/local/lib/python3.11/dist-packages/pwnagotchi/_version.py)
echo echo
echo "(☉_☉ ) $_hostname" echo "(◕‿‿◕) $_hostname"
echo echo
echo " Hi! I'm a pwnagotchi $_version, please take good care of me!" echo " Hi! I'm a pwnagotchi $_version, please take good care of me!"
echo " Here are some basic things you need to know to raise me properly!" echo " Here are some basic things you need to know to raise me properly!"

View File

@ -9,7 +9,6 @@ if is_crypted_mode; then
done done
fi fi
# start mon0
start_monitor_interface start_monitor_interface
if is_auto_mode_no_delete; then if is_auto_mode_no_delete; then

View File

@ -10,7 +10,8 @@ if is_crypted_mode; then
fi fi
if is_auto_mode; then if is_auto_mode; then
/usr/local/bin/pwnagotchi /usr/local/src/pwnagotchi/env/bin/pwnagotchi
systemctl restart bettercap
else else
/usr/local/bin/pwnagotchi --manual /usr/local/src/pwnagotchi/env/bin/pwnagotchi --manual
fi fi

View File

@ -1,13 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# check if brcm is stuck
check_brcm() {
if [[ "$(journalctl -n10 -k --since -5m | grep -c 'brcmf_cfg80211_nexmon_set_channel.*Set Channel failed')" -ge 5 ]]; then
return 1
fi
return 0
}
# reload mod # reload mod
reload_brcm() { reload_brcm() {
if ! modprobe -r brcmfmac; then if ! modprobe -r brcmfmac; then
@ -26,8 +18,10 @@ reload_brcm() {
start_monitor_interface() { start_monitor_interface() {
rfkill unblock all rfkill unblock all
ifconfig wlan0 up ifconfig wlan0 up
sleep 3
iw dev wlan0 set power_save off iw dev wlan0 set power_save off
iw phy "$(iw phy | head -1 | cut -d" " -f2)" interface add wlan0mon type monitor iw phy "$(iw phy | head -1 | cut -d" " -f2)" interface add wlan0mon type monitor
sleep 2
rfkill unblock all rfkill unblock all
ifconfig wlan0 down ifconfig wlan0 down
ifconfig wlan0mon up ifconfig wlan0mon up
@ -41,7 +35,7 @@ stop_monitor_interface() {
ifconfig wlan0 up ifconfig wlan0 up
} }
# returns 0 if the specificed network interface is up # returns 0 if the specified network interface is up
is_interface_up() { is_interface_up() {
if grep -qi 'up' /sys/class/net/"$1"/operstate; then if grep -qi 'up' /sys/class/net/"$1"/operstate; then
return 0 return 0

View File

@ -1,8 +1,8 @@
packer { packer {
required_plugins { required_plugins {
arm = { arm-image = {
version = "1.0.0" source = "github.com/solo-io/arm-image"
source = "github.com/cdecoux/builder-arm" version = ">= 0.0.1"
} }
ansible = { ansible = {
source = "github.com/hashicorp/ansible" source = "github.com/hashicorp/ansible"
@ -19,38 +19,21 @@ variable "pwn_version" {
type = string type = string
} }
source "arm" "rpi32-pwnagotchi" { source "arm-image" "rpi32-pwnagotchi" {
file_checksum_url = "https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-12-06/2023-12-05-raspios-bullseye-armhf-lite.img.xz.sha256" image_type = "raspberrypi"
file_urls = ["https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-12-06/2023-12-05-raspios-bullseye-armhf-lite.img.xz"] iso_url = "https://downloads.raspberrypi.com/raspios_lite_armhf/images/raspios_lite_armhf-2024-07-04/2024-07-04-raspios-bookworm-armhf-lite.img.xz"
file_checksum_type = "sha256" iso_checksum = "sha256:df9c192d66d35e1ce67acde33a5b5f2b81ff02d2b986ea52f1f6ea211d646a1b"
file_target_extension = "xz" output_filename = "../../../pwnagotchi-32bit.img"
file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] qemu_binary = "qemu-arm-static"
image_path = "../../pwnagotchi-32bit.img" qemu_args = ["-cpu", "arm1176"]
qemu_binary_source_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" image_arch = "arm"
qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/arm-binfmt-P" image_mounts = ["/boot/firmware","/"]
image_build_method = "resize" target_image_size = 19969908736
image_size = "9G"
image_type = "dos"
image_partitions {
name = "boot"
type = "c"
start_sector = "8192"
filesystem = "fat"
size = "256M"
mountpoint = "/boot"
}
image_partitions {
name = "root"
type = "83"
start_sector = "532480"
filesystem = "ext4"
size = "0"
mountpoint = "/"
}
} }
build { build {
name = "Raspberry Pi 32 Pwnagotchi" name = "Raspberry Pi 32 Pwnagotchi"
sources = ["source.arm.rpi32-pwnagotchi"] sources = ["source.arm-image.rpi32-pwnagotchi"]
provisioner "file" { provisioner "file" {
destination = "/usr/bin/" destination = "/usr/bin/"
sources = [ sources = [
@ -66,7 +49,13 @@ build {
provisioner "shell" { provisioner "shell" {
inline = ["chmod +x /usr/bin/*"] inline = ["chmod +x /usr/bin/*"]
} }
provisioner "shell" {
inline = ["mkdir -p /usr/local/src/pwnagotchi"]
}
provisioner "file" {
destination = "/usr/local/src/pwnagotchi/"
source = "../"
}
provisioner "file" { provisioner "file" {
destination = "/etc/systemd/system/" destination = "/etc/systemd/system/"
sources = [ sources = [
@ -88,7 +77,6 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_dir = "data/32bit/extras/" playbook_file = "raspberrypi32.yml"
playbook_file = "data/32bit/raspberrypi32.yml"
} }
} }

View File

@ -4,66 +4,15 @@
gather_facts: true gather_facts: true
become: true become: true
vars: vars:
boards:
- {
kernel: "6.1.21+",
name: "PiZeroW",
firmware: "brcmfmac43430-sdio.bin",
patch: "bcm43430a1/7_45_41_46",
cpu: arm1176,
arch_flags: "-arch armv6l"
}
- {
kernel: "6.1.21-v7+",
name: "PiZero2W",
firmware: "brcmfmac43436-sdio.bin",
patch: "bcm43436b0/9_88_4_65",
cpu: any, #cortex-a53
arch_flags: "-arch armv7l"
}
- {
kernel: "6.1.21-v7l+",
name: "Pi4b_32",
firmware: "brcmfmac43455-sdio.bin",
patch: "bcm43455c0/7_45_206",
cpu: any, #cortex-a72
arch_flags: "-arch armv7l"
}
kernel: kernel:
min: "6.1" min: "6.6"
full: "6.1.21+" full: "6.6.31+rpt-rpi-v6"
full_2w: "6.1.21-v7+"
full_4b: "6.1.21-v7l+"
arch: "v6l"
pwnagotchi: pwnagotchi:
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}" version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}"
custom_plugin_dir: "/usr/local/share/pwnagotchi/custom-plugins"
system:
boot_options:
- "#### pwnagotchi additions"
- "# this pwnagotchi image is 32-bit only no v8+ headers to build nexmon for 64 bit"
- "arm_64bit=0"
- "# dwc2 for RNDIS. comment out, and remove dwc2 and g_ether from cmdline.txt for X306 usb battery hat"
- "dtoverlay=dwc2"
- "dtoverlay=spi1-3cs"
- "dtparam=i2c1=on"
- "dtparam=i2c_arm=on"
- "dtparam=spi=on"
- "gpu_mem=16"
- "#### audio out on pins 18 and 19"
- "#dtoverlay=audremap,pins_18_19"
- "#### touchscreen on waveshare touch e-paper"
- "#dtoverlay=goodix,interrupt=27,reset=22"
- "#### for PWM backlighting on pimoroni displayhatmini"
- "dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4"
modules:
- "i2c-dev"
services: services:
enable: enable:
- bettercap.service - bettercap.service
- bluetooth.service
- dphys-swapfile.service
- fstrim.timer - fstrim.timer
- pwnagotchi.service - pwnagotchi.service
- pwngrid-peer.service - pwngrid-peer.service
@ -72,25 +21,24 @@
- apt-daily-upgrade.timer - apt-daily-upgrade.timer
- apt-daily.service - apt-daily.service
- apt-daily.timer - apt-daily.timer
- bluetooth.service
- ifup@wlan0.service - ifup@wlan0.service
- triggerhappy.service
- wpa_supplicant.service
packages: packages:
caplets: caplets:
source: "https://github.com/jayofelony/caplets.git" source: "https://github.com/jayofelony/caplets.git"
branch: "lite" # or master
bettercap: bettercap:
source: "https://github.com/jayofelony/bettercap.git" source: "https://github.com/jayofelony/bettercap.git"
url: "https://github.com/jayofelony/bettercap/releases/download/2.32.2/bettercap-2.32.2-armhf.zip" branch: "lite" # or master
ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip" pwngrid:
opwngrid:
source: "https://github.com/jayofelony/pwngrid.git" source: "https://github.com/jayofelony/pwngrid.git"
url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.7/pwngrid-1.10.7-armhf.zip"
torch: torch:
wheel: "torch-2.1.0a0+gitunknown-cp39-cp39-linux_armv6l.whl" wheel: "torch-2.1.0a0+gita8e7c98-cp311-cp311-linux_armv6l.whl"
url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/v1.0.0/torch-2.1.0a0+gitunknown-cp39-cp39-linux_armv6l.whl" url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/py0torch-bookworm-2024-05/torch-2.1.0a0+gita8e7c98-cp311-cp311-linux_armv6l.whl"
torchvision: torchvision:
wheel: "torchvision-0.16.0a0-cp39-cp39-linux_armv6l.whl" wheel: "torchvision-0.16.0+fbb4cc5-cp311-cp311-linux_armv6l.whl"
url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/v1.0.0/torchvision-0.16.0a0-cp39-cp39-linux_armv6l.whl" url: "https://github.com/Sniffleupagus/Torch4Pizero/releases/download/py0torch-bookworm-2024-05/torchvision-0.16.0+fbb4cc5-cp311-cp311-linux_armv6l.whl"
apt: apt:
downgrade: downgrade:
- libpcap-dev_1.9.1-4_armhf.deb - libpcap-dev_1.9.1-4_armhf.deb
@ -105,106 +53,145 @@
- firmware-realtek - firmware-realtek
- libpcap-dev - libpcap-dev
- libpcap0.8 - libpcap0.8
- libpcap0.8-dev
- libpcap0.8-dbg - libpcap0.8-dbg
- libpcap0.8-dev
remove: remove:
- avahi-daemon
- nfs-common - nfs-common
- triggerhappy - triggerhappy
- wpasupplicant
install: install:
- aircrack-ng
- autoconf - autoconf
- bc
- bison - bison
- bluez - bluez
- bluez-tools
- build-essential - build-essential
- curl - curl
- dkms
- dphys-swapfile - dphys-swapfile
- espeak-ng
- evtest
- fbi - fbi
- firmware-atheros
- firmware-brcm80211
- firmware-libertas
- firmware-misc-nonfree
- firmware-realtek
- flex - flex
- fonts-dejavu
- fonts-dejavu-core
- fonts-dejavu-extra
- fonts-freefont-ttf
- g++ - g++
- gawk - gawk
- gcc-arm-none-eabi - gcc-arm-none-eabi
- git - git
- libatlas-base-dev - libatlas-base-dev
- libavcodec58
- libavformat58
- libblas-dev
- libbluetooth-dev
- libbz2-dev
- libc-ares-dev
- libc6-dev - libc6-dev
- libcpuinfo-dev - libcpuinfo-dev
- libcurl-ocaml-dev
- libdbus-1-dev - libdbus-1-dev
- libdbus-glib-1-dev - libdbus-glib-1-dev
- libeigen3-dev
- libelf-dev
- libffi-dev
- libfl-dev - libfl-dev
- libfuse-dev
- libgdbm-dev
- libgl1-mesa-glx
- libgmp3-dev - libgmp3-dev
- libgstreamer1.0-0
- libhdf5-dev
- liblapack-dev
- libncursesw5-dev
- libnetfilter-queue-dev - libnetfilter-queue-dev
- libopenblas-dev - libopenblas-dev # https://stackoverflow.com/questions/14570011/explain-why-numpy-should-not-be-imported-from-source-directory
- libopenjp2-7 - libopenjp2-7
- libopenmpi-dev
- libopenmpi3
- libpcap-dev - libpcap-dev
- libprotobuf-dev #- libraspberrypi-bin ## seems to be provided by raspi-utils now
- libraspberrypi-bin
- libraspberrypi-dev - libraspberrypi-dev
- libraspberrypi-doc - libraspberrypi-doc
- libraspberrypi0 - libraspberrypi0
- libsleef-dev - libsleef-dev
- libsqlite3-dev
- libssl-dev - libssl-dev
- libswscale5 - libssl-ocaml-dev
- libtiff5
- libtool - libtool
- libts-bin
- libusb-1.0-0-dev - libusb-1.0-0-dev
- lsof
- make - make
- python3-flask - ntp
- python3-flask-cors - pkg-config
- python3-flaskext.wtf - python3-dev
- python3-pil
- python3-pip - python3-pip
- python3-protobuf - python3-protobuf
- python3-setuptools
- python3-smbus - python3-smbus
- qpdf - qpdf
- raspberrypi-kernel-headers - raspberrypi-kernel-headers
- rsync - rsync
- screen
- tcpdump - tcpdump
- texinfo - texinfo
- time
- tk-dev
- unzip - unzip
- vim
- wget - wget
- wl - wl
- xxd - xxd
- zlib1g-dev - zlib1g-dev
environment:
ARCHFLAGS: "-arch armv6l"
tasks: tasks:
# First we install packages
- name: install packages
apt:
name: "{{ packages.apt.install }}"
state: latest
update_cache: yes
install_recommends: no
- name: update pip3, setuptools, wheel
shell: "python3 -m pip install --upgrade pip setuptools wheel --break-system-packages"
args:
executable: /bin/bash
chdir: /usr/local/src
- name: install 32bit torch
shell: "python3 -m pip install {{ packages.torch.url }} {{ packages.torchvision.url }} --break-system-packages"
args:
executable: /bin/bash
environment:
QEMU_UNAME: "{{ kernel.full }}"
ARCHFLAGS: "-arch armv6l"
# Now we set up /boot/firmware
- name: Create pi user - name: Create pi user
copy: copy:
dest: /boot/userconf dest: /boot/firmware/userconf
content: | content: |
pi:$6$3jNr0GA9KIyt4hmM$efeVIopdMQ8DGgEPCWWlbx3mJJNAYci1lEXGdlky0xPyjqwKNbwTL5SrCcpb4144C4IvzWjn7Iv.QjqmU7iyT/ pi:$5$733Efsksay$SEFUKemv8FaNAu6X4GUfxdSzSDh6PbpOcdtNe5b7Nt0
- name: enable ssh on boot
file:
path: /boot/firmware/ssh
state: touch
- name: remove current rc.local
file:
path: /etc/rc.local
state: absent
- name: change root partition
replace:
dest: /boot/firmware/cmdline.txt
backup: no
regexp: "root=PARTUUID=[a-zA-Z0-9\\-]+"
replace: "root=/dev/mmcblk0p2"
- name: configure /boot/firmware/cmdline.txt
lineinfile:
path: /boot/firmware/cmdline.txt
backrefs: True
state: present
backup: no
regexp: '(.*)$'
line: '\1 modules-load=dwc2,g_ether'
- name: setup /boot/firmware/config.txt
blockinfile:
path: /boot/firmware/config.txt
insertafter: EOF
block: |
dtparam=i2c1=on
dtparam=i2c_arm=on
dtparam=spi=on
gpu_mem=1
dtoverlay=dwc2
#dtoverlay=disable-wifi
enable_uart=1
[pi0]
dtoverlay=spi0-2cs
#dtoverlay=disable-wifi
- name: change hostname - name: change hostname
lineinfile: lineinfile:
@ -223,26 +210,14 @@
state: present state: present
when: hostname.changed when: hostname.changed
- name: Create custom plugin directory # Now we disable sap and a2dp, we don't use them on rpi
file: - name: disable sap plugin for bluetooth.service
path: '{{ pwnagotchi.custom_plugin_dir }}' lineinfile:
state: directory dest: /lib/systemd/system/bluetooth.service
regexp: '^ExecStart=/usr/libexec/bluetooth/bluetoothd$'
- name: update apt package cache line: 'ExecStart=/usr/libexec/bluetooth/bluetoothd --noplugin=sap,a2dp'
apt:
update_cache: yes
- name: install packages
apt:
name: "{{ packages.apt.install }}"
state: present state: present
- name: update pip3, setuptools, wheel
shell: "python3 -m pip install --upgrade pip setuptools wheel"
args:
executable: /bin/bash
chdir: /usr/local/src
########################################### ###########################################
# #
# libpcap v1.9 - build from source # libpcap v1.9 - build from source
@ -276,17 +251,61 @@
dest: /usr/local/lib/libpcap.so.0.8 dest: /usr/local/lib/libpcap.so.0.8
state: link state: link
############################################################### # install latest hcxtools
# Install nexmon to fix wireless scanning (takes 2.5G of space) - name: clone hcxtools
############################################################### git:
repo: https://github.com/ZerBea/hcxtools.git
dest: /usr/local/src/hcxtools
# Install nexmon for all boards - name: install hcxtools
- name: build and install nexmon as needed shell: "make && make install"
include_tasks: nexmon.yml args:
loop: "{{ boards }}" executable: /bin/bash
chdir: /usr/local/src/hcxtools
- name: remove hcxtools directory
file:
state: absent
path: /usr/local/src/hcxtools
# Installing nexmon
- name: clone nexmon repository
git:
repo: https://github.com/DrSchottky/nexmon.git
dest: /usr/local/src/nexmon
- name: make firmware
shell: "source ./setup_env.sh && make"
args:
executable: /bin/bash
chdir: /usr/local/src/nexmon/
environment:
QEMU_UNAME: "{{ kernel.full }}"
ARCHFLAGS: "-arch armv6l"
- name: make firmware patch (bcm43430a1)
shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/ && make"
args:
executable: /bin/bash
chdir: /usr/local/src/nexmon/
environment:
QEMU_UNAME: "{{ kernel.full }}"
ARCHFLAGS: "-arch armv6l"
- name: install new firmware (bcm43430a1)
copy:
src: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/brcmfmac43430-sdio.bin
dest: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin
follow: true
- name: copy modified driver
copy:
src: "/usr/local/src/nexmon/patches/driver/brcmfmac_{{ kernel.min }}.y-nexmon/brcmfmac.ko"
dest: "/usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko"
environment:
QEMU_UNAME: "{{ kernel.full }}"
ARCHFLAGS: "-arch armv6l"
# some pizero2w have the pizeroW wifi chip
# could this be a link instead of a copy? and force, only if not a link?
- name: copy 43430-sdio as 43436s-sdio for the special 43430/1 /2 - name: copy 43430-sdio as 43436s-sdio for the special 43430/1 /2
copy: copy:
src: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin src: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin
@ -301,9 +320,14 @@
loop: loop:
- /usr/lib/firmware/brcm/brcmfmac43430-sdio.clm_blob - /usr/lib/firmware/brcm/brcmfmac43430-sdio.clm_blob
- /usr/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.clm_blob - /usr/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,model-zero-w.clm_blob
- /usr/lib/firmware/brcm/brcmfmac43430b0-sdio.raspberrypi,model-zero-2-w.clm_blob
- /usr/lib/firmware/brcm/brcmfmac43436-sdio.raspberrypi,model-zero-2-w.clm_blob - name: backup original driver
- /usr/lib/firmware/brcm/brcmfmac43430-sdio.raspberrypi,3-model-b.clm_blob command: "mv /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig"
- name: load brcmfmac drivers
command: "/sbin/depmod {{ kernel.full }}"
environment:
QEMU_UNAME: "{{ kernel.full }}"
# To shrink the final image, remove the nexmon directory (takes 2.5G of space) post build and installation # To shrink the final image, remove the nexmon directory (takes 2.5G of space) post build and installation
- name: Delete nexmon content & directory - name: Delete nexmon content & directory
@ -311,58 +335,36 @@
state: absent state: absent
path: /usr/local/src/nexmon/ path: /usr/local/src/nexmon/
- name: clone pwnagotchi repository - name: Create custom config directory
git: file:
repo: https://github.com/jayofelony/pwnagotchi.git path: /etc/pwnagotchi/conf.d/
dest: /usr/local/src/pwnagotchi state: directory
register: pwnagotchigit
#- name: clone pwnagotchi repository
# git:
# repo: https://github.com/jayofelony/pwnagotchi.git
# dest: /usr/local/src/pwnagotchi
# is this even necessary? Can't we just link from /home/pi/pwnagotchi to /usr/local/{bin,lib,etc}
# then just git update in the home dir and encourage hacking?
# make owned by pi.pi, and custom plugins.
- name: build pwnagotchi wheel - name: build pwnagotchi wheel
command: "python3 setup.py sdist bdist_wheel" command: "pip3 install . --no-cache-dir --break-system-packages"
args: args:
chdir: /usr/local/src/pwnagotchi chdir: /usr/local/src/pwnagotchi
when: (pwnagotchigit.changed) or (pip_packages['pwnagotchi'] is undefined) or (pip_packages['pwnagotchi'] != pwnagotchi_version)
- name: download torch whl
get_url:
url: "{{ packages.torch.url }}"
dest: /usr/local/src/
- name: download torchvision whl
get_url:
url: "{{ packages.torchvision.url }}"
dest: /usr/local/src/
- name: install 32-bit pwnagotchi wheel and dependencies with 32-bit torch wheels
pip:
name:
- "{{ lookup('fileglob', '/usr/local/src/pwnagotchi/dist/pwnagotchi*.whl') }}"
- "{{ packages.torch.url }}"
- "{{ packages.torchvision.url }}"
extra_args: "--no-cache-dir"
environment:
QEMU_CPU: arm1176
QEMU_UNAME: "{{ kernel.full }}"
when: (pwnagotchigit.changed) or (pip_packages['pwnagotchi'] is undefined) or (pip_packages['pwnagotchi'] != pwnagotchi_version)
- name: create /usr/local/share/pwnagotchi/ folder - name: create /usr/local/share/pwnagotchi/ folder
file: file:
path: /usr/local/share/pwnagotchi/ path: /usr/local/share/pwnagotchi/
state: directory state: directory
- name: Create custom plugin directory
file:
path: /usr/local/share/pwnagotchi/custom-plugins/
state: directory
- name: remove pwnagotchi folder - name: remove pwnagotchi folder
file: file:
state: absent state: absent
path: /usr/local/src/pwnagotchi path: /usr/local/src/pwnagotchi
- name: remove torch whl
file:
state: absent
path: "{{ lookup('fileglob', '/usr/local/src/torch*.whl') }}"
########################################## ##########################################
# #
# pwngrid, bettercap # pwngrid, bettercap
@ -371,45 +373,57 @@
- name: Install go-1.21 - name: Install go-1.21
unarchive: unarchive:
src: https://go.dev/dl/go1.21.6.linux-armv6l.tar.gz src: https://go.dev/dl/go1.22.3.linux-armv6l.tar.gz
dest: /usr/local dest: /usr/local
remote_src: yes remote_src: yes
register: golang register: golang
- name: Update .bashrc for go-1.21 - name: Update .bashrc for go-1.21
blockinfile: blockinfile:
dest: /home/pi/.bashrc dest: /etc/profile
state: present state: present
block: | block: |
export GOPATH=$HOME/go export GOPATH=$HOME/go
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'
when: golang.changed when: golang.changed
- name: download pwngrid - name: download pwngrid
unarchive: git:
remote_src: yes repo: "{{ packages.pwngrid.source }}"
src: "{{ packages.opwngrid.url }}" dest: /usr/local/src/pwngrid
dest: /usr/local/bin/
mode: 0755
- name: download and install bettercap - name: install pwngrid
unarchive: shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
src: "{{ packages.bettercap.url }}" args:
dest: /usr/local/bin executable: /bin/bash
remote_src: yes chdir: /usr/local/src/pwngrid
exclude:
- README.md - name: remove pwngrid folder
- LICENSE.md file:
mode: 0755 state: absent
path: /usr/local/src/pwngrid
- name: download bettercap
git:
repo: "{{ packages.bettercap.source }}"
version: "{{ packages.bettercap.branch }} "
dest: /usr/local/src/bettercap
- name: install bettercap 2.32.4
shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
args:
executable: /bin/bash
chdir: /usr/local/src/bettercap
- name: remove bettercap folder
file:
state: absent
path: /usr/local/src/bettercap
- name: clone bettercap caplets - name: clone bettercap caplets
git: git:
repo: "{{ packages.caplets.source }}" repo: "{{ packages.caplets.source }}"
version: "{{ packages.caplets.branch }}"
dest: /tmp/caplets dest: /tmp/caplets
register: capletsgit register: capletsgit
@ -419,31 +433,11 @@
target: install target: install
when: capletsgit.changed when: capletsgit.changed
- name: download and install bettercap ui
unarchive:
src: "{{ packages.bettercap.ui }}"
dest: /usr/local/share/bettercap/
remote_src: yes
mode: 0755
# to always have the bettercap webui available (because why not?)
- name: copy pwnagotchi-manual over pwnagotchi-auto caplet
ansible.builtin.copy:
src: /usr/local/share/bettercap/caplets/pwnagotchi-manual.cap
dest: /usr/local/share/bettercap/caplets/pwnagotchi-auto.cap
force: true
ignore_errors: true
- name: create /etc/pwnagotchi folder - name: create /etc/pwnagotchi folder
file: file:
path: /etc/pwnagotchi path: /etc/pwnagotchi
state: directory state: directory
- name: create log folder
file:
path: /home/pi/logs
state: directory
- name: check if user configuration exists - name: check if user configuration exists
stat: stat:
path: /etc/pwnagotchi/config.toml path: /etc/pwnagotchi/config.toml
@ -459,46 +453,16 @@
# ui.display.type = "waveshare_4" # ui.display.type = "waveshare_4"
when: not user_config.stat.exists when: not user_config.stat.exists
- name: Delete motd
file:
state: absent
path: /etc/motd
- name: Delete motd 10-uname - name: Delete motd 10-uname
file: file:
state: absent state: absent
path: /etc/update-motd.d/10-uname path: /etc/update-motd.d/10-uname
- 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: "{{system.boot_options}}"
- name: adjust /etc/modules
lineinfile:
dest: /etc/modules
insertafter: EOF
line: '{{ item }}'
with_items: "{{system.modules}}"
- 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: add firmware packages to hold - name: add firmware packages to hold
dpkg_selections: dpkg_selections:
name: "{{ item }}" name: "{{ item }}"
@ -518,16 +482,7 @@
enabled: true enabled: true
state: stopped state: stopped
with_items: "{{ services.enable }}" with_items: "{{ services.enable }}"
register: enabled
#- name: remove golang build libraries
# file:
# state: absent
# path: /root/go
#- name: remove golang
# file:
# state: absent
# path: /usr/local/go
- name: make /root readable, becauase that's where all the files are - name: make /root readable, becauase that's where all the files are
file: file:
@ -541,53 +496,65 @@
group: pi group: pi
recurse: true recurse: true
- name: remove unnecessary apt packages
apt:
name: "{{ packages.apt.remove }}"
state: absent
purge: yes
- name: remove dependencies that are no longer required
apt:
autoremove: yes
- name: clean apt cache
apt:
autoclean: true
- name: remove golang build libraries
file:
state: absent
path: /root/go
- name: remove pre-collected packages zip - name: remove pre-collected packages zip
file: file:
path: /root/go_pkgs.tgz path: /root/go_pkgs.tgz
state: absent state: absent
- name: remove golang - name: remove /root/go folder
file:
state: absent
path: /root/go
- name: remove /usr/local/go folder
file: file:
state: absent state: absent
path: /usr/local/go path: /usr/local/go
- name: remove /root/.cache (pip cache) - name: remove pip cache
file: file:
state: absent state: absent
path: /root/.cache path: /root/.cache/pip
- name: remove ssh keys - name: remove ssh keys
file: file:
state: absent state: absent
path: "{{ item }}" path: "{{ item }}"
with_fileglob: with_fileglob:
- "/etc/ssh/ssh_host*_key*" - "/etc/ssh/ssh_host*_key*"
- name: regenerate ssh keys - name: regenerate ssh keys
shell: "dpkg-reconfigure openssh-server" shell: "dpkg-reconfigure openssh-server"
args: args:
executable: /bin/bash executable: /bin/bash
# Now we remove packages
- name: remove unnecessary apt packages
apt:
name: "{{ packages.apt.remove }}"
state: absent
purge: yes
register: removed
- name: remove dependencies that are no longer required
apt:
autoremove: yes
when: removed.changed
- name: install rpi-sys-mods again?
apt:
state: present
name: raspberrypi-sys-mods
update_cache: yes
install_recommends: no
- name: clean apt cache
apt:
autoclean: true
when: removed.changed
handlers: handlers:
- name: reload systemd services - name: reload systemd services
systemd: systemd:
daemon_reload: yes daemon_reload: yes
when: enabled.changed

View File

@ -1,8 +1,8 @@
packer { packer {
required_plugins { required_plugins {
arm = { arm-image = {
version = "1.0.0" source = "github.com/solo-io/arm-image"
source = "github.com/cdecoux/builder-arm" version = ">= 0.0.1"
} }
ansible = { ansible = {
source = "github.com/hashicorp/ansible" source = "github.com/hashicorp/ansible"
@ -19,44 +19,22 @@ variable "pwn_version" {
type = string type = string
} }
source "arm" "rpi64-pwnagotchi" { source "arm-image" "rpi64-pwnagotchi" {
file_checksum_url = "https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-11/2023-12-11-raspios-bookworm-arm64-lite.img.xz.sha256" image_type = "raspberrypi"
file_urls = ["https://downloads.raspberrypi.org/raspios_lite_arm64/images/raspios_lite_arm64-2023-12-11/2023-12-11-raspios-bookworm-arm64-lite.img.xz"] iso_url = "https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2024-07-04/2024-07-04-raspios-bookworm-arm64-lite.img.xz"
file_checksum_type = "sha256" iso_checksum = "sha256:43d150e7901583919e4eb1f0fa83fe0363af2d1e9777a5bb707d696d535e2599"
file_target_extension = "xz" output_filename = "../../../pwnagotchi-64bit.img"
file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] qemu_binary = "qemu-aarch64-static"
image_path = "../../../pwnagotchi-64bit.img" target_image_size = 19969908736
qemu_binary_source_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P" image_mounts = ["/boot/firmware","/"]
qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P"
image_build_method = "resize"
image_size = "9G"
image_type = "dos"
image_partitions {
name = "boot"
type = "c"
start_sector = "8192"
filesystem = "fat"
size = "256M"
mountpoint = "/boot/firmware"
}
image_partitions {
name = "root"
type = "83"
start_sector = "532480"
filesystem = "ext4"
size = "0"
mountpoint = "/"
}
} }
# a build block invokes sources and runs provisioning steps on them. The # a build block invokes sources and runs provisioning steps on them. The
# documentation for build blocks can be found here: # documentation for build blocks can be found here:
# https://www.packer.io/docs/from-1.5/blocks/build # https://www.packer.io/docs/from-1.5/blocks/build
build { build {
name = "Raspberry Pi 64 Pwnagotchi" name = "Raspberry Pi 64 Pwnagotchi"
sources = ["source.arm.rpi64-pwnagotchi"] sources = ["source.arm-image.rpi64-pwnagotchi"]
provisioner "file" { provisioner "file" {
destination = "/usr/bin/" destination = "/usr/bin/"
@ -73,7 +51,13 @@ build {
provisioner "shell" { provisioner "shell" {
inline = ["chmod +x /usr/bin/*"] inline = ["chmod +x /usr/bin/*"]
} }
provisioner "shell" {
inline = ["mkdir -p /usr/local/src/pwnagotchi"]
}
provisioner "file" {
destination = "/usr/local/src/pwnagotchi/"
source = "../"
}
provisioner "file" { provisioner "file" {
destination = "/etc/systemd/system/" destination = "/etc/systemd/system/"
sources = [ sources = [
@ -95,6 +79,6 @@ build {
provisioner "ansible-local" { provisioner "ansible-local" {
command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook" command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 PWN_VERSION=${var.pwn_version} PWN_HOSTNAME=${var.pwn_hostname} ansible-playbook"
extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""] extra_arguments = ["--extra-vars \"ansible_python_interpreter=/usr/bin/python3\""]
playbook_file = "data/64bit/raspberrypi64.yml" playbook_file = "raspberrypi64.yml"
} }
} }

View File

@ -5,22 +5,12 @@
become: true become: true
vars: vars:
kernel: kernel:
min: "6.1" min: "6.6"
full: "6.1.0-rpi8-rpi-v8" full: "6.6.31+rpt-rpi-v8"
full_pi5: "6.1.0-rpi8-rpi-2712" full_pi5: "6.6.31+rpt-rpi-2712"
pwnagotchi: pwnagotchi:
hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}" hostname: "{{ lookup('env', 'PWN_HOSTNAME') | default('pwnagotchi', true) }}"
version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}" version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi', true) }}"
system:
boot_options:
- "dtoverlay=dwc2"
- "dtoverlay=spi1-3cs"
- "dtparam=i2c1=on"
- "dtparam=i2c_arm=on"
- "dtparam=spi=on"
- "gpu_mem=16"
modules:
- "i2c-dev"
services: services:
enable: enable:
- bettercap.service - bettercap.service
@ -37,10 +27,11 @@
packages: packages:
caplets: caplets:
source: "https://github.com/jayofelony/caplets.git" source: "https://github.com/jayofelony/caplets.git"
branch: "lite" # or master
bettercap: bettercap:
source: "https://github.com/jayofelony/bettercap.git" source: "https://github.com/jayofelony/bettercap.git"
url: "https://github.com/jayofelony/bettercap/releases/download/2.32.4/bettercap-2.32.4.zip" url: "https://github.com/jayofelony/bettercap/releases/download/2.32.4/bettercap-2.32.4.zip"
ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip" branch: "lite" # or master
pwngrid: pwngrid:
source: "https://github.com/jayofelony/pwngrid.git" source: "https://github.com/jayofelony/pwngrid.git"
url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.5/pwngrid-1.10.5-aarch64.zip" url: "https://github.com/jayofelony/pwngrid/releases/download/v1.10.5/pwngrid-1.10.5-aarch64.zip"
@ -61,22 +52,17 @@
- libpcap0.8-dbg - libpcap0.8-dbg
- libpcap0.8-dev - libpcap0.8-dev
remove: remove:
- avahi-daemon
- dhpys-swapfile - dhpys-swapfile
- libcurl-ocaml-dev
- libssl-ocaml-dev
- nfs-common - nfs-common
- triggerhappy - triggerhappy
- wpasupplicant
install: install:
- aircrack-ng - aircrack-ng
- autoconf - autoconf
- bc
- bison - bison
- bluez - bluez
- bluez-tools
- build-essential - build-essential
- curl - curl
- dkms
- dphys-swapfile - dphys-swapfile
- fbi - fbi
- firmware-atheros - firmware-atheros
@ -85,85 +71,40 @@
- firmware-misc-nonfree - firmware-misc-nonfree
- firmware-realtek - firmware-realtek
- flex - flex
- fonts-dejavu
- fonts-dejavu-core
- fonts-dejavu-extra
- fonts-freefont-ttf
- g++ - g++
- gawk - gawk
- gcc-arm-none-eabi - gcc-arm-none-eabi
- git - git
- hcxtools
- libatlas-base-dev
- libavcodec59
- libavformat59
- libblas-dev
- libbluetooth-dev
- libbz2-dev
- libc-ares-dev
- libc6-dev - libc6-dev
- libcap-dev
- libcurl-ocaml-dev - libcurl-ocaml-dev
- libdbus-1-dev - libdbus-1-dev
- libdbus-glib-1-dev - libdbus-glib-1-dev
- libeigen3-dev
- libelf-dev
- libffi-dev
- libfl-dev - libfl-dev
- libfuse-dev
- libgdbm-dev
- libgl1-mesa-glx
- libgmp3-dev - libgmp3-dev
- libgstreamer1.0-0
- libhdf5-dev
- liblapack-dev
- libncursesw5-dev
- libnetfilter-queue-dev - libnetfilter-queue-dev
- libopenblas-dev
- libopenjp2-7
- libopenmpi-dev
- libopenmpi3
- libpcap-dev - libpcap-dev
- libraspberrypi-bin #- libraspberrypi-bin ## seems to be provided by raspi-utils now
- libraspberrypi-dev - libraspberrypi-dev
- libraspberrypi-doc - libraspberrypi-doc
- libraspberrypi0 - libraspberrypi0
- libsqlite3-dev
- libssl-dev - libssl-dev
- libssl-ocaml-dev - libssl-ocaml-dev
- libswscale5
- libtiff6
- libtool - libtool
- libusb-1.0-0-dev - libusb-1.0-0-dev
- lsof
- make - make
- python3-dbus - ntp
- python3-flask - pkg-config
- python3-flask-cors - python3-dev
- python3-flaskext.wtf
- python3-gast
- python3-pil
- python3-pip - python3-pip
- python3-pycryptodome
- python3-requests
- python3-scapy
- python3-setuptools - python3-setuptools
- python3-smbus - python3-smbus
- python3-smbus2
- python3-spidev
- python3-tweepy
- python3-werkzeug
- python3-yaml
- qpdf - qpdf
- raspberrypi-kernel-headers - raspberrypi-kernel-headers
- raspberrypi-sys-mods
- rsync - rsync
- screen
- tcpdump - tcpdump
- texinfo - texinfo
- time
- tk-dev
- unzip - unzip
- vim
- wget - wget
- wl - wl
- xxd - xxd
@ -176,9 +117,9 @@
- name: install packages - name: install packages
apt: apt:
name: "{{ packages.apt.install }}" name: "{{ packages.apt.install }}"
state: present state: latest
update_cache: yes update_cache: yes
install_recommends: false install_recommends: no
- name: update pip3, setuptools, wheel - name: update pip3, setuptools, wheel
shell: "python3 -m pip install --upgrade pip setuptools wheel --break-system-packages" shell: "python3 -m pip install --upgrade pip setuptools wheel --break-system-packages"
@ -186,24 +127,32 @@
executable: /bin/bash executable: /bin/bash
chdir: /usr/local/src chdir: /usr/local/src
- name: build pwnagotchi wheel
command: "pip3 install . --no-cache-dir --break-system-packages"
args:
chdir: /usr/local/src/pwnagotchi
- name: remove pwnagotchi folder
file:
state: absent
path: /usr/local/src/pwnagotchi
# Now we set up /boot/firmware # Now we set up /boot/firmware
- name: Create pi user - name: Create pi user
copy: copy:
dest: /boot/firmware/userconf dest: /boot/firmware/userconf
content: | content: |
pi:$6$3jNr0GA9KIyt4hmM$efeVIopdMQ8DGgEPCWWlbx3mJJNAYci1lEXGdlky0xPyjqwKNbwTL5SrCcpb4144C4IvzWjn7Iv.QjqmU7iyT/ pi:$5$733Efsksay$SEFUKemv8FaNAu6X4GUfxdSzSDh6PbpOcdtNe5b7Nt0
- name: enable ssh on boot - name: enable ssh on boot
file: file:
path: /boot/firmware/ssh path: /boot/firmware/ssh
state: touch state: touch
- name: adjust /boot/firmware/config.txt - name: remove current rc.local
lineinfile: file:
dest: /boot/firmware/config.txt path: /etc/rc.local
insertafter: EOF state: absent
line: '{{ item }}'
with_items: "{{ system.boot_options }}"
- name: change root partition - name: change root partition
replace: replace:
@ -221,6 +170,35 @@
regexp: '(.*)$' regexp: '(.*)$'
line: '\1 modules-load=dwc2,g_ether' line: '\1 modules-load=dwc2,g_ether'
- name: setup /boot/firmware/config.txt
blockinfile:
path: /boot/firmware/config.txt
insertafter: EOF
block: |
dtparam=i2c1=on
dtparam=i2c_arm=on
dtparam=spi=on
gpu_mem=1
dtoverlay=dwc2
#dtoverlay=disable-wifi
enable_uart=1
[pi02w]
dtoverlay=spi0-2cs
#dtoverlay=disable-wifi
[pi3]
dtoverlay=spi0-2cs
#dtoverlay=disable-wifi
[pi4]
dtoverlay=spi0-2cs
#dtoverlay=disable-wifi
[pi5]
dtoverlay=spi0-2cs
#dtoverlay=disable-wifi
- name: change hostname - name: change hostname
lineinfile: lineinfile:
dest: /etc/hostname dest: /etc/hostname
@ -280,7 +258,6 @@
state: link state: link
# install latest hcxtools # install latest hcxtools
- name: clone hcxtools - name: clone hcxtools
git: git:
repo: https://github.com/ZerBea/hcxtools.git repo: https://github.com/ZerBea/hcxtools.git
@ -297,13 +274,13 @@
state: absent state: absent
path: /usr/local/src/hcxtools path: /usr/local/src/hcxtools
# Installing nexmon
- name: clone nexmon repository - name: clone nexmon repository
git: git:
repo: https://github.com/DrSchottky/nexmon.git repo: https://github.com/DrSchottky/nexmon.git
dest: /usr/local/src/nexmon dest: /usr/local/src/nexmon
# FIRST WE BUILD DRIVER FOR RPi5 # FIRST WE BUILD DRIVER FOR RPi5
- name: make firmware, RPi5 - name: make firmware, RPi5
shell: "source ./setup_env.sh && make" shell: "source ./setup_env.sh && make"
args: args:
@ -330,11 +307,6 @@
QEMU_UNAME: "{{ kernel.full_pi5 }}" QEMU_UNAME: "{{ kernel.full_pi5 }}"
ARCHFLAGS: "-arch aarch64" ARCHFLAGS: "-arch aarch64"
- name: Delete the modified driver, RPi5
file:
state: absent
path: '/usr/local/src/nexmon/patches/driver/brcmfmac_{{ kernel.min }}.y-nexmon/brcmfmac.ko'
- name: backup original driver, RPi5 - name: backup original driver, RPi5
command: "mv /usr/lib/modules/{{ kernel.full_pi5 }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full_pi5 }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig" command: "mv /usr/lib/modules/{{ kernel.full_pi5 }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full_pi5 }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig"
@ -349,7 +321,6 @@
path: /usr/local/src/nexmon/ path: /usr/local/src/nexmon/
# NOW WE BUILD DRIVERS FOR RPi4, RPizero2w and RPi3 # NOW WE BUILD DRIVERS FOR RPi4, RPizero2w and RPi3
- name: clone nexmon repository - name: clone nexmon repository
git: git:
repo: https://github.com/DrSchottky/nexmon.git repo: https://github.com/DrSchottky/nexmon.git
@ -380,7 +351,6 @@
follow: true follow: true
# NOW WE BUILD DRIVERS FOR RPiZero2W, RPi 3 # NOW WE BUILD DRIVERS FOR RPiZero2W, RPi 3
- name: make firmware patch (bcm43436b0) - name: make firmware patch (bcm43436b0)
shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43436b0/9_88_4_65/nexmon/ && make" shell: "source ./setup_env.sh && cd /usr/local/src/nexmon/patches/bcm43436b0/9_88_4_65/nexmon/ && make"
args: args:
@ -405,6 +375,12 @@
QEMU_UNAME: "{{ kernel.full }}" QEMU_UNAME: "{{ kernel.full }}"
ARCHFLAGS: "-arch aarch64" ARCHFLAGS: "-arch aarch64"
- name: install new firmware (bcm43430a1)
copy:
src: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/brcmfmac43430-sdio.bin
dest: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin
follow: true
- name: copy modified driver, RPi4 - name: copy modified driver, RPi4
copy: copy:
src: "/usr/local/src/nexmon/patches/driver/brcmfmac_{{ kernel.min }}.y-nexmon/brcmfmac.ko" src: "/usr/local/src/nexmon/patches/driver/brcmfmac_{{ kernel.min }}.y-nexmon/brcmfmac.ko"
@ -413,12 +389,6 @@
QEMU_UNAME: "{{ kernel.full }}" QEMU_UNAME: "{{ kernel.full }}"
ARCHFLAGS: "-arch aarch64" ARCHFLAGS: "-arch aarch64"
- name: install new firmware (bcm43430a1)
copy:
src: /usr/local/src/nexmon/patches/bcm43430a1/7_45_41_46/nexmon/brcmfmac43430-sdio.bin
dest: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin
follow: true
- name: copy 43430-sdio as 43436s-sdio for the special 43430/1 /2 - name: copy 43430-sdio as 43436s-sdio for the special 43430/1 /2
copy: copy:
src: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin src: /usr/lib/firmware/brcm/brcmfmac43430-sdio.bin
@ -438,6 +408,7 @@
- /usr/lib/firmware/brcm/brcmfmac43436-sdio.clm_blob - /usr/lib/firmware/brcm/brcmfmac43436-sdio.clm_blob
- /usr/lib/firmware/brcm/brcmfmac43436-sdio.raspberrypi,model-zero-2-w.clm_blob - /usr/lib/firmware/brcm/brcmfmac43436-sdio.raspberrypi,model-zero-2-w.clm_blob
- /usr/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob - /usr/lib/firmware/brcm/brcmfmac43455-sdio.clm_blob
- /usr/lib/firmware/brcm/BCM43430A1.raspberrypi,model-zero-2-w.hcd
- name: backup original driver - name: backup original driver
command: "mv /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig" command: "mv /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz /usr/lib/modules/{{ kernel.full }}/kernel/drivers/net/wireless/broadcom/brcm80211/brcmfmac/brcmfmac.ko.xz.orig"
@ -453,55 +424,35 @@
state: absent state: absent
path: /usr/local/src/nexmon/ path: /usr/local/src/nexmon/
- name: Create custom plugin directory
file:
path: /usr/local/share/pwnagotchi/custom-plugins/
state: directory
- name: Create custom config directory - name: Create custom config directory
file: file:
path: /etc/pwnagotchi/conf.d/ path: /etc/pwnagotchi/conf.d/
state: directory state: directory
- name: clone pwnagotchi repository
git:
repo: https://github.com/jayofelony/pwnagotchi.git
dest: /usr/local/src/pwnagotchi
- name: build pwnagotchi wheel
command: "pip3 install . --no-cache-dir --break-system-packages"
args:
chdir: /usr/local/src/pwnagotchi
- name: remove pwnagotchi folder
file:
state: absent
path: /usr/local/src/pwnagotchi
- name: create /usr/local/share/pwnagotchi/ folder - name: create /usr/local/share/pwnagotchi/ folder
file: file:
path: /usr/local/share/pwnagotchi/ path: /usr/local/share/pwnagotchi/
state: directory state: directory
- name: Create custom plugin directory
file:
path: /usr/local/share/pwnagotchi/custom-plugins/
state: directory
- name: Install go-1.21 - name: Install go-1.21
unarchive: unarchive:
src: https://go.dev/dl/go1.21.5.linux-arm64.tar.gz src: https://go.dev/dl/go1.22.3.linux-arm64.tar.gz
dest: /usr/local dest: /usr/local
remote_src: yes remote_src: yes
register: golang register: golang
- name: Update .bashrc for go-1.21 - name: Update .bashrc for go-1.21
blockinfile: blockinfile:
dest: /home/pi/.bashrc dest: /etc/profile
state: present state: present
block: | block: |
export GOPATH=$HOME/go export GOPATH=$HOME/go
export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin
alias custom='cd /usr/local/share/pwnagotchi/custom-plugins/'
alias config='sudo nano /etc/pwnagotchi/config.toml'
alias pwnlog='tail -f -n300 /etc/pwnagotchi/log/pwn*.log | sed --unbuffered "s/,[[:digit:]]\\{3\\}\\]//g" | cut -d " " -f 2-'
alias pwnver='python3 -c "import pwnagotchi as p; print(p.__version__)"'
alias pwnkill='sudo killall -USR1 pwnagotchi'
when: golang.changed when: golang.changed
- name: download pwngrid - name: download pwngrid
@ -523,6 +474,7 @@
- name: download bettercap - name: download bettercap
git: git:
repo: "{{ packages.bettercap.source }}" repo: "{{ packages.bettercap.source }}"
version: "{{ packages.bettercap.branch }}"
dest: /usr/local/src/bettercap dest: /usr/local/src/bettercap
- name: install bettercap 2.32.4 - name: install bettercap 2.32.4
@ -549,6 +501,7 @@
- name: clone bettercap caplets - name: clone bettercap caplets
git: git:
repo: "{{ packages.caplets.source }}" repo: "{{ packages.caplets.source }}"
version: "{{ packages.caplets.branch }}"
dest: /tmp/caplets dest: /tmp/caplets
register: capletsgit register: capletsgit
@ -558,21 +511,6 @@
target: install target: install
when: capletsgit.changed when: capletsgit.changed
- name: download and install bettercap ui
unarchive:
src: "{{ packages.bettercap.ui }}"
dest: /usr/local/share/bettercap/
remote_src: yes
mode: 0755
# to always have the bettercap webui available (because why not?)
- name: copy pwnagotchi-manual over pwnagotchi-auto caplet
ansible.builtin.copy:
src: /usr/local/share/bettercap/caplets/pwnagotchi-manual.cap
dest: /usr/local/share/bettercap/caplets/pwnagotchi-auto.cap
force: true
ignore_errors: true
- name: create /etc/pwnagotchi folder - name: create /etc/pwnagotchi folder
file: file:
path: /etc/pwnagotchi path: /etc/pwnagotchi
@ -690,4 +628,4 @@
- name: reload systemd services - name: reload systemd services
systemd: systemd:
daemon_reload: yes daemon_reload: yes
when: enabled.changed when: enabled.changed

View File

@ -1 +1 @@
__version__ = '2.8.6' __version__ = '2.9.2'

View File

@ -4,7 +4,9 @@ import os
import re import re
import logging import logging
import asyncio import asyncio
import _thread #import _thread
import threading
import subprocess
import pwnagotchi import pwnagotchi
import pwnagotchi.utils as utils import pwnagotchi.utils as utils
@ -254,7 +256,7 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
txt = '%d (%d)' % (len(self._handshakes), tot) txt = '%d (%d)' % (len(self._handshakes), tot)
if self._last_pwnd is not None: if self._last_pwnd is not None:
txt += ' [%s]' % self._last_pwnd[:11] # So it doesn't overlap with fix_brcmfmac_plugin txt += ' [%s]' % self._last_pwnd
self._view.set('shakes', txt) self._view.set('shakes', txt)
@ -269,9 +271,9 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
self._save_recovery_data() self._save_recovery_data()
pwnagotchi.reboot() pwnagotchi.reboot()
def _restart(self): def _restart(self, mode='AUTO'):
self._save_recovery_data() self._save_recovery_data()
pwnagotchi.restart("AUTO") pwnagotchi.restart(mode)
def _save_recovery_data(self): def _save_recovery_data(self):
logging.warning("writing recovery data to %s ...", RECOVERY_DATA_FILE) logging.warning("writing recovery data to %s ...", RECOVERY_DATA_FILE)
@ -304,7 +306,8 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
raise raise
def start_session_fetcher(self): def start_session_fetcher(self):
_thread.start_new_thread(self._fetch_stats, ()) #_thread.start_new_thread(self._fetch_stats, ())
threading.Thread(target=self._fetch_stats, args=(), name="Session Fetcher", daemon=True).start()
def _fetch_stats(self): def _fetch_stats(self):
while True: while True:
@ -387,7 +390,8 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
def start_event_polling(self): def start_event_polling(self):
# start a thread and pass in the mainloop # start a thread and pass in the mainloop
_thread.start_new_thread(self._event_poller, (asyncio.get_event_loop(),)) #_thread.start_new_thread(self._event_poller, (asyncio.get_event_loop(),))
threading.Thread(target=self._event_poller, args=(asyncio.get_event_loop(),), name="Event Polling", daemon=True).start()
def is_module_running(self, module): def is_module_running(self, module):
s = self.session() s = self.session()

View File

@ -1,6 +1,6 @@
import logging import logging
import gym import gymnasium as gym
from gym import spaces from gymnasium import spaces
import numpy as np import numpy as np
import pwnagotchi.ai.featurizer as featurizer import pwnagotchi.ai.featurizer as featurizer
@ -51,7 +51,7 @@ class Environment(gym.Env):
'state_v': None 'state_v': None
} }
self.action_space = spaces.MultiDiscrete([p.space_size() for p in Environment.params if p.trainable]) self.action_space = spaces.multi_discrete.MultiDiscrete([p.space_size() for p in Environment.params if p.trainable])
self.observation_space = spaces.Box(low=0, high=1, shape=featurizer.shape, dtype=np.float32) self.observation_space = spaces.Box(low=0, high=1, shape=featurizer.shape, dtype=np.float32)
self.reward_range = reward.range self.reward_range = reward.range

View File

@ -1,4 +1,4 @@
from gym import spaces from gymnasium import spaces
class Parameter(object): class Parameter(object):

View File

@ -1,4 +1,4 @@
import _thread # import _thread
import threading import threading
import time import time
import random import random
@ -111,7 +111,8 @@ class AsyncTrainer(object):
return self._training_epochs return self._training_epochs
def start_ai(self): def start_ai(self):
_thread.start_new_thread(self._ai_worker, ()) #_thread.start_new_thread(self._ai_worker, ())
threading.Thread(target=self._ai_worker, args=(), name="AI Worker", daemon=True).start()
def _save_ai(self): def _save_ai(self):
logging.info("[AI] saving model to %s ..." % self._nn_path) logging.info("[AI] saving model to %s ..." % self._nn_path)

View File

@ -100,7 +100,6 @@ class Client(object):
await asyncio.sleep(sleep_time) await asyncio.sleep(sleep_time)
continue continue
except OSError: except OSError:
sleep_time = min_sleep + max_sleep * random.random()
logging.warning('connection to the bettercap endpoint failed...') logging.warning('connection to the bettercap endpoint failed...')
pwnagotchi.restart("AUTO") pwnagotchi.restart("AUTO")

View File

@ -51,7 +51,7 @@ main.plugins.fix_services.enabled = true
main.plugins.gdrivesync.enabled = false main.plugins.gdrivesync.enabled = false
main.plugins.gdrivesync.backupfiles = [''] main.plugins.gdrivesync.backupfiles = ['']
main.plugins.gdrivesync.backup_folder = "PwnagotchiBackups" main.plugins.gdrivesync.backup_folder = "PwnagotchiBackups"
main.plugin.gdrivesync.interval = 1 main.plugins.gdrivesync.interval = 1
main.plugins.gpio_buttons.enabled = false main.plugins.gpio_buttons.enabled = false
@ -77,9 +77,8 @@ main.plugins.onlinehashcrack.email = ""
main.plugins.onlinehashcrack.dashboard = "" main.plugins.onlinehashcrack.dashboard = ""
main.plugins.onlinehashcrack.single_files = false main.plugins.onlinehashcrack.single_files = false
main.plugins.pisugar2.enabled = false main.plugins.pisugar3.enabled = false
main.plugins.pisugar2.shutdown = 5 main.plugins.pisugar3.shutdown = 5
main.plugins.pisugar2.sync_rtc_on_boot = false
main.plugins.session-stats.enabled = true main.plugins.session-stats.enabled = true
main.plugins.session-stats.save_directory = "/var/tmp/pwnagotchi/sessions/" main.plugins.session-stats.save_directory = "/var/tmp/pwnagotchi/sessions/"
@ -112,9 +111,8 @@ main.mon_stop_cmd = "/usr/bin/monstop"
main.mon_max_blind_epochs = 50 main.mon_max_blind_epochs = 50
main.no_restart = false main.no_restart = false
main.filter = ""
main.log.path = "/etc/pwnagotchi/log/pwnagotchi.log" main.log.path = "/etc/pwnagotchi/log/pwnagotchi.log"
main.log.path-debug = "/etc/pwnagotchi/log/pwnagotchi-debug.log"
main.log.rotation.enabled = true main.log.rotation.enabled = true
main.log.rotation.size = "10M" main.log.rotation.size = "10M"
@ -152,10 +150,8 @@ personality.bond_encounters_factor = 20000
personality.throttle_a = 0.4 personality.throttle_a = 0.4
personality.throttle_d = 0.9 personality.throttle_d = 0.9
personality.clear_on_exit = true # clear display when shutting down cleanly
ui.invert = false # false = black background, true = white background ui.invert = false # false = black background, true = white background
ui.cursor = true
ui.fps = 0.0 ui.fps = 0.0
ui.font.name = "DejaVuSansMono" # for japanese: fonts-japanese-gothic ui.font.name = "DejaVuSansMono" # for japanese: fonts-japanese-gothic
ui.font.size_offset = 0 # will be added to the font size ui.font.size_offset = 0 # will be added to the font size

View File

@ -3,7 +3,8 @@ import re
import tempfile import tempfile
import contextlib import contextlib
import shutil import shutil
import _thread #import _thread
import threading
import logging import logging
from time import sleep from time import sleep
@ -85,7 +86,8 @@ def setup_mounts(config):
if interval: if interval:
logging.debug("[FS] Starting thread to sync %s (interval: %d)", logging.debug("[FS] Starting thread to sync %s (interval: %d)",
options['mount'], interval) options['mount'], interval)
_thread.start_new_thread(m.daemonize, (interval,)) threading.Thread(target=m.daemonize, args=(interval,),name="File Sys", daemon=True).start()
#_thread.start_new_thread(m.daemonize, (interval,))
else: else:
logging.debug("[FS] Not syncing %s, because interval is 0", logging.debug("[FS] Not syncing %s, because interval is 0",
options['mount']) options['mount'])

View File

@ -92,7 +92,7 @@ def update_data(last_session):
'build': "Pwnagotchi by Jayofelony", 'build': "Pwnagotchi by Jayofelony",
'plugins': enabled, 'plugins': enabled,
'language': language, 'language': language,
'bettercap': subprocess.getoutput("bettercap -version").split(".\n\n")[1], 'bettercap': subprocess.getoutput("bettercap -version"),
'opwngrid': subprocess.getoutput("pwngrid -version") 'opwngrid': subprocess.getoutput("pwngrid -version")
} }

View File

@ -248,7 +248,7 @@ msgid "minutes"
msgstr "minuten" msgstr "minuten"
msgid "seconds" msgid "seconds"
msgstr "seconds" msgstr "sekondes"
msgid "hour" msgid "hour"
msgstr "oere" msgstr "oere"

View File

@ -1,16 +1,16 @@
# SOME DESCRIPTIVE TITLE. # Icelandic Translation.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2019
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the pwnagotchi package..
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # Sean Duggan <sean.duggan@pm.me>, 2024.
# #
#, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-16 21:10+0100\n" "POT-Creation-Date: 2024-11-17 20:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <sean.duggan@pm.me>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: Icelandic\n" "Language: Icelandic\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -18,218 +18,219 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
msgid "ZzzzZZzzzzZzzz" msgid "ZzzzZZzzzzZzzz"
msgstr "" msgstr "ZzzzZZzzzzZzzz"
msgid "Hi, I'm Pwnagotchi! Starting ..." msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "" msgstr "Hæ, Ég heiti Pwnagotchi! Ræsi.."
msgid "New day, new hunt, new pwns!" msgid "New day, new hunt, new pwns!"
msgstr "" msgstr "Nýr dagur, Ný veiði, Ný pwns!"
msgid "Hack the Planet!" msgid "Hack the Planet!"
msgstr "" msgstr "Hakkaðu plánetuna!"
msgid "AI ready." msgid "AI ready."
msgstr "" msgstr "AI tilbúið."
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "" msgstr "Tauganetið er tilbúið."
msgid "Generating keys, do not turn off ..." msgid "Generating keys, do not turn off ..."
msgstr "" msgstr "Bý til lykla, ekki slökkva á."
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "" msgstr "Hæ, Rás {channel} er líka ókeypis! AP þinn mun þakka fyrir."
msgid "Reading last session logs ..." msgid "Reading last session logs ..."
msgstr "" msgstr "Les fyrri leiðarbók..."
#, python-brace-format #, python-brace-format
msgid "Read {lines_so_far} log lines so far ..." msgid "Read {lines_so_far} log lines so far ..."
msgstr "" msgstr "Ég las {lines_so_far} leiðarbók línur hingað til..."
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "" msgstr "Mér leiðist ..."
msgid "Let's go for a walk!" msgid "Let's go for a walk!"
msgstr "" msgstr "Förum í göngutúr!"
msgid "This is the best day of my life!" msgid "This is the best day of my life!"
msgstr "" msgstr "Þetta er besti dagur lífs míns!"
msgid "Shitty day :/" msgid "Shitty day :/"
msgstr "" msgstr "Skítadagur :/"
msgid "I'm extremely bored ..." msgid "I'm extremely bored ..."
msgstr "" msgstr "Mér leiðist óskaplega mikið ..."
msgid "I'm very sad ..." msgid "I'm very sad ..."
msgstr "" msgstr "Ég er mjög leiður ..."
msgid "I'm sad" msgid "I'm sad"
msgstr "" msgstr "Ég er leiður"
msgid "Leave me alone ..." msgid "Leave me alone ..."
msgstr "" msgstr "Láttu mig í friði ..."
msgid "I'm mad at you!" msgid "I'm mad at you!"
msgstr "" msgstr "Ég er reiður út í þig!"
msgid "I'm living the life!" msgid "I'm living the life!"
msgstr "" msgstr "Ég lifi besta lífi!"
msgid "I pwn therefore I am." msgid "I pwn therefore I am."
msgstr "" msgstr "Ég pwn þess vegna er ég."
msgid "So many networks!!!" msgid "So many networks!!!"
msgstr "" msgstr "Svo mörg net!!!"
msgid "I'm having so much fun!" msgid "I'm having so much fun!"
msgstr "" msgstr "Mér finnst svo gaman!"
msgid "My crime is that of curiosity ..." msgid "My crime is that of curiosity ..."
msgstr "" msgstr "Glæpur minn er forvitni ..."
#, python-brace-format #, python-brace-format
msgid "Hello {name}! Nice to meet you." msgid "Hello {name}! Nice to meet you."
msgstr "" msgstr "Hæ {name}! Gaman að hitta þig!"
#, python-brace-format #, python-brace-format
msgid "Yo {name}! Sup?" msgid "Yo {name}! Sup?"
msgstr "" msgstr "Yo {name}! Sup?"
#, python-brace-format #, python-brace-format
msgid "Hey {name} how are you doing?" msgid "Hey {name} how are you doing?"
msgstr "" msgstr "Hæ {name} Hvernig hefurðu það?"
#, python-brace-format #, python-brace-format
msgid "Unit {name} is nearby!" msgid "Unit {name} is nearby!"
msgstr "" msgstr "Tæki {name} er nálægt!"
#, python-brace-format #, python-brace-format
msgid "Uhm ... goodbye {name}" msgid "Uhm ... goodbye {name}"
msgstr "" msgstr "Uhm ... bless {name}"
#, python-brace-format #, python-brace-format
msgid "{name} is gone ..." msgid "{name} is gone ..."
msgstr "" msgstr "{name} er farinn ..."
#, python-brace-format #, python-brace-format
msgid "Whoops ... {name} is gone." msgid "Whoops ... {name} is gone."
msgstr "" msgstr "Úps ... {name} er farinn."
#, python-brace-format #, python-brace-format
msgid "{name} missed!" msgid "{name} missed!"
msgstr "" msgstr "{name} saknað!'"
msgid "Missed!" msgid "Missed!"
msgstr "" msgstr "Saknað!'"
msgid "Good friends are a blessing!" msgid "Good friends are a blessing!"
msgstr "" msgstr "Góðir vinir eru blessun!"
msgid "I love my friends!" msgid "I love my friends!"
msgstr "" msgstr "Ég elska vini mína!"
msgid "Nobody wants to play with me ..." msgid "Nobody wants to play with me ..."
msgstr "" msgstr "Enginn vill leika við mig ..."
msgid "I feel so alone ..." msgid "I feel so alone ..."
msgstr "" msgstr "Mér finnst ég vera svo ein ..."
msgid "Where's everybody?!" msgid "Where's everybody?!"
msgstr "" msgstr "Hvar eru allir?!"
#, python-brace-format #, python-brace-format
msgid "Napping for {secs}s ..." msgid "Napping for {secs}s ..."
msgstr "" msgstr "Sef í {secs}s ..."
msgid "Zzzzz" msgid "Zzzzz"
msgstr "" msgstr "Zzzzz"
#, python-brace-format #, python-brace-format
msgid "ZzzZzzz ({secs}s)" msgid "ZzzZzzz ({secs}s)"
msgstr "" msgstr "ZzzZzzz ({secs})"
msgid "Good night." msgid "Good night."
msgstr "" msgstr "Góða nótt."
msgid "Zzz" msgid "Zzz"
msgstr "" msgstr "Zzz"
#, python-brace-format #, python-brace-format
msgid "Waiting for {secs}s ..." msgid "Waiting for {secs}s ..."
msgstr "" msgstr "Bíð eftir {secs} ..."
#, python-brace-format #, python-brace-format
msgid "Looking around ({secs}s)" msgid "Looking around ({secs}s)"
msgstr "" msgstr "Horfi í kringum mig ({secs}s)"
#, python-brace-format #, python-brace-format
msgid "Hey {what} let's be friends!" msgid "Hey {what} let's be friends!"
msgstr "" msgstr "Hæ {what} við skulum vera vinir!"
#, python-brace-format #, python-brace-format
msgid "Associating to {what}" msgid "Associating to {what}"
msgstr "" msgstr "Tengist við {what}"
#, python-brace-format #, python-brace-format
msgid "Yo {what}!" msgid "Yo {what}!"
msgstr "" msgstr "Yo {what}!"
#, python-brace-format #, python-brace-format
msgid "Just decided that {mac} needs no WiFi!" msgid "Just decided that {mac} needs no WiFi!"
msgstr "" msgstr "Ég ákvað að {mac} þurfi ekki WiFi!"
#, python-brace-format #, python-brace-format
msgid "Deauthenticating {mac}" msgid "Deauthenticating {mac}"
msgstr "" msgstr "Afvotta {mac}"
#, python-brace-format #, python-brace-format
msgid "Kickbanning {mac}!" msgid "Kickbanning {mac}!"
msgstr "" msgstr "Sparkbanna {mac}!"
#, python-brace-format #, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!" msgid "Cool, we got {num} new handshake{plural}!"
msgstr "" msgstr "Flott! við fengum {num} ný handatök {plural}!"
#, python-brace-format #, python-brace-format
msgid "You have {count} new message{plural}!" msgid "You have {count} new message{plural}!"
msgstr "" msgstr "þú hefur {count} ný skilaboð!"
msgid "Oops, something went wrong ... Rebooting ..." msgid "Oops, something went wrong ... Rebooting ..."
msgstr "" msgstr "Oops, eitthvað brotnaði ... Endurræsi ..."
#, python-brace-format #, python-brace-format
msgid "Uploading data to {to} ..." msgid "Uploading data to {to} ..."
msgstr "" msgstr "Hleð upp gögnum til {to} ..."
#, python-brace-format #, fuzzy, python-brace-format
msgid "Downloading from {name} ..." msgid "Downloading from {name} ..."
msgstr "" msgstr "Hleð upp gögnum til {to} ..."
#, python-brace-format #, python-brace-format
msgid "Kicked {num} stations\n" msgid "Kicked {num} stations\n"
msgstr "" msgstr "Sparkaði {num} stöðvar\n"
#, fuzzy
msgid "Made >999 new friends\n" msgid "Made >999 new friends\n"
msgstr "" msgstr "Eignaðist {num} nýja vini\n"
#, python-brace-format #, python-brace-format
msgid "Made {num} new friends\n" msgid "Made {num} new friends\n"
msgstr "" msgstr "Eignaðist {num} nýja vini\n"
#, python-brace-format #, python-brace-format
msgid "Got {num} handshakes\n" msgid "Got {num} handshakes\n"
msgstr "" msgstr "Fékk {num} ný handabönd\n"
msgid "Met 1 peer" msgid "Met 1 peer"
msgstr "" msgstr "Hitti 1 jafningja"
#, python-brace-format #, python-brace-format
msgid "Met {num} peers" msgid "Met {num} peers"
msgstr "" msgstr "Hitti {num} jafningja"
#, python-brace-format #, python-brace-format
msgid "" msgid ""
@ -237,21 +238,24 @@ msgid ""
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgstr "" msgstr ""
"Ég hef verið að pwna í {duration} og sparkað {deauthed} viðskiptavinum! Ég "
"hef líka hitt {associated} nýja vini og borðað {handshakes} handabönd! "
"#pwnagotchi #pwnlog #pwnlife #hacktheplanet #skynet"
msgid "hours" msgid "hours"
msgstr "" msgstr "klukkustundir"
msgid "minutes" msgid "minutes"
msgstr "" msgstr "mínútur"
msgid "seconds" msgid "seconds"
msgstr "" msgstr "sekúndur"
msgid "hour" msgid "hour"
msgstr "" msgstr "klukkustund"
msgid "minute" msgid "minute"
msgstr "" msgstr "mínútu"
msgid "second" msgid "second"
msgstr "" msgstr "sekúndu"

View File

@ -8,8 +8,8 @@ msgstr ""
"Project-Id-Version: 0.0.1\n" "Project-Id-Version: 0.0.1\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-16 21:51+0100\n" "POT-Creation-Date: 2023-11-16 21:51+0100\n"
"PO-Revision-Date: 2019-10-16 15:05+0200\n" "PO-Revision-Date: 2024-08-23 20:40+0900\n"
"Last-Translator: wytshadow <24534649+wytshadow@users.noreply.github.com>\n" "Last-Translator: mendoitarou_ <42207304+mendoitarou@users.noreply.github.com>\n"
"Language-Team: pwnagotchi <24534649+wytshadow@users.noreply.github.com>\n" "Language-Team: pwnagotchi <24534649+wytshadow@users.noreply.github.com>\n"
"Language: Japanese\n" "Language: Japanese\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -243,10 +243,12 @@ msgstr ""
#, python-brace-format #, python-brace-format
msgid "Uploading data to {to} ..." msgid "Uploading data to {to} ..."
msgstr "" msgstr ""
"{to} にデータをアップロードしてるよ..."
#, python-brace-format #, python-brace-format
msgid "Downloading from {name} ..." msgid "Downloading from {name} ..."
msgstr "" msgstr ""
"{name} からダウンロードしてるよ..."
#, python-brace-format #, python-brace-format
msgid "Kicked {num} stations\n" msgid "Kicked {num} stations\n"

View File

@ -1,260 +1,260 @@
# SOME DESCRIPTIVE TITLE. # pwnagotchi Brazilian Portuguese translation file.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2024
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the pwnagotchi package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # Fabiano F O <fabfernandes@hotmail.com>, 2024.
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-17 15:46+0100\n" "POT-Creation-Date: 2024-03-25 22:30+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Foxy <EMAIL@ADDRESS>\n" "Last-Translator: Fabiano F O <fabfernandes@hotmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: Portuguese (Brazil)\n" "Language: Brazilian Portuguese\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n" "Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
msgid "ZzzzZZzzzzZzzz" msgid "ZzzzZZzzzzZzzz"
msgstr "ZzzzZZzzzzZzzz" msgstr "ZzzzZZzzzzZzzz"
msgid "Hi, I'm Pwnagotchi! Starting ..." msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "Olá, Eu sou Pwnagotchi! Iniciando ..." msgstr "Olá, sou Pwnagotchi! Iniciando ..."
msgid "New day, new hunt, new pwns!" msgid "New day, new hunt, new pwns!"
msgstr "Um novo dia, Uma nova caça e novos pwns!" msgstr "Novo dia, Nova caçada, Novos pwns!"
msgid "Hack the Planet!" msgid "Hack the Planet!"
msgstr "Burle o Planeta!" msgstr "Hackeie o Planeta!"
msgid "AI ready." msgid "AI ready."
msgstr "IA pronta." msgstr "IA pronta."
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "A rede neural está pronta." msgstr "A rede neural está pronta."
msgid "Generating keys, do not turn off ..." msgid "Generating keys, do not turn off ..."
msgstr "Criando chaves, não desligue o sistema ..." msgstr "Gerando chaves, não desligue ..."
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "Ei, canal {channel} está livre! Seu AP vai agradecer." msgstr "Ei, o canal {channel} está livre! Seu AP vai agradecer."
msgid "Reading last session logs ..." msgid "Reading last session logs ..."
msgstr "Lendo os logs da ultima sessão" msgstr "Lendo os logs da última sessão ..."
#, python-brace-format #, python-brace-format
msgid "Read {lines_so_far} log lines so far ..." msgid "Read {lines_so_far} log lines so far ..."
msgstr "Leia {lines_so_far} linha de logs até agora ..." msgstr "Li {lines_so_far} linhas de logs até agora ..."
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "Eu estou entediado ..." msgstr "Estou entediado ..."
msgid "Let's go for a walk!" msgid "Let's go for a walk!"
msgstr "Vamos ir numa caminhada!" msgstr "Vamos dar um passeio!"
msgid "This is the best day of my life!" msgid "This is the best day of my life!"
msgstr "Esse é o melhor dia da minha vida!" msgstr "Este é o melhor dia da minha vida!"
msgid "Shitty day :/" msgid "Shitty day :/"
msgstr "Dia ruim :/" msgstr "Que dia ruim :/"
msgid "I'm extremely bored ..." msgid "I'm extremely bored ..."
msgstr "Eu estou extremamente entediado ..." msgstr "Estou extremamente entediado ..."
msgid "I'm very sad ..." msgid "I'm very sad ..."
msgstr "Eu estou muito triste ..." msgstr "Estou muito triste ..."
msgid "I'm sad" msgid "I'm sad"
msgstr "Eu estou triste" msgstr "Estou triste"
msgid "Leave me alone ..." msgid "Leave me alone ..."
msgstr "Me deixe em paz ..." msgstr "Me deixe em paz ..."
msgid "I'm mad at you!" msgid "I'm mad at you!"
msgstr "Eu estou bravo com você!" msgstr "Estou bravo com você!"
msgid "I'm living the life!" msgid "I'm living the life!"
msgstr "Eu estou vivendo a vida!" msgstr "Estou aproveitando a vida!"
msgid "I pwn therefore I am." msgid "I pwn therefore I am."
msgstr "Eu pwn então Eu sou." msgstr "Eu pwn, logo existo."
msgid "So many networks!!!" msgid "So many networks!!!"
msgstr "Tantas redes!!!" msgstr "Uau! Quantas redes!!"
msgid "I'm having so much fun!" msgid "I'm having so much fun!"
msgstr "Eu estou tendo muita diversão" msgstr "Estou me divertindo muito!"
msgid "My crime is that of curiosity ..." msgid "My crime is that of curiosity ..."
msgstr "Meu crime é de curiosidade ..." msgstr "Meu crime é a curiosidade ..."
#, python-brace-format #, python-brace-format
msgid "Hello {name}! Nice to meet you." msgid "Hello {name}! Nice to meet you."
msgstr "Olá {name}! É bom em conhecê-lo" msgstr "Olá {name}! Prazer em conhecê-lo."
#, python-brace-format #, python-brace-format
msgid "Yo {name}! Sup?" msgid "Yo {name}! Sup?"
msgstr "Ei {name}! Como vai?" msgstr "Ei {name}! Como vai?"
#, python-brace-format #, python-brace-format
msgid "Hey {name} how are you doing?" msgid "Hey {name} how are you doing?"
msgstr "Ei {name} como você está indo?" msgstr "Ei {name}, como você está?"
#, python-brace-format #, python-brace-format
msgid "Unit {name} is nearby!" msgid "Unit {name} is nearby!"
msgstr "" msgstr "A unidade {name} está próxima!"
#, python-brace-format #, python-brace-format
msgid "Uhm ... goodbye {name}" msgid "Uhm ... goodbye {name}"
msgstr "" msgstr "Hmm ... tchau {name}"
#, python-brace-format #, python-brace-format
msgid "{name} is gone ..." msgid "{name} is gone ..."
msgstr "" msgstr "{name} desapareceu ..."
#, python-brace-format #, python-brace-format
msgid "Whoops ... {name} is gone." msgid "Whoops ... {name} is gone."
msgstr "" msgstr "Oops ... {name} desapareceu."
#, python-brace-format #, python-brace-format
msgid "{name} missed!" msgid "{name} missed!"
msgstr "{name} errou!" msgstr "Perdi {name}!"
msgid "Missed!" msgid "Missed!"
msgstr "Errei!" msgstr "Perdi!"
msgid "Good friends are a blessing!" msgid "Good friends are a blessing!"
msgstr "Bom amigos são uma bensão!" msgstr "Bons amigos são uma bênção!"
msgid "I love my friends!" msgid "I love my friends!"
msgstr "Eu amo meus amigos!" msgstr "Eu amo meus amigos!"
msgid "Nobody wants to play with me ..." msgid "Nobody wants to play with me ..."
msgstr "Ninguém quer brincar comigo ..." msgstr "Ninguém quer brincar comigo ..."
msgid "I feel so alone ..." msgid "I feel so alone ..."
msgstr "Estou me sentindo sozinho" msgstr "Me sinto tão sozinho ..."
msgid "Where's everybody?!" msgid "Where's everybody?!"
msgstr "Onde está todo mundo?!" msgstr "Onde está todo mundo?!"
#, python-brace-format #, python-brace-format
msgid "Napping for {secs}s ..." msgid "Napping for {secs}s ..."
msgstr "Tirando uma soneca por {secs}s ..." msgstr "Tirando uma soneca por {secs}s ..."
msgid "Zzzzz" msgid "Zzzzz"
msgstr "Zzzzz" msgstr "Zzzzz"
#, python-brace-format #, python-brace-format
msgid "ZzzZzzz ({secs}s)" msgid "ZzzZzzz ({secs}s)"
msgstr "ZzzZzzz ({secs}s)" msgstr "ZzzZzzz ({secs}s)"
msgid "Good night." msgid "Good night."
msgstr "Boa noite." msgstr "Boa noite."
msgid "Zzz" msgid "Zzz"
msgstr "Zzz" msgstr "Zzz"
#, python-brace-format #, python-brace-format
msgid "Waiting for {secs}s ..." msgid "Waiting for {secs}s ..."
msgstr "Esperando por {secs}s ..." msgstr "Aguardando {secs}s ..."
#, python-brace-format #, python-brace-format
msgid "Looking around ({secs}s)" msgid "Looking around ({secs}s)"
msgstr "Olhando por volta ({secs}s)" msgstr "Olhando em volta ... ({secs}s)"
#, python-brace-format #, python-brace-format
msgid "Hey {what} let's be friends!" msgid "Hey {what} let's be friends!"
msgstr "Ei {what} vamos ser amigos!" msgstr "Ei {what}, vamos ser amigos!"
#, python-brace-format #, python-brace-format
msgid "Associating to {what}" msgid "Associating to {what}"
msgstr "Associando para {what}" msgstr "Associando a {what}"
#, python-brace-format #, python-brace-format
msgid "Yo {what}!" msgid "Yo {what}!"
msgstr "Ei {what}!" msgstr "Olá {what}!"
#, python-brace-format #, python-brace-format
msgid "Just decided that {mac} needs no WiFi!" msgid "Just decided that {mac} needs no WiFi!"
msgstr "Apenas decidindo que {mac} não precisa de WiFi!" msgstr "Acabei de decidir que {mac} não precisa de WiFi!"
#, python-brace-format #, python-brace-format
msgid "Deauthenticating {mac}" msgid "Deauthenticating {mac}"
msgstr "Desautenticando {mac}" msgstr "Desautenticando {mac}"
#, python-brace-format #, python-brace-format
msgid "Kickbanning {mac}!" msgid "Kickbanning {mac}!"
msgstr "Banindo {mac}!" msgstr "Banindo {mac}!"
#, python-brace-format #, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!" msgid "Cool, we got {num} new handshake{plural}!"
msgstr "Legal, conseguimos {num} novos handshake{plural}!" msgstr "Legal, conseguimos {num} novo{plural} handshake{plural}!"
#, python-brace-format #, python-brace-format
msgid "You have {count} new message{plural}!" msgid "You have {count} new message{plural}!"
msgstr "Você tem {count} novas messagem{plural}!" msgstr "Você tem {count} nova{plural} messagem{plural}!"
msgid "Oops, something went wrong ... Rebooting ..." msgid "Oops, something went wrong ... Rebooting ..."
msgstr "Oops, algo deu errado ... Reiniciando ..." msgstr "Oops, algo deu errado ... Reiniciando ..."
#, python-brace-format #, python-brace-format
msgid "Uploading data to {to} ..." msgid "Uploading data to {to} ..."
msgstr "Enviando dados para {to} ..." msgstr "Enviando dados para {to} ..."
#, python-brace-format #, python-brace-format
msgid "Downloading from {name} ..." msgid "Downloading from {name} ..."
msgstr "Instalando para {name} ..." msgstr "Baixando de {name} ..."
#, python-brace-format #, python-brace-format
msgid "Kicked {num} stations\n" msgid "Kicked {num} stations\n"
msgstr "Expulsei {num} estações\n" msgstr "Expulsei {num} estações\n"
msgid "Made >999 new friends\n" msgid "Made >999 new friends\n"
msgstr "Fiz >999 novos amigos\n" msgstr "Fiz >999 novos amigos\n"
#, python-brace-format #, python-brace-format
msgid "Made {num} new friends\n" msgid "Made {num} new friends\n"
msgstr "Fiz {num} novos amigos\n" msgstr "Fiz {num} novos amigos\n"
#, python-brace-format #, python-brace-format
msgid "Got {num} handshakes\n" msgid "Got {num} handshakes\n"
msgstr "Peguei {num} handshakes\n" msgstr "Peguei {num} handshakes\n"
msgid "Met 1 peer" msgid "Met 1 peer"
msgstr "Encontrei 1 pessoa" msgstr "Conheci 1 peer"
#, python-brace-format #, python-brace-format
msgid "Met {num} peers" msgid "Met {num} peers"
msgstr "Encontrei {num} pessoas" msgstr "Conheci {num} peers"
#, python-brace-format #, python-brace-format
msgid "" msgid ""
"I've been pwning for {duration} and kicked {deauthed} clients! I've also met " "I've been pwning for {duration} and kicked {deauthed} clients! I've also met "
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgstr "" msgstr ""
"Estou navegando há {duration} e expulsei {deauthed} clientes! Também conheci " "Estou pwning há {duration} e expulsei {deauthed} clientes! Também conheci "
"{associamos} novos amigos e comi {handshakes} handshakes! #pwnagotchi " "{associated} novos amigos e comi {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgid "hours" msgid "hours"
msgstr "horas" msgstr "horas"
msgid "minutes" msgid "minutes"
msgstr "minutos" msgstr "minutos"
msgid "seconds" msgid "seconds"
msgstr "segundos" msgstr "segundos"
msgid "hour" msgid "hour"
msgstr "hora" msgstr "hora"
msgid "minute" msgid "minute"
msgstr "minuto" msgstr "minuto"
msgid "second" msgid "second"
msgstr "segundo" msgstr "segundo"

Binary file not shown.

View File

@ -0,0 +1,260 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <dragan.miljkovic29@gmail.com>, 2024.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: Srpski prevod v1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-16 15:26-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: RS <dragan.miljkovic29@gmail.com>\n"
"Language: Serbian\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
msgid "ZzzzZZzzzzZzzz"
msgstr "ZzzzZZzzzzZzzz"
msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "Zdravo, ja sam Pwnagotchi! Započinjem ..."
msgid "New day, new hunt, new pwns!"
msgstr "Novi dan, novi lov, novi pnwovi!"
msgid "Hack the Planet!"
msgstr "Hakuj Planetu!"
msgid "AI ready."
msgstr "AI spreman."
msgid "The neural network is ready."
msgstr "Neuronska mreža je spremna."
msgid "Generating keys, do not turn off ..."
msgstr "Generišem ključeve, ne isključuj me..."
#, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "Hej, kanal {channel} je slobodan! Tvoj AP će ti se zahvaliti."
msgid "Reading last session logs ..."
msgstr "Čitanje logova poslednje sesije ..."
#, python-brace-format
msgid "Read {lines_so_far} log lines so far ..."
msgstr "Pročitao {lines_so_far} log linija do sada ..."
msgid "I'm bored ..."
msgstr "Dosadno mi je ..."
msgid "Let's go for a walk!"
msgstr "Hajmo u šetnju!"
msgid "This is the best day of my life!"
msgstr "Ovo je najbolji dan mog života!"
msgid "Shitty day :/"
msgstr "Sranje dan :/"
msgid "I'm extremely bored ..."
msgstr "Užasno mi je dosadno ..."
msgid "I'm very sad ..."
msgstr "Jako sam tužan ..."
msgid "I'm sad"
msgstr "Tužan sam"
msgid "Leave me alone ..."
msgstr "Ostavi me na miru ..."
msgid "I'm mad at you!"
msgstr "Ljut sam na tebe!"
msgid "I'm living the life!"
msgstr "Živim ga!"
msgid "I pwn therefore I am."
msgstr "Ja pwnujem dakle postojim."
msgid "So many networks!!!"
msgstr "Tako mnogo mreža!!!"
msgid "I'm having so much fun!"
msgstr "Previše se zabavljam!"
msgid "My crime is that of curiosity ..."
msgstr "Moj zločin je radoznalost ..."
#, python-brace-format
msgid "Hello {name}! Nice to meet you."
msgstr "Zdravo {name}! Drago mi je da te upoznam."
#, python-brace-format
msgid "Yo {name}! Sup?"
msgstr "Ej {name}! Šta ima?"
#, python-brace-format
msgid "Hey {name} how are you doing?"
msgstr "Hej {name} kako si?"
#, python-brace-format
msgid "Unit {name} is nearby!"
msgstr "Jedinica {name} je blizu!"
#, python-brace-format
msgid "Uhm ... goodbye {name}"
msgstr "Umm ... doviđenja {name}"
#, python-brace-format
msgid "{name} is gone ..."
msgstr "{name} je nestao ..."
#, python-brace-format
msgid "Whoops ... {name} is gone."
msgstr "Ups ... {name} je nestao."
#, python-brace-format
msgid "{name} missed!"
msgstr "{name} promašen!"
msgid "Missed!"
msgstr "Promašen!"
msgid "Good friends are a blessing!"
msgstr "Dobri prijatelji su blagoslov!"
msgid "I love my friends!"
msgstr "Volim svoje prijatelje!"
msgid "Nobody wants to play with me ..."
msgstr "Niko ne želi da se igra sa mnom ..."
msgid "I feel so alone ..."
msgstr "Osećam se toliko usamljeno ..."
msgid "Where's everybody?!"
msgstr "Gde su svi?!"
#, python-brace-format
msgid "Napping for {secs}s ..."
msgstr "Dremam {secs}s ..."
msgid "Zzzzz"
msgstr "Zzzzz"
#, python-brace-format
msgid "ZzzZzzz ({secs}s)"
msgstr "ZzzZzzz ({secs}s)"
msgid "Good night."
msgstr "Laku noć."
msgid "Zzz"
msgstr "Zzz"
#, python-brace-format
msgid "Waiting for {secs}s ..."
msgstr "Čekam {secs}s ..."
#, python-brace-format
msgid "Looking around ({secs}s)"
msgstr "Gledam unaokolo ({secs}s)"
#, python-brace-format
msgid "Hey {what} let's be friends!"
msgstr "Hej {what} hajde da budemo prijatelji!"
#, python-brace-format
msgid "Associating to {what}"
msgstr "Povezujem se sa {what}"
#, python-brace-format
msgid "Yo {what}!"
msgstr "Ej {what}!"
#, python-brace-format
msgid "Just decided that {mac} needs no WiFi!"
msgstr "Upravo sam odlučio da {mac} ne zahteva WiFi!"
#, python-brace-format
msgid "Deauthenticating {mac}"
msgstr "Deauthenticating {mac}"
#, python-brace-format
msgid "Kickbanning {mac}!"
msgstr "Kickbanning {mac}!"
#, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!"
msgstr "Kul, imamo {num} novih handshakeova"
#, python-brace-format
msgid "You have {count} new message{plural}!"
msgstr "Imas {count} novih poruka"
msgid "Oops, something went wrong ... Rebooting ..."
msgstr "Ups, nešto je poslo po zlu ... Restartujem ..."
#, python-brace-format
msgid "Uploading data to {to} ..."
msgstr "Otpremam podatke na {to} ..."
#, python-brace-format
msgid "Downloading from {name} ..."
msgstr "Preuzimam od {name} ..."
#, python-brace-format
msgid "Kicked {num} stations\n"
msgstr "Kickovano {num} stanica\n"
msgid "Made >999 new friends\n"
msgstr "Stekao sam >999 novih prijatelja\n"
#, python-brace-format
msgid "Made {num} new friends\n"
msgstr "Stekao sam {num} novih prijatelja\n"
#, python-brace-format
msgid "Got {num} handshakes\n"
msgstr "Imam {num} handshakeova\n"
msgid "Met 1 peer"
msgstr "Sreo 1 peera"
#, python-brace-format
msgid "Met {num} peers"
msgstr "Sreo {num} peerova"
#, 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 ""
"Pwnujem već {duration} i kickovao sam {deauthed} klijenata! Takođe sam sreo "
"{associated} novih prijatelja i pojeo {handshakes} handshakeova! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet"
msgid "hours"
msgstr "sati"
msgid "minutes"
msgstr "minuta"
msgid "seconds"
msgstr "sekundi"
msgid "hour"
msgstr "sat"
msgid "minute"
msgstr "minut"
msgid "second"
msgstr "sekunda"

View File

@ -9,8 +9,8 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-16 21:10+0100\n" "POT-Creation-Date: 2023-11-16 21:10+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2024-03-27 18:40+0800\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: AlanLeung <admin@mcnot.pro>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"Language: Twi\n" "Language: Twi\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -18,218 +18,218 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
msgid "ZzzzZZzzzzZzzz" msgid "ZzzzZZzzzzZzzz"
msgstr "" msgstr "ZzzzZZzzzzZzzz"
msgid "Hi, I'm Pwnagotchi! Starting ..." msgid "Hi, I'm Pwnagotchi! Starting ..."
msgstr "" msgstr "HI!我是Pwnagotchi!\n程式啟動..."
msgid "New day, new hunt, new pwns!" msgid "New day, new hunt, new pwns!"
msgstr "" msgstr "新的一天!\n新的狩獵!新的入侵!"
msgid "Hack the Planet!" msgid "Hack the Planet!"
msgstr "" msgstr "我要駭入\n地球的所有人!"
msgid "AI ready." msgid "AI ready."
msgstr "" msgstr "人工智慧已啟動。"
msgid "The neural network is ready." msgid "The neural network is ready."
msgstr "" msgstr "神經網路已啟動。"
msgid "Generating keys, do not turn off ..." msgid "Generating keys, do not turn off ..."
msgstr "" msgstr "產生金鑰中,\n請勿關閉..."
#, python-brace-format #, python-brace-format
msgid "Hey, channel {channel} is free! Your AP will say thanks." msgid "Hey, channel {channel} is free! Your AP will say thanks."
msgstr "" msgstr "嘿,{channel}很順暢!\n你的WIFI會感謝你的。"
msgid "Reading last session logs ..." msgid "Reading last session logs ..."
msgstr "" msgstr "正在閱讀最後的會話紀錄..."
#, python-brace-format #, python-brace-format
msgid "Read {lines_so_far} log lines so far ..." msgid "Read {lines_so_far} log lines so far ..."
msgstr "" msgstr "目前已經閱讀了 {lines_so_far} 行的紀錄..."
msgid "I'm bored ..." msgid "I'm bored ..."
msgstr "" msgstr "我好無聊..."
msgid "Let's go for a walk!" msgid "Let's go for a walk!"
msgstr "" msgstr "我們! 散步! 散步散步散步散步"
msgid "This is the best day of my life!" msgid "This is the best day of my life!"
msgstr "" msgstr "這是我生命中最棒的一天!"
msgid "Shitty day :/" msgid "Shitty day :/"
msgstr "" msgstr "糟糕的一天 :/"
msgid "I'm extremely bored ..." msgid "I'm extremely bored ..."
msgstr "" msgstr "我超無聊的...炒雞 炒雞的那種"
msgid "I'm very sad ..." msgid "I'm very sad ..."
msgstr "" msgstr "我好難過..."
msgid "I'm sad" msgid "I'm sad"
msgstr "" msgstr "嗚嗚嗚...."
msgid "Leave me alone ..." msgid "Leave me alone ..."
msgstr "" msgstr "尼奏凱啦臭臭"
msgid "I'm mad at you!" msgid "I'm mad at you!"
msgstr "" msgstr "喔氣氣氣氣氣ˋ^ˊ"
msgid "I'm living the life!" msgid "I'm living the life!"
msgstr "" msgstr "真是充實的一生!"
msgid "I pwn therefore I am." msgid "I pwn therefore I am."
msgstr "" msgstr "我駭故我在."
msgid "So many networks!!!" msgid "So many networks!!!"
msgstr "" msgstr "好多網路啊!!!吃! 吃他! 吃光光!!!"
msgid "I'm having so much fun!" msgid "I'm having so much fun!"
msgstr "" msgstr "我玩的超級開心!"
msgid "My crime is that of curiosity ..." msgid "My crime is that of curiosity ..."
msgstr "" msgstr "我的缺點就是\n太好奇了..."
#, python-brace-format #, python-brace-format
msgid "Hello {name}! Nice to meet you." msgid "Hello {name}! Nice to meet you."
msgstr "" msgstr "尼豪{name}!\n很高興認識你!!!!"
#, python-brace-format #, python-brace-format
msgid "Yo {name}! Sup?" msgid "Yo {name}! Sup?"
msgstr "" msgstr "嗨 {name}! 你來攻打我的村莊?"
#, python-brace-format #, python-brace-format
msgid "Hey {name} how are you doing?" msgid "Hey {name} how are you doing?"
msgstr "" msgstr "嗨 {name} 你最近過得如何˙ˇ˙?"
#, python-brace-format #, python-brace-format
msgid "Unit {name} is nearby!" msgid "Unit {name} is nearby!"
msgstr "" msgstr "{name}\n就在附近!"
#, python-brace-format #, python-brace-format
msgid "Uhm ... goodbye {name}" msgid "Uhm ... goodbye {name}"
msgstr "" msgstr "哦嗚 ... \n拜拜{name}"
#, python-brace-format #, python-brace-format
msgid "{name} is gone ..." msgid "{name} is gone ..."
msgstr "" msgstr "{name}\n不見了 ..."
#, python-brace-format #, python-brace-format
msgid "Whoops ... {name} is gone." msgid "Whoops ... {name} is gone."
msgstr "" msgstr "哦歐...\n{name}\n不見了。"
#, python-brace-format #, python-brace-format
msgid "{name} missed!" msgid "{name} missed!"
msgstr "" msgstr "我剛剛錯過了{name}!"
msgid "Missed!" msgid "Missed!"
msgstr "" msgstr "又錯過了!"
msgid "Good friends are a blessing!" msgid "Good friends are a blessing!"
msgstr "" msgstr "有個好朋友\n真幸福!"
msgid "I love my friends!" msgid "I love my friends!"
msgstr "" msgstr "我喜歡\n我的朋友!"
msgid "Nobody wants to play with me ..." msgid "Nobody wants to play with me ..."
msgstr "" msgstr "沒人想跟我玩..."
msgid "I feel so alone ..." msgid "I feel so alone ..."
msgstr "" msgstr "我覺得好孤單..."
msgid "Where's everybody?!" msgid "Where's everybody?!"
msgstr "" msgstr "大家都去哪裡了?!"
#, python-brace-format #, python-brace-format
msgid "Napping for {secs}s ..." msgid "Napping for {secs}s ..."
msgstr "" msgstr "我想瞇{secs}秒一下..."
msgid "Zzzzz" msgid "Zzzzz"
msgstr "" msgstr "Zzzzz"
#, python-brace-format #, python-brace-format
msgid "ZzzZzzz ({secs}s)" msgid "ZzzZzzz ({secs}s)"
msgstr "" msgstr "ZzzZzzz({secs}秒)"
msgid "Good night." msgid "Good night."
msgstr "" msgstr "晚安!"
msgid "Zzz" msgid "Zzz"
msgstr "" msgstr "Zzz"
#, python-brace-format #, python-brace-format
msgid "Waiting for {secs}s ..." msgid "Waiting for {secs}s ..."
msgstr "" msgstr "等我{secs}秒..."
#, python-brace-format #, python-brace-format
msgid "Looking around ({secs}s)" msgid "Looking around ({secs}s)"
msgstr "" msgstr "環顧四周({secs}秒)"
#, python-brace-format #, python-brace-format
msgid "Hey {what} let's be friends!" msgid "Hey {what} let's be friends!"
msgstr "" msgstr "嗨\n{what}\n讓我們來當朋友吧!"
#, python-brace-format #, python-brace-format
msgid "Associating to {what}" msgid "Associating to {what}"
msgstr "" msgstr "正在連接\n{what}"
#, python-brace-format #, python-brace-format
msgid "Yo {what}!" msgid "Yo {what}!"
msgstr "" msgstr "喲,\n{what}!"
#, python-brace-format #, python-brace-format
msgid "Just decided that {mac} needs no WiFi!" msgid "Just decided that {mac} needs no WiFi!"
msgstr "" msgstr "我要讓\n{mac}\n斷線!\n他不需要上網!"
#, python-brace-format #, python-brace-format
msgid "Deauthenticating {mac}" msgid "Deauthenticating {mac}"
msgstr "" msgstr "解除\n{mac}\n的授權中"
#, python-brace-format #, python-brace-format
msgid "Kickbanning {mac}!" msgid "Kickbanning {mac}!"
msgstr "" msgstr "把\n{mac}\n踢出中!"
#, python-brace-format #, python-brace-format
msgid "Cool, we got {num} new handshake{plural}!" msgid "Cool, we got {num} new handshake{plural}!"
msgstr "" msgstr "酷耶,我們抓到{num}個\n新的握手包{plural}!"
#, python-brace-format #, python-brace-format
msgid "You have {count} new message{plural}!" msgid "You have {count} new message{plural}!"
msgstr "" msgstr "你有{count}個新訊息{plural}!"
msgid "Oops, something went wrong ... Rebooting ..." msgid "Oops, something went wrong ... Rebooting ..."
msgstr "" msgstr "哦歐,有些地方出錯了...\n重新啟動中..."
#, python-brace-format #, python-brace-format
msgid "Uploading data to {to} ..." msgid "Uploading data to {to} ..."
msgstr "" msgstr "正在上傳資料到 {to} ..."
#, python-brace-format #, python-brace-format
msgid "Downloading from {name} ..." msgid "Downloading from {name} ..."
msgstr "" msgstr "正在從 {name} 下載資料..."
#, python-brace-format #, python-brace-format
msgid "Kicked {num} stations\n" msgid "Kicked {num} stations\n"
msgstr "" msgstr "踢了 {num} 個設備\n"
msgid "Made >999 new friends\n" msgid "Made >999 new friends\n"
msgstr "" msgstr "交了 >999 個新朋友\n"
#, python-brace-format #, python-brace-format
msgid "Made {num} new friends\n" msgid "Made {num} new friends\n"
msgstr "" msgstr "交了 {num} 個新朋友\n"
#, python-brace-format #, python-brace-format
msgid "Got {num} handshakes\n" msgid "Got {num} handshakes\n"
msgstr "" msgstr "捕獲了 {num} 個握手包\n"
msgid "Met 1 peer" msgid "Met 1 peer"
msgstr "" msgstr "遇到了 個同好"
#, python-brace-format #, python-brace-format
msgid "Met {num} peers" msgid "Met {num} peers"
msgstr "" msgstr "遇到了 {num} 個同好"
#, python-brace-format #, python-brace-format
msgid "" msgid ""
@ -237,21 +237,24 @@ msgid ""
"{associated} new friends and ate {handshakes} handshakes! #pwnagotchi " "{associated} new friends and ate {handshakes} handshakes! #pwnagotchi "
"#pwnlog #pwnlife #hacktheplanet #skynet" "#pwnlog #pwnlife #hacktheplanet #skynet"
msgstr "" msgstr ""
"我花了{duration}的時間\n駭入和踢了{deauthed}好多設備."
"我還交了好多{associated}新朋友,\n而且抓到了{handshakes}握手包!"
"#pwnagotchi#入侵日志 #駭客人生 #入侵整個星球 #天網 #我好棒˙ˇ˙"
msgid "hours" msgid "hours"
msgstr "" msgstr ""
msgid "minutes" msgid "minutes"
msgstr "" msgstr ""
msgid "seconds" msgid "seconds"
msgstr "" msgstr ""
msgid "hour" msgid "hour"
msgstr "" msgstr ""
msgid "minute" msgid "minute"
msgstr "" msgstr ""
msgid "second" msgid "second"
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-02-16 15:26-0300\n" "POT-Creation-Date: 2024-11-17 20:51+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"

View File

@ -217,25 +217,45 @@ class LastSession(object):
def setup_logging(args, config): def setup_logging(args, config):
cfg = config['main']['log'] cfg = config['main']['log']
filename = cfg['path'] filename = cfg['path']
filenameDebug = cfg['path-debug']
formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] %(message)s") #global formatter
root = logging.getLogger() formatter = logging.Formatter("[%(asctime)s] [%(levelname)s] [%(threadName)s] : %(message)s")
logger = logging.getLogger()
root.setLevel(logging.DEBUG if args.debug else logging.INFO)
for handler in logger.handlers:
handler.setLevel(logging.DEBUG if args.debug else logging.INFO)
handler.setFormatter(formatter)
logger.setLevel(logging.DEBUG if args.debug else logging.INFO)
if filename: if filename:
# since python default log rotation might break session data in different files, # since python default log rotation might break session data in different files,
# we need to do log rotation ourselves # we need to do log rotation ourselves
log_rotation(filename, cfg) log_rotation(filename, cfg)
log_rotation(filenameDebug, cfg)
file_handler = logging.FileHandler(filename)
file_handler.setFormatter(formatter)
root.addHandler(file_handler) # File handler for logging all normal messages
file_handler = logging.FileHandler(filename) #creates new
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
console_handler = logging.StreamHandler() # File handler for logging all debug messages
console_handler.setFormatter(formatter) file_handler = logging.FileHandler(filenameDebug) #creates new
root.addHandler(console_handler) file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
# Console handler for logging debug messages if args.debug is true else just log normal
#console_handler = logging.StreamHandler() #creates new
#console_handler.setLevel(logging.DEBUG if args.debug else logging.INFO)
#console_handler.setFormatter(formatter)
#logger.addHandler(console_handler)
if not args.debug: if not args.debug:
# disable scapy and tensorflow logging # disable scapy and tensorflow logging
logging.getLogger("scapy").disabled = True logging.getLogger("scapy").disabled = True
@ -250,6 +270,8 @@ def setup_logging(args, config):
requests_log.prpagate = False requests_log.prpagate = False
def log_rotation(filename, cfg): def log_rotation(filename, cfg):
rotation = cfg['rotation'] rotation = cfg['rotation']
if not rotation['enabled']: if not rotation['enabled']:

View File

@ -1,4 +1,5 @@
import _thread #import _thread
import threading
import logging import logging
import time import time
@ -41,7 +42,8 @@ class AsyncAdvertiser(object):
def start_advertising(self): def start_advertising(self):
if self._config['personality']['advertise']: if self._config['personality']['advertise']:
_thread.start_new_thread(self._adv_poller, ()) #_thread.start_new_thread(self._adv_poller, ())
threading.Thread(target=self._adv_poller,args=(), name="Grid", daemon=True).start()
grid.set_advertisement_data(self._advertisement) grid.set_advertisement_data(self._advertisement)
grid.advertise(True) grid.advertise(True)

View File

@ -6,6 +6,7 @@ import logging
import os import os
import threading import threading
import pwnagotchi.grid import pwnagotchi.grid
import prctl
default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default") default_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "default")
loaded = {} loaded = {}
@ -72,6 +73,7 @@ def toggle_plugin(name, enable=True):
def on(event_name, *args, **kwargs): def on(event_name, *args, **kwargs):
for plugin_name in loaded.keys(): for plugin_name in loaded.keys():
one(plugin_name, event_name, *args, **kwargs) one(plugin_name, event_name, *args, **kwargs)
@ -82,7 +84,10 @@ def locked_cb(lock_name, cb, *args, **kwargs):
locks[lock_name] = threading.Lock() locks[lock_name] = threading.Lock()
with locks[lock_name]: with locks[lock_name]:
cb(*args, *kwargs) # Setting the thread name using prctl
plugin_name, plugin_cb = lock_name.split("::")
prctl.set_name(f"{plugin_name}.{plugin_cb}")
cb(*args, **kwargs)
def one(plugin_name, event_name, *args, **kwargs): def one(plugin_name, event_name, *args, **kwargs):
@ -95,8 +100,10 @@ def one(plugin_name, event_name, *args, **kwargs):
if callback is not None and callable(callback): if callback is not None and callable(callback):
try: try:
lock_name = "%s::%s" % (plugin_name, cb_name) lock_name = "%s::%s" % (plugin_name, cb_name)
locked_cb_args = (lock_name, callback, *args, *kwargs) thread_name = f'{plugin_name}.{cb_name}'
_thread.start_new_thread(locked_cb, locked_cb_args) thread = threading.Thread(target=locked_cb, args=(lock_name, callback, *args, *kwargs), name=thread_name, daemon=True)
thread.start()
except Exception as e: except Exception as e:
logging.error("error while running %s.%s : %s" % (plugin_name, cb_name, e)) logging.error("error while running %s.%s : %s" % (plugin_name, cb_name, e))
logging.error(e, exc_info=True) logging.error(e, exc_info=True)
@ -144,4 +151,4 @@ def load(config):
plugin.options = config['main']['plugins'][name] plugin.options = config['main']['plugins'][name]
on('loaded') on('loaded')
on('config_changed', config) on('config_changed', config)

View File

@ -230,7 +230,7 @@ class AutoUpdate(plugins.Plugin):
if num_installed > 0: if num_installed > 0:
display.update(force=True, new_data={'status': 'Rebooting ...'}) display.update(force=True, new_data={'status': 'Rebooting ...'})
time.sleep(3) time.sleep(3)
os.system("service pwnagotchi restart") pwnagotchi.reboot()
except Exception as e: except Exception as e:
logging.error("[update] %s" % e) logging.error("[update] %s" % e)

View File

@ -578,7 +578,7 @@ class BTTether(plugins.Plugin):
def on_ui_setup(self, ui): def on_ui_setup(self, ui):
with ui._lock: with ui._lock:
ui.add_element('bluetooth', LabeledValue(color=BLACK, label='BT', value='-', ui.add_element('bluetooth', LabeledValue(color=BLACK, label='BT', value='-',
position=(ui.width() / 2 - 10, 0), position=(ui.width() / 2 - 20, 0),
label_font=fonts.Bold, text_font=fonts.Medium)) label_font=fonts.Bold, text_font=fonts.Medium))
def on_ui_update(self, ui): def on_ui_update(self, ui):

View File

@ -4,6 +4,7 @@ import subprocess
import time import time
import random import random
from io import TextIOWrapper from io import TextIOWrapper
import os
import pwnagotchi import pwnagotchi
from pwnagotchi import plugins from pwnagotchi import plugins
@ -28,10 +29,13 @@ class FixServices(plugins.Plugin):
def __init__(self): def __init__(self):
self.options = dict() self.options = dict()
self.pattern = re.compile(r'brcmf_cfg80211_nexmon_set_channel.*?Set Channel failed') self.pattern = re.compile(r'ieee80211 phy0: brcmf_cfg80211_add_iface: iface validation failed: err=-95')
self.pattern2 = re.compile(r'wifi error while hopping to channel') self.pattern2 = re.compile(r'wifi error while hopping to channel')
self.pattern3 = re.compile(r'Firmware has halted or crashed') self.pattern3 = re.compile(r'Firmware has halted or crashed')
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon') self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
self.pattern5 = re.compile(r'fatal error: concurrent map iteration and map write')
self.pattern6 = re.compile(r'panic: runtime error')
self.pattern7 = re.compile(r'ieee80211 phy0: _brcmf_set_multicast_list: Setting allmulti failed, -110')
self.isReloadingMon = False self.isReloadingMon = False
self.connection = None self.connection = None
self.LASTTRY = 0 self.LASTTRY = 0
@ -51,20 +55,6 @@ class FixServices(plugins.Plugin):
if ",UP," in str(cmd_output): if ",UP," in str(cmd_output):
logging.debug("wlan0mon is up.") logging.debug("wlan0mon is up.")
if len(self.pattern.findall(last_lines)) >= 3:
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Blind-Bug detected. Restarting.')
display.update(force=True)
logging.debug('[Fix_Services] Blind-Bug detected. Restarting.')
try:
self._tryTurningItOffAndOnAgain(agent)
except Exception as err:
logging.warning("[Fix_Services turnOffAndOn] %s" % repr(err))
else:
logging.debug("[Fix_Services] Logs look good!")
except Exception as err: except Exception as err:
logging.error("[Fix_Services ip link show wlan0mon]: %s" % repr(err)) logging.error("[Fix_Services ip link show wlan0mon]: %s" % repr(err))
try: try:
@ -102,34 +92,26 @@ class FixServices(plugins.Plugin):
other_last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl', '-n10'], other_last_lines = ''.join(list(TextIOWrapper(subprocess.Popen(['journalctl', '-n10'],
stdout=subprocess.PIPE).stdout))[-10:]) stdout=subprocess.PIPE).stdout))[-10:])
other_other_last_lines = ''.join( other_other_last_lines = ''.join(
list(TextIOWrapper(subprocess.Popen(['tail', '-n10', '/var/log/pwnagotchi.log'], list(TextIOWrapper(subprocess.Popen(['tail', '-n10', '/etc/pwnagotchi/log/pwnagotchi.log'],
stdout=subprocess.PIPE).stdout))[-10:]) stdout=subprocess.PIPE).stdout))[-10:])
# don't check if we ran a reset recently # don't check if we ran a reset recently
logging.debug("[Fix_Services]**** epoch") logging.debug("[Fix_Services]**** epoch")
if time.time() - self.LASTTRY > 180: if time.time() - self.LASTTRY > 180:
# get last 10 lines # get last 10 lines
display = None display = agent.view()
logging.debug("[Fix_Services]**** checking") logging.debug("[Fix_Services]**** checking")
if len(self.pattern.findall(last_lines)) >= 1:
# Look for pattern 1 subprocess.check_output("monstop", shell=True)
if len(self.pattern.findall(last_lines)) >= 3: subprocess.check_output("monstart", shell=True)
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) display.set('status', 'Wifi channel stuck. Restarting recon.')
if hasattr(agent, 'view'): display.update(force=True)
display = agent.view() pwnagotchi.restart("AUTO")
display.set('status', 'Blind-Bug detected. Restarting.')
display.update(force=True)
logging.debug('[Fix_Services] Blind-Bug detected. Restarting.')
try:
self._tryTurningItOffAndOnAgain(agent)
except Exception as err:
logging.warning("[Fix_Services] TTOAOA: %s" % repr(err))
# Look for pattern 2 # Look for pattern 2
elif len(self.pattern2.findall(other_last_lines)) >= 5: elif len(self.pattern2.findall(other_last_lines)) >= 5:
logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines) logging.debug("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Wifi channel stuck. Restarting recon.') display.set('status', 'Wifi channel stuck. Restarting recon.')
display.update(force=True) display.update(force=True)
logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.') logging.debug('[Fix_Services] Wifi channel stuck. Restarting recon.')
@ -153,7 +135,6 @@ class FixServices(plugins.Plugin):
elif len(self.pattern3.findall(other_last_lines)) >= 1: elif len(self.pattern3.findall(other_last_lines)) >= 1:
logging.debug("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.") logging.debug("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.")
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Firmware has halted or crashed. Restarting wlan0mon.') display.set('status', 'Firmware has halted or crashed. Restarting wlan0mon.')
display.update(force=True) display.update(force=True)
try: try:
@ -167,7 +148,6 @@ class FixServices(plugins.Plugin):
elif len(self.pattern4.findall(other_other_last_lines)) >= 3: elif len(self.pattern4.findall(other_other_last_lines)) >= 3:
logging.debug("[Fix_Services] wlan0 is down!") logging.debug("[Fix_Services] wlan0 is down!")
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Restarting wlan0 now!') display.set('status', 'Restarting wlan0 now!')
display.update(force=True) display.update(force=True)
try: try:
@ -177,6 +157,41 @@ class FixServices(plugins.Plugin):
except Exception as err: except Exception as err:
logging.error("[Fix_Services monstart]: %s" % repr(err)) logging.error("[Fix_Services monstart]: %s" % repr(err))
# Look for pattern 5
elif len(self.pattern5.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
# Look for pattern 6
elif len(self.pattern6.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Bettercap has crashed!")
if hasattr(agent, 'view'):
display.set('status', 'Restarting pwnagotchi!')
display.update(force=True)
os.system("systemctl restart bettercap")
pwnagotchi.restart("AUTO")
# Look for pattern 7
elif len(self.pattern7.findall(other_other_last_lines)) >= 1:
logging.debug("[Fix_Services] Monitor mode failed!")
try:
result = agent.run("wifi.recon off; wifi.recon on")
if result["success"]:
logging.debug("[Fix_Services] wifi.recon flip: success!")
if display:
display.update(force=True, new_data={"status": "Wifi recon flipped!",
"face": faces.COOL})
else:
print("Wifi recon flipped\nthat was easy!")
else:
logging.warning("[Fix_Services] wifi.recon flip: FAILED: %s" % repr(result))
except Exception as err:
logging.error("[Fix_Services wifi.recon flip] %s" % repr(err))
else: else:
print("logs look good") print("logs look good")

View File

@ -14,8 +14,9 @@ class GPIOButtons(plugins.Plugin):
self.running = False self.running = False
self.ports = {} self.ports = {}
self.commands = None self.commands = None
self.options = dict()
def runCommand(self, channel): def runcommand(self, channel):
command = self.ports[channel] command = self.ports[channel]
logging.info(f"Button Pressed! Running command: {command}") logging.info(f"Button Pressed! Running command: {command}")
process = subprocess.Popen(command, shell=True, stdin=None, stdout=open("/dev/null", "w"), stderr=None, process = subprocess.Popen(command, shell=True, stdin=None, stdout=open("/dev/null", "w"), stderr=None,
@ -35,8 +36,8 @@ class GPIOButtons(plugins.Plugin):
gpio = int(gpio) gpio = int(gpio)
self.ports[gpio] = command self.ports[gpio] = command
GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP) GPIO.setup(gpio, GPIO.IN, GPIO.PUD_UP)
GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runCommand, bouncetime=600) GPIO.add_event_detect(gpio, GPIO.FALLING, callback=self.runcommand, bouncetime=600)
#set pimoroni display hat mini LED off/dim # set pimoroni display hat mini LED off/dim
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

View File

@ -98,7 +98,7 @@ class GPS(plugins.Plugin):
lat_pos = (127, 74) lat_pos = (127, 74)
lon_pos = (122, 84) lon_pos = (122, 84)
alt_pos = (127, 94) alt_pos = (127, 94)
elif ui.is_waveshare27inch(): elif ui.is_waveshare2in7():
lat_pos = (6, 120) lat_pos = (6, 120)
lon_pos = (1, 135) lon_pos = (1, 135)
alt_pos = (6, 150) alt_pos = (6, 150)

View File

@ -5,7 +5,6 @@ import glob
import re import re
import pwnagotchi.grid as grid import pwnagotchi.grid as grid
import pwnagotchi.plugins
import pwnagotchi.plugins as plugins import pwnagotchi.plugins as plugins
from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap from pwnagotchi.utils import StatusFile, WifiInfo, extract_from_pcap
from threading import Lock from threading import Lock
@ -48,7 +47,7 @@ class Grid(plugins.Plugin):
__version__ = '1.0.1' __version__ = '1.0.1'
__license__ = 'GPL3' __license__ = 'GPL3'
__description__ = 'This plugin signals the unit cryptographic identity and list of pwned networks and list of pwned ' \ __description__ = 'This plugin signals the unit cryptographic identity and list of pwned networks and list of pwned ' \
'networks to api.pwnagotchi.ai ' 'networks to opwngrid.xyz '
def __init__(self): def __init__(self):
self.options = dict() self.options = dict()
@ -87,10 +86,10 @@ class Grid(plugins.Plugin):
agent.view().on_unread_messages(self.unread_messages, self.total_messages) agent.view().on_unread_messages(self.unread_messages, self.total_messages)
def check_handshakes(self, agent): def check_handshakes(self, agent):
logging.debug("checking pcaps") logging.debug("checking pcap's")
config = agent.config() config = agent.config()
pcap_files = glob.glob(os.path.join(agent.config()['bettercap']['handshakes'], "*.pcap")) pcap_files = glob.glob(os.path.join(config['bettercap']['handshakes'], "*.pcap"))
num_networks = len(pcap_files) num_networks = len(pcap_files)
reported = self.report.data_field_or('reported', default=[]) reported = self.report.data_field_or('reported', default=[])
num_reported = len(reported) num_reported = len(reported)

View File

@ -253,7 +253,6 @@ class Logtail(plugins.Plugin):
""" """
logging.info("Logtail plugin loaded.") logging.info("Logtail plugin loaded.")
def on_webhook(self, path, request): def on_webhook(self, path, request):
if not self.ready: if not self.ready:
return "Plugin not ready" return "Plugin not ready"

View File

@ -130,7 +130,7 @@ class MemTemp(plugins.Plugin):
except Exception: except Exception:
# Set default position based on screen type # Set default position based on screen type
if ui.is_waveshare_v2(): if ui.is_waveshare_v2():
h_pos = (178, 84) h_pos = (175, 84)
v_pos = (197, 74) v_pos = (197, 74)
elif ui.is_waveshare_v1(): elif ui.is_waveshare_v1():
h_pos = (170, 80) h_pos = (170, 80)

View File

@ -1,150 +0,0 @@
import logging
import json
import os
import threading
import requests
import time
import pwnagotchi.plugins as plugins
from pwnagotchi.utils import StatusFile
class NetPos(plugins.Plugin):
__author__ = 'zenzen san'
__version__ = '2.0.3'
__license__ = 'GPL3'
__description__ = """Saves a json file with the access points with more signal
whenever a handshake is captured.
When internet is available the files are converted in geo locations
using Mozilla LocationService """
API_URL = 'https://location.services.mozilla.com/v1/geolocate?key={api}'
def __init__(self):
self.report = StatusFile('/root/.net_pos_saved', data_format='json')
self.skip = list()
self.ready = False
self.lock = threading.Lock()
self.options = dict()
def on_loaded(self):
if 'api_key' not in self.options or ('api_key' in self.options and not self.options['api_key']):
logging.error("NET-POS: api_key isn't set. Can't use mozilla's api.")
return
if 'api_url' in self.options:
self.API_URL = self.options['api_url']
self.ready = True
logging.info("net-pos plugin loaded.")
logging.debug(f"net-pos: use api_url: {self.API_URL}")
def _append_saved(self, path):
to_save = list()
if isinstance(path, str):
to_save.append(path)
elif isinstance(path, list):
to_save += path
else:
raise TypeError("Expected list or str, got %s" % type(path))
with open('/root/.net_pos_saved', 'a') as saved_file:
for x in to_save:
saved_file.write(x + "\n")
def on_internet_available(self, agent):
if self.lock.locked():
return
with self.lock:
if self.ready:
config = agent.config()
display = agent.view()
reported = self.report.data_field_or('reported', default=list())
handshake_dir = config['bettercap']['handshakes']
all_files = os.listdir(handshake_dir)
all_np_files = [os.path.join(handshake_dir, filename)
for filename in all_files
if filename.endswith('.net-pos.json')]
new_np_files = set(all_np_files) - set(reported) - set(self.skip)
if new_np_files:
logging.debug("NET-POS: Found %d new net-pos files. Fetching positions ...", len(new_np_files))
display.set('status', f"Found {len(new_np_files)} new net-pos files. Fetching positions ...")
display.update(force=True)
for idx, np_file in enumerate(new_np_files):
geo_file = np_file.replace('.net-pos.json', '.geo.json')
if os.path.exists(geo_file):
# got already the position
reported.append(np_file)
self.report.update(data={'reported': reported})
continue
try:
geo_data = self._get_geo_data(np_file) # returns json obj
except requests.exceptions.RequestException as req_e:
logging.error("NET-POS: %s - RequestException: %s", np_file, req_e)
self.skip += np_file
continue
except json.JSONDecodeError as js_e:
logging.error("NET-POS: %s - JSONDecodeError: %s, removing it...", np_file, js_e)
os.remove(np_file)
continue
except OSError as os_e:
logging.error("NET-POS: %s - OSError: %s", np_file, os_e)
self.skip += np_file
continue
with open(geo_file, 'w+t') as sf:
json.dump(geo_data, sf)
reported.append(np_file)
self.report.update(data={'reported': reported})
display.set('status', f"Fetching positions ({idx + 1}/{len(new_np_files)})")
display.update(force=True)
def on_handshake(self, agent, filename, access_point, client_station):
netpos = self._get_netpos(agent)
if not netpos['wifiAccessPoints']:
return
netpos["ts"] = int("%.0f" % time.time())
netpos_filename = filename.replace('.pcap', '.net-pos.json')
logging.debug("NET-POS: Saving net-location to %s", netpos_filename)
try:
with open(netpos_filename, 'w+t') as net_pos_file:
json.dump(netpos, net_pos_file)
except OSError as os_e:
logging.error("NET-POS: %s", os_e)
def _get_netpos(self, agent):
aps = agent.get_access_points()
netpos = dict()
netpos['wifiAccessPoints'] = list()
# 6 seems a good number to save a wifi networks location
for access_point in sorted(aps, key=lambda i: i['rssi'], reverse=True)[:6]:
netpos['wifiAccessPoints'].append({'macAddress': access_point['mac'],
'signalStrength': access_point['rssi']})
return netpos
def _get_geo_data(self, path, timeout=30):
geourl = self.API_URL.format(api=self.options['api_key'])
try:
with open(path, "r") as json_file:
data = json.load(json_file)
except json.JSONDecodeError as js_e:
raise js_e
except OSError as os_e:
raise os_e
try:
result = requests.post(geourl,
json=data,
timeout=timeout)
return_geo = result.json()
if data["ts"]:
return_geo["ts"] = data["ts"]
return return_geo
except requests.exceptions.RequestException as req_e:
raise req_e

View File

@ -142,6 +142,6 @@ class OnlineHashCrack(plugins.Plugin):
for row in csv.DictReader(cracked_list): for row in csv.DictReader(cracked_list):
if row['password']: if row['password']:
filename = re.sub(r'[^a-zA-Z0-9]', '', row['ESSID']) + '_' + row['BSSID'].replace(':','') filename = re.sub(r'[^a-zA-Z0-9]', '', row['ESSID']) + '_' + row['BSSID'].replace(':','')
if os.path.exists( os.path.join(handshake_dir, filename+'.pcap') ): if os.path.exists( os.path.join(handshake_dir, filename+'.pcap')):
with open(os.path.join(handshake_dir, filename+'.pcap.cracked'), 'w') as f: with open(os.path.join(handshake_dir, filename+'.pcap.cracked'), 'w') as f:
f.write(row['password']) f.write(row['password'])

View File

@ -1,42 +0,0 @@
import logging
import requests
import pwnagotchi.plugins as plugins
'''
You need an bluetooth connection to your android phone which is running PAW server with the GPS "hack" from Systemik and edited by shaynemk
GUIDE HERE: https://community.pwnagotchi.ai/t/setting-up-paw-gps-on-android
'''
class PawGPS(plugins.Plugin):
__author__ = 'leont'
__version__ = '1.0.1'
__name__ = 'pawgps'
__license__ = 'GPL3'
__description__ = 'Saves GPS coordinates whenever an handshake is captured. The GPS data is get from PAW on android.'
def __init__(self):
self.options = dict()
def on_loaded(self):
logging.info("[paw-gps] plugin loaded")
if 'ip' not in self.options or ('ip' in self.options and self.options['ip'] is None) or (len('ip' in self.options and self.options['ip']) is 0):
logging.info("[paw-gps] no IP Address defined in the config file, will uses paw server default (192.168.44.1:8080)")
def on_handshake(self, agent, filename, access_point, client_station):
if 'ip' not in self.options or ('ip' in self.options and self.options['ip'] is None or (len('ip' in self.options and self.options['ip']) is 0)):
ip = "192.168.44.1:8080"
else:
ip = self.options['ip']
try:
gps = requests.get('http://' + ip + '/gps.xhtml')
try:
gps_filename = filename.replace('.pcap', '.paw-gps.json')
logging.info("[paw-gps] saving GPS data to %s" % (gps_filename))
with open(gps_filename, 'w+t') as f:
f.write(gps.text)
except Exception as error:
logging.error(f"[paw-gps] encountered error while saving gps data: {error}")
except Exception as error:
logging.error(f"[paw-gps] encountered error while getting gps data: {error}")

View File

@ -0,0 +1,105 @@
# Based on UPS Lite v1.1 from https://github.com/xenDE
import logging
import time
from pwnagotchi.ui.components import LabeledValue
from pwnagotchi.ui.view import BLACK
import pwnagotchi.ui.fonts as fonts
import pwnagotchi.plugins as plugins
import pwnagotchi
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:
low = self._bus.read_byte_data(0x57, 0x23)
high = self._bus.read_byte_data(0x57, 0x22)
v = (((high << 8) + low) / 1000)
return v
except:
return 0.0
def capacity(self):
battery_level = 0
# battery_v = self.voltage()
try:
battery_level = self._bus.read_byte_data(0x57, 0x2a)
return battery_level
except:
return battery_level
def status(self):
stat02 = self._bus.read_byte_data(0x57, 0x02)
stat03 = self._bus.read_byte_data(0x57, 0x03)
stat04 = self._bus.read_byte_data(0x57, 0x04)
return stat02, stat03, stat04
class PiSugar3(plugins.Plugin):
__author__ = 'taiyonemo@protonmail.com'
__editor__ = 'jayofelony'
__version__ = '1.0.1'
__license__ = 'GPL3'
__description__ = 'A plugin that will add a percentage indicator for the PiSugar 3'
def __init__(self):
self.ups = None
self.lasttemp = 69
self.drot = 0 # display rotation
self.nextDChg = 0 # last time display changed, rotate on updates after 5 seconds
self.options = dict()
def on_loaded(self):
self.ups = UPS()
logging.info("[PiSugar3] plugin loaded.")
def on_ui_setup(self, ui):
try:
ui.add_element('bat', LabeledValue(color=BLACK, label='BAT', value='0%', position=(ui.width() / 2 + 10, 0),
label_font=fonts.Bold, text_font=fonts.Medium))
except Exception as err:
logging.warning("[PiSugar3] setup err: %s" % repr(err))
def on_unload(self, ui):
try:
with ui._lock:
ui.remove_element('bat')
except Exception as err:
logging.warning("[PiSugar3] unload err: %s" % repr(err))
def on_ui_update(self, ui):
capacity = self.ups.capacity()
voltage = self.ups.voltage()
stats = self.ups.status()
temp = stats[2] - 40
if temp != self.lasttemp:
logging.debug("[PiSugar3] (chg %X, info %X, temp %d)" % (stats[0], stats[1], temp))
self.lasttemp = temp
if stats[0] & 0x80: # charging, or has power connected
ui._state._state['bat'].label = "CHG"
else:
ui._state._state['bat'].label = "BAT"
if time.time() > self.nextDChg:
self.drot = (self.drot + 1) % 3
self.nextDChg = time.time() + 5
if self.drot == 0: # show battery voltage
ui.set('bat', "%2.2fv" % voltage)
elif self.drot == 1:
ui.set('bat', "%2i%%" % capacity)
else:
ui.set('bat', "%2i\xb0" % temp)
if capacity <= self.options['shutdown']:
logging.info('[PiSugar3] Empty battery (<= %s%%): shutting down' % self.options['shutdown'])
ui.update(force=True, new_data={'status': 'Battery exhausted, bye ...'})
pwnagotchi.shutdown()

View File

@ -18,12 +18,14 @@ def systemd_dropin(name, content):
systemctl("daemon-reload") systemctl("daemon-reload")
def systemctl(command, unit=None): def systemctl(command, unit=None):
if unit: if unit:
os.system("/bin/systemctl %s %s" % (command, unit)) os.system("/bin/systemctl %s %s" % (command, unit))
else: else:
os.system("/bin/systemctl %s" % command) os.system("/bin/systemctl %s" % command)
def run_task(name, options): def run_task(name, options):
task_service_name = "switcher-%s-task.service" % name task_service_name = "switcher-%s-task.service" % name
# save all the commands to a shell script # save all the commands to a shell script
@ -57,7 +59,7 @@ def run_task(name, options):
""" % (name, task_service_name, name)) """ % (name, task_service_name, name))
if 'reboot' in options and options['reboot']: if 'reboot' in options and options['reboot']:
# create a indication file! # create an indication file!
# if this file is set, we want the switcher-tasks to run # if this file is set, we want the switcher-tasks to run
open('/root/.switcher', 'a').close() open('/root/.switcher', 'a').close()
@ -98,6 +100,7 @@ def run_task(name, options):
systemctl("daemon-reload") systemctl("daemon-reload")
systemctl("start", task_service_name) systemctl("start", task_service_name)
class Switcher(plugins.Plugin): class Switcher(plugins.Plugin):
__author__ = '33197631+dadav@users.noreply.github.com' __author__ = '33197631+dadav@users.noreply.github.com'
__version__ = '0.0.1' __version__ = '0.0.1'

Some files were not shown because too many files have changed in this diff Show More