在 EAP-PEAP 身份验证下从 WiFi 客户端提取 PMK,用于 Wireshark 分析
Extracting the PMK from a WiFi client under EAP-PEAP authentication, for analysis on Wireshark
我正在开始一个与 WiFi 相关的研究项目,这需要我在连接设置期间分析 WiFi 客户端和 AP 之间的帧交换。
实验设置:我有一台笔记本电脑 M,在监控模式下使用 Wireshark 捕获 WiFi 流量,设备 A (运行 Linux) 连接到通过 802.1x 身份验证的 WiFi 网络,特别是使用 EAP-PEAP 协议。
我只控制笔记本电脑 M 和设备 A,但不控制 AP 或网络(包括 RADIUS 服务器)。
Objective: 我想解码笔记本电脑M上Wireshark捕获的WiFi数据帧。根据this Wireshark how to,我需要以某种方式提取网络和设备 A 之间交换的 PMK(成对主密钥)。
因为我只控制设备 A,所以我需要从中提取 PMK。
问题:我不知道如何从设备 A 中提取 PMK(假设是 Linux 操作系统),特别是考虑到我们正在谈论一个EAP-PEAP session,我在网上搜索也没有找到任何结论性的提示。
我可以找到 this discussion,这意味着 PMK 直接存储在 WiFi NIC 或驱动程序中。
问题:
- 是否有可能提取 PMK,例如在 Linux 系统中,没有对客户端系统进行重大修改(例如修改无线驱动程序的代码等)?考虑到 'security breach' 的严重程度,我认为这会非常困难。
- PMK 是否以某种方式存储(例如 Linux)?综上所述,我不希望出现这种情况。
- 我需要修改什么代码(让我们假设一个 Linux 操作系统)来提取 PMK?
P.S.: 我想指出,我不认为这是一个 'hacking' 问题(因此与 whosebug.com 的政策并不矛盾) ,因为我控制客户端设备(不仅是监控设备)。
我找到了两种让 wpa_supplicant
输出 PMK 的方法:
- 简单方法: 使用
-K
选项和一些调试选项(例如 -dd
)调用 wpa_supplicant
。这将在调试输出中包含密钥(密码等)。
- 困难的方法: 改变
wpa_supplicant
的代码来输出密钥。考虑到 -K
选项存在,这种方式不必要地困难,但这是我尝试的第一件事(不要问)。我在下面总结了我是如何做到这一点的,这对于希望更改 wpa_supplicant
. 代码的人来说可能很有趣
2) 困难的方法:改变 wpa_supplicant
代码
我通过更改 wpa_supplicant
的代码找到了答案,使其在身份验证期间输出 PMK。在我的例子中,客户端设备是 Raspberry Pi model B+, V1 2, 运行 Raspbian GNU/Linux 7 (wheezy),它使用旧版本的 wpa_supplicant
,即v1.0, 2012-05-10.
对于任何想知道的人,我已经更改了源文件 src/rsn_supp/wpa.c
、函数 wpa_supplicant_key_neg_complete()
以输出 PMK,如下所示:
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] = {'[=10=]'};
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) = '[=10=]';
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Key negotiation completed with "MACSTR": \
\n\tPMK=%s \
\n\t[PTK=%s GTK=%s]",
MAC2STR(addr),
pmk_str,
wpa_cipher_txt(sm->pairwise_cipher),
wpa_cipher_txt(sm->group_cipher));
(...)
}
此自定义可用 on my github。
我正在开始一个与 WiFi 相关的研究项目,这需要我在连接设置期间分析 WiFi 客户端和 AP 之间的帧交换。
实验设置:我有一台笔记本电脑 M,在监控模式下使用 Wireshark 捕获 WiFi 流量,设备 A (运行 Linux) 连接到通过 802.1x 身份验证的 WiFi 网络,特别是使用 EAP-PEAP 协议。
我只控制笔记本电脑 M 和设备 A,但不控制 AP 或网络(包括 RADIUS 服务器)。
Objective: 我想解码笔记本电脑M上Wireshark捕获的WiFi数据帧。根据this Wireshark how to,我需要以某种方式提取网络和设备 A 之间交换的 PMK(成对主密钥)。
因为我只控制设备 A,所以我需要从中提取 PMK。
问题:我不知道如何从设备 A 中提取 PMK(假设是 Linux 操作系统),特别是考虑到我们正在谈论一个EAP-PEAP session,我在网上搜索也没有找到任何结论性的提示。
我可以找到 this discussion,这意味着 PMK 直接存储在 WiFi NIC 或驱动程序中。
问题:
- 是否有可能提取 PMK,例如在 Linux 系统中,没有对客户端系统进行重大修改(例如修改无线驱动程序的代码等)?考虑到 'security breach' 的严重程度,我认为这会非常困难。
- PMK 是否以某种方式存储(例如 Linux)?综上所述,我不希望出现这种情况。
- 我需要修改什么代码(让我们假设一个 Linux 操作系统)来提取 PMK?
P.S.: 我想指出,我不认为这是一个 'hacking' 问题(因此与 whosebug.com 的政策并不矛盾) ,因为我控制客户端设备(不仅是监控设备)。
我找到了两种让 wpa_supplicant
输出 PMK 的方法:
- 简单方法: 使用
-K
选项和一些调试选项(例如-dd
)调用wpa_supplicant
。这将在调试输出中包含密钥(密码等)。 - 困难的方法: 改变
wpa_supplicant
的代码来输出密钥。考虑到-K
选项存在,这种方式不必要地困难,但这是我尝试的第一件事(不要问)。我在下面总结了我是如何做到这一点的,这对于希望更改wpa_supplicant
. 代码的人来说可能很有趣
2) 困难的方法:改变 wpa_supplicant
代码
我通过更改 wpa_supplicant
的代码找到了答案,使其在身份验证期间输出 PMK。在我的例子中,客户端设备是 Raspberry Pi model B+, V1 2, 运行 Raspbian GNU/Linux 7 (wheezy),它使用旧版本的 wpa_supplicant
,即v1.0, 2012-05-10.
对于任何想知道的人,我已经更改了源文件 src/rsn_supp/wpa.c
、函数 wpa_supplicant_key_neg_complete()
以输出 PMK,如下所示:
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] = {'[=10=]'};
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) = '[=10=]';
wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
"WPA: Key negotiation completed with "MACSTR": \
\n\tPMK=%s \
\n\t[PTK=%s GTK=%s]",
MAC2STR(addr),
pmk_str,
wpa_cipher_txt(sm->pairwise_cipher),
wpa_cipher_txt(sm->group_cipher));
(...)
}
此自定义可用 on my github。