New Web Interface

Completly reworked design!
I also improved the way you add/clone SSIDs to the list
This commit is contained in:
Stefan Kremser
2017-07-20 15:10:57 +02:00
parent 6f2c99aa42
commit d842c76a4f
23 changed files with 507 additions and 520 deletions

View File

@@ -119,9 +119,6 @@ String APScan::getAPEncryption(int num) {
String APScan::getAPMac(int num) {
return aps._get(num).toString();
}
bool APScan::getAPSelected(int num) {
return selected[num];
}
bool APScan::isHidden(int num) {
return hidden[num];
}
@@ -185,7 +182,7 @@ void APScan::sendResults() {
json += "\"r\":" + (String)getAPRSSI(i) + ",";
json += "\"e\":" + (String)encryption[i] + ",";
//json += "\"v\":\""+getAPVendor(i)+"\",";
json += "\"se\":" + (String)getAPSelected(i);
json += "\"se\":" + (String)isSelected(i);
json += "}";
if ((i != results - 1) && (i != maxAPScanResults - 1)) json += ",";
@@ -218,7 +215,7 @@ String APScan::getResultsJSON() {
json += "\"r\":" + (String)getAPRSSI(i) + ",";
json += "\"e\":" + (String)encryption[i] + ",";
//json += "\"v\":\""+getAPVendor(i)+"\",";
json += "\"se\":" + (String)getAPSelected(i);
json += "\"se\":" + (String)isSelected(i);
json += "}";
if ((i != results - 1) && (i != maxAPScanResults - 1)) json += ",";
}

View File

@@ -32,7 +32,6 @@ class APScan {
String getAPEncryption(int num);
//String getAPVendor(int num);
String getAPMac(int num);
bool getAPSelected(int num);
bool isHidden(int num);
int getAPRSSI(int num);
int getAPChannel(int num);

View File

@@ -211,11 +211,7 @@ void Attack::run() {
prevTime[1] = 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);
buildBeacon(beaconAdrs._get(a), ssidList.get(a), channels[a], ssidList.isEncrypted(a));
if (send()) packetsCounter[1]++;
}
@@ -376,7 +372,11 @@ size_t Attack::getSize(){
json = "\"ssid\":[";
jsonSize += json.length();
for (int i = 0; i < ssidList.len; i++) {
json = "\"" + ssidList.get(i) + "\"";
json = "[";
json += "\"" + ssidList.get(i) + "\",";
json += String( ssidList.isEncrypted(i) ) + "";
Serial.print(ssidList.isEncrypted(i));
json += "]";
if (i != ssidList.len - 1) json += ",";
jsonSize += json.length();
}
@@ -437,7 +437,10 @@ void Attack::sendResults(){
json = "\"ssid\":[";
sendToBuffer(json);
for (int i = 0; i < ssidList.len; i++) {
json = "\"" + ssidList.get(i) + "\"";
json = "[";
json += "\"" + ssidList.get(i) + "\",";
json += (String)ssidList.isEncrypted(i) + "";
json += "]";
if (i != ssidList.len - 1) json += ",";
sendToBuffer(json);
}

View File

@@ -15,6 +15,7 @@ void SSIDList::load() {
char _nextChar = EEPROM.read(listAdr + (i * SSIDLength) + h);
names[i][h] = _nextChar;
}
encrypted[i] = EEPROM.read(encAdr + i);
}
}
@@ -22,17 +23,18 @@ void SSIDList::clear() {
len = 0;
}
void SSIDList::add(String name) {
void SSIDList::add(String name, bool enc) {
if (len < SSIDListLength) {
for (int i = 0; i < SSIDLength; i++) {
if (i < name.length()) names[len][i] = name[i];
else names[len][i] = 0x00;
}
encrypted[len] = enc;
len++;
}
}
void SSIDList::addClone(String name, int num) {
void SSIDList::addClone(String name, int num, bool enc) {
int _restSSIDLen = SSIDLength - name.length();
String _apName;
@@ -52,14 +54,7 @@ void SSIDList::addClone(String name, int num) {
for (int d = 0; d < _restSSIDLen - 2; d++) _apName += " ";
_apName += (String)c;//e.g. "SAMPLEAP 78"
}
add(_apName);
}
}
void SSIDList::edit(int num, String name) {
for (int i = 0; i < SSIDLength; i++) {
if (i < name.length()) names[num][i] = name[i];
else names[num][i] = 0x00;
add(_apName, enc);
}
}
@@ -71,12 +66,17 @@ String SSIDList::get(int num) {
return _name;
}
bool SSIDList::isEncrypted(int num){
return encrypted[num];
}
void SSIDList::remove(int num) {
if (num >= 0 && num < len) {
for (int i = num; i < len - 1; i++) {
for (int h = 0; h < SSIDLength; h++) {
names[i][h] = names[i + 1][h];
}
encrypted[i] = encrypted[i + 1];
}
len--;
}
@@ -89,6 +89,7 @@ void SSIDList::save() {
for (int h = 0; h < SSIDLength; h++) {
EEPROM.write(listAdr + (i * SSIDLength) + h, names[i][h]);
}
EEPROM.write(encAdr + i, encrypted[i]);
}
EEPROM.commit();
if (debug) Serial.println("done");
@@ -99,7 +100,7 @@ void SSIDList::_random() {
for (int i = len; i < SSIDListLength; i++) {
_rName = "";
for (int h = 0; h < SSIDLength; h++) _rName += letters[random(0, sizeof(letters))];
add(_rName);
add(_rName, random(2) > 0.5 );
}
}

View File

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

View File

@@ -80,7 +80,6 @@ void Settings::load() {
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);
@@ -110,7 +109,6 @@ void Settings::reset() {
attackTimeout = 5 * 60;
attackPacketRate = 10;
clientScanTime = 15;
attackEncrypted = false;
useLed = true;
channelHop = false;
multiAPs = false;
@@ -150,7 +148,6 @@ void Settings::save() {
EEPROM.write(attackPacketRateAdr, attackPacketRate);
EEPROM.write(clientScanTimeAdr, clientScanTime);
EEPROM.write(attackEncryptedAdr, attackEncrypted);
EEPROM.write(useLedAdr, useLed);
EEPROM.write(channelHopAdr, channelHop);
EEPROM.write(multiAPsAdr, multiAPs);
@@ -183,7 +180,6 @@ void Settings::info() {
Serial.println("attack timeout: " + (String)attackTimeout);
Serial.println("attack packet rate: " + (String)attackPacketRate);
Serial.println("client scan time: " + (String)clientScanTime);
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);
@@ -208,7 +204,6 @@ size_t Settings::getSize() {
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 + ",";
@@ -237,7 +232,6 @@ void Settings::send() {
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 + ",";

View File

@@ -30,7 +30,7 @@ extern NameList nameList;
#define attackTimeoutAdr 1091
#define attackPacketRateAdr 1093
#define clientScanTimeAdr 1094
#define attackEncryptedAdr 1095
//#define attackEncryptedAdr 1095 <-- address is now free for another setting
#define ssidHiddenAdr 1096
#define apScanHiddenAdr 1097
#define apChannelAdr 1098
@@ -68,7 +68,6 @@ class Settings
unsigned int attackTimeout;
int attackPacketRate;
int clientScanTime;
bool attackEncrypted;
bool useLed;
bool channelHop;
bool multiAPs;

File diff suppressed because one or more lines are too long

View File

@@ -107,7 +107,7 @@ void drawInterface() {
else if (i == 2) display.drawString(3, i * fontSize, "-> " + attackMode + " attack");
else if (i - 3 < apScan.results) {
display.drawString(3, _lrow * fontSize, apScan.getAPName(i - 3));
if (apScan.getAPSelected(i - 3)) {
if (apScan.isSelected(i - 3)) {
display.drawVerticalLine(1, _lrow * fontSize, fontSize);
display.drawVerticalLine(2, _lrow * fontSize, fontSize);
}
@@ -335,18 +335,32 @@ void startAttack() {
}
void addSSID() {
if(server.hasArg("ssid") && server.hasArg("num")){
if(server.hasArg("ssid") && server.hasArg("num") && server.hasArg("enc")){
int num = server.arg("num").toInt();
if(num > 0){
ssidList.addClone(server.arg("ssid"),num);
ssidList.addClone(server.arg("ssid"),num, server.arg("enc") == "true");
}else{
ssidList.add(server.arg("ssid"));
ssidList.add(server.arg("ssid"), server.arg("enc") == "true" || server.arg("enc") == "1");
}
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}else server.send( 200, "text/json", "false");
}
void cloneSelected(){
if(apScan.selectedSum > 0){
int clonesPerSSID = 48/apScan.selectedSum;
ssidList.clear();
for(int i=0;i<apScan.results;i++){
if(apScan.isSelected(i)){
ssidList.addClone(apScan.getAPName(i),clonesPerSSID, apScan.getAPEncryption(i) != "none");
}
}
}
attack.ssidChange = true;
server.send( 200, "text/json", "true");
}
void deleteSSID() {
ssidList.remove(server.arg("num").toInt());
attack.ssidChange = true;
@@ -422,10 +436,6 @@ void saveSettings() {
if (server.arg("randMacAp") == "false") settings.isMacAPRand = false;
else settings.isMacAPRand = true;
}
if (server.hasArg("ssidEnc")) {
if (server.arg("ssidEnc") == "false") settings.attackEncrypted = false;
else settings.attackEncrypted = true;
}
if (server.hasArg("scanTime")) settings.clientScanTime = server.arg("scanTime").toInt();
if (server.hasArg("timeout")) settings.attackTimeout = server.arg("timeout").toInt();
if (server.hasArg("deauthReason")) settings.deauthReason = server.arg("deauthReason").toInt();
@@ -541,6 +551,7 @@ void setup() {
server.on("/clearNameList.json", clearNameList);
server.on("/editNameList.json", editClientName);
server.on("/addSSID.json", addSSID);
server.on("/cloneSelected.json", cloneSelected);
server.on("/deleteSSID.json", deleteSSID);
server.on("/randomSSID.json", randomSSID);
server.on("/clearSSID.json", clearSSID);

View File

@@ -8,6 +8,12 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="html/style.css">
<script src="jquery-3.2.1.min.js"></script>
<style>
textarea{
width: 96%;
height: 350px;
}
</style>
</head>
<body>
@@ -22,8 +28,8 @@
<div class="col-12">
<h1 class="header">Text to Byte Array Converter</h1>
<p>
Please use <a href="https://htmlcompressor.com/compressor/" target="_blank">HTMLCompressor</a> first to get your HTML, CSS and JS minified.<br />
Every saved byte can improve the stability of the ESP8266's webserver!<br />
Please use <a href="https://htmlcompressor.com/compressor/" target="_blank">HTMLCompressor</a> (or something similar) first to get your HTML, CSS and JS minified.<br />
Every saved byte can improve the stability of the ESP8266's webserver!
</p>
</div>
</div>
@@ -46,12 +52,6 @@
</div>
</div>
<div id="copyright">
version 1.5<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
</div>
</div>
<script>

View File

@@ -2,12 +2,13 @@
<html>
<head>
<meta charset="utf-8">
<title>ESP8266 Deauther</title>
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="js/functions.js"></script>
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
@@ -17,41 +18,43 @@
<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">
<div id="error" class="hide"></div>
<h1 class="header">Scan for Wi-Fi access points</h1>
<a id="scanInfo">scanning...</a>
<a id="scanInfo" class="left labelFix">scanning...</a>
<button onclick="scan()" id="apScanStart" class="right button-primary">scan</button>
<p>
Networks found:
<span id="networksFound">0</span>
<p class="clear">
Networks found: <span id="networksFound">0</span><br />
MAC: <span id="apMAC"></span><br />
<br />
MAC: <span id="apMAC"></span>
<span id="selectAllBtns" style="visibility:'hidden'">
<br />
<button class="marginNull button-primary left" onclick="select(-2)">deselect all</button>
<button class="marginNull button-primary right" onclick="select(-1)">select all</button>
</span>
</p>
<br />
</span>
</p>
<table></table>
<p class="small">
<span class="warn">INFO: </span><span class="bold">You may have to reload the site to see the results.</span>
<span class="red">INFO: </span><span class="bold">You may have to reload the site to see the results.</span>
<br />
<br />
WPA* = WPA/WPA2 auto mode
</p>
<div id="copyright">
version 1.5<br />
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
<script src="js/apscan.js"></script>

View File

@@ -2,12 +2,13 @@
<html>
<head>
<meta charset="utf-8">
<title>ESP8266 Deauther</title>
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="js/functions.js"></script>
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
@@ -17,35 +18,32 @@
<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">
<div id="error" class="hide"></div>
<h1 class="header">Attacks</h1>
<p class="bold">Selected AP(s):</p>
<ul id="selectedAPs">
</ul>
<br />
<p class="bold">Selected AP(s): <button onclick='cloneSelected()'>clone</button></p>
<ul id="selectedAPs"></ul>
<p class="bold">Selected Station(s):</p>
<ul id="selectedClients">
</ul>
<ul id="selectedClients"></ul>
<br />
<table></table>
<table>
</table>
<label class="left">
<input type="number" id="randomIntrvl" value="5" min="1" max="65000"/>s
</label>
<br />
<label class="left"><input type="number" id="randomIntrvl" value="5" min="1" max="65000"/>s</label>
<button class="right" id="randomBtn" onclick="random()">Enable Random</button>
<p class="clear">
<br />
<span class="warn">INFO: </span><span class="bold">You may loose connection when starting the attack.</span><br />
<span class="red">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.
</p>
@@ -58,7 +56,7 @@
<label for="ssid">SSID</label>
</div>
<div class="col-6">
<input type="text" id="ssid" minlength="1" maxlength="32" placeholder="SSID">
<input type="text" id="ssid" minlength="1" maxlength="32" placeholder="SSID" />
</div>
</div>
@@ -67,7 +65,16 @@
<label for="num">Number of Clones</label>
</div>
<div class="col-6">
<input type="number" id="num" min="0" max="48" value="0">
<input type="number" id="num" min="0" max="48" value="0" />
</div>
</div>
<div class="row">
<div class="col-6">
<label for="enc">Encrypted</label>
</div>
<div class="col-6">
<input type="checkbox" id="enc" name="enc" />
</div>
</div>
@@ -76,37 +83,38 @@
<button class="button-primary col-4" onclick="addSSID()">add</button>
<br class="clear" />
<hr />
<p class="left">SSIDs: <span id="ssidCounter">0/48</span>
<p class="left">SSIDs: <span id="ssidCounter">0/48</span></p>
<div class="right">
<button class="button-warn" onclick="clearSSID()">clear</button>
<button class="red" onclick="clearSSID()">clear</button>
<button onclick="randomSSID()">random</button>
</div>
</p>
<br />
<table></table>
<br />
<button class="marginNull button-warn" onclick="resetSSID()">reset</button>
<button class="marginNull red" onclick="resetSSID()">reset</button>
<button class="marginNull button-primary right" onclick="saveSSID()">save</button>
<p class="small" id="saved">saved</p>
<p>
<br />
<span class="bold">Deauth [deauthentication attack]:</span><br />
Sends deauthentication and dissociation frames to the selected station(s) and access point(s).<br />
Sends constantly deauthentication and disassociation 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 />
<span class="bold">Beacon [beacon flooding]:</span><br />
Broadcasts constantly beacon frames to advertise all 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.
<span class="bold">Probe-Request [probe request flooding]:</span><br />
Broadcasts constantly probe request frames with all SSIDs in the list below.
</p>
<div id="copyright">
version 1.5<br />
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
<script src="js/attack.js"></script>

View File

@@ -2,11 +2,13 @@
<html>
<head>
<meta charset="utf-8">
<title>ESP8266 Deauther</title>
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
@@ -16,18 +18,16 @@
<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>
<p class="centered bold"><br />Page not found &macr;\_(ツ)_/&macr;</p>
<div id="copyright">
version 1.5<br />
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>

View File

@@ -2,38 +2,43 @@
<html>
<head>
<meta charset="utf-8">
<title>ESP8266 Deauther</title>
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="js/functions.js"></script>
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</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 meant for testing common vulnerabilities in the 802.11 standard only.<br />
It can disrupt unprotected Wi-Fi connections.<br/>
Please check the laws in your country before using it.<br />
<p class="centered bold">
This software is meant for testing common vulnerabilities in the 802.11 standard.<br />
Please check the laws for 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 />
You are resposible for everything you do with this software.<br />
The device will log every attack against any network or device.<br />
<br />
Referring to this project as "jammer" is prohibited! Name the project by its correct name.
Please do not call this project a "jammer", it does not jam any frequencies!
<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 id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
</div>

View File

@@ -2,11 +2,13 @@
<html>
<head>
<meta charset="utf-8">
<title>ESP8266 Deauther</title>
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
@@ -16,58 +18,55 @@
<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 />
<br />
This project is licensed under the MIT License. See the <a href="license">license file</a> for details.
<br />
This project is licensed under the MIT License. See the <a href="license">license file</a> for details.<br />
The source code is available on <a href="https://github.com/spacehuhn/esp8266_deauther" target="_blank">GitHub</a>.<br />
<br />
Use it only for testing or educational purposes on your own devices!<br />
Use it only for testing or educational purposes against your own devices!<br />
<br />
<span class="bold">
Referring to this project as "jammer" is prohibited! Name the project by its correct name.<br />
</span>
<span class="bold">Please do not call this project a "jammer", it does not jam any frequencies!</span>
</p>
<h2>Contributors</h2>
<p>
<a href="https://github.com/andrbmgi" target="_blank">@andrbmgi</a>
<a href="https://github.com/N0vaPixel" target="_blank">@N0vaPixel</a> (Aur&eacute;lien Hernandez)<br />
<a href="https://github.com/SaltyViper" target="_blank">@SaltyViper</a><br />
<a href="https://github.com/tobozo" target="_blank">@tobozo</a><br />
<a href="https://github.com/andrbmgi" target="_blank">@andrbmgi</a><br />
<a href="https://github.com/dalmirdasilva" target="_blank">@dalmirdasilva</a> (Dalmir da Silva)<br />
<a href="https://github.com/ericktedeschi" target="_blank">@ericktedeschi</a> (Erick Belluci Tedeschi)<br />
<a href="https://github.com/SamuelKlit" target="_blank">@SamuelKlit</a> (Samuel KS)<br />
<a href="https://github.com/schinfo" target="_blank">@schinfo</a> (Helmut)<br />
<a href="https://github.com/ajnavarro" target="_blank">@ajnavarro</a> (Antonio Navarro Perez)<br />
<br />
<a href="https://github.com/N0vaPixel" target="_blank">@N0vaPixel</a> (Aur&eacute;lien Hernandez)
Also special thanks to <a href="https://github.com/deantonious" target="_blank">@deantonious</a> for the help with the webdesign!<br />
<br />
<a href="https://github.com/tobozo" target="_blank">@tobozo</a>
<br />
<a href="https://github.com/SaltyViper" target="_blank">@SaltyViper</a>
<br />
<a href="https://github.com/ajnavarro" target="_blank">@ajnavarro</a> (Antonio Navarro Perez)
<br />
<a href="https://github.com/schinfo" target="_blank">@schinfo</a> (Helmut)
<br />
<a href="https://github.com/SamuelKlit" target="_blank">@SamuelKlit</a> (Samuel KS)
For more information go to <a href="https://github.com/spacehuhn/esp8266_deauther/graphs/contributors">contributors</a> on this projects GitHub page.
</p>
<p>
For more information go to <a href="https://github.com/spacehuhn/esp8266_deauther/graphs/contributors">contributors</a> on the GitHub page.
</p>
<br />
<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 />
<a href="https://github.com/ThisIsDallas/Simple-Grid">SIMPLE GRID</a> - (C) ZACH COLE 2016<br />
<br />
The MAC address list is based on Wireshark manufacturer database.<br />
The MAC address vendor list is based on the 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.5<br />
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>

View File

@@ -18,11 +18,15 @@ function compare(a, b) {
}
function getEncryption(num) {
/*
if (num == 8) return "WPA*";
else if (num == 4) return "WPA2";
else if (num == 2) return "WPA";
else if (num == 7) return "none";
else if (num == 5) return "WEP";
*/
if (num == 7) return " ";
else return "&#128274;";
}
function getResults() {
@@ -38,7 +42,7 @@ function getResults() {
var tr = '';
if (res.aps.length > 0) {
tr += '<tr><th>Ch</th><th>SSID</th><th>RSSI</th><th>Encrypt.</th><th>Select</th></tr>';
tr += '<tr><th>Ch</th><th>SSID</th><th> </th><th>RSSI</th><th>Select</th></tr>';
}
for (var i = 0; i < res.aps.length; i++) {
@@ -47,14 +51,20 @@ function getResults() {
else tr += '<tr>';
tr += '<td>' + res.aps[i].c + '</td>';
tr += '<td>' + res.aps[i].ss + '</td>';
tr += '<td>' + res.aps[i].r + ' <meter value="' + res.aps[i].r + '" max="-30" min="-100" low="-80" high="-60" optimum="-50"></meter></td>';
tr += '<td>' + getEncryption(res.aps[i].e) + '</td>';
//tr += '<td>' + res.aps[i].r + ' <meter value="' + res.aps[i].r + '" max="-30" min="-100" low="-80" high="-60" optimum="-50"></meter></td>';
var _width = res.aps[i].r + 130;
var _color;
if(res.aps[i].r < -80) _color = "meter_red";
else if(res.aps[i].r < -60) _color = "meter_orange";
else _color = "meter_green";
tr += '<td><div class="meter_background"> <div class="meter_forground '+_color+'" style="width: '+_width+'%;"><div class="meter_value">' + res.aps[i].r + '</div></div> </div></td>';
if (res.aps[i].se) {
tr += '<td><button class="marginNull selectedBtn" onclick="select(' + res.aps[i].i + ')">deselect</button></td>';
tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">deselect</button></td>';
apMAC.innerHTML = res.aps[i].m;
}
else tr += '<td><button class="marginNull" onclick="select(' + res.aps[i].i + ')">select</button></td>';
else tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">select</button></td>';
tr += '</tr>';
}
table.innerHTML = tr;

View File

@@ -6,6 +6,7 @@ var saved = getE("saved");
var ssidCounter = getE("ssidCounter");
var ssid = getE("ssid");
var num = getE("num");
var enc = getE("enc");
var randomIntrvl = getE("randomIntrvl");
var randomBtn = getE("randomBtn");
var resultInterval;
@@ -17,7 +18,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] + " <button onclick='cloneSSID(\""+res.aps[i]+"\")'>clone</button></li>";
for (var i = 0; i < res.aps.length; i++) aps += "<li>" + res.aps[i] + "</li>";
for (var i = 0; i < res.clients.length; i++) clients += "<li>" + res.clients[i] + "</li>";
selectedAPs.innerHTML = aps;
@@ -31,10 +32,10 @@ function getResults() {
else tr += "<tr>";
tr += "<td>" + res.attacks[i].name + "</td>";
if (res.attacks[i].status == "ready") tr += "<td class='green' id='status"+i+"'>" + res.attacks[i].status + "</td>";
else tr += "<td class='red' id='status"+i+"'>" + 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>";
if (res.attacks[i].status == "ready") tr += "<td class='green status' id='status"+i+"'>" + res.attacks[i].status + "</td>";
else tr += "<td class='red status' id='status"+i+"'>" + res.attacks[i].status + "</td>";
if (res.attacks[i].running) tr += "<td><button class='select' onclick='startStop(" + i + ")'>stop</button></td>";
else tr += "<td><button class='select' onclick='startStop(" + i + ")'>start</button></td>";
tr += "</tr>";
}
@@ -44,11 +45,13 @@ function getResults() {
data = res.ssid;
ssidCounter.innerHTML = data.length + "/48";
var tr = "<tr><th>Name</th><th>X</th></tr>";
var tr = "<tr><th>Name</th><th></th><th>Del.</th></tr>";
for (var i = 0; i < data.length; i++) {
tr += "<tr>";
tr += "<td>" + data[i] + "</td>";
tr += '<td><button class="marginNull button-warn" onclick="deleteSSID(' + i + ')">x</button></td>';
tr += "<td>" + data[i][0] + "</td>";
if(data[i][1] == 1) tr += "<td>&#128274;</td>";
else tr += "<td></td>";
tr += '<td><button class="button-warn" onclick="deleteSSID(' + i + ')">x</button></td>';
tr += "</tr>";
}
ssidList.innerHTML = tr;
@@ -75,15 +78,13 @@ function addSSID() {
if(data.length >= 64) showMessage("SSID list full :(", 2500);
else{
saved.innerHTML = "";
getResponse("addSSID.json?ssid=" + _ssidName + "&num="+num.value, getResults);
getResponse("addSSID.json?ssid=" + _ssidName + "&num="+num.value + "&enc=" + enc.checked, getResults);
}
}
}
function cloneSSID(_ssidName) {
ssid.value = _ssidName;
if(data.length > 0) num.value = 48 - data.length;
else num.value = 48;
function cloneSelected() {
getResponse("cloneSelected.json", getResults);
}
function deleteSSID(num) {

View File

@@ -1,16 +1,23 @@
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 showMessage(msg, closeAfter){
var errorE = getE("error");
errorE.innerHTML = msg;
errorE.classList.remove('hide');
errorE.classList.add('show');
if(closeAfter !== undefined){
setTimeout(function(){
errorE.innerHTML = "";
errorE.classList.remove('show');
errorE.classList.add('hide');
},closeAfter);
}
}
function getResponse(adr, callback, timeoutCallback, timeout, method){
if(timeoutCallback === undefined) {
timeoutCallback = function(){
@@ -23,7 +30,6 @@ function getResponse(adr, callback, timeoutCallback, timeout, method){
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4){
if(xmlhttp.status == 200){
showMessage("");
callback(xmlhttp.responseText);
}
else timeoutCallback();

View File

@@ -11,7 +11,6 @@ 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');
@@ -42,7 +41,6 @@ function getData() {
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;
@@ -67,7 +65,6 @@ function saveSettings() {
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;

View File

@@ -35,21 +35,21 @@ function getResults() {
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>';
if (res.clients.length > 0) tr += '<tr><th>Pkts</th><th>Name</th><th>MAC</th><th>AP</th><th>Select</th></tr>';
for (var i = 0; i < res.clients.length; i++) {
if (res.clients[i].s == 1) tr += '<tr class="selected">';
else tr += '<tr>';
tr += '<td>' + res.clients[i].p + '</td>';
tr += '<td>' + res.clients[i].v + '</td>';
if(res.clients[i].l >= 0) tr += '<td>' + res.clients[i].n + ' <a onclick="editNameList(' + res.clients[i].l + ')">edit</a></td>';
if(res.clients[i].l >= 0) tr += '<td>' + res.clients[i].n + ' <a onclick="editNameList(' + res.clients[i].l + ')"></a></td>';
else tr += '<td><a onclick="setName(' + res.clients[i].i + ')">set</a></td>';
tr += '<td>' + res.clients[i].m + '</td>';
if(res.clients[i].v.length > 1) tr += '<td>' + res.clients[i].v + res.clients[i].m.substring(8, 20) + '</td>';
else tr += '<td>' + res.clients[i].m + '</td>';
tr += '<td>' + 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>';
if (res.clients[i].s == 1) tr += '<td><button class="marginNull select" onclick="select(' + res.clients[i].i + ')">deselect</button></td>';
else tr += '<td><button class="marginNull select" onclick="select(' + res.clients[i].i + ')">select</button></td>';
tr += '</tr>';
}
@@ -57,7 +57,7 @@ function getResults() {
clientNames.innerHTML = res.nameList.length + "/50";
var tr = '<tr><th>MAC</th><th>Name</th><th>X</th><th>Add</th></tr>';
var tr = '<tr><th>MAC</th><th>Name</th><th>Del.</th><th>Add</th></tr>';
for (var i = 0; i < res.nameList.length; i++) {

View File

@@ -2,12 +2,13 @@
<html>
<head>
<meta charset="utf-8">
<title>ESP8266 Deauther</title>
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="js/functions.js"></script>
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
@@ -17,72 +18,79 @@
<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">
<div id="error" class="hide"></div>
<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>
<label for="ssid" class="labelFix">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>
<label for="password" class="labelFix">Password (<span class="red">min.8 chars</span>)</label>
</div>
<div class="col-6">
<input type="text" id="password" minlength="8" maxlength="32">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="apChannel">Channel</label>
<label for="ssidHidden">Hide SSID (<span class="red">be careful with this setting!</span>)</label>
</div>
<div class="col-6">
<input type="checkbox" name="ssidHidden" id="ssidHidden" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="apChannel" class="labelFix">Channel</label>
</div>
<div class="col-6">
<input type="number" id="apChannel" min="1" max="14">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="apChannel">MAC</label>
<label for="apChannel" class="labelFix">MAC</label>
</div>
<div class="col-6">
<input type="text" id="macAp" min="1" max="14">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ssidHidden">Random MAC</label>
<label for="randMacAp" class="labelFix">Random MAC</label>
</div>
<div class="col-6">
<input type="checkbox" name="randMacAp" id="randMacAp" value="false">
</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>
@@ -91,6 +99,7 @@
<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>
@@ -99,34 +108,39 @@
<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>
<label for="scanTime" class="labelFix">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>
<label for="timeout" class="labelFix">Timeout (0 = no 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="useLed">Use LED</label>
@@ -135,22 +149,16 @@
<input type="checkbox" id="useLed" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ledPin">LED Pin</label>
<label for="ledPin" class="labelFix">LED Pin</label>
</div>
<div class="col-6">
<input type="number" id="ledPin" min="0" max="18">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ssidEnc">WPA2 Beacons</label>
</div>
<div class="col-6">
<input type="checkbox" id="ssidEnc" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="beaconInterval">1s Beacon Interval (default: 100ms)</label>
@@ -159,33 +167,37 @@
<input type="checkbox" id="beaconInterval" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="deauthReason">Deauth Reason-Code</label>
<label for="deauthReason" class="labelFix">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>
<label for="packetRate" class="labelFix">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="multiAttacks">Multiple Attacks</label>
<label for="multiAttacks">Enable Simultaneous Attacks</label>
</div>
<div class="col-6">
<input type="checkbox" id="multiAttacks" value="false">
</div>
</div>
<div class="row">
<div class="col-6">
<label for="macInterval">MAC Change Interval (used for beacons & probes)</label>
<label for="macInterval" class="labelFix">MAC Change Interval (used for beacons & probes)</label>
</div>
<div class="col-6">
<input type="number" id="macInterval" min="0" max="65000">s
@@ -206,17 +218,17 @@
<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="red" onclick="resetSettings()">reset</button>
<button class="red" onclick="restart()">restart</button>
<button class="button-primary right" onclick="saveSettings()">save</button>
<br class="clear" />
<p id="saved"></p>
<br class="clear" />
<div id="copyright">
version 1.5<br />
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
<script src="js/settings.js"></script>

View File

@@ -2,12 +2,13 @@
<html>
<head>
<meta charset="utf-8">
<title>ESP8266 Deauther</title>
<meta name="viewport" content="width=device-width, initial-scale=0.8, minimal-ui">
<meta name="description" content="Wi-Fi Deauthenticator">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="js/functions.js"></script>
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
</head>
<body>
<nav>
@@ -17,59 +18,75 @@
<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">
<div id="error" class="hide"></div>
<h1 class="header">Scan for Wi-Fi Stations</h1>
<label for="scanTime">Scan time:</label>
<label>Scan time:
<input type="number" id="scanTime" value="10">s
</label>
<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>
<a id="clientScanStatus"><br />scanning...</a>
<p class="red">The access point will be unavailable while scanning and you may have to reconnect!</p>
<p>
Stations found: <span id="clientsFound">0</span>
Stations found: <span id="clientsFound">0</span><br />
<br />
<button class="marginNull button-primary left" onclick="select(-2)">deselect all</button>
<button class="marginNull button-primary right" onclick="select(-1)">select all</button>
<button class="marginNull button-primary right" onclick="select(-1)">select all</button><br />
</p>
<br />
<table></table>
<p class="block bold" >Saved stations: <span id="clientNames"></span></p>
<p class="block bold" >
Saved stations: <span id="clientNames"></span>
</p>
<table id="nameList"></table>
<button class="button-warn left" onclick="clearNameList()">clear</button>
<button class="red left" onclick="clearNameList()">clear</button>
<p>
<br class="clear" />
<p>Add station:</p>
<br />
Add station:
</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>
<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>
<label>Name <input type="text" placeholder="EXAMPLE" id="cName" /></label>
</div>
<div class="col-4">
<button class="button-primary" onclick="addClient()">add</button>
<button class="button-primary" style="width: 100%" onclick="addClient()">add</button>
</div>
</div>
<div class="row">
<div class="col-12">
<div id="copyright">
version 1.5<br />
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a><br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
</div>
</div>
<script src="js/stations.js"></script>
</div>
</div>
</div>
</body>
</html>

View File

@@ -1,245 +1,227 @@
/* Global */
.header{
font-size: 1.6rem;
background: #00B0FF;
color: #fff;
padding:0.2rem;
border-radius:4px;
margin-top: 0;
}
input,
.button,
button,
textarea{
border-radius: 4px;
border: 1px solid #bbb;
padding: 0 6px;
}
textarea{
width: 96%;
height: 350px;
}
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;
body {
background: #36393e;
color: #bfbfbf;
font-family: sans-serif;
margin: 0;
}
h1 {
font-size: 1.7rem;
margin-top: 1rem;
background: #2f3136;
color: #bfbfbb;
padding: 0.2em 1em;
border-radius: 3px;
border-left: solid #4974a9 5px;
font-weight: 100;
}
h2 {
font-size: 1.1rem;
margin-top: 1rem;
background: #2f3136;
color: #bfbfbb;
padding: 0.4em 1.8em;
border-radius: 3px;
border-left: solid #4974a9 5px;
font-weight: 100;
}
table{
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{
.left {
float: left;
}
.right{
.right {
float: right;
}
.bold{
.bold {
font-weight: bold;
}
.clear{
clear: both;
}
.warn{
font-weight: bold;
color: #f00;
}
.middle{
text-align: center;
}
.red{
color:#f00;
color: #f00;
}
.green{
color:#1ecb1e;
}
.padding{
padding: 0 1rem;
.clear {
clear: both;
}
.fullWidth{
width: 100%
.centered{
text-align: center;
}
#error{
.select{
width: 98px !important;
padding: 0 !important;
}
.selected{
background: #4974a9;
}
.status{
width: 120px;
padding-left: 8px;
}
.labelFix {
line-height: 40px;
}
#error {
text-align: center;
color: #fff;
background: #f00;
background: #af3535;
border-radius: 5px;
padding: 10px;
margin-top: 10px;
}
#copyright{
font-size: 0.95em;
text-align: center;
margin-top: 3em;
margin-bottom: 3em;
}
.selectedBtn{
background: #fff;
/* ERROR */
.hide {
display: none;
}
a{
color: #39C2FF;
cursor: pointer;
.show {
display: block !important;
animation-name: fadeIn;
animation-duration: 1s;
}
input{
padding: 3px;
@keyframes fadeIn {
0% {opacity: 0;}
100% {opacity: 1;}
}
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
hr {
background: #3e4146;
}
a {
color: #5281bb;
text-decoration: none;
}
a:hover {
color: #95b8e4;
}
li{
margin: 4px 0;
}
/* Meter */
.meter_background{
background: #42464D;
width: 100%;
min-width: 90px;
}
.meter_forground{
color: #fff;
padding: 4px 0;
/* + one of the colors below
(width will be set by the JS) */
}
.meter_green{
background: #43B581;
}
.meter_orange{
background: #FAA61A;
}
.meter_red{
background: #F04747;
}
.meter_value{
padding-left: 8px;
}
/* Tables */
table {
width: 100%;
margin-bottom: 50px;
}
th, td {
padding: 10px 6px;
text-align: left;
border-bottom: 1px solid #5d5d5d;
}
/* Navigation bar */
nav {
display: block;
padding: 8px 10px;
background: #2f3136;
}
nav a {
color: #bfbfbf;
padding: 0.5em;
display: inline-block;
height: 31px;
color: #555;
text-decoration: none;
}
nav a:hover{
background: #36393f;
color:#cecece;
border-radius: 4px;
}
/* Inputs and buttons */
.upload-script, .button, button, input[type="submit"], input[type="reset"], input[type="button"] {
display: inline-block;
height: 38px;
padding: 0 25px;
color:#fff;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 30px;
line-height: 38px;
letter-spacing: .1rem;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
background: #2f3136;
border-radius: 4px;
border: none;
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;
box-sizing: border-box;
}
/**
*** 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%;
button:hover, input[type="submit"]:hover, input[type="reset"]:hover, input[type="button"]:hover {
background: #42444a;
}
/* ROOT FONT STYLES */
* {
font-family: /*'Lato',*/ Helvetica, sans-serif;
color: #333447;
line-height: 1.5;
/* Forms */
input[type="email"], input[type="number"], input[type="search"], input[type="text"], input[type="tel"], input[type="url"], input[type="password"], textarea, select {
height: 38px;
padding: 6px 10px; /* The 6px vertically centers text on FF, ignored by Webkit */
background-color: #2f3136;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
color: #d4d4d4;
border: none;
}
/* TYPOGRAPHY */
h1 {
font-size: 2.5rem;
.setting {
width: 100% !important;
max-width: 284px !important;
}
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;
input[type="file"] {
display: none;
}
/* ==== GRID SYSTEM ==== */
@@ -248,6 +230,7 @@ p {
width: 100%;
margin-left: auto;
margin-right: auto;
max-width: 1140px;
}
.row {
@@ -257,7 +240,7 @@ p {
.row [class^="col"] {
float: left;
margin: 0.5rem 2%;
margin: 0.25rem 2%;
min-height: 0.125rem;
}
@@ -276,54 +259,6 @@ p {
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;
@@ -334,13 +269,7 @@ p {
display: none;
}
@media only screen and (min-width: 33.75em) { /* 540px */
.container {
width: 85%;
}
}
@media only screen and (min-width: 45em) { /* 720px */
@media only screen and (min-width: 45em) {
.col-1 {
width: 4.33%;
}
@@ -393,10 +322,3 @@ p {
display: block;
}
}
@media only screen and (min-width: 60em) { /* 960px */
.container {
width: 80%;
max-width: 60rem;
}
}