◂ BACK TO ARCHIVE

H4CK1NG-101: WiFi

Disclaimer

H4CK1NG-101 is educational. Every post in this series explains how a technology works and then how it fails so you can defend it, test your own systems and understand the attacks that already exist. Understanding an attack is not the same as being entitled to run it. Everything here is written for systems you own or have explicit, written permission to test. Using any of it against networks, devices or accounts that are not yours is illegal in most of the world and the author accepts no responsibility for misuse. If you break something that is not yours, that is on you and “I read it on a blog” has never worked as a defence in court.

For this post specifically: build your own access point and attack that. Capturing a WPA2 handshake off a network you do not own and cracking its password is a crime whether or not you ever connect to it. Set up a spare router or use a phone hotspot with a password you choose and point everything below at that.

How the magic actually happens

I already wrote a post about listening to WiFi without touching anything. Wardriving stops at the beacon. This is what happens when a device actually joins a network and what someone can do with the parts of that conversation they are able to hear.

The rules of a room where everyone talks at once

WiFi is the marketing name for the IEEE 802.11 family of standards. It is Ethernet’s ideas moved onto radio and the radio part is where the complications come from. A cable is a private medium: two endpoints, a wire between them, nobody else listening. Radio is a shared medium in a public space. Every device on a channel hears every other device, there is no wire to isolate a conversation and two radios transmitting at the same instant on the same frequency just produce noise neither of them can read.

So the first job of the protocol is deciding who gets to talk. Wired Ethernet uses CSMA/CD where CD is collision detection: transmit and if you detect a collision, back off and retry. A radio cannot do that because it cannot listen and transmit on the same frequency at once so it cannot hear a collision while it is causing one. 802.11 uses CSMA/CA instead, collision avoidance: listen until the channel is idle, wait a short random interval, then transmit. For frames that need it there is an optional RTS/CTS exchange (request to send, clear to send) that reserves the air for a moment so a large frame does not get stepped on and every unicast data frame is acknowledged because radio is lossy and the sender has no other way to know the frame arrived.

The physical layer is radio so there are bands and channels. The two classic bands are 2.4 GHz which travels far and through walls but is crowded and slow and 5 GHz which is faster and cleaner but shorter range. WiFi 6E and 7 add 6 GHz. Each band is chopped into channels and on 2.4 GHz the channels overlap which is why the only non-overlapping choices are 1, 6 and 11 and why your router spends its life fighting the neighbours’ routers for air.

Everything above the radio is frames and 802.11 has three kinds. Management frames set up and tear down the relationship: beacons, probes, authentication, association, deauthentication. Control frames keep the medium orderly: RTS, CTS, the acknowledgements. Data frames carry your actual traffic. For this whole post the management frames are where the action is because they are how a device finds a network, joins it and gets kicked off it and most of them are sent unprotected.

When a client wants to join, a surprising amount has to be agreed. Which network, by SSID. Which access point, by BSSID since one network can have many. Which channel. Which data rates both sides support. And the part that matters here, the security suite: the router advertises an RSN information element in its beacon (Robust Security Network) listing the cipher suites it will use and the authentication methods it accepts. The client reads that, picks a compatible set and the negotiation begins.

Knock, knock, who’s there

Discovery comes first and it happens two ways. Passive scanning is the client sitting on a channel waiting for beacon frames which every router broadcasts roughly ten times a second. Active scanning is the client sending a probe request, either naming a network it wants or asking who is out there and routers answering with probe responses. This is why a phone with saved networks leaks the names of places it has been: it actively asks for them by name. It is also the raw material of wardriving.

Once the client has chosen an access point, the join is a short sequence of management frames:

  1. Authentication. In WPA2-Personal this is a formality called Open System authentication that always succeeds. It is a leftover from the WEP era when authentication and encryption were bolted together and the real proof of identity now happens later.
  2. Association. The client sends an association request stating the SSID, its supported rates and its security choice; the router replies with an association response and assigns an association ID. At this point the client is associated but, on a secured network, cannot send real traffic yet.
  3. Key negotiation. On WPA2-Personal the two sides run the four-way handshake described below. On WPA2-Enterprise there is an extra step first: an 802.1X exchange (EAP) against a RADIUS server so each user has their own credentials instead of one shared password and that exchange produces the master key the handshake then uses.

Only after key negotiation succeeds do encrypted data frames start to flow.

WEP to WPA3: a speedrun of broken promises

Home networks almost all run WPA2-PSK where PSK is pre-shared key: everyone types the same passphrase. That passphrase is never used directly to encrypt anything. It is stretched into a key first.

Both the router and the client run the passphrase through PBKDF2, a deliberately slow key-derivation function, using the SSID as the salt and 4096 iterations of HMAC-SHA1. Out comes a 256-bit value called the Pairwise Master Key, the PMK:

PMK = PBKDF2(HMAC-SHA1, passphrase, SSID, 4096, 256)

Two details here decide everything later. The SSID is the salt so the same password on a network named linksys produces a different PMK than on one named home which is why an attacker cannot precompute one universal table and why generic rainbow tables do not work against WPA2. And the 4096 iterations exist to make each single guess cost real CPU or GPU work which is the only reason a weak password is not cracked literally instantly.

To see why WPA2 is built this way, walk the lineage:

  • WEP (1997) used the RC4 stream cipher with a short, reused initialisation vector. It was broken by 2001 when Fluhrer, Mantin and Shamir showed you could recover the key from captured traffic in minutes. WEP is not a lock, it is a sticker that says “locked” and WiGLE still finds tens of millions of networks running it.
  • WPA (2003) was a rushed interim fix that kept the old RC4 hardware but wrapped it in TKIP which rotated keys per packet. It bought time until the real standard shipped and is considered broken now too.
  • WPA2 (2004, the 802.11i standard) replaced the stream cipher with AES in CCMP mode, a proper authenticated block cipher. This is the four-way handshake and PBKDF2 world this post lives in and it is still what most networks run.
  • WPA3 (2018) keeps AES but changes the two things that let WPA2 be attacked. It swaps the PSK exchange for SAE, a handshake where a captured session cannot be used to guess the password offline and it mandates Protected Management Frames so the forgeable management frames above stop being forgeable. WPA3 can also use GCMP, a faster authenticated cipher. Remember the word SAE because it is the whole reason the attack later stops working.

The other axis is Personal versus Enterprise which is separate from the WPA version. Personal means one shared passphrase, the PSK. Enterprise means each user authenticates individually through 802.1X and a RADIUS server so there is no single password to steal and the master key is derived per session from the user’s own credentials. Home networks are almost always Personal which is exactly why they are the soft target.

The four-way handshake

When a client joins a WPA2-Personal network, the two sides run a four-message exchange to prove they both know the PMK and to agree on a fresh session key, without either one ever sending the PMK or the passphrase across the air. These messages ride on EAPOL frames (EAP over LAN).

Message 1, router to client. The router picks a random number, the ANonce and sends it in the clear.

The client now has everything it needs to build the session key: its own random number, the SNonce, both MAC addresses and the PMK it just derived from the passphrase. It feeds all of that into a pseudo-random function and produces the Pairwise Transient Key, the PTK:

PTK = PRF(PMK, ANonce, SNonce, AP_MAC, client_MAC)

The PTK is the real per-session key and it splits into parts: the KCK that authenticates the handshake itself, the KEK that encrypts key material in message 3 and the temporal key that actually encrypts your data frames.

Message 2, client to router. The client sends its SNonce plus a MIC, a message integrity code computed over the frame with the KCK. The router now has the client’s SNonce so it can derive the exact same PTK and verify the MIC. If the MIC checks out, the client has proven it knows the PMK and therefore the passphrase, without ever sending either one.

Message 3, router to client. The router sends the Group Temporal Key, used to decrypt broadcast and multicast traffic, encrypted under the KEK, with its own MIC.

Message 4, client to router. An acknowledgement. After this, every data frame is encrypted under the session key with AES-CCMP.

Read what actually crossed the air: two random nonces, two MAC addresses and a MIC. The password never travelled and the PMK never travelled. But here is the hinge of the whole post. Everything an attacker needs to test a password guess sits in messages 1 and 2 and both are sent before anyone has proven anything to anyone. The handshake is designed to leak nothing to a passive eavesdropper who does not already know the password. It is not designed to stop someone willing to guess.

Now the fun part

An attacker cannot extract the password from a handshake. There is no equation to invert. What they can do is guess and the handshake gives them a way to check each guess on their own machine: take a candidate passphrase, run it through PBKDF2 with the SSID they already know, derive the PMK, derive the PTK from the captured nonces and MACs, compute what the MIC should be and compare it to the MIC they captured. A match means the guess was right.

That check is entirely offline. Capture the handshake once, then guess forever, at whatever speed the hardware allows, with no further contact with the network and nothing the victim can see or rate-limit. So the attack is two problems: get a handshake, then grind it.

Capturing a handshake

You need a wireless adapter that supports monitor mode which lets it receive frames not addressed to it. Aircrack-ng is the standard toolkit. Put the card into monitor mode:

sudo airmon-ng start wlan0

That usually gives you an interface named wlan0mon. Survey the air to find your own network and note its BSSID and channel:

sudo airodump-ng wlan0mon

Then lock onto the target and write every frame to a file:

sudo airodump-ng -c 6 --bssid AA:BB:CC:DD:EE:FF -w capture wlan0mon

Now you need a device to join because the handshake only happens at join time. You can wait for something to connect or you can make it happen.

Have you tried turning it off and on again

WPA2 encrypts your data but leaves management frames unauthenticated and a deauthentication frame is a management frame. So you can spoof one that looks like it came from the router, the client believes it has been kicked off and it immediately reconnects, producing a fresh handshake while your capture is running:

sudo aireplay-ng --deauth 5 -a AA:BB:CC:DD:EE:FF -c 11:22:33:44:55:66 wlan0mon

Here -a is the router’s BSSID and -c is the client you want to nudge (drop -c to hit everyone). Watch the top line of airodump: when it captures the exchange it prints WPA handshake: followed by the BSSID. That is your messages 1 and 2, saved to the capture file.

This step is also exactly why WPA3 and Protected Management Frames close the door. When management frames are authenticated, a spoofed deauth is simply ignored and the attacker loses the ability to force a reconnection on demand. On a pure WPA3 network this does not work at all.

The router never has to know

With the capture in hand, the guessing is a dictionary attack. The old way is aircrack-ng itself against a wordlist:

aircrack-ng -w rockyou.txt capture-01.cap

The fast way is hashcat on a GPU. Convert the capture into hashcat’s format with hcxpcapngtool, then run mode 22000, the unified WPA format:

hcxpcapngtool -o hash.22000 capture-01.cap
hashcat -m 22000 hash.22000 rockyou.txt

Speed depends entirely on the GPU and on the SSID because the SSID is the salt: hashcat cannot precompute anything until it knows which network it is attacking. A single modern GPU does anywhere from a few hundred thousand to several million WPA2 candidates per second which feels enormous until you count how many passwords are actually possible.

Asking nicely instead

In 2018 Jens Steube, the author of hashcat, published a cleaner attack that needs no connected client and no deauth. Many routers include a value called the PMKID in the first handshake message, computed like this:

PMKID = HMAC-SHA1(PMK, "PMK Name" + AP_MAC + client_MAC)

Because it is derived from the PMK, it is just as crackable as a MIC and you can request it from the router yourself just by starting to associate, with no victim involved. A tool like hcxdumptool collects it directly:

sudo hcxdumptool -i wlan0mon -o dump.pcapng --enable_status=1

hcxdumptool’s flags have changed across releases so check hcxdumptool --help for your build. Then convert and crack in the same mode 22000. One frame, straight from the router and you are grinding.

Garbage in, credentials out

Every attack above ends in the same place: you are only as strong as your list of guesses. rockyou.txt is the famous starting point, about fourteen million real passwords leaked in the 2009 RockYou breach and it works because people reuse the same weak passwords everywhere. But a WPA2 passphrase must be 8 to 63 characters so any entry shorter than 8 is dead weight and good tooling filters those out before wasting a GPU cycle on them.

A generic list only gets you the lazy passwords. The interesting work and the part that teaches the most about why real passwords fall, is building a wordlist aimed at one specific target.

The dog’s name and a birth year

Start with a seed file. This is pure OSINT and it is where the person leaks into their password: family and pet names, birth years, the street, the football club, the employer, the phone number, the kids. Everything you can learn about the target goes into seed.txt, one token per line:

# seed.txt
emma
james
london
liverpool
arsenal
2019
mittens
acmecorp

You can also scrape a target’s own website into a seed with cewl which crawls a site and emits every word it finds which is startlingly effective against small businesses that put the founder’s dog on the About page:

cewl -d 2 -m 5 -w seed.txt https://example.com

Combine the seed with itself because people build passwords by gluing two things together. The combinator attack pairs every word in one list with every word in another. In hashcat that is attack mode 1:

hashcat -m 22000 -a 1 hash.22000 seed.txt seed.txt

That turns liverpool plus 2019 into liverpool2019 and every other pairing. For three-way combinations there is combinator3 in the hashcat-utils package.

Mask for the structured part, the digits and symbols people staple onto a word. A mask is a template built from character-set tokens: ?l is a lowercase letter, ?u uppercase, ?d a digit, ?s a symbol. A pure mask attack is mode 3; to try a known word followed by four digits, say a year or a PIN, you use a hybrid attack (mode 6 is wordlist then mask, mode 7 is mask then wordlist):

# every "word + 4 digits", e.g. Liverpool2019
hashcat -m 22000 -a 6 hash.22000 seed.txt '?d?d?d?d'

# a fixed prefix then six digits
hashcat -m 22000 -a 3 hash.22000 'admin?d?d?d?d?d?d'

You can also generate raw candidate files with crunch, for example every eight-digit number which is exactly what a lot of default router passwords are:

crunch 8 8 0123456789 -o digits.txt

Mutate with rules which transform each word: capitalise the first letter, append a year, do the leetspeak substitutions (a to @, o to 0). hashcat ships best64.rule as the standard first pass:

hashcat -m 22000 -a 0 hash.22000 seed.txt -r rules/best64.rule

That single rule turns password into Password1, p@ssw0rd, password123 and dozens more. Stack rules on a good seed and you are no longer guessing random strings, you are guessing the specific ways this specific person mangles words they already care about. Just keep the 8-to-63 length rule in mind because a rule that produces a six-character candidate is producing a WPA2 password that cannot exist.

And that is the honest lesson buried in all the tooling. A random twelve-character passphrase is in no wordlist, cannot be built from a seed and cannot be generated fast enough to matter so every attack in this section simply fails against it. WPA2’s real weakness is not the cipher, it is that the protocol lets an attacker guess as fast as their hardware allows, forever, once they hold your handshake. The only thing standing between them and your network is whether your password is guessable.

WPA3 ruins the whole party

WPA3 replaces the PSK exchange with SAE, Simultaneous Authentication of Equals, built on the Dragonfly handshake. The property that matters is that a captured SAE exchange does not let you check a password guess offline. Each guess requires a fresh, live interaction with the router so an attacker cannot capture once and grind forever on their own GPU. They are pushed back to online guessing, one attempt at a time, against a router that can rate-limit and lock them out after a handful of tries. Combined with mandatory Protected Management Frames killing the deauth, that single change dismantles the whole workflow above. It is why understanding the arithmetic of the four-way handshake is worth more than memorising the commands: the commands stop working, the reasoning tells you why.

Try it on your own network

Everything here runs against a router you control in an afternoon. Stand up a test SSID, set a deliberately weak password like password123, capture your own handshake and crack it, then set a long random passphrase and watch the same attack run until you get bored and kill it. The gap between those two runs is the only WiFi security advice that has ever mattered and doing it with your own hands teaches it better than any awareness slide.

Next in the series: passwords and hashes which is really the PBKDF2 story from this post told properly, plus why rockyou.txt keeps working fifteen years after the breach that produced it.

Sources