如何使用 NL80211_BSS_CAPABILITY 获取扫描网络的 WiFi 安全密钥WPA、WPA2、ESS?

问题描述

我正在使用 netlink 库 nl80211.h 来扫描 wifi 网络并成功获取 ssid、mac 地址、状态、频率和信号。我想使用相同的库添加每个网络的安全类型。 我使用 NL80211_BSS_CAPABILITY 作为枚举之一,它给出一个整数,我将其硬编码到我的代码中以确保安全。这似乎很乏味,并且必须使用这种方法提供大量数据(整数值)。获取 WPA/WPA2 很好,但是当开放网络存在时代码会失败。以下是我到目前为止使用的值。更好的逻辑可以让我打开网络(ESS 或 WEP),最好类似于 wpa_supplicant 和 netlink 库。

int keynum;
char *keytype;
keynum = nla_get_u32(bss[NL80211_BSS_CAPABILITY]);

if(keynum==5153 || keynum == 34)
    keytype="NONE";

else if(keynum==5169 || keynum == 1297 || keynum==1073|| keynum == 5393)
    keytype="WPA2";

else if (keynum == 1041)
    keytype="WPA WPA2";

else
    keytype="WPA WPA2";

解决方法

首先我们来看看NL80211_BSS_CAPABILITY
里面是什么类型的数据 为了理解这一点,我将首先提请您注意属性 NL80211_BSS_BEACON_IES
该字段的说明如下:

/**
* @NL80211_BSS_BEACON_IES: binary attribute containing the raw
* information
*/

source
但我觉得这样的描述太少了,更详细的描述,我们转here
首先,我们感兴趣的是:

  1. 能力信息(2 字节) 该字段包含用于指示请求或通告可选的子字段数 能力。

以使用wireshark捕获的数据包之一及其Сapabilities Information字段为例(有关如何执行此操作的好文章是here):

Сapabilities Information: 0x0431
            .... .... .... ...1 = ESS capabilities: Transmitter is an AP
            .... .... .... ..0. = IBSS status: Transmitter belongs to a BSS
            .... ..0. .... 00.. = CFP participation capabilities: No point coordinator at AP (0x00)
            .... .... ...1 .... = Privacy: AP/STA can support WEP
            .... .... ..1. .... = Short Preamble: Allowed
            .... .... .0.. .... = PBCC: Not Allowed
            .... .... 0... .... = Channel Agility: Not in use
            .... ...0 .... .... = Spectrum Management: Not Implemented
            .... .1.. .... .... = Short Slot Time: In use
            .... 0... .... .... = Automatic Power Save Delivery: Not Implemented
            ...0 .... .... .... = Radio Measurement: Not Implemented
            ..0. .... .... .... = DSSS-OFDM: Not Allowed
            .0.. .... .... .... = Delayed Block Ack: Not Implemented
            0... .... .... .... = Immediate Block Ack: Not Implemented

正如我们所观察到的,其中一个标志(在本例中的通用名称为 securityPrivacy: AP/STA can support WEP)。这个标志,正如所写的那样,告诉我们这个网络支持 wep 加密。但是,该标签的其他标志不携带有关网络使用的其他编码算法的信息。因此,后续对这个领域的分析将变成:

if (bss[NL80211_BSS_CAPABILITY] != NULL) {
    wlan_info.bss_capability = nla_get_u16(bss[NL80211_BSS_CAPABILITY]);
  }
  if (!(wlan_info.bss_wpa1_wpa2 | wlan_info.bss_wpa2 | wlan_info.bss_wpa1)) {
    wlan_info.bss_wep = wlan_info.bss_capability & 16;
  }

但这还没有结束。我们还需要寻找其他加密算法的信息。
为此,我们回到NL80211_BSS_BEACON_IES
1.我们检查它是否为空。

if (NULL != bss[NL80211_BSS_BEACON_IES] && NULL != nla_data(bss[NL80211_BSS_BEACON_IES]))

2.我们遍历每个标签,读取前两个字节,从上面的文章中可以看出,我们由此找出标签的类型和它包含的数据长度。

for (int i = 0;;) {
      bool first = i;
      uint8_t header_type =
          *(uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) + i++);
      uint8_t header_len =
          *(uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) + i++);
      i += header_len;

3.在所有标签中,我们正在寻找 2 个特定标签:# 48 (0x30)# 221 (0xDD)。它们可能如下所示:

首先:

Tag: RSN Information
            Tag Number: RSN Information (48)
            Tag length: 20
            RSN Version: 1
            Group Cipher Suite: 00:0f:ac (Ieee 802.11) AES (CCM)
                Group Cipher Suite OUI: 00:0f:ac (Ieee 802.11)
                Group Cipher Suite type: AES (CCM) (4)
            Pairwise Cipher Suite Count: 1
            Pairwise Cipher Suite List 00:0f:ac (Ieee 802.11) AES (CCM)
                Pairwise Cipher Suite: 00:0f:ac (Ieee 802.11) AES (CCM)
                    Pairwise Cipher Suite OUI: 00:0f:ac (Ieee 802.11)
                    Pairwise Cipher Suite type: AES (CCM) (4)
            Auth Key Management (AKM) Suite Count: 1
            Auth Key Management (AKM) List 00:0f:ac (Ieee 802.11) PSK
                Auth Key Management (AKM) Suite: 00:0f:ac (Ieee 802.11) PSK
                    Auth Key Management (AKM) OUI: 00:0f:ac (Ieee 802.11)
                    Auth Key Management (AKM) type: PSK (2)
            RSN Capabilities: 0x0000

在 RSN 信息标签中,我们对 2 个字段(未来 4 个字节)感兴趣:Auth Key Management (AKM) OUI: 00: 0f: ac (Ieee 802.11)Auth Key Management (AKM) type: PSK (2)

根据 (AKM) type: PSK (2)(AKM) type: WPA (1) 这些将分别是 WPA2WPA1

第二:

Tag: Vendor Specific: Microsoft Corp.: WPA Information Element
            Tag Number: Vendor Specific (221)
            Tag length: 22
            OUI: 00:50:f2 (Microsoft Corp.)
            Vendor Specific OUI Type: 1
            Type: WPA Information Element (0x01)
            WPA Version: 1
            Multicast Cipher Suite: 00:50:f2 (Microsoft Corp.) AES (CCM)
                Multicast Cipher Suite OUI: 00:50:f2 (Microsoft Corp.)
                Multicast Cipher Suite type: AES (CCM) (4)
            Unicast Cipher Suite Count: 1
            Unicast Cipher Suite List 00:50:f2 (Microsoft Corp.) AES (CCM)
                Unicast Cipher Suite: 00:50:f2 (Microsoft Corp.) AES (CCM)
                    Unicast Cipher Suite OUI: 00:50:f2 (Microsoft Corp.)
                    Unicast Cipher Suite type: AES (CCM) (4)
            Auth Key Management (AKM) Suite Count: 1
            Auth Key Management (AKM) List 00:50:f2 (Microsoft Corp.) PSK
                Auth Key Management (AKM) Suite: 00:50:f2 (Microsoft Corp.) PSK
                    Auth Key Management (AKM) OUI: 00:50:f2 (Microsoft Corp.)
                    Auth Key Management (AKM) type: PSK (2)

这一点将我们指向 WPA1 WPA2。这是我们如何处理它的片段。

if (header_type == VENDOR_TAG_ID) {
        long long int oui = 0;
        memcpy(&oui,(uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) -
                           header_len + i),6);
        if (oui == WPA1_WPA2_BEACON) wlan_info.bss_wpa1_wpa2 = 1;
      } else if (header_type == RSN_TAG_ID) {
        int32_t oui = 0;
        memcpy(&oui,(uint8_t *)((nla_data(bss[NL80211_BSS_BEACON_IES])) - 6 + i),4);
        if ((oui == WPA2_BEACON_1) || (oui == WPA2_BEACON_2))
          wlan_info.bss_wpa2 = 1;
        else if (oui == WPA1_BEACON)
          wlan_info.bss_wpa1 = 1;
      }

这里使用的定义是:

#define RSN_TAG_ID 0x30
#define VENDOR_TAG_ID 0xdd
#define BEACON_DATA_LEN 0x100
#define BSS_SSID_LEN BEACON_DATA_LEN
#define WPA1_BEACON 0x1AC0F00
#define WPA2_BEACON_1 0x2AC0F00
#define WPA2_BEACON_2 0x4AC0F00
#define WPA1_WPA2_BEACON 0x101F25000

另一个有趣的点是iw kernel impl
here 这是一个现成的函数,但我没有研究它是如何工作的。

void print_ies(unsigned char *ie,int ielen,bool unknown,enum print_ie_type ptype)
{
    struct print_ies_data ie_buffer = {
        .ie = ie,.ielen = ielen };

    if (ie == NULL || ielen < 0)
        return;

    while (ielen >= 2 && ielen - 2 >= ie[1]) {
        if (ie[0] < ARRAY_SIZE(ieprinters) &&
            ieprinters[ie[0]].name &&
            ieprinters[ie[0]].flags & BIT(ptype)) {
            print_ie(&ieprinters[ie[0]],ie[0],ie[1],ie + 2,&ie_buffer);
        } else if (ie[0] == 221 /* vendor */) {
            print_vendor(ie[1],unknown,ptype);
        } else if (ie[0] == 255 /* extension */) {
            print_extension(ie[1],ptype);
        } else if (unknown) {
            int i;

            printf("\tUnknown IE (%d):",ie[0]);
            for (i=0; i<ie[1]; i++)
                printf(" %.2x",ie[2+i]);
            printf("\n");
        }
        ielen -= ie[1] + 2;
        ie += ie[1] + 2;
    }
}

最后一点是“组”“attr”的属性。与“组”属性“bss”不同,它们适用于 wiphy structures
我对此的研究还不够深入,无法了解网络管理员如何从中提取有关网络的必要信息,但您可以尝试查看 linblnetlink 来源,可能会有关于此的信息。这里还有一个如何使用它们的例子:
repo
source file
安全密钥的枚举值:

/**
 * NMDeviceWifiCapabilities:
 * @NM_WIFI_DEVICE_CAP_NONE: device has no encryption/authentication capabilities
 * @NM_WIFI_DEVICE_CAP_CIPHER_WEP40: device supports 40/64-bit WEP encryption
 * @NM_WIFI_DEVICE_CAP_CIPHER_WEP104: device supports 104/128-bit WEP encryption
 * @NM_WIFI_DEVICE_CAP_CIPHER_TKIP: device supports TKIP encryption
 * @NM_WIFI_DEVICE_CAP_CIPHER_CCMP: device supports AES/CCMP encryption
 * @NM_WIFI_DEVICE_CAP_WPA: device supports WPA1 authentication
 * @NM_WIFI_DEVICE_CAP_RSN: device supports WPA2/RSN authentication
 * @NM_WIFI_DEVICE_CAP_AP: device supports Access Point mode
 *
 * 802.11 specific device encryption and authentication capabilities.
 **/
typedef enum {
    NM_WIFI_DEVICE_CAP_NONE          = 0x00000000,NM_WIFI_DEVICE_CAP_CIPHER_WEP40  = 0x00000001,NM_WIFI_DEVICE_CAP_CIPHER_WEP104 = 0x00000002,NM_WIFI_DEVICE_CAP_CIPHER_TKIP   = 0x00000004,NM_WIFI_DEVICE_CAP_CIPHER_CCMP   = 0x00000008,NM_WIFI_DEVICE_CAP_WPA           = 0x00000010,NM_WIFI_DEVICE_CAP_RSN           = 0x00000020,NM_WIFI_DEVICE_CAP_AP            = 0x00000040
} NMDeviceWifiCapabilities;

以及使用方法:
source file

if (tb[NL80211_ATTR_CIPHER_SUITES]) {
    int num;
    int i;
    __u32 *ciphers = nla_data (tb[NL80211_ATTR_CIPHER_SUITES]);

    num = nla_len (tb[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32);
    for (i = 0; i < num; i++) {
        switch (ciphers[i]) {
        case 0x000fac01:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP40;
            break;
        case 0x000fac05:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_WEP104;
            break;
        case 0x000fac02:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_TKIP |
                      NM_WIFI_DEVICE_CAP_WPA;
            break;
        case 0x000fac04:
            info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_CCMP |
                      NM_WIFI_DEVICE_CAP_RSN;
            break;
        default:
            nm_log_err (LOGD_HW | LOGD_WIFI,"Don't know the meaning of NL80211_ATTR_CIPHER_SUITES %#8.8x.",ciphers[i]);
            break;
        }
    }
}

以及那里使用的调用和回调“链”:

     wifi_utils_init (const char *iface,int ifindex,gboolean check_scan)
                                  ^
                                  ||
             wifi_nl80211_init (const char *iface,int ifindex)
                                   ^
                                  ||
    static int nl80211_wiphy_info_handler (struct nl_msg *msg,void *arg)

WPA 3 编辑:
我还不能说什么。我的搜索从 this page 开始,并继续浏览有链接的页面。
nmcli 可能不支持 WPA 3,因为上次提交,根据存储库判断,是 9 年前(而 WPA 3 是由 802.11ax standard如果我两年前没记错的话,这是出来的。
如果您的接入点采用 WPA 3 加密,则可以使用命令 nmcli dev wifi 轻松检查。 与 nmcli 不同,iw 存储库中的最后一次提交相对较新,因此,它可能已经在处理我们的案例。
此外,我无法对来自 wiresharkWPA 3 加密数据包的内容发表任何意见,因为我没有必要的访问点,因此我没有对其进行测试。