Compare commits

...

99 Commits

Author SHA1 Message Date
611a3e7fb5 fix for waveshare3in7.py 2024-02-15 20:51:55 +01:00
599c6211e4 version 2.8.4 2024-02-15 20:48:27 +01:00
eb48d29851 fix on 38 displays 2024-02-15 20:46:48 +01:00
0999b95be0 update build 2024-02-15 09:55:01 +01:00
ae351e5e9c update waveshare3in0g.py 2024-02-15 09:54:49 +01:00
fa58136c0e update waveshare3in7.py 2024-02-15 09:34:45 +01:00
3d5185f2c1 update waveshare3in7.py 2024-02-15 09:30:03 +01:00
b6bb7b9080 update waveshare3in7.py 2024-02-15 09:26:33 +01:00
20715351af revert back to drschottky 2024-02-14 08:53:54 +01:00
1d3c781d12 version 2.8.3 2024-02-13 23:25:55 +01:00
bd51b4330f version 2.8.3 2024-02-13 23:15:05 +01:00
f216a21132 update 2024-02-13 23:13:49 +01:00
5ae357c3dc Merge remote-tracking branch 'origin/master' 2024-02-13 23:11:10 +01:00
ed9afe6856 Revert "Changed from dphys-swapfile to zram-tools"
This reverts commit 26913016b9.
2024-02-13 23:10:53 +01:00
25d932fa9b Revert "zramswap"
This reverts commit 0dbd611ed5.
2024-02-13 23:10:52 +01:00
ebd25d50b0 Update README.md 2024-02-09 23:13:26 +01:00
27e784a5d7 update 2024-02-09 13:12:40 +01:00
c02efb5224 update Makefile 2024-02-09 13:11:02 +01:00
107d366c82 update Makefile 2024-02-08 21:40:28 +01:00
488968ba7f Revert "update Makefile"
This reverts commit 9a40567d
2024-02-08 20:18:58 +01:00
0dd8f72c95 Merge pull request #58 from jayofelony/dev
dev
2024-02-08 20:07:20 +01:00
0e274af5a0 Revert "Testing pcapng fileformat"
This reverts commit 7040be2d30.
2024-02-08 20:06:33 +01:00
8627c8800d Merge pull request #57 from jayofelony/dev
Dev
2024-02-08 07:53:53 +01:00
53ed6f61c6 Merge branch 'master' into dev
Signed-off-by: Jayofelony <oudshoorn.jeroen@gmail.com>
2024-02-08 07:53:45 +01:00
835523241b update build 2024-02-08 07:51:19 +01:00
9a40567daa update Makefile 2024-02-06 22:12:05 +01:00
eab331686d Merge pull request #54 from crs-k/dev
Add PiShrink step to the workflow (#1)
2024-02-06 22:10:12 +01:00
e1d8001fb4 Add PiShrink step to the workflow (#1)
* Add PiShrink step to the workflow

* Add environment variables for Raspberry Pi 64-bit builder

* Update Makefile command to include debug information

* Add source distribution target to Makefile

* Remove unnecessary provisioner command

* Add armhf architecture support

* Remove armhf architecture provisioning

* Refactor Makefile to remove unnecessary files

* Update Makefile command in publish.yml

* Update pwngrid URL in raspberrypi64.yml

* Add permissions to publish workflow

* Remove unnecessary permissions in publish.yml
2024-02-06 12:53:45 -05:00
3cc172a526 update Makefile 2024-02-06 09:06:54 +01:00
41afe302d9 update Makefile 2024-02-06 09:05:42 +01:00
5bcca7e89b update README.md 2024-02-06 08:52:16 +01:00
4a12436942 add architecture armhf 2024-02-06 08:41:28 +01:00
d8b6363d37 Merge pull request #51
Waveshare 3.52 in e-ink update
2024-02-06 08:36:21 +01:00
b3d8a44208 Update waveshare3in52.py
Signed-off-by: Chris Kerins <clkerins@gmail.com>
2024-02-05 20:14:18 -05:00
ck
3fb91498cd Enable Makefile execution and remove disk image creation 2024-02-05 17:52:51 -05:00
ck
7587f38c28 Update disk.img path in publish.yml 2024-02-05 17:46:20 -05:00
ck
d7fefa78f0 Commented out make step and added code to create .img file 2024-02-05 17:40:38 -05:00
ck
1ef3a88679 Update distDir path in publish.yml 2024-02-05 17:34:23 -05:00
291ef39563 Update README.md to show support for Pi 5 2024-02-05 22:10:53 +01:00
16d80a09e6 Update README.md to show support for Pi 5 2024-02-05 22:10:34 +01:00
ck
4ffad03c91 Update distDir path in publish.yml 2024-02-05 15:44:50 -05:00
ck
0638832532 Update mountpoint for boot partition 2024-02-05 13:42:59 -05:00
ck
f895b06978 Update qemu binary paths for arm64 2024-02-05 13:19:56 -05:00
ck
f410feb2bb Add check for qemu-aarch64 in binfmt_misc 2024-02-05 13:09:36 -05:00
ck
1ffe6c4e3d Remove Makefile2 and update build process 2024-02-05 12:34:34 -05:00
ck
dfbfd7f891 Update pwngrid to version 1.11.1 2024-02-05 12:34:09 -05:00
ck
a50695aef2 Update publish workflow and add Makefile2 2024-02-05 12:18:04 -05:00
ck
829a6962d6 Update binfmt-support and add checks for qemu-user-static package, binfmt-support service, and binfmt_misc filesystem 2024-02-05 12:17:41 -05:00
ck
ce1315b85f Add binfmt_misc registration for qemu-aarch64 2024-02-05 12:08:07 -05:00
ck
6a2703cc27 Update QEMU in publish.yml 2024-02-05 11:34:03 -05:00
ck
502e856934 Update QEMU and restart binfmt-support 2024-02-05 11:22:39 -05:00
dffcbbf447 Revert "Revert "Testing pcapng fileformat""
This reverts commit d142840307.
2024-02-05 17:16:13 +01:00
ck
333804c3bb Remove unnecessary build configuration for Raspberry Pi 32 Pwnagotchi 2024-02-05 11:10:29 -05:00
ck
50b1ceed81 Remove unnecessary file from pwnagotchi build process 2024-02-05 11:01:49 -05:00
ck
877b9fbba3 Update Makefile and builder/pwnagotchi.json.pkr.hcl 2024-02-05 10:57:33 -05:00
ck
8724ca546d Update packer builder-arm source URL 2024-02-05 10:51:18 -05:00
961d3a536a Merge pull request #2 from crs-k/waveshare-352-support
Waveshare 352 support
2024-02-05 10:38:39 -05:00
ck
c882d0b67a Update arm plugin source in pwnagotchi.json.pkr.hcl 2024-02-05 10:29:01 -05:00
ck
12fd081ae0 Update required_plugins in pwnagotchi.json.pkr.hcl 2024-02-05 10:09:57 -05:00
ck
e1be0f7674 Remove unnecessary clean-up step in Makefile 2024-02-05 10:01:12 -05:00
396b30f780 Merge pull request #1 from crs-k:waveshare-352-support
Add publish workflow and update display layout
2024-02-05 09:31:24 -05:00
ck
e7d8d632a0 Add publish workflow and update display layout 2024-02-05 09:30:49 -05:00
5a6ec7b4b8 Next version will be 2.8.2 2024-02-04 18:28:09 +01:00
92cd5d3fdb Merge pull request #47 from jayofelony/dev
removed blind bug check from fix_services.py
2024-02-04 18:09:33 +01:00
99caa7a973 removed blind bug check from fix_services.py 2024-02-04 18:08:31 +01:00
a94e7eef02 Merge pull request #46 from jayofelony/dev
Dev to master
2024-02-04 18:04:44 +01:00
1cefae55d1 moved the majority of logging to debug 2024-02-04 17:48:22 +01:00
c5ee1df855 unused function 2024-02-04 17:44:05 +01:00
d142840307 Revert "Testing pcapng fileformat"
This reverts commit 7040be2d30.
2024-02-04 17:42:56 +01:00
e558146e28 moves the majority of logging to debug 2024-02-04 17:42:40 +01:00
11a3330153 small fix 2024-02-04 17:42:22 +01:00
53b2dd8628 update build for latest kernel 2024-02-04 17:42:10 +01:00
6381f9443b remove blind bug, as its not a blind bug anymore. 2024-02-04 17:41:57 +01:00
fa7e87b974 remove blind bug, as its not a blind bug anymore.
delayed hopping channels by .2 seconds to give firmware time to get ready for hopping.
2024-02-04 17:41:41 +01:00
cca2ff2da4 Merge pull request #45 from wpa-2/patch-1
MOTD updated
2024-02-03 17:09:03 +01:00
78415b3137 Update 01-motd
Maybe a good idea to point people to the new wiki instead. 


Signed-off-by: wpa-2 <9049886+wpa-2@users.noreply.github.com>
2024-02-03 15:13:44 +00:00
34284aa1bc Change to seemoo-lab nexmon 2024-02-01 13:50:51 +01:00
56ebb60662 Change to seemoo-lab nexmon 2024-02-01 13:26:20 +01:00
84f6624844 Change to seemoo-lab nexmon 2024-02-01 13:04:06 +01:00
3bcbb0ce9a Version 2.8.1 2024-01-29 22:52:16 +01:00
e01e457992 Remove bettercap client settings, so you cannot mess it up. 2024-01-29 22:24:20 +01:00
1780859889 Merge pull request #37 from Ravioli5/patch-1
Update 01-motd
2024-01-29 16:15:12 +01:00
fdd98bb37a Update 01-motd
-fixed grammar (added a word)

Signed-off-by: Ravioli5 <157115073+Ravioli5@users.noreply.github.com>
2024-01-29 13:33:47 +05:30
86991304a5 Merge remote-tracking branch 'origin/dev' into dev 2024-01-28 22:12:20 +01:00
4f62759d6d Revert grid name 2024-01-28 22:12:06 +01:00
7b7ba02aad Changed setup.py 2024-01-28 22:12:06 +01:00
7040be2d30 Testing pcapng fileformat 2024-01-28 22:12:05 +01:00
d0617ccfaf Revert grid name 2024-01-28 22:08:17 +01:00
a0b5078b64 Changed setup.py 2024-01-28 22:05:14 +01:00
54c1ffd63c Updated wiglewifi version to 1.6 2024-01-28 22:02:57 +01:00
7530709d0c Updated wiglewifi version to 1.6 2024-01-28 21:46:50 +01:00
a9a6fd424b Small changes/fixes for debugging 2024-01-28 21:46:22 +01:00
8c97301992 Readability changes for webgpsmap.py 2024-01-28 21:45:53 +01:00
91eaa22188 Fix for waveshare2in13b_V4.py implementation 2024-01-28 21:44:19 +01:00
31a4af4c21 sudo pwnagotchi plugins update
`sudo pwnagotchi plugins list`

Do not work, somehow I forgot to remove a test I did.
2024-01-28 21:44:04 +01:00
dceeaff1fb Next update will be 2.8.0 2024-01-28 21:43:17 +01:00
c0241dc8df Update README.md 2024-01-27 16:11:59 +01:00
8f405f4ab2 Merge pull request #35 from Kal-Toh/patch-1
Update README.md
2024-01-27 16:11:19 +01:00
bd79e71563 Update README.md
This is a small change to address questions I had about the installation process.

Signed-off-by: Rory <104321806+Kal-Toh@users.noreply.github.com>
2024-01-27 14:03:40 +00:00
68 changed files with 430 additions and 228 deletions

1
.github/FUNDING.yml vendored
View File

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

212
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,212 @@
name: Publish
on:
workflow_dispatch:
inputs:
version:
description: 'Version number'
required: true
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Remove unnecessary directories
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf /usr/local/share/boost
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
- name: Check disk space
run: df -BG
- name: Checkout code
uses: actions/checkout@v4
- name: Validate tag
id: tag-setter
run: |
TAG=${{ github.event.inputs.version }}
if [[ $TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Tag $TAG is valid."
echo "TAG=$TAG" >> $GITHUB_OUTPUT
else
echo "Tag $TAG is not a valid semantic version. Aborting."
exit 1
fi
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.9
- name: Install dependencies
run: |
sudo apt-get update && sudo apt-get install -y libdbus-1-dev curl unzip gettext qemu-utils qemu qemu-user-static binfmt-support
pip install -r requirements.txt
- name: Update QEMU
run: |
sudo update-binfmts --enable qemu-aarch64
echo $(ls /usr/bin/qemu-aarch64-static)
- name: Restart binfmt-support
run: sudo service binfmt-support restart
- name: Mount binfmt_misc
run: |
if ! grep -qs '/proc/sys/fs/binfmt_misc ' /proc/mounts; then
echo "Mounting binfmt_misc"
sudo mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc
fi
- name: Restart binfmt-support
run: sudo service binfmt-support restart
- name: Update Languages
run: make update_langs
- name: Compile Languages
run: make compile_langs
- name: Check disk space
run: df -BG
- name: Check qemu-user-static package
run: |
echo "Checking qemu-user-static package..."
dpkg -s qemu-user-static && echo "qemu-user-static is installed." || echo "qemu-user-static is NOT installed."
- name: Check binfmt-support service
run: |
echo "Checking binfmt-support service..."
service binfmt-support status && echo "binfmt-support service is running." || echo "binfmt-support service is NOT running."
- name: Check binfmt_misc filesystem
run: |
echo "Checking binfmt_misc filesystem..."
mount | grep binfmt_misc && echo "binfmt_misc is mounted." || echo "binfmt_misc is NOT mounted."
echo $(ls /proc/sys/fs/binfmt_misc | grep qemu-aarch64)
- name: Run Makefile
run: make
env:
PWN_VERSION: ${{ steps.tag-setter.outputs.TAG }}
- name: PiShrink
run: |
wget https://raw.githubusercontent.com/Drewsif/PiShrink/master/pishrink.sh
chmod +x pishrink.sh
sudo mv pishrink.sh /usr/local/bin
find /home/runner/work/ -type f -name "*.img" -exec sudo pishrink.sh {} \;
- name: Compress .img files
run: |
find /home/runner/work/ -type f -name "*.img" -exec xz --no-warn {} \;
- name: Create tag
uses: actions/github-script@v7
with:
script: |
const version = "${{ steps.tag-setter.outputs.TAG }}"
console.log(`Creating tag ${version}`)
await github.rest.git.createRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `refs/tags/${version}`,
sha: context.sha
})
- name: Create Release
id: create_release
uses: actions/github-script@v7
with:
script: |
const tag = "${{ steps.tag-setter.outputs.TAG }}"
console.log(`Creating release with tag: ${tag}`)
const release = await github.rest.repos.createRelease({
owner: context.repo.owner,
repo: context.repo.repo,
tag_name: tag,
name: tag,
draft: false,
prerelease: true,
generate_release_notes: true
})
console.log(`Created release with id: ${release.data.id}`)
return release.data.id
- name: Upload Release Asset
id: upload-release-asset
uses: actions/github-script@v7
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
script: |
const fs = require('fs');
const path = require('path');
const release_id = "${{ steps.create_release.outputs.result }}";
const asset_content_type = 'application/octet-stream';
const distDir = '/home/runner/work/';
const uploadFile = async (filePath) => {
if (fs.lstatSync(filePath).isDirectory()) {
const files = fs.readdirSync(filePath);
for (const file of files) {
await uploadFile(path.join(filePath, file));
}
} else {
// Check if the file has a .xz extension
if (path.extname(filePath) === '.xz') {
console.log(`Uploading ${filePath}...`);
const asset_name = path.basename(filePath);
const asset_size = fs.statSync(filePath).size;
const asset = fs.createReadStream(filePath);
const response = await github.rest.repos.uploadReleaseAsset({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release_id,
name: asset_name,
data: asset,
headers: {
'content-type': asset_content_type,
'content-length': asset_size
}
});
console.log(`Uploaded ${filePath}: ${response.data.browser_download_url}`);
}
}
}
await uploadFile(distDir);
- name: Update Release
uses: actions/github-script@v7
with:
script: |
const release_id = "${{ steps.create_release.outputs.result }}"
console.log(`Updating release with id: ${release_id}`)
github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: release_id,
tag_name: "${{ steps.tag-setter.outputs.TAG }}",
name: "${{ steps.tag-setter.outputs.TAG }}",
draft: false,
prerelease: false
})
- name: Save environment variable
run: echo "${{ steps.tag-setter.outputs.TAG }}" > env_var.txt
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: env-var
path: env_var.txt

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 (pwnagotchi-torch-bookworm)" project-jdk-type="Python SDK" /> <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" 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 (pwnagotchi-torch-bookworm)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.10" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
<component name="PyDocumentationSettings"> <component name="PyDocumentationSettings">

View File

@ -1,4 +1,4 @@
PACKER_VERSION := 1.10.0 PACKER_VERSION := 1.10.1
PWN_HOSTNAME := pwnagotchi PWN_HOSTNAME := pwnagotchi
PWN_VERSION := $(shell cut -d"'" -f2 < pwnagotchi/_version.py) PWN_VERSION := $(shell cut -d"'" -f2 < pwnagotchi/_version.py)
@ -64,5 +64,5 @@ pwnagotchi: $(SDIST) builder/pwnagotchi.json.pkr.hcl builder/raspberrypi64.yml $
image: pwnagotchi image: pwnagotchi
clean: clean:
- rm -rf build dist pwnagotchi.egg-info - rm -rf dist pwnagotchi.egg-info
- rm -f $(PACKER) - rm -f $(PACKER)

View File

@ -1,15 +1,19 @@
# Pwnagotchi-Torch # Pwnagotchi-Torch
<a href="https://github.com/jayofelony/pwnagotchi-bookworm/releases/latest"><img alt="Release" src="https://img.shields.io/github/release/jayofelony/pwnagotchi-bookworm.svg"></a><br/> <a href="https://github.com/jayofelony/pwnagotchi-bookworm/releases/latest"><img alt="Release" src="https://img.shields.io/github/release/jayofelony/pwnagotchi-bookworm.svg"></a><br/>
**This fork of [Pwnagotchi](https://www.pwnagotchi.ai) is only for 64-bit Raspberry Pi's. Such as the 02W, 3(b+) and 4(b) ~~and the new Raspberry Pi 5~~!!.** **This fork of [Pwnagotchi](https://www.pwnagotchi.ai) is only for 64-bit Raspberry Pi's. Such as the 02W, 3(b+) and 4(b) and the new Raspberry Pi 5!!.**
The RPi5 can only be used headless currently. (without display.)
It seems the Pi 5 is unable to run in monitor mode, will keep you updated on this.
If you are using an older 32-bit version Raspberry Pi, ZeroWH, use this [fork](https://github.com/jayofelony/pwnagotchi-torch/releases/tag/v2.6.4) and make sure you download the `armhf` version. If you are using an older 32-bit version Raspberry Pi, ZeroWH, use this [fork](https://github.com/jayofelony/pwnagotchi-torch/releases/tag/v2.6.4) and make sure you download the `armhf` version.
--- ---
Download latest image file [here](https://github.com/jayofelony/pwnagotchi-bookworm/releases/tag/v2.7.3), and let it auto-update from here on out. Download the latest image file [here](https://github.com/jayofelony/pwnagotchi-bookworm/releases/tag/v2.8.2), and let it auto-update from here on out.
**Use RPi imager to flash, please don't flash a new user as this will mess with logs created.** **Use RPi imager to flash, please don't flash a new user as this will mess with logs created.**
- Select `Use Custom Image`
- Browse for the downloaded image file
- Select No under `Use OS Customization`
SSH credentials are `pi/raspberry`. SSH credentials are `pi/raspberry`.

View File

@ -1 +0,0 @@
hcxtools

View File

@ -60,6 +60,7 @@ def pwnagotchi_cli():
channels = agent.get_access_points_by_channel() channels = agent.get_access_points_by_channel()
# for each channel # for each channel
for ch, aps in channels: for ch, aps in channels:
time.sleep(0.2) # This is to make sure it doesn't error (https://github.com/seemoo-lab/nexmon/issues/596)
agent.set_channel(ch) agent.set_channel(ch)
if not agent.is_stale() and agent.any_activity(): if not agent.is_stale() and agent.any_activity():

View File

@ -1,15 +0,0 @@
# Specifies amount of zram devices to create.
# By default, zramswap-start will use all available cores.
#CORES=1
# Specifies the amount of RAM that should be used for zram
# based on a percentage the total amount of available memory
PERCENTAGE=60
# Specifies a static amount of RAM that should be used for
# the ZRAM devices, this is in MiB
#ALLOCATION=256
# Specifies the priority for the swap devices, see swapon(2)
# for more details.
#PRIORITY=100

View File

@ -0,0 +1,26 @@
# /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,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
@ -8,6 +8,7 @@ After=pwngrid-peer.service
Type=simple Type=simple
WorkingDirectory=~ WorkingDirectory=~
ExecStart=/usr/bin/pwnagotchi-launcher 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 Restart=always
RestartSec=30 RestartSec=30
TasksMax=infinity TasksMax=infinity

View File

@ -30,4 +30,4 @@ echo
echo " You can restart me using" echo " You can restart me using"
echo " pwnkill" echo " pwnkill"
echo echo
echo " You learn more about me at https://pwnagotchi.ai/" echo " You can learn more about me at https://pwnagotchi.org/"

View File

@ -9,15 +9,6 @@ if is_crypted_mode; then
done done
fi fi
# check if wifi driver is bugged
if ! check_brcm; then
if ! reload_brcm; then
echo "Could not reload wifi driver. Reboot"
reboot
fi
sleep 10
fi
# start mon0 # start mon0
start_monitor_interface start_monitor_interface

View File

@ -13,14 +13,6 @@ blink_led() {
sleep 0.3 sleep 0.3
} }
# check if brcm is stuck
check_brcm() {
if [[ "$(journalctl -n10 -k --since -5m | grep -c 'brcmf_cfg80211_nexmon_set_channel.*Set Channel failed')" -ge 5 ]]; then
return 1
fi
return 0
}
# reload mod # reload mod
reload_brcm() { reload_brcm() {
if ! modprobe -r brcmfmac; then if ! modprobe -r brcmfmac; then

View File

@ -1,11 +1,9 @@
# This is not working quite yet
# https://github.com/mkaczanowski/packer-builder-arm/pull/172
packer { packer {
required_plugins { required_plugins {
#arm = { arm = {
# version = "~> 1" version = "1.0.0"
# source = "github.com/cdecoux/builder-arm" source = "github.com/cdecoux/builder-arm"
#} }
ansible = { ansible = {
source = "github.com/hashicorp/ansible" source = "github.com/hashicorp/ansible"
version = "~> 1" version = "~> 1"
@ -28,8 +26,8 @@ source "arm" "rpi64-pwnagotchi" {
file_target_extension = "xz" file_target_extension = "xz"
file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"] file_unarchive_cmd = ["unxz", "$ARCHIVE_PATH"]
image_path = "../../../pwnagotchi-rpi-bookworm-${var.pwn_version}-arm64.img" image_path = "../../../pwnagotchi-rpi-bookworm-${var.pwn_version}-arm64.img"
qemu_binary_source_path = "/usr/bin/qemu-aarch64-static" qemu_binary_source_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P"
qemu_binary_destination_path = "/usr/bin/qemu-aarch64-static" qemu_binary_destination_path = "/usr/libexec/qemu-binfmt/aarch64-binfmt-P"
image_build_method = "resize" image_build_method = "resize"
image_size = "9G" image_size = "9G"
image_type = "dos" image_type = "dos"
@ -51,6 +49,8 @@ source "arm" "rpi64-pwnagotchi" {
} }
} }
# 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
@ -82,7 +82,6 @@ build {
"data/etc/systemd/system/pwngrid-peer.service", "data/etc/systemd/system/pwngrid-peer.service",
] ]
} }
provisioner "file" { provisioner "file" {
destination = "/etc/update-motd.d/01-motd" destination = "/etc/update-motd.d/01-motd"
source = "data/etc/update-motd.d/01-motd" source = "data/etc/update-motd.d/01-motd"

View File

@ -6,8 +6,8 @@
vars: vars:
kernel: kernel:
min: "6.1" min: "6.1"
full: "6.1.0-rpi7-rpi-v8" full: "6.1.0-rpi8-rpi-v8"
full_pi5: "6.1.0-rpi7-rpi-2712" full_pi5: "6.1.0-rpi8-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-torch', true) }}" version: "{{ lookup('env', 'PWN_VERSION') | default('pwnagotchi-torch', true) }}"
@ -27,7 +27,6 @@
- fstrim.timer - fstrim.timer
- pwnagotchi.service - pwnagotchi.service
- pwngrid-peer.service - pwngrid-peer.service
- zramswap.service
disable: disable:
- apt-daily-upgrade.service - apt-daily-upgrade.service
- apt-daily-upgrade.timer - apt-daily-upgrade.timer
@ -40,7 +39,7 @@
source: "https://github.com/jayofelony/caplets.git" source: "https://github.com/jayofelony/caplets.git"
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.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" ui: "https://github.com/bettercap/ui/releases/download/v1.3.0/ui.zip"
pwngrid: pwngrid:
source: "https://github.com/jayofelony/pwngrid.git" source: "https://github.com/jayofelony/pwngrid.git"
@ -78,7 +77,13 @@
- build-essential - build-essential
- curl - curl
- dkms - dkms
- dphys-swapfile
- fbi - fbi
- firmware-atheros
- firmware-brcm80211
- firmware-libertas
- firmware-misc-nonfree
- firmware-realtek
- flex - flex
- fonts-dejavu - fonts-dejavu
- fonts-dejavu-core - fonts-dejavu-core
@ -99,7 +104,6 @@
- libc6-dev - libc6-dev
- libcap-dev - libcap-dev
- libcurl-ocaml-dev - libcurl-ocaml-dev
- libssl-ocaml-dev
- libdbus-1-dev - libdbus-1-dev
- libdbus-glib-1-dev - libdbus-glib-1-dev
- libeigen3-dev - libeigen3-dev
@ -126,34 +130,30 @@
- libraspberrypi0 - libraspberrypi0
- libsqlite3-dev - libsqlite3-dev
- libssl-dev - libssl-dev
- libssl-ocaml-dev
- libswscale5 - libswscale5
- libtiff6 - libtiff6
- libtool - libtool
- libusb-1.0-0-dev - libusb-1.0-0-dev
- lsof - lsof
- make - make
- python3-yaml
- python3-dbus - python3-dbus
- python3-flask - python3-flask
- python3-flask-cors - python3-flask-cors
- python3-flaskext.wtf - python3-flaskext.wtf
- python3-gast - python3-gast
- python3-pil - python3-pil
- python3-pip
- python3-pycryptodome - python3-pycryptodome
- python3-requests - python3-requests
- python3-scapy - python3-scapy
- python3-setuptools
- python3-smbus
- python3-smbus2 - python3-smbus2
- python3-spidev - python3-spidev
- python3-tweepy - python3-tweepy
- python3-werkzeug - python3-werkzeug
- firmware-atheros - python3-yaml
- firmware-brcm80211
- firmware-libertas
- firmware-misc-nonfree
- firmware-realtek
- python3-pip
- python3-setuptools
- python3-smbus
- qpdf - qpdf
- raspberrypi-kernel-headers - raspberrypi-kernel-headers
- rsync - rsync
@ -168,7 +168,8 @@
- wl - wl
- xxd - xxd
- zlib1g-dev - zlib1g-dev
- zram-tools environment:
ARCHFLAGS: "-arch aarch64"
tasks: tasks:
# First we install packages # First we install packages
@ -290,7 +291,6 @@
state: absent state: absent
path: /usr/local/src/hcxtools path: /usr/local/src/hcxtools
# Install nexmon to fix wireless scanning (takes 2.5G of space)
- name: clone nexmon repository - name: clone nexmon repository
git: git:
repo: https://github.com/DrSchottky/nexmon.git repo: https://github.com/DrSchottky/nexmon.git
@ -514,7 +514,7 @@
repo: "{{ packages.bettercap.source }}" repo: "{{ packages.bettercap.source }}"
dest: /usr/local/src/bettercap dest: /usr/local/src/bettercap
- name: install bettercap 2.32.2 - 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" shell: "export GOPATH=$HOME/go && export PATH=/usr/local/go/bin:$PATH:$GOPATH/bin && go mod tidy && make && make install"
args: args:
executable: /bin/bash executable: /bin/bash

View File

@ -1 +1 @@
__version__ = '2.7.9' __version__ = '2.8.4'

View File

@ -21,11 +21,12 @@ RECOVERY_DATA_FILE = '/root/.pwnagotchi-recovery'
class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer): class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
def __init__(self, view, config, keypair): def __init__(self, view, config, keypair):
Client.__init__(self, config['bettercap']['hostname'], Client.__init__(self,
config['bettercap']['scheme'], "127.0.0.1" if "hostname" not in config['bettercap'] else config['bettercap']['hostname'],
config['bettercap']['port'], "http" if "scheme" not in config['bettercap'] else config['bettercap']['scheme'],
config['bettercap']['username'], 8081 if "port" not in config['bettercap'] else config['bettercap']['port'],
config['bettercap']['password']) "pwnagotchi" if "username" not in config['bettercap'] else config['bettercap']['username'],
"pwnagotchi" if "password" not in config['bettercap'] else config['bettercap']['password'])
Automata.__init__(self, config, view) Automata.__init__(self, config, view)
AsyncAdvertiser.__init__(self, config, view, keypair) AsyncAdvertiser.__init__(self, config, view, keypair)
AsyncTrainer.__init__(self, config) AsyncTrainer.__init__(self, config)
@ -362,7 +363,8 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
plugins.on('handshake', self, filename, ap_mac, sta_mac) plugins.on('handshake', self, filename, ap_mac, sta_mac)
else: else:
(ap, sta) = ap_and_station (ap, sta) = ap_and_station
self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap['hostname'] != '<hidden>' else ap_mac self._last_pwnd = ap['hostname'] if ap['hostname'] != '' and ap[
'hostname'] != '<hidden>' else ap_mac
logging.warning( logging.warning(
"!!! captured new handshake on channel %d, %d dBm: %s (%s) -> %s [%s (%s)] !!!", "!!! captured new handshake on channel %d, %d dBm: %s (%s) -> %s [%s (%s)] !!!",
ap['channel'], ap['rssi'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor']) ap['channel'], ap['rssi'], sta['mac'], sta['vendor'], ap['hostname'], ap['mac'], ap['vendor'])

View File

@ -156,6 +156,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.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
@ -198,11 +200,6 @@ ui.display.enabled = false
ui.display.rotation = 180 ui.display.rotation = 180
ui.display.type = "waveshare_4" ui.display.type = "waveshare_4"
bettercap.scheme = "http"
bettercap.hostname = "localhost"
bettercap.port = 8081
bettercap.username = "pwnagotchi"
bettercap.password = "pwnagotchi"
bettercap.handshakes = "/root/handshakes" bettercap.handshakes = "/root/handshakes"
bettercap.silence = [ bettercap.silence = [
"ble.device.new", "ble.device.new",

View File

@ -199,7 +199,7 @@ def list_plugins(args, config, pattern='*'):
available_not_installed = set(available.keys()) - set(installed.keys()) available_not_installed = set(available.keys()) - set(installed.keys())
max_len_list = available_and_installed if args.installed else available_not_installed max_len_list = available_and_installed if args.installed else available_not_installed
max_len = max(map(len, max_len_list)) if max_len_list else 0 max_len = max(map(len, max_len_list))
header = line.format(name='Plugin', width=max_len, version='Version', enabled='Active', status='Status') header = line.format(name='Plugin', width=max_len, version='Version', enabled='Active', status='Status')
line_length = max(max_len, len('Plugin')) + len(header) - len('Plugin') - 12 # lol line_length = max(max_len, len('Plugin')) + len(header) - len('Plugin') - 12 # lol

View File

@ -27,10 +27,9 @@ 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.pattern1 = re.compile(r'wifi error while hopping to channel')
self.pattern2 = re.compile(r'wifi error while hopping to channel') self.pattern2 = re.compile(r'Firmware has halted or crashed')
self.pattern3 = re.compile(r'Firmware has halted or crashed') self.pattern3 = re.compile(r'error 400: could not find interface wlan0mon')
self.pattern4 = re.compile(r'error 400: could not find interface wlan0mon')
self.isReloadingMon = False self.isReloadingMon = False
self.connection = None self.connection = None
self.LASTTRY = 0 self.LASTTRY = 0
@ -46,22 +45,10 @@ class FixServices(plugins.Plugin):
last_lines = self.get_last_lines('journalctl', ['-n10', '-k'], 10) last_lines = self.get_last_lines('journalctl', ['-n10', '-k'], 10)
try: try:
cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True) cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True)
logging.info("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output)) logging.debug("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output))
if ",UP," in str(cmd_output): if ",UP," in str(cmd_output):
logging.info("wlan0mon is up.") logging.info("wlan0mon is up.")
if len(self.pattern.findall(last_lines)) >= 3:
if hasattr(agent, 'view'):
display = agent.view()
display.set('status', 'Blind-Bug detected. Restarting.')
display.update(force=True)
logging.info('[Fix_Services] Blind-Bug detected. Restarting.')
try:
self._tryTurningItOffAndOnAgain(agent)
except Exception as err:
logging.warning("[Fix_Services turnOffAndOn] %s" % repr(err))
else:
logging.info("[Fix_Services] Logs look good!") logging.info("[Fix_Services] Logs look good!")
except Exception as err: except Exception as err:
@ -121,21 +108,8 @@ class FixServices(plugins.Plugin):
logging.debug("[Fix_Services]**** checking") logging.debug("[Fix_Services]**** checking")
# Look for pattern 1 # Look for pattern 1
if len(self.pattern.findall(last_lines)) >= 3: if len(self.pattern1.findall(other_last_lines)) >= 5:
logging.info("[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'):
display = agent.view()
display.set('status', 'Blind-Bug detected. Restarting.')
display.update(force=True)
logging.info('[Fix_Services] Blind-Bug detected. Restarting.')
try:
self._tryTurningItOffAndOnAgain(agent)
except Exception as err:
logging.warning("[Fix_Services] TTOAOA: %s" % repr(err))
# Look for pattern 2
elif len(self.pattern2.findall(other_last_lines)) >= 5:
logging.info("[Fix_Services]**** Should trigger a reload of the wlan0mon device:\n%s" % last_lines)
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view() display = agent.view()
display.set('status', 'Wifi channel stuck. Restarting recon.') display.set('status', 'Wifi channel stuck. Restarting recon.')
@ -157,8 +131,8 @@ class FixServices(plugins.Plugin):
except Exception as err: except Exception as err:
logging.error("[Fix_Services wifi.recon flip] %s" % repr(err)) logging.error("[Fix_Services wifi.recon flip] %s" % repr(err))
# Look for pattern 3 # Look for pattern 2
elif len(self.pattern3.findall(other_last_lines)) >= 1: elif len(self.pattern2.findall(other_last_lines)) >= 1:
logging.info("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.") logging.info("[Fix_Services] Firmware has halted or crashed. Restarting wlan0mon.")
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view() display = agent.view()
@ -167,12 +141,12 @@ class FixServices(plugins.Plugin):
try: try:
# Run the monstart command to restart wlan0mon # Run the monstart command to restart wlan0mon
cmd_output = subprocess.check_output("monstart", shell=True) cmd_output = subprocess.check_output("monstart", shell=True)
logging.info("[Fix_Services monstart]: %s" % repr(cmd_output)) logging.debug("[Fix_Services monstart]: %s" % repr(cmd_output))
except Exception as err: except Exception as err:
logging.error("[Fix_Services monstart]: %s" % repr(err)) logging.error("[Fix_Services monstart]: %s" % repr(err))
# Look for pattern 4 # Look for pattern 3
elif len(self.pattern4.findall(other_other_last_lines)) >= 3: elif len(self.pattern3.findall(other_other_last_lines)) >= 3:
logging.info("[Fix_Services] wlan0 is down!") logging.info("[Fix_Services] wlan0 is down!")
if hasattr(agent, 'view'): if hasattr(agent, 'view'):
display = agent.view() display = agent.view()
@ -181,7 +155,7 @@ class FixServices(plugins.Plugin):
try: try:
# Run the monstart command to restart wlan0mon # Run the monstart command to restart wlan0mon
cmd_output = subprocess.check_output("monstart", shell=True) cmd_output = subprocess.check_output("monstart", shell=True)
logging.info("[Fix_Services monstart]: %s" % repr(cmd_output)) logging.debug("[Fix_Services monstart]: %s" % repr(cmd_output))
except Exception as err: except Exception as err:
logging.error("[Fix_Services monstart]: %s" % repr(err)) logging.error("[Fix_Services monstart]: %s" % repr(err))
@ -237,7 +211,7 @@ class FixServices(plugins.Plugin):
# is it up? # is it up?
try: try:
cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True) cmd_output = subprocess.check_output("ip link show wlan0mon", shell=True)
logging.info("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output)) logging.debug("[Fix_Services ip link show wlan0mon]: %s" % repr(cmd_output))
if ",UP," in str(cmd_output): if ",UP," in str(cmd_output):
logging.info("wlan0mon is up. Skip reset?") logging.info("wlan0mon is up. Skip reset?")
# not reliable, so don't skip just yet # not reliable, so don't skip just yet
@ -309,11 +283,9 @@ class FixServices(plugins.Plugin):
# stop looping and get back to recon # stop looping and get back to recon
break break
else: else:
logging.info( logging.debug("[Fix_Services set wifi.interfaceface wlan0mon] failed? %s" % repr(result))
"[Fix_Services set wifi.interfaceface wlan0mon] failed? %s" % repr(result))
except Exception as err: except Exception as err:
logging.info( logging.debug("[Fix_Services set wifi.interface wlan0mon] except: %s" % repr(err))
"[Fix_Services set wifi.interface wlan0mon] except: %s" % repr(err))
except Exception as cerr: # except Exception as cerr: #
if not display: if not display:
print("failed loading wlan0mon attempt #%s: %s" % (tries, repr(cerr))) print("failed loading wlan0mon attempt #%s: %s" % (tries, repr(cerr)))
@ -362,7 +334,7 @@ class FixServices(plugins.Plugin):
"face": faces.HAPPY}) "face": faces.HAPPY})
else: else:
print("I can see again") print("I can see again")
logging.info("[Fix_Services] wifi.recon on") logging.debug("[Fix_Services] wifi.recon on")
self.LASTTRY = time.time() + 120 # 2-minute pause until next time. self.LASTTRY = time.time() + 120 # 2-minute pause until next time.
else: else:
logging.error("[Fix_Services] wifi.recon did not start up") logging.error("[Fix_Services] wifi.recon did not start up")
@ -378,7 +350,7 @@ class FixServices(plugins.Plugin):
try: try:
logging.info("[Fix_Services] unloaded") logging.info("[Fix_Services] unloaded")
except Exception as err: except Exception as err:
logging.info("[Fix_Services] unload err %s " % repr(err)) logging.error("[Fix_Services] unload err %s " % repr(err))
pass pass

View File

@ -20,6 +20,7 @@ class GPS(plugins.Plugin):
def __init__(self): def __init__(self):
self.running = False self.running = False
self.coordinates = None self.coordinates = None
self.options = dict()
def on_loaded(self): def on_loaded(self):
logging.info(f"gps plugin loaded for {self.options['device']}") logging.info(f"gps plugin loaded for {self.options['device']}")

View File

@ -117,7 +117,6 @@ class NetPos(plugins.Plugin):
except OSError as os_e: except OSError as os_e:
logging.error("NET-POS: %s", os_e) logging.error("NET-POS: %s", os_e)
def _get_netpos(self, agent): def _get_netpos(self, agent):
aps = agent.get_access_points() aps = agent.get_access_points()
netpos = dict() netpos = dict()

View File

@ -1,9 +1,10 @@
import sys
import pwnagotchi.plugins as plugins import pwnagotchi.plugins as plugins
import logging import logging
import os import os
import json import json
import re import re
import datetime
from flask import Response from flask import Response
from functools import lru_cache from functools import lru_cache
from dateutil.parser import parse from dateutil.parser import parse
@ -22,6 +23,7 @@ from dateutil.parser import parse
''' '''
class Webgpsmap(plugins.Plugin): class Webgpsmap(plugins.Plugin):
__author__ = 'https://github.com/xenDE and https://github.com/dadav' __author__ = 'https://github.com/xenDE and https://github.com/dadav'
__version__ = '1.4.0' __version__ = '1.4.0'
@ -103,7 +105,7 @@ class Webgpsmap(plugins.Plugin):
response_status = 200 response_status = 200
response_mimetype = "application/xhtml+xml" response_mimetype = "application/xhtml+xml"
response_header_contenttype = 'text/html' response_header_contenttype = 'text/html'
response_header_contentdisposition = 'attachment; filename=webgpsmap.html'; response_header_contentdisposition = 'attachment; filename=webgpsmap.html'
except Exception as error: except Exception as error:
logging.error(f"[webgpsmap] on_webhook offlinemap: error: {error}") logging.error(f"[webgpsmap] on_webhook offlinemap: error: {error}")
return return
@ -149,7 +151,6 @@ class Webgpsmap(plugins.Plugin):
def _get_pos_from_file(self, path): def _get_pos_from_file(self, path):
return PositionFile(path) return PositionFile(path)
def load_gps_from_dir(self, gpsdir, newest_only=False): def load_gps_from_dir(self, gpsdir, newest_only=False):
""" """
Parses the gps-data from disk Parses the gps-data from disk
@ -160,13 +161,9 @@ class Webgpsmap(plugins.Plugin):
logging.info(f"[webgpsmap] scanning {handshake_dir}") logging.info(f"[webgpsmap] scanning {handshake_dir}")
all_files = os.listdir(handshake_dir) all_files = os.listdir(handshake_dir)
#print(all_files) # print(all_files)
all_pcap_files = [os.path.join(handshake_dir, filename) all_pcap_files = [os.path.join(handshake_dir, filename) for filename in all_files if filename.endswith('.pcap')]
for filename in all_files
if filename.endswith('.pcap')
]
all_geo_or_gps_files = [] all_geo_or_gps_files = []
for filename_pcap in all_pcap_files: for filename_pcap in all_pcap_files:
filename_base = filename_pcap[:-5] # remove ".pcap" filename_base = filename_pcap[:-5] # remove ".pcap"
@ -300,7 +297,6 @@ class PositionFile:
return parsed_ssid.groups()[0] return parsed_ssid.groups()[0]
return None return None
def json(self): def json(self):
""" """
returns the parsed json returns the parsed json

View File

@ -52,10 +52,10 @@ def _transform_wigle_entry(gps_data, pcap_data, plugin_version):
""" """
dummy = StringIO() dummy = StringIO()
# write kismet header # write kismet header
dummy.write(f"WigleWifi-1.4,appRelease={plugin_version},model=pwnagotchi,release={__pwnagotchi_version__}," dummy.write(f"WigleWifi-1.6,appRelease={plugin_version},model=pwnagotchi,release={__pwnagotchi_version__},"
f"device={pwnagotchi.name()},display=kismet,board=RaspberryPi,brand=pwnagotchi\n") f"device={pwnagotchi.name()},display=kismet,board=RaspberryPi,brand=pwnagotchi,star=Sol,body=3,subBody=0\n")
dummy.write("MAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude," dummy.write(
"CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\n") "MAC,SSID,AuthMode,FirstSeen,Channel,RSSI,CurrentLatitude,CurrentLongitude,AltitudeMeters,AccuracyMeters,Type\n")
writer = csv.writer(dummy, delimiter=",", quoting=csv.QUOTE_NONE, escapechar="\\") writer = csv.writer(dummy, delimiter=",", quoting=csv.QUOTE_NONE, escapechar="\\")
writer.writerow([ writer.writerow([
@ -89,7 +89,7 @@ def _send_to_wigle(lines, api_key, donate=True, timeout=30):
headers = {'Authorization': f"Basic {api_key}", headers = {'Authorization': f"Basic {api_key}",
'Accept': 'application/json'} 'Accept': 'application/json'}
data = {'donate': 'on' if donate else 'false'} data = {'donate': 'on' if donate else 'false'}
payload = {'file': (pwnagotchi.name()+".csv", dummy), 'type': 'multipart/form-data'} payload = {'file': (pwnagotchi.name() + ".csv", dummy, 'multipart/form-data', {'Expires': '0'})}
try: try:
res = requests.post('https://api.wigle.net/api/v2/file/upload', res = requests.post('https://api.wigle.net/api/v2/file/upload',
data=data, data=data,
@ -104,10 +104,10 @@ def _send_to_wigle(lines, api_key, donate=True, timeout=30):
class Wigle(plugins.Plugin): class Wigle(plugins.Plugin):
__author__ = 'Dadav and fixed by Jayofelony' __author__ = "Dadav and updated by Jayofelony"
__version__ = '3.0.0' __version__ = "3.0.1"
__license__ = 'GPL3' __license__ = "GPL3"
__description__ = 'This plugin automatically uploads collected wifis to wigle.net' __description__ = "This plugin automatically uploads collected WiFi to wigle.net"
def __init__(self): def __init__(self):
self.ready = False self.ready = False
@ -121,17 +121,16 @@ class Wigle(plugins.Plugin):
logging.debug("WIGLE: api_key isn't set. Can't upload to wigle.net") logging.debug("WIGLE: api_key isn't set. Can't upload to wigle.net")
return return
if not 'donate' in self.options: if 'donate' not in self.options:
self.options['donate'] = True self.options['donate'] = False
self.ready = True self.ready = True
logging.info("WIGLE: ready") logging.info("WIGLE: ready")
def on_internet_available(self, agent): def on_internet_available(self, agent):
""" """
Called in manual mode when there's internet connectivity Called when there's internet connectivity
""" """
global pcap_filename
if not self.ready or self.lock.locked(): if not self.ready or self.lock.locked():
return return

View File

@ -12,6 +12,7 @@ from . import config
from . import LCD_1in44 from . import LCD_1in44
from PIL import ImageOps from PIL import ImageOps
class EPD(object): class EPD(object):
def __init__(self): def __init__(self):
self.width = 128 self.width = 128
@ -24,9 +25,8 @@ class EPD(object):
pass pass
def clear(self): def clear(self):
#self.LCD.LCD_Clear() self.LCD.LCD_Clear()
pass
def display(self, image): def display(self, image):
rgb_im = ImageOps.colorize(image.convert("L"), black ="green", white ="black") rgb_im = ImageOps.colorize(image.convert("L"), black="green", white="black")
self.LCD.LCD_ShowImage(rgb_im, 0, 0) self.LCD.LCD_ShowImage(rgb_im, 0, 0)

View File

@ -38,7 +38,8 @@ class Waveshare13in3k(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare1in02(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -39,7 +39,7 @@ class Waveshare154(DisplayImpl):
def render(self, canvas): def render(self, canvas):
buf = self._display.getbuffer(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None) self._display.display(buf)
def clear(self): def clear(self):
# pass # pass

View File

@ -39,7 +39,7 @@ class Waveshare154V2(DisplayImpl):
def render(self, canvas): def render(self, canvas):
buf = self._display.getbuffer(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None) self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare1in54c(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare1in64g(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -7,7 +7,7 @@ from PIL import Image
class Waveshare213bV4(DisplayImpl): class Waveshare213bV4(DisplayImpl):
def __init__(self, config): def __init__(self, config):
super(Waveshare213bV4, self).__init__(config, 'waveshare213inb_v4') super(Waveshare213bV4, self).__init__(config, 'waveshare2in13b_v4')
def layout(self): def layout(self):
if self.config['color'] == 'black': if self.config['color'] == 'black':

View File

@ -38,7 +38,8 @@ class Waveshare2in36g(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -34,11 +34,12 @@ class Waveshare2in66(DisplayImpl):
logging.info("initializing waveshare 2.66 inch lcd display") logging.info("initializing waveshare 2.66 inch lcd display")
from pwnagotchi.ui.hw.libs.waveshare.v2in66.epd2in66 import EPD from pwnagotchi.ui.hw.libs.waveshare.v2in66.epd2in66 import EPD
self._display = EPD() self._display = EPD()
self._display.init(0) self._display.init(1)
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare2in66g(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -39,7 +39,7 @@ class Waveshare27b(DisplayImpl):
def render(self, canvas): def render(self, canvas):
buf = self._display.getbuffer(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf) self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear(0xff) self._display.Clear(0xff)

View File

@ -39,7 +39,7 @@ class Waveshare27bV2(DisplayImpl):
def render(self, canvas): def render(self, canvas):
buf = self._display.getbuffer(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf) self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear(0xff) self._display.Clear(0xff)

View File

@ -35,12 +35,12 @@ class Waveshare29bV3(DisplayImpl):
from pwnagotchi.ui.hw.libs.waveshare.v2in9b_v3.epd2in9b_V3 import EPD from pwnagotchi.ui.hw.libs.waveshare.v2in9b_v3.epd2in9b_V3 import EPD
self._display = EPD() self._display = EPD()
self._display.init() self._display.init()
self._display.Clear(0xFF) self._display.Clear()
self._display.init() self._display.init()
def render(self, canvas): def render(self, canvas):
buf = self._display.getbuffer(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf) self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear(0xFF) self._display.Clear()

View File

@ -35,12 +35,12 @@ class Waveshare29bV4(DisplayImpl):
from pwnagotchi.ui.hw.libs.waveshare.v2in9b_v4.epd2in9b_V4 import EPD from pwnagotchi.ui.hw.libs.waveshare.v2in9b_v4.epd2in9b_V4 import EPD
self._display = EPD() self._display = EPD()
self._display.init() self._display.init()
self._display.Clear(0xFF) self._display.Clear()
self._display.init() self._display.init()
def render(self, canvas): def render(self, canvas):
buf = self._display.getbuffer(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf) self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear(0xFF) self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare2in9bc(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare2in9d(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare3in0g(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -9,36 +9,39 @@ class Waveshare3in52(DisplayImpl):
super(Waveshare3in52, self).__init__(config, 'waveshare3in52') super(Waveshare3in52, self).__init__(config, 'waveshare3in52')
def layout(self): def layout(self):
fonts.setup(10, 8, 10, 18, 25, 9) fonts.setup(16, 14, 16, 100, 31, 15)
self._layout['width'] = 240 self._layout['width'] = 360
self._layout['height'] = 360 self._layout['height'] = 240
self._layout['face'] = (0, 43) self._layout['face'] = (0, 40)
self._layout['name'] = (0, 14) self._layout['name'] = (0, 0)
self._layout['channel'] = (0, 0) self._layout['channel'] = (300, 0)
self._layout['aps'] = (0, 71) self._layout['aps'] = (0, 220)
self._layout['uptime'] = (0, 25) self._layout['uptime'] = (120, 0)
self._layout['line1'] = [0, 12, 240, 12] self._layout['line1'] = [0, 24, 360, 24]
self._layout['line2'] = [0, 116, 240, 116] self._layout['line2'] = [0, 220, 360, 220]
self._layout['friend_face'] = (12, 88) self._layout['friend_face'] = (0, 195)
self._layout['friend_name'] = (1, 103) self._layout['friend_name'] = (0, 185)
self._layout['shakes'] = (26, 117) self._layout['shakes'] = (100, 220)
self._layout['mode'] = (0, 117) self._layout['mode'] = (0,200)
self._layout['status'] = { self._layout['status'] = {
'pos': (65, 26), 'pos': (3, 170),
'font': fonts.status_font(fonts.Small), 'font': fonts.status_font(fonts.Small),
'max': 12 'max': 100
} }
return self._layout return self._layout
def initialize(self): def initialize(self):
logging.info("initializing waveshare 3.52 inch lcd display") logging.info("initializing waveshare 3.52 inch display")
from pwnagotchi.ui.hw.libs.waveshare.v3in52.epd3in52 import EPD from pwnagotchi.ui.hw.libs.waveshare.v3in52.epd3in52 import EPD
self._display = EPD() self._display = EPD()
self._display.init() self._display.init()
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
self._display.refresh()
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -36,9 +36,11 @@ class Waveshare3in7(DisplayImpl):
self._display = EPD() self._display = EPD()
self._display.init(0) self._display.init(0)
self._display.Clear(0) self._display.Clear(0)
self._display.init(1) # 1Gray mode
def render(self, canvas): def render(self, canvas):
self._display.display_4Gray(canvas) buf = self._display.getbuffer(canvas)
self._display.display_1Gray(buf)
def clear(self): def clear(self):
self._display.Clear(0) self._display.Clear(0)

View File

@ -38,7 +38,8 @@ class Waveshare4in01f(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare4in2(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare4in26(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare4in2V2(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare4in2bV2(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare4in2bc(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare4in37g(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare5in65f(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare5in83(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare5in83V2(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare5in83bV2(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare5in83bc(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare7in3f(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare7in3g(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare7in5(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare7in5HD(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -51,7 +51,8 @@ class Waveshare7in5V2(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare7in5bHD(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare7in5bV2(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -38,7 +38,8 @@ class Waveshare7in5bc(DisplayImpl):
self._display.Clear() self._display.Clear()
def render(self, canvas): def render(self, canvas):
self._display.display(canvas) buf = self._display.getbuffer(canvas)
self._display.display(buf, None)
def clear(self): def clear(self):
self._display.Clear() self._display.Clear()

View File

@ -153,8 +153,7 @@ class View(object):
self.set('uptime', last_session.duration) self.set('uptime', last_session.duration)
self.set('channel', '-') self.set('channel', '-')
self.set('aps', "%d" % last_session.associated) self.set('aps', "%d" % last_session.associated)
self.set('shakes', '%d (%s)' % (last_session.handshakes, \ self.set('shakes', '%d (%s)' % (last_session.handshakes, utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
utils.total_unique_handshakes(self._config['bettercap']['handshakes'])))
self.set_closest_peer(last_session.last_peer, last_session.peers) self.set_closest_peer(last_session.last_peer, last_session.peers)
self.update() self.update()

View File

@ -30,13 +30,6 @@ def install_file(source_filename, dest_filename):
def install_system_files(): def install_system_files():
f = open("apt_packages.txt", "r")
for x in f:
if x == "":
continue
os.system(f"apt-get install {x}")
f.close()
setup_path = os.path.dirname(__file__) setup_path = os.path.dirname(__file__)
data_path = os.path.join(setup_path, "builder/data") data_path = os.path.join(setup_path, "builder/data")