Merge remote-tracking branch 'origin/testing'

This commit is contained in:
Stefan Kremser
2018-03-24 16:59:13 +01:00
33 changed files with 25478 additions and 23383 deletions

View File

@@ -166,10 +166,25 @@ If no port shows up you may have to reinstall the drivers.
**18** Upload!
**19** Install the [ESP8266 Sketh Data uploader](https://github.com/esp8266/arduino-esp8266fs-plugin) plugin, your mileage may vary depending on your version of Arduino IDE.
**20** Restart Arduino IDE, reopen the project, and from the "tools" menu, choose "ESP8266 Sketch Data Upload".
**Note:** If you use a 512kb version of the ESP8266, you will need to comment out a part of the mac vendor list in data.h. Otherwise it will use too much memory to fit on 512kb.
**Your ESP8266 Deauther is now ready!**
### Updating the MAC vendor list
The utils folder includes a python script for downloading the latest ["manuf"](https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=manuf) file from Whireshark and convert it to the format understood by esp8266_deauther.
The usage of the script is quite simple: `update_manuf.py [-h] [-o OUTPUT] [-u URL]` , e.g:
```
cd utils
python update_manuf.py -o ../esp8266_deauther/oui.h
```
### Adding an OLED display
![image of the esp8266 deauther with an OLED and three buttons](https://raw.githubusercontent.com/spacehuhn/esp8266_deauther/master/screenshots/esp8266_with_oled.jpg)

View File

@@ -20,7 +20,7 @@ bool APScan::start() {
if (debug) Serial.println("Scan results: "+(String)results);
for (int i = 0; i < results; i++) {
for (int i = 0; i < results && i < maxAPScanResults; i++) {
Mac _ap;
_ap.set(WiFi.BSSID(i)[0], WiFi.BSSID(i)[1], WiFi.BSSID(i)[2], WiFi.BSSID(i)[3], WiFi.BSSID(i)[4], WiFi.BSSID(i)[5]);
aps.add(_ap);
@@ -29,7 +29,6 @@ bool APScan::start() {
encryption[i] = WiFi.encryptionType(i);
hidden[i] = WiFi.isHidden(i);
String _ssid = WiFi.SSID(i);
_ssid.replace("\"", "\\\"");
_ssid.toCharArray(names[i], 33);
//data_getVendor(WiFi.BSSID(i)[0],WiFi.BSSID(i)[1],WiFi.BSSID(i)[2]).toCharArray(vendors[i],9);
if (debug) {
@@ -109,7 +108,7 @@ String APScan::getEncryption(int code) {
}
String APScan::getAPName(int num) {
if (isHidden(num)) return "* Hidden SSID *";
//if (isHidden(num)) return "* Hidden SSID *";
return names[num];
}
String APScan::getAPEncryption(int num) {
@@ -136,6 +135,18 @@ int APScan::getFirstTarget() {
return -1;
}
String APScan::sanitizeJson(String input){
input.replace("\\","\\\\");
input.replace("\"","\\\"");
input.replace("/","\\/");
input.replace("\b","\\b");
input.replace("\f","\\f");
input.replace("\n","\\n");
input.replace("\r","\\r");
input.replace("\t","\\t");
return input;
}
void APScan::sendResults() {
if (debug) Serial.print("sending AP scan result JSON ");
@@ -155,10 +166,10 @@ void APScan::sendResults() {
_size += 6; // "e": ,
_size += 6; // "se":0
_size++; // }*/
_size += 61;
_size += 67;
_size += String(i).length();
_size += String(getAPChannel(i)).length();
_size += getAPName(i).length();
_size += sanitizeJson(getAPName(i)).length();
_size += String(getAPRSSI(i)).length();
if ((i != results - 1) && (i != maxAPScanResults - 1)) _size++; // ,
@@ -178,11 +189,12 @@ void APScan::sendResults() {
json += "\"i\":" + (String)i + ",";
json += "\"c\":" + (String)getAPChannel(i) + ",";
json += "\"m\":\"" + getAPMac(i) + "\",";
json += "\"ss\":\"" + getAPName(i) + "\",";
json += "\"ss\":\"" + sanitizeJson(getAPName(i)) + "\",";
json += "\"r\":" + (String)getAPRSSI(i) + ",";
json += "\"e\":" + (String)encryption[i] + ",";
//json += "\"v\":\""+getAPVendor(i)+"\",";
json += "\"se\":" + (String)isSelected(i);
json += "\"h\":" + (String)hidden[i] + ",";
json += "\"se\":" + (String)isSelected(i);
json += "}";
if ((i != results - 1) && (i != maxAPScanResults - 1)) json += ",";
@@ -211,10 +223,11 @@ String APScan::getResultsJSON() {
json += "\"i\":" + (String)i + ",";
json += "\"c\":" + (String)getAPChannel(i) + ",";
json += "\"m\":\"" + getAPMac(i) + "\",";
json += "\"ss\":\"" + getAPName(i) + "\",";
json += "\"ss\":\"" + sanitizeJson(getAPName(i)) + "\",";
json += "\"r\":" + (String)getAPRSSI(i) + ",";
json += "\"e\":" + (String)encryption[i] + ",";
//json += "\"v\":\""+getAPVendor(i)+"\",";
json += "\"h\":" + (String)hidden[i] + ",";
json += "\"se\":" + (String)isSelected(i);
json += "}";
if ((i != results - 1) && (i != maxAPScanResults - 1)) json += ",";

View File

@@ -39,6 +39,8 @@ class APScan {
int getFirstTarget();
bool isSelected(int num);
String sanitizeJson(String input);
int results = 0;
int selectedSum;
MacList aps;

View File

@@ -139,12 +139,8 @@ void Attack::sendDeauths(Mac from, Mac to){
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);
if(send()) packetsCounter[0]++;
delay(3);
}
}

File diff suppressed because one or more lines are too long

View File

@@ -12,11 +12,11 @@
</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>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
@@ -25,19 +25,19 @@
<div id="error" class="hide"></div>
<h1 class="header">Scan for Wi-Fi access points</h1>
<h1 class="header">{h1}</h1>
<a id="scanInfo" class="left labelFix">scanning...</a>
<a id="scanInfo" class="left labelFix">{a1}</a>
<button onclick="scan()" id="apScanStart" class="right button-primary">scan</button>
<button onclick="scan()" id="apScanStart" class="right button-primary">{button1}</button>
<p class="clear">
Networks found: <span id="networksFound">0</span><br />
MAC: <span id="apMAC"></span><br />
{p1} <span id="networksFound">0</span><br />
{p2} <span id="apMAC"></span><br />
<br />
<span id="selectAllBtns" style="visibility:'hidden'">
<button class="marginNull button-primary left" onclick="select(-2)">deselect all</button>
<button class="marginNull button-primary right" onclick="select(-1)">select all</button>
<button class="marginNull button-primary left" onclick="select(-2)">{button2}</button>
<button class="marginNull button-primary right" onclick="select(-1)">{button3}</button>
<br />
</span>
@@ -46,7 +46,7 @@
<table></table>
<p class="small">
<span class="red">INFO: </span><span class="bold">You may have to reload the site to see the results.</span>
<span class="red">{p3} </span><span class="bold">{p4}</span>
<br />
<br />
</p>
@@ -57,10 +57,10 @@
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
<script src="js/apscan.js"></script>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/apscan.js"></script>
</body>
</html>

View File

@@ -12,11 +12,11 @@
</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>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
@@ -25,12 +25,12 @@
<div id="error" class="hide"></div>
<h1 class="header">Attacks</h1>
<h1 class="header">{h1}</h1>
<p class="bold">Selected AP(s): <button onclick='cloneSelected()'>clone</button></p>
<p class="bold">{p1} <button onclick='cloneSelected()'>{button1}</button></p>
<ul id="selectedAPs"></ul>
<p class="bold">Selected Station(s):</p>
<p class="bold">{p2}</p>
<ul id="selectedClients"></ul>
<table></table>
@@ -39,12 +39,12 @@
<input type="number" id="randomIntrvl" value="5" min="1" max="65000"/>s
</label>
<button class="right" id="randomBtn" onclick="random()">Enable Random</button>
<button class="right" id="randomBtn" onclick="random()">{button2}</button>
<p class="clear">
<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.
<span class="red">{p3} </span><span class="bold">{p4}</span><br />
{p5}
</p>
<hr />
@@ -53,16 +53,16 @@
<div class="row">
<div class="col-6">
<label for="ssid">SSID</label>
<label for="ssid">{label1}</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="{placeholder1}" />
</div>
</div>
<div class="row">
<div class="col-6">
<label for="num">Number of Clones</label>
<label for="num">{label2}</label>
</div>
<div class="col-6">
<input type="number" id="num" min="0" max="48" value="0" />
@@ -71,7 +71,7 @@
<div class="row">
<div class="col-6">
<label for="enc">Encrypted</label>
<label for="enc">{label3}</label>
</div>
<div class="col-6">
<input type="checkbox" id="enc" name="enc" />
@@ -81,34 +81,34 @@
<div class="row">
<div class="col-12">
<button class="button-primary col-4" onclick="addSSID()">add</button>
<button class="button-primary col-4" onclick="addSSID()">{button3}</button>
<hr />
<p class="left">SSIDs: <span id="ssidCounter">0/48</span></p>
<p class="left">{p6} <span id="ssidCounter">0/48</span></p>
<div class="right">
<button class="red" onclick="clearSSID()">clear</button>
<button onclick="randomSSID()">random</button>
<button class="red" onclick="clearSSID()">{button4}</button>
<button onclick="randomSSID()">{button5}</button>
</div>
<table></table>
<button class="marginNull red" onclick="resetSSID()">reset</button>
<button class="marginNull button-primary right" onclick="saveSSID()">save</button>
<button class="marginNull red" onclick="resetSSID()">{button6}</button>
<button class="marginNull button-primary right" onclick="saveSSID()">{button7}</button>
<p class="small" id="saved">saved</p>
<p class="small" id="saved">{p7}</p>
<p>
<br />
<span class="bold">Deauth [deauthentication attack]:</span><br />
Sends constantly deauthentication and disassociation frames to the selected station(s) and access point(s).<br />
<span class="bold">{p8}</span><br />
{p9}<br />
<br />
<span class="bold">Beacon [beacon flooding]:</span><br />
Broadcasts constantly beacon frames to advertise all SSIDs in the list below.<br />
<span class="bold">{pa}</span><br />
{pb}<br />
<br />
<span class="bold">Probe-Request [probe request flooding]:</span><br />
Broadcasts constantly probe request frames with all SSIDs in the list below.
<span class="bold">{pc}</span><br />
{pd}
</p>
<div id="copyright">
@@ -116,11 +116,10 @@
Copyright (c) 2017 Stefan Kremser<br />
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
<script src="js/attack.js"></script>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/attack.js"></script>
</body>
</html>
</html>

View File

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

View File

@@ -12,17 +12,17 @@
</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>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="header">ERROR 404</h1>
<p class="centered bold"><br />Page not found &macr;\_(ツ)_/&macr;</p>
<h1 class="header">{h1}</h1>
<p class="centered bold"><br />{p1}</p>
<div id="copyright">
Version 1.6<br />
Copyright (c) 2017 Stefan Kremser<br />
@@ -31,5 +31,6 @@
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -8,29 +8,29 @@
<meta name="theme-color" content="#36393E" />
<title>ESP8266 Deauther</title>
<link rel="stylesheet" href="style.css">
<script src="js/functions.js"></script>
<script src="js/functions.js" defer async></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="header">WARNING</h1>
<h1 class="header">{h1}</h1>
<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 />
{p1}<br />
{p2}<br />
<br />
<span class="warn">Use it only on your own networks and devices!</span><br />
<span class="warn">{p3}</span><br />
<br />
You are resposible for everything you do with this software.<br />
The device will log every attack against any network or device.<br />
{p4}<br />
{p5}<br />
<br />
Please do not call this project a "jammer", it does not jam any frequencies!
{p6}
<br />
Go to <a href="https://github.com/spacehuhn/esp8266_deauther">github.com/spacehuhn/esp8266_deauther</a> for more information.<br />
{p7} <a href="https://github.com/spacehuhn/esp8266_deauther">github.com/spacehuhn/esp8266_deauther</a> {p8}<br />
<br />
<br />
<a class="button" href="apscan.html">I've read and understood the notice above</a>
<a class="button" href="apscan.html">{p9}</a>
</p>
<div id="copyright">
@@ -42,5 +42,6 @@
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
</body>
</html>

View File

@@ -12,29 +12,29 @@
</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>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="header">Info</h1>
<h1 class="header">{h1}</h1>
<h2>ESP8266 Deauther</h2>
<h2>{h2}</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 />
The source code is available on <a href="https://github.com/spacehuhn/esp8266_deauther" target="_blank">GitHub</a>.<br />
{p1} <a href="license">{a1}</a> {p2}<br />
{p3} <a href="https://github.com/spacehuhn/esp8266_deauther" target="_blank">{a2}</a>.<br />
<br />
Use it only for testing or educational purposes against your own devices!<br />
{p4}<br />
<br />
<span class="bold">Please do not call this project a "jammer", it does not jam any frequencies!</span>
<span class="bold">{p5}</span>
</p>
<h2>Contributors</h2>
@@ -48,6 +48,8 @@
<a href="https://github.com/SamuelKlit" target="_blank">@SamuelKlit</a> (Samuel KS)<br />
<a href="https://github.com/schinfo" target="_blank">@schinfo</a> (Helmut)<br />
<a href="https://github.com/ajnavarro" target="_blank">@ajnavarro</a> (Antonio Navarro Perez)<br />
<a href="https://github.com/rubfi" target="_blank">@rubfi</a><br />
<br />
Also special thanks to <a href="https://github.com/deantonious" target="_blank">@deantonious</a> for the help with the webdesign!<br />
<br />
@@ -58,21 +60,21 @@
<p>
<a href="https://github.com/ThisIsDallas/Simple-Grid">SIMPLE GRID</a> - (C) ZACH COLE 2016<br />
<br />
The MAC address vendor list is based on the Wireshark manufacturer database.<br />
{p6}<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 />
{p7}<br />
</p>
<h2>Contact</h2>
<h2>{p8}</h2>
<p>
Web: spacehuhn.de<br />
GitHub: github.com/spacehuhn<br />
Twitter: @spacehuhn<br />
E-mail: mail@spacehuhn.de<br />
<br />
If you would like to support me with my projects, please consider becoming a patron on <a target="_blank" href="https://patreon.com/spacehuhn">patreon.com/spacehuhn</a>.<br />
{p9} <a target="_blank" href="https://patreon.com/spacehuhn">patreon.com/spacehuhn</a>.<br />
<br />
Or buy the official hardware for this project from DSTIKE on <a target="_blank" href="https://www.tindie.com/stores/lspoplove/">tindie.com/stores/lspoplove</a>.
{pa} <a target="_blank" href="https://www.tindie.com/stores/lspoplove/">tindie.com/stores/lspoplove</a>.
</p>
<div id="copyright">
@@ -83,5 +85,6 @@
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
</body>
</html>

View File

@@ -17,22 +17,32 @@ function compare(a, b) {
return 0;
}
function getEncryption(num) {
function getStatus(enc, hid) {
/*
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 (enc == 8) return "WPA*";
else if (enc == 4) return "WPA2";
else if (enc == 2) return "WPA";
else if (enc == 7) return "none";
else if (enc == 5) return "WEP";
*/
if (num == 7) return " ";
else return "&#128274;";
var buff = "";
if (enc != 7) buff += "&#128274; ";
if (hid == 1) buff += "&#128123; ";
return buff;
}
function getResults() {
toggleScan(true);
getResponse("APScanResults.json", function(responseText) {
var res = JSON.parse(responseText);
var res;
try {
res = JSON.parse(responseText);
} catch(e) {
// wut
showMessage(_("JSON Parsing failed :-("), 2500);
return;
}
// TODO: more sanity checks on res && res.aps
res.aps = res.aps.sort(compare);
networkInfo.innerHTML = res.aps.length;
apMAC.innerHTML = "";
@@ -42,7 +52,7 @@ function getResults() {
var tr = '';
if (res.aps.length > 0) {
tr += '<tr><th>Ch</th><th>SSID</th><th> </th><th>RSSI</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++) {
@@ -51,7 +61,7 @@ function getResults() {
else tr += '<tr>';
tr += '<td>' + res.aps[i].c + '</td>';
tr += '<td>' + escapeHTML(res.aps[i].ss) + '</td>';
tr += '<td>' + getEncryption(res.aps[i].e) + '</td>';
tr += '<td>' + getStatus(res.aps[i].e, res.aps[i].h) + '</td>';
//tr += '<td>' + res.aps[i].r + ' <meter value="' + res.aps[i].r + '" max="-30" min="-100" low="-80" high="-60" optimum="-50"></meter></td>';
var _width = res.aps[i].r + 130;
var _color;
@@ -61,10 +71,10 @@ function getResults() {
tr += '<td><div class="meter_background"> <div class="meter_forground '+_color+'" style="width: '+_width+'%;"><div class="meter_value">' + res.aps[i].r + '</div></div> </div></td>';
if (res.aps[i].se) {
tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">deselect</button></td>';
tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">' + _('deselect') + '</button></td>';
apMAC.innerHTML = res.aps[i].m;
}
else tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">select</button></td>';
else tr += '<td><button class="select" onclick="select(' + res.aps[i].i + ')">' + _('select') + '</button></td>';
tr += '</tr>';
}
table.innerHTML = tr;
@@ -75,7 +85,7 @@ function scan() {
toggleScan(false);
getResponse("APScan.json", function(responseText) {
if (responseText == "true") getResults();
else showMessage("response error APScan.json");
else showMessage(_("response error APScan.json"));
toggleScan(true);
});
}
@@ -83,7 +93,7 @@ function scan() {
function select(num) {
getResponse("APSelect.json?num=" + num, function(responseText) {
if (responseText == "true") getResults();
else showMessage("response error APSelect.json");
else showMessage(_("response error APSelect.json"));
});
}

View File

@@ -14,18 +14,26 @@ var data = {};
function getResults() {
getResponse("attackInfo.json", function(responseText) {
var res = JSON.parse(responseText);
var res;
try {
res = JSON.parse(responseText);
} catch(e) {
// wut
showMessage(_("JSON Parsing failed :-("), 2500);
return;
}
// TODO: more sanity checks on res && res.aps
var aps = "";
var clients = "";
var tr = "<tr><th>Attack</th><th>Status</th><th>Start/Stop</th></tr>";
var tr = "<tr><th>" + _('Attack') + "</th><th>" + _('Status') + "</th><th>" + _('Start/Stop') + "</th></tr>";
for (var i = 0; i < res.aps.length; i++) aps += "<li>" + escapeHTML(res.aps[i]) + "</li>";
for (var i = 0; i < res.clients.length; i++) clients += "<li>" + escapeHTML(res.clients[i]) + "</li>";
selectedAPs.innerHTML = aps;
selectedClients.innerHTML = clients;
if(res.randomMode == 1) randomBtn.innerHTML = "Disable Random";
else randomBtn.innerHTML = "Enable Random";
if(res.randomMode == 1) randomBtn.innerHTML = _("Disable Random");
else randomBtn.innerHTML = _("Enable Random");
for (var i = 0; i < res.attacks.length; i++) {
if (res.attacks[i].running) tr += "<tr class='selected'>";
@@ -35,7 +43,7 @@ function getResults() {
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>";
else tr += "<td><button class='select' onclick='startStop(" + i + ")'>" + _('start') + "</button></td>";
tr += "</tr>";
}
@@ -45,7 +53,7 @@ function getResults() {
data = res.ssid;
ssidCounter.innerHTML = data.length + "/48";
var tr = "<tr><th>Name</th><th></th><th>Del.</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>" + escapeHTML(data[i][0]) + "</td>";
@@ -59,7 +67,7 @@ function getResults() {
}, function() {
clearInterval(resultInterval);
showMessage("error loading attackInfo.json");
showMessage(_("error loading attackInfo.json"));
});
}
@@ -67,7 +75,7 @@ function startStop(num) {
getResponse("attackStart.json?num=" + num, function(responseText) {
getE("status"+num).innerHTML = "loading";
if (responseText == "true") getResults();
else showMessage("response error attackStart.json");
else showMessage(_("response error attackStart.json"));
});
}
@@ -75,7 +83,7 @@ function addSSID() {
var _ssidName = ssid.value;
if(_ssidName.length > 0){
if(data.length >= 64) showMessage("SSID list full :(", 2500);
if(data.length >= 64) showMessage(_("SSID list full :("), 2500);
else{
saved.innerHTML = "";
getResponse("addSSID.json?ssid=" + _ssidName + "&num="+num.value + "&enc=" + enc.checked, getResults);

View File

@@ -28,10 +28,12 @@ function showMessage(msg, closeAfter){
}
}
function getResponse(adr, callback, timeoutCallback, timeout, method){
if(timeoutCallback === undefined) {
timeoutCallback = function(){
showMessage("error loading "+adr);
showMessage(_("Timeout loading") +" "+adr);
};
}
if(timeout === undefined) timeout = 8000;
@@ -49,4 +51,16 @@ function getResponse(adr, callback, timeoutCallback, timeout, method){
xmlhttp.send();
xmlhttp.timeout = timeout;
xmlhttp.ontimeout = timeoutCallback;
}
xmlhttp.onabort = function(e) {
showMessage(_("ABORT")+" "+adr);
};
xmlhttp.onerror = function(e) {
showMessage(_("ERROR loading")+" "+adr +" :: "+ this.statusText);
};
}
function _(l10nid) {
return l10n.jsStrings[l10nid];
}

View File

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

View File

@@ -27,7 +27,7 @@ function getData() {
try {
res = JSON.parse(responseText);
} catch(e) {
showMessage("Error: reset the settings.");
showMessage(_("Error: reset the settings."));
return;
}
ssid.value = res.ssid;
@@ -52,7 +52,7 @@ function getData() {
}
function saveSettings() {
saved.innerHTML = "saving...";
saved.innerHTML = _("saving...");
var url = "settingsSave.json";
url += "?ssid=" + ssid.value;
url += "&ssidHidden=" + ssidHidden.checked;
@@ -76,9 +76,9 @@ function saveSettings() {
getResponse(url, function(responseText) {
if (responseText == "true") {
getData();
saved.innerHTML = "saved";
saved.innerHTML = _("saved");
}
else showMessage("response error settingsSave.json");
else showMessage(_("response error settingsSave.json"));
});
}
@@ -86,9 +86,9 @@ function resetSettings() {
getResponse("settingsReset.json", function(responseText) {
if (responseText == "true") {
getData();
saved.innerHTML = "saved";
saved.innerHTML = _("saved");
}
else showMessage("response error settingsReset.json");
else showMessage(_("response error settingsReset.json"));
});
}

View File

@@ -26,7 +26,7 @@ function getResults() {
try{
res = JSON.parse(responseText);
}catch(e){
showMessage("Error: clear the client list.");
showMessage(_("Error: clear the client list."));
return;
}
@@ -35,7 +35,7 @@ function getResults() {
clientsFound.innerHTML = res.clients.length;
var tr = '';
if (res.clients.length > 0) tr += '<tr><th>Pkts</th><th>Name</th><th>MAC</th><th>AP</th><th>Select</th></tr>';
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++) {
@@ -43,13 +43,13 @@ function getResults() {
else tr += '<tr>';
tr += '<td>' + res.clients[i].p + '</td>';
if(res.clients[i].l >= 0) tr += '<td>' + escapeHTML(res.clients[i].n) + ' <a onclick="editNameList(' + res.clients[i].l + ')"></a></td>';
else tr += '<td><a onclick="setName(' + res.clients[i].i + ')">set</a></td>';
else tr += '<td><a onclick="setName(' + res.clients[i].i + ')">' + _('set') + '</a></td>';
if(res.clients[i].v.length > 1) tr += '<td>' + res.clients[i].v + res.clients[i].m.substring(8, 20) + '</td>';
else tr += '<td>' + res.clients[i].m + '</td>';
tr += '<td>' + escapeHTML(res.clients[i].a) + '</td>';
if (res.clients[i].s == 1) tr += '<td><button class="marginNull select" onclick="select(' + res.clients[i].i + ')">deselect</button></td>';
else tr += '<td><button class="marginNull select" onclick="select(' + res.clients[i].i + ')">select</button></td>';
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,22 +57,22 @@ function getResults() {
clientNames.innerHTML = res.nameList.length + "/50";
var tr = '<tr><th>MAC</th><th>Name</th><th>Del.</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++) {
tr += '<tr>';
tr += '<td>' + res.nameList[i].m + '</td>';
tr += '<td>' + escapeHTML(res.nameList[i].n) + ' <a onclick="editNameList(' + i + ')">edit</a></td>';
tr += '<td>' + escapeHTML(res.nameList[i].n) + ' <a onclick="editNameList(' + i + ')">'+ _('edit') + '</a></td>';
tr += '<td><button class="marginNull button-warn" onclick="deleteName(' + i + ')">x</button></td>';
tr += '<td><button class="marginNull button-primary" onclick="add(' + i + ')">add</button></td>';
tr += '<td><button class="marginNull button-primary" onclick="add(' + i + ')">'+ _('add') + '</button></td>';
tr += '</tr>';
}
nameListTable.innerHTML = tr;
}, function() {
showMessage("reconnect and reload the site");
showMessage(_("reconnect and reload the site"));
}, 6000);
}
@@ -86,49 +86,49 @@ function scan() {
getResults();
}, scanTime.value * 1000);
}
else showMessage("response error ClientScan.json");
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");
else showMessage(_("response error clientSelect.json"));
});
}
function clearNameList() {
getResponse("clearNameList.json", function(responseText) {
if (responseText == "true") getResults();
else showMessage("response error clearNameList.json");
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");
else showMessage(_("response error addClient.json"));
});
}
function setName(id) {
var newName = prompt("Name for " + res.clients[id].m);
var newName = prompt(_("Name for ") + res.clients[id].m);
if (newName != null) {
getResponse("setName.json?id=" + id + "&name=" + newName, function(responseText) {
if(responseText == "true") getResults();
else showMessage("response error editNameList.json");
else showMessage(_("response error editNameList.json"));
});
}
}
function editNameList(id) {
var newName = prompt("Name for " + res.nameList[id].m);
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");
else showMessage(_("response error editNameList.json"));
});
}
}
@@ -136,20 +136,19 @@ function editNameList(id) {
function deleteName(id) {
getResponse("deleteName.json?num=" + id, function(responseText) {
if (responseText == "true") getResults();
else showMessage("response error deleteName.json");
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");
else showMessage(_("response error addClientFromList.json"));
});
}
getResponse("ClientScanTime.json", function(responseText) {
scanTime.value = responseText;
getResults();
toggleBtn(false);
});
getResults();
toggleBtn(false);

View File

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

View File

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

View File

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

View File

@@ -12,11 +12,11 @@
</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>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
@@ -25,14 +25,37 @@
<div id="error" class="hide"></div>
<h1 class="header">Settings</h1>
<h2>Wi-Fi</h2>
<h1 class="header">{h1}</h1>
<h2>{locale}</h2>
</div>
</div>
<div class="row">
<div class="col-12">
<span class="flag" data-lang="en">{english}</span>
<span class="flag" data-lang="fr">{french}</span>
<span class="flag" data-lang="zh-CN">{chinese}</span>
<!--
<span class="flag" data-lang="de">{german}</span>
<span class="flag" data-lang="es">{spanish}</span>
<span class="flag" data-lang="it">{italian}</span>
<span class="flag" data-lang="kl">{klingon}</span>
-->
</div>
</div>
<div class="row">
<div class="col-12">
<h2>{h2}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="ssid" class="labelFix">SSID</label>
<label for="ssid" class="labelFix">{label01}</label>
</div>
<div class="col-6">
<input type="text" id="ssid" minlength="1" maxlength="32">
@@ -41,7 +64,7 @@
<div class="row">
<div class="col-6">
<label for="password" class="labelFix">Password (<span class="red">min.8 chars</span>)</label>
<label for="password" class="labelFix">{label02} (<span class="red">{label03}</span>)</label>
</div>
<div class="col-6">
<input type="text" id="password" minlength="8" maxlength="32">
@@ -50,7 +73,7 @@
<div class="row">
<div class="col-6">
<label for="ssidHidden">Hide SSID (<span class="red">be careful with this setting!</span>)</label>
<label for="ssidHidden">{label04} (<span class="red">{label05}</span>)</label>
</div>
<div class="col-6">
<input type="checkbox" name="ssidHidden" id="ssidHidden" value="false">
@@ -59,7 +82,7 @@
<div class="row">
<div class="col-6">
<label for="apChannel" class="labelFix">Channel</label>
<label for="apChannel" class="labelFix">{label06}</label>
</div>
<div class="col-6">
<input type="number" id="apChannel" min="1" max="14">
@@ -68,7 +91,7 @@
<div class="row">
<div class="col-6">
<label for="apChannel" class="labelFix">MAC</label>
<label for="apChannel" class="labelFix">{label07}</label>
</div>
<div class="col-6">
<input type="text" id="macAp" min="1" max="14">
@@ -77,7 +100,7 @@
<div class="row">
<div class="col-6">
<label for="randMacAp" class="labelFix">Random MAC</label>
<label for="randMacAp" class="labelFix">{label08}</label>
</div>
<div class="col-6">
<input type="checkbox" name="randMacAp" id="randMacAp" value="false">
@@ -87,13 +110,13 @@
<div class="row">
<div class="col-12">
<h2>AP Scan</h2>
<h2>{h3}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="apScanHidden">Scan Hidden APs</label>
<label for="apScanHidden">{label09}</label>
</div>
<div class="col-6">
<input type="checkbox" name="apScanHidden" id="apScanHidden" value="false">
@@ -102,7 +125,7 @@
<div class="row">
<div class="col-6">
<label for="multiAPs">Select multiple SSIDs</label>
<label for="multiAPs">{label10}</label>
</div>
<div class="col-6">
<input type="checkbox" name="multiAPs" id="multiAPs" value="false">
@@ -112,13 +135,13 @@
<div class="row">
<div class="col-12">
<h2>Station Scan</h2>
<h2>{h4}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="scanTime" class="labelFix">Default Scan Time</label>
<label for="scanTime" class="labelFix">{label11}</label>
</div>
<div class="col-6">
<input type="number" id="scanTime" min="1" max="255"> s
@@ -128,13 +151,13 @@
<div class="row">
<div class="col-12">
<h2>Attack</h2>
<h2>{h5}</h2>
</div>
</div>
<div class="row">
<div class="col-6">
<label for="timeout" class="labelFix">Timeout (0 = no timeout)</label>
<label for="timeout" class="labelFix">{label12}</label>
</div>
<div class="col-6">
<input type="number" id="timeout" min="-1" max="65536"> s
@@ -143,7 +166,7 @@
<div class="row">
<div class="col-6">
<label for="useLed">Use LED</label>
<label for="useLed">{label13}</label>
</div>
<div class="col-6">
<input type="checkbox" id="useLed" value="false">
@@ -152,7 +175,7 @@
<div class="row">
<div class="col-6">
<label for="ledPin" class="labelFix">LED Pin</label>
<label for="ledPin" class="labelFix">{label14}</label>
</div>
<div class="col-6">
<input type="number" id="ledPin" min="0" max="18">
@@ -161,7 +184,7 @@
<div class="row">
<div class="col-6">
<label for="beaconInterval">1s Beacon Interval (default: 100ms)</label>
<label for="beaconInterval">{label15}</label>
</div>
<div class="col-6">
<input type="checkbox" id="beaconInterval" value="false">
@@ -170,7 +193,7 @@
<div class="row">
<div class="col-6">
<label for="deauthReason" class="labelFix">Deauth Reason-Code</label>
<label for="deauthReason" class="labelFix">{label16}e</label>
</div>
<div class="col-6">
<input type="number" id="deauthReason" min="1" max="45">
@@ -179,7 +202,7 @@
<div class="row">
<div class="col-6">
<label for="packetRate" class="labelFix">Packetrate (<span class="red">may cause instability!</span>)</label>
<label for="packetRate" class="labelFix">{label17} (<span class="red">{label18}</span>)</label>
</div>
<div class="col-6">
<input type="number" id="packetRate" min="1" max="50"> pkts/s
@@ -188,7 +211,7 @@
<div class="row">
<div class="col-6">
<label for="multiAttacks">Enable Simultaneous Attacks</label>
<label for="multiAttacks">{label19}</label>
</div>
<div class="col-6">
<input type="checkbox" id="multiAttacks" value="false">
@@ -197,7 +220,7 @@
<div class="row">
<div class="col-6">
<label for="macInterval" class="labelFix">MAC Change Interval (used for beacons & probes)</label>
<label for="macInterval" class="labelFix">{label20}</label>
</div>
<div class="col-6">
<input type="number" id="macInterval" min="0" max="65000">s
@@ -208,7 +231,7 @@
<!--
<div class="row">
<div class="col-6">
<label for="channelHop">Channel Hopping</label>
<label for="channelHop">{label21}</label>
</div>
<div class="col-6">
<input type="checkbox" name="channelHop" id="channelHop" value="false">
@@ -231,9 +254,10 @@
<a href="https://github.com/spacehuhn" target="_blank">github.com/spacehuhn</a>
</div>
<script src="js/settings.js"></script>
</div>
</div>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/settings.js"></script>
</body>
</html>

View File

@@ -12,11 +12,11 @@
</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>
<a href="apscan.html">{APs}</a>
<a href="stations.html">{Stations}</a>
<a href="attack.html">{Attacks}</a>
<a href="settings.html">{Settings}</a>
<a class="right" href="info.html">{Info}</a>
</nav>
<div class="container">
@@ -25,39 +25,39 @@
<div id="error" class="hide"></div>
<h1 class="header">Scan for Wi-Fi Stations</h1>
<h1 class="header">{h1}</h1>
<label>Scan time:
<label>{label1}
<input type="number" id="scanTime" value="10">s
</label>
<button onclick="scan()" id="startScan" class="right button-primary">start</button>
<button onclick="scan()" id="startScan" class="right button-primary">{button1}</button>
<a id="clientScanStatus"><br />scanning...</a>
<a id="clientScanStatus"><br />{a1}</a>
<p class="red">The access point will be unavailable while scanning and you may have to reconnect!</p>
<p class="red">{p1}</p>
<p>
Stations found: <span id="clientsFound">0</span><br />
{p2} <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><br />
<button class="marginNull button-primary left" onclick="select(-2)">{button2}</button>
<button class="marginNull button-primary right" onclick="select(-1)">{button3}</button><br />
</p>
<table></table>
<p class="block bold" >
Saved stations: <span id="clientNames"></span>
{p3} <span id="clientNames"></span>
</p>
<table id="nameList"></table>
<button class="red left" onclick="clearNameList()">clear</button>
<button class="red left" onclick="clearNameList()">{button4}</button>
<p>
<br class="clear" />
<br />
Add station:
{p4}
</p>
</div>
@@ -65,13 +65,13 @@
<div class="row">
<div class="col-4">
<label>MAC <input type="text" placeholder="AA:BB:CC:DD:EE:FF" id="cMac" /></label>
<label>{label2} <input type="text" placeholder="{placeholder1}" id="cMac" /></label>
</div>
<div class="col-4">
<label>Name <input type="text" placeholder="EXAMPLE" id="cName" /></label>
<label>{label3} <input type="text" placeholder="{placeholder2}" id="cName" /></label>
</div>
<div class="col-4">
<button class="button-primary" style="width: 100%" onclick="addClient()">add</button>
<button class="button-primary" style="width: 100%" onclick="addClient()">{button5}</button>
</div>
</div>
@@ -84,9 +84,8 @@
</div>
</div>
</div>
<script src="js/stations.js"></script>
</div>
<script src="js/l10n.js" async defer></script>
<script data-src="js/stations.js"></script>
</body>
</html>

View File

@@ -119,6 +119,19 @@ li{
margin: 4px 0;
}
/* language selector */
.flag.selected {
color: black;
}
.flag {
line-height: 1.5em;
padding: 0.2em 0.5em;
margin: 0;
font-weight: bold;
cursor: pointer;
}
/* Meter */
.meter_background{
background: #42464D;

View File

@@ -15,7 +15,7 @@
// Settings //
//#define USE_DISPLAY /* <-- uncomment that if you want to use the display */
#define USE_DISPLAY /* <-- uncomment that if you want to use the display */
#define resetPin 4 /* <-- comment out or change if you need GPIO 4 for other purposes */
#define USE_LED16 /* <-- for the Pocket ESP8266 which has a LED on GPIO 16 to indicate if it's running */
@@ -27,11 +27,11 @@
//include the library you need
#include "SSD1306.h"
#include "SH1106.h"
//create display(Adr, SDA-pin, SCL-pin)
SSD1306 display(0x3c, 5, 4); //GPIO 5 = D1, GPIO 4 = D2
//SH1106 display(0x3c, 5, 4);
//create display(Adr, SDA-pin, SCL-pin)
//SSD1306 display(0x3c, 5, 4); //GPIO 5 = D1, GPIO 4 = D2
SH1106 display(0x3c, 5, 4);
#include "screensaver.h"
//button pins
#define upBtn 12 //GPIO 12 = D6
#define downBtn 13 //GPIO 13 = D7
@@ -144,57 +144,10 @@ void stopWifi() {
wifiMode = "OFF";
}
void loadIndexHTML() {
if(warning){
sendFile(200, "text/html", data_indexHTML, sizeof(data_indexHTML));
}else{
sendFile(200, "text/html", data_apscanHTML, sizeof(data_apscanHTML));
}
}
void loadAPScanHTML() {
warning = false;
sendFile(200, "text/html", data_apscanHTML, sizeof(data_apscanHTML));
}
void loadStationsHTML() {
sendFile(200, "text/html", data_stationsHTML, sizeof(data_stationsHTML));
}
void loadAttackHTML() {
sendFile(200, "text/html", data_attackHTML, sizeof(data_attackHTML));
}
void loadSettingsHTML() {
sendFile(200, "text/html", data_settingsHTML, sizeof(data_settingsHTML));
}
void load404() {
sendFile(200, "text/html", data_errorHTML, sizeof(data_errorHTML));
if(loadFromFlash(server.uri())) return;
sendSPIFFSFile("/error.html", "text/html");
}
void loadInfoHTML(){
sendFile(200, "text/html", data_infoHTML, sizeof(data_infoHTML));
}
void loadLicense(){
sendFile(200, "text/plain", data_license, sizeof(data_license));
}
void loadFunctionsJS() {
sendFile(200, "text/javascript", data_js_functionsJS, sizeof(data_js_functionsJS));
}
void loadAPScanJS() {
sendFile(200, "text/javascript", data_js_apscanJS, sizeof(data_js_apscanJS));
}
void loadStationsJS() {
sendFile(200, "text/javascript", data_js_stationsJS, sizeof(data_js_stationsJS));
}
void loadAttackJS() {
attack.ssidChange = true;
sendFile(200, "text/javascript", data_js_attackJS, sizeof(data_js_attackJS));
}
void loadSettingsJS() {
sendFile(200, "text/javascript", data_js_settingsJS, sizeof(data_js_settingsJS));
}
void loadStyle() {
sendFile(200, "text/css;charset=UTF-8", data_styleCSS, sizeof(data_styleCSS));
}
void startWiFi(bool start) {
if (start) startWifi();
@@ -513,28 +466,9 @@ void setup() {
/* ========== Web Server ========== */
/* HTML */
/* HTML, css, js, json, juste serve everything on the flash */
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);
@@ -703,8 +637,16 @@ void loop() {
display.clear();
display.display();
}
screensavertimer = 0;
lastactivity = millis();
} else {
screensavertimer = millis() - lastactivity;
}
if(screensavertimer>saveeafter) {
drawScreenSaver();
} else {
drawInterface();
}
drawInterface();
#endif
}
}

23983
esp8266_deauther/oui.h Normal file

File diff suppressed because it is too large Load Diff

View File

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

81
utils/update_manuf.py Normal file
View File

@@ -0,0 +1,81 @@
#/usr/bin/env python
"""This scripts downloads the last OUI manufaturer file from the Whireshark
project and converts it to esp8266_deauther format"""
import argparse
from urllib.request import urlopen
WS_MANUF_FILE_URL = "https://code.wireshark.org/review/gitweb?p=wireshark.git;a=blob_plain;f=manuf"
def parse_options():
"""Parses command line options"""
parser = argparse.ArgumentParser()
parser.add_argument("-o", "--output", help="Output file name (e.g oui.h)")
parser.add_argument("-u", "--url", help="Wireshark oui/manuf file url")
opt = parser.parse_args()
return opt
def generate_oui_h(url, filename):
"""Generates the vendors/oui file"""
if url:
data = urlopen(url)
else:
data = urlopen(WS_MANUF_FILE_URL)
out = """#ifndef oui_h
#define oui_h
/*
Based on Wireshark manufacturer database
source: https://www.wireshark.org/tools/oui-lookup.html
Wireshark is released under the GNU General Public License version 2
*/
const static uint8_t data_vendors[] PROGMEM = {///*
"""
for line in data:
line = line.decode()
# Skipping empty lines and comments
if line.startswith('#') or line.startswith('\n'):
continue
mac, short_desc, *rest = line.strip().split('\t')
# Limiting short_desc to 8 chars
short_desc = short_desc[0:8]
# Convert to ascii
short_desc = short_desc.encode("ascii", "ignore").decode()
mac_octects = len(mac.split(':'))
if mac_octects == 6:
continue
else:
# Convert to esp8266_deauther format
short_desc = short_desc.ljust(8, '\0')
hex_sdesc = ", 0x".join("{:02x}".format(ord(c)) for c in short_desc)
(oc1, oc2, oc3) = mac.split(':')
out = out + (" 0x{}, 0x{}, 0x{}, 0x{},\n".format(oc1.upper(), oc2.upper(), oc3.upper(),
hex_sdesc.upper().replace('X', 'x')))
out = out[:-2] # Removing last comma
out = out + "\n};\n#endif"
# Saving to file
if filename:
with open(filename, 'w') as out_file:
out_file.write("%s" % out)
else:
print(out)
if __name__ == "__main__":
options = parse_options()
generate_oui_h(options.url, options.output)

View File

@@ -1,57 +0,0 @@
#!/bin/bash
#
# This script walks through the html folder and minify all JS, HTML and CSS files. It also generates
# the corresponding constants that is added to the data.h file on esp8266_deauther folder.
#
# @Author Erick B. Tedeschi < erickbt86 [at] gmail [dot] com >
#
outputfile="$(pwd)/data_h_temp"
rm $outputfile
function minify_html_css {
file=$1
curl -X POST -s --data-urlencode "input@$file" http://html-minifier.com/raw > /tmp/converter.temp
}
function minify_js {
file=$1
curl -X POST -s --data-urlencode "input@$file" https://javascript-minifier.com/raw > /tmp/converter.temp
}
function ascii2hexCstyle {
file_name=$(constFileName $1)
result=$(cat /tmp/converter.temp | hexdump -ve '1/1 "0x%.2x,"')
result=$(echo $result | sed 's/,$//')
echo "const char data_${file_name}[] PROGMEM = {$result};"
}
function constFileName {
extension=$(echo $1 | egrep -io "(css|js|html)$" | tr "[:lower:]" "[:upper:]")
file=$(echo $1 | sed 's/\.css//' | sed 's/\.html//' | sed 's/\.js//' | sed 's/\.\///' | tr '/' '_' | tr '.' '_')
echo $file$extension
}
cd html
file_list=$(find . -type f)
for file in $file_list; do
echo "Processing: $file"
if [[ "$file" == *.js ]]; then
echo "-> JS minifier"
minify_js $file
ascii2hexCstyle $file >> $outputfile
elif [[ "$file" == *.html ]] || [[ "$file" == *.css ]]; then
echo "-> HTML and CSS minifier"
minify_html_css $file
ascii2hexCstyle $file >> $outputfile
else
echo "-> without minifier"
cat $file > /tmp/converter.temp
ascii2hexCstyle $file >> $outputfile
fi
sleep 1
done

View File

@@ -1,71 +0,0 @@
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Byte Converter</title>
<meta name="description" content="OConvert Text into Hex-Bytes">
<meta name="author" content="Spacehuhn - Stefan Kremser">
<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>
<nav>
<a href="index.html">Converter</a>
<a href="https://github.com/spacehuhn" class="right">GitHub</a>
</nav>
<div class="container">
<div class="row">
<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> (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>
<div class="row">
<div class="col-6">
<textarea id="input"></textarea>
</div>
<div class="col-6">
<textarea id="output" onclick="this.focus();this.select()" readonly="readonly"></textarea>
</div>
</div>
<div class="row">
<div class="col-12">
<button onclick="convert()" class="fullWidth button-primary">convert</button>
</div>
</div>
<div class="row">
<div class="col-12">
<p>Length: <span id="info_len">0</span> Bytes</p>
</div>
</div>
</div>
<script>
String.prototype.convertToHex = function (delim) {
return this.split("").map(function(c) {
return ("0" + c.charCodeAt(0).toString(16)).slice(-2);
}).join(delim || "");
};
function convert(){
var input = $('#input').val().convertToHex(",0x");
$('#output').val("0x"+input);
$('#info_len').html((input.match(new RegExp(",", "g")) || []).length + 1);
}
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@@ -1,40 +0,0 @@
# How to update files inside html folder?
The files related to the Frontend of ESP8266_Deauther are inside html folder.
To reflect on the firmware it needs to be: minified, converted to hex and updated on data.h on esp8266_deauther folder on the root of this project.
The following process can be used:
## Script Mode (Linux/Mac)
**1** Update the desired files on ./html folder
**2** at the command line run the shell script: ./convert_all.sh
**3** open the generated file "data_h_temp" and copy the content (CTRL+C)
**4** Go to data.h and replace the content between the comments like below:
```c
/* constants generated by convert_all.sh - start */
const char data_apscanHTML[] PROGMEM = {0x3c,0x21,0x44,0x4f,0x43...
const char data_attackHTML[] PROGMEM = {0x3c,0x21,0x44,0x4f,0x43...
const char data_errorHTML[] PROGMEM = {0x3c,0x21,0x44,0x4f,0x43,...
const char data_indexHTML[] PROGMEM = {0x3c,0x21,0x44,0x4f,0x43,...
const char data_infoHTML[] PROGMEM = {0x3c,0x21,0x44,0x4f,0x43,0...
const char data_js_apscanJS[] PROGMEM = {0x66,0x75,0x6e,0x63,0x7...
const char data_js_attackJS[] PROGMEM = {0x66,0x75,0x6e,0x63,0x7...
const char data_js_functionsJS[] PROGMEM = {0x66,0x75,0x6e,0x63,...
const char data_js_settingsJS[] PROGMEM = {0x66,0x75,0x6e,0x63,0...
const char data_js_stationsJS[] PROGMEM = {0x66,0x75,0x6e,0x63,0...
const char data_license[] PROGMEM = {0x43,0x6f,0x70,0x79,0x72,0x...
const char data_settingsHTML[] PROGMEM = {0x3c,0x21,0x44,0x4f,0x...
const char data_stationsHTML[] PROGMEM = {0x3c,0x21,0x44,0x4f,0x...
const char data_styleCSS[] PROGMEM = {0x2f,0x2a,0x20,0x47,0x6c,0...
/* constants generated by convert_all.sh - end */
```
## Manual mode
**1** Use a minifier (e.g. htmlcompressor.com) to get your files as small as possible
**2** Open converter.html
**3** Paste the code in the left textfield
**4** Press Convert
**5** Copy the results from the right textfield
**6** Go to data.h and replace the array of the changed file with the copied bytes
**Now compile and upload your new sketch :)**