< back to research

WiFi Pentesting: WPA2 & WPS

This covers two attack paths against WiFi networks - WPA2 handshake capture and WPS exploitation - along with a wordlist generation approach that actually makes sense for targeted attacks. Everything here is for authorized testing on networks you own or have explicit permission to test.

You need a wireless card that supports monitor mode and packet injection. Most Alfa cards work. Built-in cards on laptops usually don't.

Setup

Before anything, kill whatever is going to interfere with your wireless card. NetworkManager, wpa_supplicant, dhclient - they all try to manage the interface and will corrupt your captures if left running.

sudo airmon-ng check kill
sudo airmon-ng start wlan0
# interface is now wlan0mon

airmon-ng check kill does the dirty work of identifying and killing conflicting processes. If it prints a list of PIDs it killed, good. If your interface name isn't wlan0 check ip link first.

At the end of your session, bring everything back:

sudo airmon-ng stop wlan0mon
sudo systemctl restart NetworkManager

WPA2 - Handshake Capture

WPA2 doesn't get cracked in real time. What you're actually doing is capturing a 4-way handshake between a client and the AP, then cracking it offline. The handshake contains enough information to verify password guesses without ever touching the router again.

1. Scan

sudo airodump-ng wlan0mon

This shows everything in range. You want the target's BSSID (MAC address of the AP), CH (channel), and ESSID (network name). Ctrl+C once you have what you need.

2. Lock onto the target

sudo airodump-ng -c [CH] --bssid [BSSID] -w ~/wifi-crack/captures/handshake wlan0mon

Leave this terminal running. It's now only listening on that channel and BSSID, writing everything to handshake-01.cap. The bottom section will start showing connected clients under STATION as devices communicate.

3. Deauth a client

You need a client to reconnect to the AP so you can catch the handshake. A deauth frame forces that reconnect. Open a second terminal and send a few:

# targeted - preferred, less noise
sudo aireplay-ng -0 3 -a [BSSID] -c [STATION_MAC] wlan0mon

The -0 3 means send 3 deauth frames. Three is enough. Don't go higher - flooding deauths doesn't help and makes the capture messier. If no clients are showing yet just wait, they'll appear as devices communicate naturally.

If you genuinely have no clients and can't wait, broadcast deauth as a last resort:

# broadcast fallback - use sparingly
sudo aireplay-ng -0 3 -a [BSSID] wlan0mon

Watch terminal 1 for WPA handshake: AA:BB:CC:DD:EE:FF in the top right. The moment you see it, Ctrl+C on the airodump terminal. You have what you need.

4. Crack it

You have two options - CPU via aircrack-ng, or GPU via hashcat. GPU wins by a large margin. On a modern card, hashcat will be 50-100x faster than aircrack on CPU.

CPU (aircrack-ng):

aircrack-ng ~/wifi-crack/captures/handshake-01.cap -w ~/wifi-crack/wordlists/rockyou.txt

GPU (hashcat - do this instead):

# convert the .cap to hashcat format first
hcxpcapngtool -o ~/wifi-crack/captures/handshake.hc22000 ~/wifi-crack/captures/handshake-01.cap

# crack
hashcat -m 22000 ~/wifi-crack/captures/handshake.hc22000 ~/wifi-crack/wordlists/rockyou.txt

-m 22000 is the WPA2 mode in hashcat. The hc22000 format contains both the PMKID (if captured) and the EAPOL handshake, so hashcat can work with either.

rockyou.txt is fine as a starting point. It's 14 million passwords from a real breach and covers a lot of common choices. But if the target is a home network, a targeted wordlist will almost always outperform it - more on that below.

WPS - Two Attack Paths

WPS (Wi-Fi Protected Setup) is a feature that lets devices connect via an 8-digit PIN instead of the full password. The PIN design is broken - it's validated in two halves, meaning there are only 11,000 possible combinations rather than 100 million. Many routers also have a Pixie Dust vulnerability that leaks the PIN immediately.

1. Scan for WPS targets

sudo wash -i wlan0mon

Look for WPS Locked: No. A locked AP has rate-limited or disabled WPS after too many failed attempts - still sometimes worth trying Pixie Dust, but brute force is pointless against it. Note the BSSID of anything unlocked.

2. Pixie Dust - try this first

sudo reaver -i wlan0mon -b [BSSID] -K 1 -vv

Pixie Dust works by exploiting weak random number generation in the router's WPS implementation. On vulnerable devices it recovers the PIN in seconds with a single exchange. -K 1 enables it. If it works, reaver will print the WPS PIN and the actual WPA2 password.

If it fails (not all routers are vulnerable), fall back to brute force:

3. Brute force

sudo reaver -i wlan0mon -b [BSSID] -vv

This tries all PIN combinations. Takes anywhere from 20 minutes to a few hours depending on the router's response time. Some routers slow down or lock after a number of attempts - watch the output.

Wordlists - Generic vs. Targeted

rockyou.txt is 14 million entries. That sounds like a lot until you realize that for a home WiFi network, the password was probably set by one specific person, and people are predictable. They use their name, their kid's name, their birthdate, their pet, their neighborhood, their football team - often combined with a number or a special character because the router told them to.

A generic wordlist has to cover everyone. A targeted one only has to cover one person. If you know anything about the target - names, birthdays, interests, city - a focused 1,000-entry wordlist built from that information will outperform rockyou in most real-world cases.

wordgen.py

This is a script I wrote to do exactly that. You feed it what you know and it generates every plausible combination: names with numbers, names with special chars, names combined with other names, leet variants, capitalization variants, combinations padded to hit specific target lengths.

python3 wordgen.py

It prompts you interactively:

──────────────────────────────────────────────────
  TARGETED WORDLIST GENERATOR
──────────────────────────────────────────────────
Names (target, family members, pets):
  example: ahmed, sara, layla
  enter one per line, empty line when done:
  > sara
  > milo
  >
Birthdays / years:
  example: 1995, 0510, 250595, 2001
  > 1994
  > 0203
  >
Keywords (city, team, pet, anything relevant):
  > cairo
  > arsenal
  >

For each base word it generates casing variants (lowercase, uppercase, capitalized), a basic leet substitution (a→4, e→3, i→1, o→0, s→5, t→7), then combines all of that with your numbers, birthdays, and special characters in every meaningful order. Name + number, number + name, name + special + number, two names combined, two names with birthday appended - and so on.

It then filters the entire output down to only your target lengths. WPA2 requires a minimum of 8 characters, so you'd typically target 8, 10, 12, 16 - whatever you think the person would pick based on what you know. Filtering by length cuts the list dramatically without losing anything useful.

Feed the output straight to hashcat:

hashcat -m 22000 ~/wifi-crack/captures/handshake.hc22000 ~/wifi-crack/wordlists/targeted.txt

Or aircrack if you're on CPU:

aircrack-ng ~/wifi-crack/captures/handshake-01.cap -w ~/wifi-crack/wordlists/targeted.txt

The real advantage shows up on networks where rockyou fails. If someone uses Sara@1994 or milo0203! as their password, rockyou probably doesn't have it. wordgen will.

hashcat rules - taking it further

If you want to extend a targeted list without manually adding every variant, hashcat's rule engine can do it at crack time. The built-in best64.rule covers the most common mutations:

hashcat -m 22000 handshake.hc22000 targeted.txt -r /usr/share/hashcat/rules/best64.rule

Rules apply transformations like appending common suffixes, toggling case, inserting digits - without bloating your wordlist file. Good middle ground between a pure wordlist and full brute force.

Folder layout

mkdir -p ~/wifi-crack/{captures,wordlists}

~/wifi-crack/
├── wordgen.py
├── captures/
│   └── handshake-01.cap
└── wordlists/
    ├── rockyou.txt
    └── targeted.txt

Get rockyou:

curl -L -o ~/wifi-crack/wordlists/rockyou.txt.gz \
  https://github.com/praetorian-inc/Hob0Rules/raw/master/wordlists/rockyou.txt.gz
gunzip ~/wifi-crack/wordlists/rockyou.txt.gz
[EOF]