Skip to content

haKC-ai/CapturedPortal

Repository files navigation

Captured Portal

Captured Portal

Captured Portal

PlatformIO Python 3.13 hakcer ESP32

                                                                  /\        
 _ _ __________________________________________________________  /  \__ _ _ 
 __ __ __ ____________________________________________________ \/ /\____ ___
   |  Notes from the author:                                  \  /        |
   |                                                           \/         |
   |  If you or a loved one are fond of wifi #hacking tools, #ESP32       |
   |  based devices, #LLMs and other octothorpable terms please keep      |
   |  reading.                                                            |
   |                                                                      |
   |  Since I have enough #microcontrollers to be an Adafruit Industries  |
   |  distribution center I thought I should probably start using them.   |
   |                                                                      |
   |  Captured Portal is an ESP32-based captive portal scanner and        |
   |  credential enumerator. In simple terms, it finds an open AP,        |
   |  decides if its a captive portal then enumerates it and will tell    |
   |  you exactly what room and name combinations work. It tests for      |
   |  administrative and other goodies by using the known vendors that    |
   |  supply the majority of these services for industry.                 |
   |                                                                      |
   |  It automatically detects hotel/hospital/airport/conference/etc      |
   |  style WiFi captive portals, analyzes login forms using on device    |
   |  TINY LLMs to identify field types (room number, last name, access   |
   |  codes), then brute-forces valid combinations using built-in         |
   |  wordlists.                                                          |
   |                                                                      |
   |  It runs standalone on the device, or during build configure it to   |
   |  host a web server for all the work.                                 |
   |                                                                      |
   |  Speaking of configuration, it even includes an interactive build    |
   |  system with automatic hardware detection, the ability to detect     |
   |  when the device is on battery or USB power and gain new             |
   |  capabilities when plugged in. Best of all, because I hate having    |
   |  to setup the environment when building these things, ive automated  |
   |  that for you, and builds and flashes everything for you.            |
   |                                                                      |
   |  remember, theres no cheating in hacking.                            |
   |                                                                      |
   |                                     Greetz to the real ones. cory    |
   |*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^*|
        NAME..............................Captured Portal v1.0  
        Collective................................haKC.ai
        System.............................ESP32 / ESP32-S3
        Size.................1 MCU + Wordlists + Audacity
        Supplied by............................/dev/COR.23  
        Release date..................................2025  

        GROUP NEWS: haKC.ai Still Looking For Embedded Devs
                    & RF Enthusiasts. Hit cory@haKC.ai

        GR33TZ: SecKC, haKC.ai, Adafruit, the ESP32 silicon
                gods, anyone still flashing firmware at 3am

        SHOUTZ:
                [*] Badge lords & their blinkenlights
                [*] Packet sniffers with purpose
                [*] Anyone who reads datasheets for fun

                   FU to [LAMERZ] still asking for the WiFi
                          password at DEF CON

             ----- + signed, /dev/COR.23: + -----

How it works

flowchart TB
 subgraph Parse["HTML PARSING"]
        HTML[/"Portal HTML"/]
        Extract["Extract input fields"]
        Detect["Detect field types"]
  end
 subgraph Fields["FIELD DETECTION"]
        Room["room, number, rm"]
        Name["last, surname, family"]
        Email["email, mail"]
        Code["code, access, pin"]
  end
 subgraph Wordlists["WORDLISTS"]
        Rooms["~90 Room Numbers<br>101, 102... 1103<br>A1, A2, B1, C3"]
        Names["~60 Surnames<br>Smith, Johnson<br>Kennedy, Garcia, Patel"]
  end
 subgraph Bruteforce["ENUMERATION"]
        Combo["Generate Combinations"]
        Test1["101 + Smith"]
        Test2["101 + Johnson"]
        Test3["102 + Smith"]
        TestN["... + ..."]
        POST["POST to /login"]
  end
 subgraph Response["RESPONSE ANALYSIS"]
        Check{{"Check Response"}}
        Success["SUCCESS<br>welcome, connected<br>authenticated, success"]
        Failure["FAILURE<br>invalid, error<br>incorrect, wrong"]
  end
 subgraph Results["RESULTS"]
        Log["Log to successes"]
        JSON@{ label: "{'room':'101','name':'Kennedy'}" }
        Stats["Valid combos found<br>Estimated room count<br>Venue insights"]
  end
    HTML --> Extract --> Detect
    Detect --> Room & Name & Email & Code
    Room & Name --> Rooms & Names
    Rooms & Names --> Combo
    Combo --> Test1 & Test2 & Test3 & TestN
    Test1 & Test2 & Test3 & TestN --> POST
    POST --> Check
    Check -- Keywords found --> Success
    Check -- Error keywords --> Failure
    Success --> Log --> JSON --> Stats
    Failure -. Next combo .-> Combo

    JSON@{ shape: lean-r}
    style HTML fill:#e94560,stroke:#fff,color:#fff
    style Check fill:#ff00ff,stroke:#fff,color:#fff
    style JSON fill:#00ff41,stroke:#000,color:#000
    style Fields fill:#16213e,stroke:#0f3460,stroke-width:2px,color:#fff
    style Wordlists fill:#0f3460,stroke:#00ff41,stroke-width:2px,color:#fff
    style Bruteforce fill:#1a1a2e,stroke:#ff00ff,stroke-width:3px,color:#fff
    style Parse fill:#1a1a2e,stroke:#e94560,stroke-width:2px,color:#fff
    style Response fill:#16213e,stroke:#00ff41,stroke-width:2px,color:#fff
    style Results fill:#0f3460,stroke:#e94560,stroke-width:2px,color:#fff
Loading

Features

  • Captive Portal Detection - Automatically scans for and identifies captive portals
  • LLM-Powered Analysis - On-device AI analyzes portal responses to extract venue information
  • Credential Enumeration - Tests room numbers and surnames to discover valid combinations
  • Hacker Aesthetic UI - Matrix-style animations, decrypt effects, synthwave colors
  • Dual Interface - Physical display + web dashboard
  • Dual Power Mode - Battery-powered standalone OR USB-powered with boosted capabilities
  • Data Logging - Stores all findings for later review

Quick Start

build23b.mp4

How It's Built

System Architecture

graph TB
    subgraph Device[ESP32-S3 Device]
        Scanner[WiFi Scanner]
        Portal[Portal Detector]
        Enum[Enumerator]
        LLM[LLM Engine]
        UI[Display UI]
        Web[Web Server]
        Power[Power Manager]
    end

    subgraph External[External]
        WiFi[Open WiFi Networks]
        CP[Captive Portals]
        Browser[Web Browser]
    end

    WiFi --> Scanner
    Scanner --> Portal
    Portal --> CP
    CP --> Enum
    CP --> LLM
    LLM --> UI
    Enum --> UI
    Web --> Browser
    Power --> Scanner
    Power --> Web

    style Device fill:#1a1a2e,stroke:#0f3460,color:#fff
    style External fill:#16213e,stroke:#0f3460,color:#fff
    style Scanner fill:#e94560,stroke:#0f3460,color:#fff
    style Portal fill:#e94560,stroke:#0f3460,color:#fff
    style Enum fill:#e94560,stroke:#0f3460,color:#fff
    style LLM fill:#16213e,stroke:#0f3460,color:#fff
    style UI fill:#16213e,stroke:#0f3460,color:#fff
    style Web fill:#16213e,stroke:#0f3460,color:#fff
    style Power fill:#16213e,stroke:#0f3460,color:#fff
    style WiFi fill:#0f3460,stroke:#e94560,color:#fff
    style CP fill:#0f3460,stroke:#e94560,color:#fff
    style Browser fill:#0f3460,stroke:#e94560,color:#fff
Loading

Detection Flow

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#1a1a2e', 'primaryTextColor': '#fff', 'primaryBorderColor': '#e94560', 'lineColor': '#e94560', 'secondaryColor': '#16213e', 'tertiaryColor': '#0f3460', 'actorBkg': '#e94560', 'actorTextColor': '#fff', 'actorLineColor': '#0f3460', 'signalColor': '#e94560', 'signalTextColor': '#fff'}}}%%
sequenceDiagram
    participant D as Device
    participant W as WiFi Network
    participant C as Captive Portal
    participant L as LLM Engine

    D->>W: Scan for open networks
    W-->>D: Network list
    D->>W: Connect to network
    D->>C: Request connectivity check
    C-->>D: 302 Redirect
    D->>D: Portal detected!
    D->>C: Fetch portal HTML
    C-->>D: Login page HTML
    D->>L: Analyze HTML
    L-->>D: Venue info + fields
    D->>D: Begin enumeration
Loading

Power Mode States

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e94560', 'primaryTextColor': '#fff', 'primaryBorderColor': '#0f3460', 'lineColor': '#e94560', 'secondaryColor': '#16213e', 'tertiaryColor': '#1a1a2e', 'background': '#1a1a2e', 'mainBkg': '#1a1a2e', 'stateBkg': '#16213e', 'stateTextColor': '#fff', 'stateLabelColor': '#fff', 'transitionColor': '#e94560', 'transitionLabelColor': '#fff'}}}%%
stateDiagram-v2
    [*] --> Boot
    Boot --> DetectPower

    DetectPower --> BatteryMode: No USB
    DetectPower --> USBMode: USB Connected

    BatteryMode --> Scanning: Start scan
    USBMode --> Scanning: Start scan

    Scanning --> PortalFound: Portal detected
    Scanning --> Idle: No portals

    PortalFound --> Analyzing: USB Mode
    PortalFound --> Enumerating: Battery Mode

    Analyzing --> Enumerating: Analysis complete
    Enumerating --> Idle: Complete

    Idle --> DeepSleep: Timeout
    Idle --> Scanning: User input

    DeepSleep --> [*]
Loading

Captive Portal Detection

  1. Scans for open WiFi networks
  2. Connects and requests http://connectivitycheck.gstatic.com/generate_204
  3. If redirected (302) or content differs, it's a captive portal
  4. Captures portal HTML for analysis

Credential Enumeration

  1. Analyzes portal form fields (room number, last name, etc.)
  2. Uses wordlists (data/wordlists/room_numbers.txt, data/wordlists/surnames.txt)
  3. Tests combinations based on detected field types
  4. Logs successful combinations
  5. Estimates venue size from valid room numbers

Captured Portal

LLM Analysis (USB Mode)

  1. Feeds captured HTML to on-device LLM
  2. Extracts: venue name, type, form fields, security issues
  3. Provides enumeration strategy recommendations

Easy Install (Recommended)

# Clone this repo
git clone https://github.com/haKC-ai/CapturedPortal.git
cd CapturedPortal

# Run the installer (creates venv, installs deps, launches build tool)
./installer.sh

The installer will:

  • Create a Python 3.13 virtual environment
  • Install all dependencies (hakcer, platformio)
  • Launch the interactive build tool with menus for:
    • Build & Flash - Configure hardware, colors, network, then build/upload
    • Test Portal - Run a fake captive portal server for testing

Hardware Build Guide

Supported Boards (Available on Amazon)

Board Price Display Best For
LILYGO T-Display S3 ~$20 1.9" LCD Recommended - Great balance
LILYGO T-Deck ~$50 2.8" LCD + Keyboard Full Featured - Keyboard + Trackball
Waveshare LCD 1.47 ~$13 1.47" LCD USB Dongle form factor
ESP32-S3 Round 1.28" ~$15 1.28" Round Compact watch-like
Waveshare Touch 1.69 ~$25 1.69" Touch Touch interface

LILYGO T-Display S3 (Recommended Budget Option)

Price: ~$20 | Display: 1.9" color LCD (170x320)

Component Link Price
LILYGO T-Display-S3 Amazon ~$20
3.7V LiPo Battery (optional) Amazon ~$10

Specs:

  • ESP32-S3 dual-core @ 240MHz
  • 16MB Flash, 8MB PSRAM
  • Two programmable buttons
  • Battery charging built-in
  • WiFi + Bluetooth 5.0

Assembly: No soldering required! Just flash and go. Optional battery connects via JST connector.


LILYGO T-Deck (Full Featured Option)

Price: ~$50 | Display: 2.8" LCD (320x240) + Physical Keyboard

Component Link Price
LILYGO T-Deck Amazon ~$50
LILYGO T-Deck (with LoRa) LILYGO Store ~$60

Specs:

  • ESP32-S3 dual-core @ 240MHz
  • 16MB Flash, 8MB PSRAM
  • Full QWERTY keyboard - Type room numbers, names directly
  • Trackball navigation - Scroll through networks smoothly
  • Built-in speaker and microphone
  • Optional LoRa radio (433/868/915MHz)
  • SD card slot for extended logging
  • Battery charging built-in

Why T-Deck?

  • Type credentials directly for manual testing
  • Trackball makes navigation fast
  • Larger screen shows more networks at once
  • LoRa version can share findings with other devices

Assembly: Ready to use out of the box. Power on and the keyboard/trackball work automatically.

Controls:

Input Action
Trackball Up/Down Navigate list
Trackball Left/Right Switch screens
Trackball Click Select / Short: action, Long: scan
Keyboard Type directly into fields

Other Options

Waveshare ESP32-S3 LCD 1.47 (~$13)

USB dongle form factor. Plugs directly into any USB port. Great for covert use.

ESP32-S3 Round 1.28" (~$15)

Compact watch-like form factor. Built-in IMU. Smallest option.

Waveshare Touch 1.69" (~$25)

Capacitive touch screen. No buttons needed - tap to interact.


Software Setup

Prerequisites

  • Python 3.13 (recommended) or 3.9+
  • USB cable for your board

Method 1: Interactive Installer (Recommended)

git clone https://github.com/haKC-ai/CapturedPortal.git
cd CapturedPortal
./installer.sh

The installer:

  1. Creates a Python 3.13 virtual environment in .venv/
  2. Installs dependencies from tools/requirements.txt
  3. Launches tools/build.py with an interactive menu

The build tool uses the hakcer library for cool terminal effects and provides:

  • Menu 1: Build & Flash - Hardware selection, color scheme, network config, build/upload
  • Menu 2: Test Portal - Run fake captive portals for device testing

Method 2: Manual Setup

# Clone repo
git clone https://github.com/haKC-ai/CapturedPortal.git
cd CapturedPortal

# Create venv and install deps
python3.13 -m venv .venv
source .venv/bin/activate
pip install -r tools/requirements.txt

# Build for your board
pio run -e lilygo-t-display-s3    # T-Display S3
pio run -e lilygo-t-deck          # T-Deck
pio run -e waveshare-esp32s3-lcd147  # Waveshare Dongle

# Upload firmware
pio run -t upload

# Upload web interface
pio run -t uploadfs

Configuration

Edit include/config.h or use the build tool:

// Color scheme
#define COLOR_SCHEME COLOR_MATRIX  // COLOR_MATRIX, COLOR_SYNTHWAVE, COLOR_CYBERPUNK, COLOR_DRACULA

// WiFi AP settings
#define AP_SSID_PREFIX "CapturedPortal_"
#define AP_PASSWORD ""  // Empty = open network

// Enable web server on battery (uses more power)
#define WEB_SERVER_ON_BATTERY false

// Scan intervals
#define BATTERY_SCAN_INTERVAL 10000  // 10s on battery
#define USB_SCAN_INTERVAL 3000       // 3s on USB

Testing

Test Captive Portal Server

Run a fake captive portal on your computer to test the device:

# List available portal types
python3 tools/test_portal.py --list

# Run hotel portal (default)
python3 tools/test_portal.py

# Run specific portal type
python3 tools/test_portal.py -t airport
python3 tools/test_portal.py -t cafe
python3 tools/test_portal.py -t conference
python3 tools/test_portal.py -t hospital

To test:

  1. Create a WiFi hotspot on your computer
  2. Run python3 tools/test_portal.py
  3. Connect your Captured Portal device to the hotspot
  4. The device will detect and analyze the test portal

Available test portals:

Type Fields Valid Test Credentials
hotel Room + Last Name Rooms: 101, 201, 420 / Names: smith, guest
airport Email Any valid email format
cafe Access Code COFFEE2024, LATTE, 1234
conference Badge ID + Email TC001, TC002, SPEAKER, VIP
hospital Patient Room + Name ICU1, 101, ER1

Usage

Power Modes

Mode Power Source Capabilities
Standalone Battery Scanning, display UI, logging
Boosted USB + Web server, LLM analysis, faster scans

Set WEB_SERVER_ON_BATTERY true in config to enable web server on battery (drains faster).

Physical Controls

T-Display S3 / Button boards:

Button Short Press Long Press
Left Scroll up Start scan
Right Scroll down Select/Connect

T-Deck:

Input Action
Trackball Navigate in all directions
Trackball Click Short: Select, Long: Scan
Keyboard Type directly

Web Interface

When web server is running:

  1. Connect to WiFi: CapturedPortal_XXXX
  2. Open: http://192.168.4.1
  3. Features:
    • Real-time network scanner
    • Portal analysis dashboard
    • Enumeration controls
    • LLM insights
    • Activity log

Project Structure

CapturedPortal/
├── installer.sh              # Main installer script
├── banner                    # ASCII art banner
├── platformio.ini            # Build configuration
├── DISCLAIMER.md             # Legal disclaimer
├── USAGE_GUIDELINES.md       # Acceptable use policy
├── RESPONSIBLE_DISCLOSURE.md # Vulnerability disclosure policy
├── CODE_OF_CONDUCT.md        # Community standards
├── src/
│   ├── main.cpp              # Entry point
│   ├── core/
│   │   ├── scanner.cpp       # WiFi scanning & portal detection
│   │   ├── enumerator.cpp    # Credential enumeration
│   │   └── power.cpp         # Power management
│   ├── display/
│   │   ├── ui.cpp            # Display UI
│   │   └── effects.cpp       # Hacker animations
│   ├── web/
│   │   └── server.cpp        # Web server & API
│   └── llm/
│       └── engine.cpp        # LLM inference
├── include/
│   └── config.h              # Configuration
├── data/
│   ├── web/                  # Web UI files
│   └── wordlists/            # Enumeration wordlists
└── tools/
    ├── requirements.txt      # Python dependencies (hakcer, platformio, pyserial)
    ├── build.py              # Build & test menu tool
    └── test_portal.py        # Test captive portal server

Legal and Ethical Use

This tool is intended for authorized security testing only.

Before using this tool, you must:

  1. Read the Disclaimer
  2. Review the Usage Guidelines
  3. Understand the Responsible Disclosure Policy
  4. Agree to the Code of Conduct

Unauthorized access to computer systems is a crime. The authors assume no liability for misuse.

By using this software, you accept full responsibility for ensuring your use complies with all applicable laws.


License

MIT License - hack responsibly.


Credits

  • Inspired by the hakcer Python library aesthetic
  • LLM engine based on esp32-llm
  • Built with love for the hacker community

About

An ESP32-based captive portal scanner and credential enumerator. Automatically detects hotel style WiFi captive portals, analyzes login forms to identify field types (room number, last name, access codes), then brute-forces valid combinations using built-in wordlists. Includes an interactive build system with automatic hardware detection.

Topics

Resources

Code of conduct

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors