SkillAgentSearch skills...

Hacktivity2016

Repository for my workshop 'Wifi hacking with a 4 dollar microcontroller' on Hacktivity 2016

Install / Use

/learn @markszabo/Hacktivity2016
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Wifi hacking with a 4 dollar microcontroller

Introduction

The ESP8266 is a wifi enabled microcontroller, which is popular among makers thanks to its low price: the base module costs ~$2 and you can get one with USB connector for $4. In this workshop I will show you three hacks using this module:

  1. Fake captive portal - Captive portals are widely used in hotels and other public networks, where the wifi network is open, but upon connection a login page is showed to the user. We will see how to setup a fake captive portal and collect the login credentials. This exercises will show the basic capabilities of the microcontroller and how to use the existing functions.
  2. Send beacon frames - These packets are used to introduce wifi networks, so if we send them with random SSID and MAC, whenever someone scans for wifi they will see a lot of new wifi networks, but they will not be able to connect to them.
  3. Send deauthentication frames - We will continue with raw packets, and see how to send deauthentication packets to a client to make them drop their connection.

About ESP8266

The ESP8266 is a low-cost Wi-Fi chip with full TCP/IP stack and MCU (Micro Controller Unit) capability produced by Shanghai-based Chinese manufacturer, Espressif Systems.

Technical details:

  • 32-bit RISC CPU: Tensilica Xtensa LX106 running at 80 MHz
  • 64 KiB of instruction RAM, 96 KiB of data RAM
  • External QSPI flash - 512 KiB to 4 MiB (up to 16 MiB is supported)
  • IEEE 802.11 b/g/n Wi-Fi
  • Integrated TR switch, balun, LNA, power amplifier and matching network
  • WEP or WPA/WPA2 authentication, or open networks
  • 16 GPIO pins
  • SPI, I²C,
  • I²S interfaces with DMA (sharing pins with GPIO)
  • UART on dedicated pins, plus a transmit-only UART can be enabled on GPIO2
  • 1 10-bit ADC

Source and more info: Wikipedia, Espressif.

Setting up the environment

  1. Download the Arduino IDE from arduino.cc
  2. Start Arduino IDE, go to File > Preferences and add http://arduino.esp8266.com/stable/package_esp8266com_index.json under Additional board manager.
  3. Go to Tools > Board > Board Manager, search for ESP8266 and install it.
  4. Go to Tools > Board and select Generic ESP8266 module (if your hardware looks like an Arduino, then you have the WeMos D1 and you need to select WeMos D1 (retired)).

Test the environment setup

To test the setup let's upload two simple example: blink and WifiScan.

Blink

  1. Go to File > Examples > Basics > Blink
  2. Rewrite every 13 to 2, since the ESP8266 has its build-in led on GPIO 2.
  3. Connect ESP8266 to your computer and select the right port under Tools > Port.
  4. Click Upload
  5. While it compiles (and before upload) press and hold the flash button (on the ESP8266) and press reset once, to make the microcontroller enter flash mode. If the upload fails, check the port. If still fails, make sure it enters flash mode. Hold flash and press reset multiple times before it starts to upload. (If you have the WeMos D1 or an other ESP without flash button, you can just simply press Upload and wait. If it fails first, just repeat.)
  6. The ESP8266 should blink with its build in led.
  7. Bonus: change it to blink faster, try to find an other build in LED (pin definition from the slides might help).

WifiScan

  1. Go to File > Examples > ESP8266Wifi > WifiScan
  2. Upload it as before (don't forget to enter flash mode)
  3. Go to Tools > Serial Monitor and set the Baudrate to 115200 (in the bottom right corner)
  4. Wait a few seconds and see the nearby Wifi networks listed. If you see gibberish characters, check the baudrate.
  5. Bonus: display other information on the Wifi networks, for example channel. (hint: ESP8266WiFi.h).

Fake captive portal

The scenario

You are staying in the imaginary Hotel Hacktivity. It has an open wifi HotelHacktivity but upon connection you are faced with the following captive portal to enter your access code:

"Captive portal of Hotel Hacktivity"

Every guest receives an access code at check-in, but you have lost yours. Can you get someone else's code?

The code

Open Examples > DNSServer > CaptivePortal, and upload it.

Connect to the Wifi DNSServer CaptivePortal example and go to any http website (eg. bbc.com or hotelhacktivity.com. Doesn't matter if it exists or not.) You will be faced with a captive portal.

First change the name of the network in the 18th line: WiFi.softAP("DNSServer CaptivePortal example");. In reality we would set it to HotelHacktivity but to avoid collusion with others, please set it to something else (eg. add a random number to the end like HotelHacktivity5943, or use your nickname). Upload & test.

Let's add the login.php! Open Examples > ESP8266WebServer > HelloServer to see an example, or just follow my instructions.

Based on HelloServer add the following lines between webServer.onNotFound([](){...}); and webServer.begin():

webServer.on("/login.php", []() {
  webServer.send(200, "text/html", "TODO: implement login form here");
});

Upload, connect and go to anysite.com/login.php (sine the ESP8266 is working as a DNS server, it will reply to any domain with its own ip address, so the url doesn't matter).

Add the actual login page. In real life we would save the html code of the actual login page, now let's use my code. Declare the following new variable outside any function (eg. after String responseHTML):

String login = ""
"<!DOCTYPE html>"
"<html>"
"<head>"
"  <title>Login</title>"
"  <meta charset=\"utf-8\">"
"  <style>"
"    body {"
"      color: #FFFFFF;"
"      background: rgb(0, 132, 121);"
"      margin: 0px;"
"    }"
"    #header {"
"      padding: 30px;"
"      font-size: 40px;"
"      background: rgb(36, 35, 51);"
"    }"
"    #login {"
"      text-align:center;"
"      padding: 100px;"
"      background: rgb(0, 132, 121);"
"    }"
"    #submit {"
"      padding: 10px;"
"    }"
"  </style>"
"</head>"
"<body>"
"<div id=\"header\">"
"  <img src=\""
"https://hacktivity.com/images/news/170x170/9e13bf40.jpg"
"\" width=\"60px\" height=\"60px\"> Hotel Hacktivity Wifi Service"
"</div>"
"<div id=\"login\">"
"  <h2>Please enter your access code:</h2>"
"  <form action=\"login.php\" method=\"get\">"
"   <div>Access code: <input type=\"text\" name=\"code\" autofocus></div>"
"   <div id=\"submit\"><input type=\"submit\" value=\"Submit\"></div>"
"  </form>"
"</div>"
"</body>"
"</html>";

Also change the previously added code to use this variable (replace "TODO: implement login form here" with login):

webServer.on("/login.php", []() {
  webServer.send(200, "text/html", login);
});

Upload and test: go to anysite.com/login.php to see the login page, and go to anysite.com to see the original captive portal.

Instead of the original captive portal, we need it to redirect the visitors to http://www.hotelhacktivity.com/login.php. So let's change webServer.onNotFound into the following:

webServer.onNotFound([]() {
  webServer.sendHeader("Location", String("http://www.hotelhacktivity.com/login.php"), true);
  webServer.send(302, "text/plain", "");
});

This will send an http response with code 302 (redirect) and Location set to http://www.hotelhacktivity.com/login.php if any page but /login.php is visited.

Upload, test the redirect. If you look closely, the image in the header is not displayed (or if it is, then it's from cache). Fortunately html supports base64 encoded images. To do this, we would need to download the image, resize and compress it (I used jpg quality 50% in Gimp), and then base64 encode it (either use a website like b64.io or base64-image.de or use this linux command: cat HacktivityLogoSmall.jpg | base64. Either do these things, or just use my code below. Change the login string into the following:

String login = ""
"<!DOCTYPE html>"
"<html>"
"<head>"
"  <title>Login</title>"
"  <meta charset=\"utf-8\">"
"  <style>"
"    body {"
"      color: #FFFFFF;"
"      background: rgb(0, 132, 121);"
"      margin: 0px;"
"    }"
"    #header {"
"      padding: 30px;"
"      font-size: 40px;"
"      background: rgb(36, 35, 51);"
"    }"
"    #login {"
"      text-align:center;"
"      padding: 100px;"
"      background: rgb(0, 132, 121);"
"    }"
"    #submit {"
"      padding: 10px;"
"    }"
"  </style>"
"</head>"
"<body>"
"<div id=\"header\">"
"  <img src=\""
"data:image/jpeg;base64,"
"/9j/4AAQSkZJRgABAQEASABIAAD/4QecaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hw"
"YWNrZXQgYmVnaW49J++7vycgaWQ9J1c1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCc/Pgo8eDp4bXBt"
"ZXRhIHhtbG5zOng9J2Fkb2JlOm5zOm1ldGEvJz4KPHJkZjpSREYgeG1sbnM6cmRmPSdodHRwOi8v"
"d3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjJz4KCiA8cmRmOkRlc2NyaXB0aW9u"
"IHhtbG5zOmRjPSdodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyc+CiAgPGRjOmZvcm1h"
"dD5pbWFnZS9qcGVnPC9kYzpmb3JtYXQ+CiAgPGRjOnRpdGxlPgogICA8cmRmOkFsdD4KICAgIDxy"
"ZGY6bGkgeG1sOmxhbmc9J3gtZGVmYXVsdCc+eC1kZWZhdWx0PC9yZGY6bGk+CiAgIDwvcmRmOkFs"
"dD4KICA8L2RjOnRpdGxlPgogPC9yZGY6RGVzY3JpcHRpb24+CgogPHJkZjpEZXNjcmlwdGlvbiB4"
"bWxuczp4bXA9J2h0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8nPgogIDx4bXA6TWV0YWRhdGFE"
"YXRlPjIwMTUtMDQtMTZUMjM6Mzg6NDcrMDI6MDA8L3htcDpNZXRhZGF0YURhdGU+CiAgPHhtcDpN"
"b2RpZnlEYXRlPjIwMTUtMDQtMTZUMjE6Mzg6NTdaPC94bXA6TW9kaWZ5RGF0ZT4KICA8eG1wOkNy"
"ZWF0ZURhdGU+MjAxNS0wNC0xNlQyMzozODo0NyswMjowMDwveG1wOkNyZWF0ZURhdGU+CiAgPHht"
"cDpDcmVhdG9yVG9v

Related Skills

View on GitHub
GitHub Stars43
CategoryDevelopment
Updated2mo ago
Forks10

Languages

Arduino

Security Score

75/100

Audited on Jan 24, 2026

No findings