I’m starting a research project related to WiFi, which requires me to analyze the exchange of frames in between a WiFi client and AP during connection setup.
Experimental setup: I have a laptop M, capturing WiFi traffic with Wireshark on monitor mode, a device A (running Linux) connecting to a WiFi network via 802.1x authentication, specifically using the EAP-PEAP protocol.
I only control the laptop M and device A, but not the APs nor the network (which includes the RADIUS servers).
Objective: I’d like to decode the WiFi data frames captured by Wireshark on laptop M. According to this Wireshark how to, I would need to somehow extract the PMK (Pairwise Master Key) exchanged between the network and device A.
Since I only control device A, I would need to extract the PMK from it.
Problem: I don’t know how to extract that PMK from device A (assuming a Linux operating system), specially considering we’re talking about a EAP-PEAP session, and I haven’t been able to find any conclusive hints while searching on the Web.
I could find this discussion, which implies the PMK is stored directly at the WiFi NIC or the driver.
Questions:
- Is it even possible to extract the PMKs, e.g. in a Linux system, without a major modification on the client system (e.g. modifying the code of the wireless drivers, etc.)? I would imagine that to be very hard, given how serious such a ‘security breach’ would be.
- Are the PMKs stored in some way (e.g. in Linux)? Following from the above, I would not expect that to be the case.
- What code would I need to modify (let’s assume a Linux operating system) to extract the PMKs?
P.S.: I’d like to note that I don’t consider this to be a ‘hacking’ question (and thus not at odds with the policies of stackoverflow.com), since I control the client device (not only the monitoring device).
Advertisement
Answer
I found 2 ways of having wpa_supplicant
output the PMK:
- Easy way: Call
wpa_supplicant
with the-K
option, together with some debug option (e.g.-dd
). This will include keys (passwords, etc.) in debug output. - Hard way: Alter the code of
wpa_supplicant
to output keys. Given that the-K
option exists, this way is unnecessarily hard, but it was the first thing I tried (don’t ask). I’ve summarized how I’ve done this below, which may be interesting for someone wishing to alter the code ofwpa_supplicant
.
2) Hard Way: Altering wpa_supplicant
Code
I was able to find an answer by altering the code of wpa_supplicant
, making it output the PMK during authentication. In my case, the client device was a Raspberry Pi model B+, V1 2, running Raspbian GNU/Linux 7 (wheezy), which used an old version of wpa_supplicant
, namely v1.0, 2012-05-10.
For anyone wondering, I’ve altered the source file src/rsn_supp/wpa.c
, function wpa_supplicant_key_neg_complete()
, to output the PMK, as follows:
static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, const u8 *addr, int secure) { // pass the pmk (pairwise master key) to a hex string. int i; // hex str to hold pmk. 1024 bit // should be enough (the pmk is supposed to be 256 bit, thus 32 byte, thus // 64 hex chars) char pmk_str[1024] = {''}; char * pmk_ptr = pmk_str; // use os_snprintf() (as used by other methods in wpa.c) for (i = 0; i < sm->pmk_len; i++) { // wpa_msg(sm->ctx->msg_ctx, MSG_INFO, // "WPA: pmk[%d]: %02X", i, sm->pmk[i]); pmk_ptr += sprintf(pmk_ptr, "%02X", sm->pmk[i]); } *(pmk_ptr + 1) = ''; wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Key negotiation completed with "MACSTR": ntPMK=%s nt[PTK=%s GTK=%s]", MAC2STR(addr), pmk_str, wpa_cipher_txt(sm->pairwise_cipher), wpa_cipher_txt(sm->group_cipher)); (...) }
This customization is available on my github.