The ESP32 is an incredibly versatile chip that comes in all kinds of forms and devices. From smart "Now Playing"-style displays to security systems, it can do a whole lot. For those with a supported display, you can even turn it into a Flipper Zero-competitor of sorts thanks to Marauder. However, I decided to build my own Wi-Fi scanner and honeypot using a regular ESP32-S3 and a Python server on my computer.

You see, the options out there require an ESP32 with a display to be used to their full capabilities. Marauder does have a headless mode, but it still requires an SD card at the very least to dump the collected data to. I wanted a simple way to mimic some of that functionality (complete with an "Evil Portal") using just an ESP32: nothing else.

These tools should only be used for testing your own home internet and devices. This article is for educational purposes only and has been written to demonstrate how the ESP32 is a powerful tool that anyone can use to test their own security.

Making a plan and a dashboard

What use is data if it's not easy to see?

The ESP32 has a "station" mode, which allows an ESP32 to create its own local network for devices to connect to the portal while maintaining its own connection to the internet. We can conceivably host an open access point on the ESP32 while connecting to a central command and control server for reporting data back to. No display or SD card required, and it just requires crafting a receiver.

It took a while to get station mode working, and I initially opted to simply collect data and then report it in minute intervals, shutting off the AP in between. That's when I realized I was using a blocking call every time I collected data, so... yeah. It threw off all of my logic, and even though it technically worked and I could see reports streaming in from the ESP32, it caused frequent timeouts.

Once I'd overcome that hurdle, the plan was simple:

  • Host an access point on the ESP32 with a web server and wildcard DNS server
    • The DNS server resolves all hostnames to the ESP32's IP
  • Serve a web page to anyone who connects to it where they are prompted to log in
  • Log the ESP32 reporting the data to the central server, log the credentials used
    • We do this as a central server could be monitoring multiple ESP32 devices
    • This could be modified to return the client's MAC and hostname instead
  • Redirect the user to Google and disconnect them from the AP

As for the Wi-Fi scanner, that part is simple. We just scan every Wi-Fi network the ESP32 picks up, then pull some of the data and save it. These are:

  • SSID
  • RSSI
  • Channel
  • Encryption type
  • BSSID

I also tried to capture the user-agent of a client, though I never ended up implementing it. Finally, I have built in functionality to capture the URL that a user attempts to resolve once connected to the ESP32. However, I haven't completed that.

Finally, I created a dashboard as well. The dashboard doesn't contain all of the stats, and serves as a quick way to look at the incoming data. There's a JSON endpoint that shows you more detailed information, such as the Wi-Fi scanner reports.

Building the ESP32 honeypot

There's a GitHub repository with all of the code

To build this, first initiate the ESP32-S3 in AP+STA mode, bringing up a soft AP that redirects all client DNS lookups. It then serves a basic captive portal with a login form while scanning nearby networks. Finally, the collected data is serialized to JSON and submitted to the Python helper server with a POST request.

For building this, I started off with PlatformIO, but I ran into issues when it came to flashing. So, I switched to Arduino IDE, and installed the following libraries:

  • ArduinoJson
  • NTPClient

Everything else is in the arduino-esp32 library. Next I set up the connection details for both the access point on the ESP32 itself, and for connecting to my network. I also define the connection details for reporting the collected data.

All collected information is submitted to the server, and network scanning results are batched into a JSON array and sent in interval time periods, too. The data I collected here is also not everything that you can collect, and you could spend time building Marauder's functionality into it, such as PMKID sniffing, as well.

If you want to check out everything that I've built so far, I've published a GitHub repository containing all of the code. There are very likely to be bugs and the code is "unfinished," though it will likely not be updated in the future.

The ESP32 can do it all

The limit is your imagination

The reason I undertook this project was to prove that the ESP32 can do a lot even without a display. It's a little bit janky, but also, it was a morning project that I whipped up in a couple of hours as a proof of concept. You can scan your networks, check for channel interference, and more.

In a sense, it's proof that the ESP32 can do a lot even without a display. You definitely need some workarounds without an SD card either, but it does work, and you can use unique aspects of the ESP32, like using it in station mode, to forward data over the network while still hosting an access point, too.

If you didn't want an access point, and instead wanted to host a web portal on it to serve as a display, that would likely work significantly better than trying to host an access point alongside the regular Wi-Fi connectivity stack. There's a lot of room to do unique things with these microcontrollers, and a honeypot and Wi-Fi scanner is merely scratching the surface.