0%

无线嗅探及 airkiss 协议分析

airkiss 用于智能配网,基于 802.11 协议,本文记录相关知识点

概述

airkiss 首先需要网卡有监听空中无线包的能力,包括 监听混杂 两种模式,并以 802.11 格式从数据链路层截取数据(要求的是不带 radiotap header802.11 数据帧)

radiotap header

radiotap 包含了信号强度、噪声强度、信道、时间戳等信息。 radiotap 比传统的 PrismAVS 头更有灵活性,成为 ieee802.11 事实上的标准。在 WLAN 无线网络抓包的时候不管是用 wiresharktcpdump 还是 scapy 都会出现 RadiotapLLCSNAP 协议层。典型数据帧如下

Frame 6662: 103 bytes on wire (824 bits), 103 bytes captured (824 bits) on interface 0
Radiotap Header v0, Length 21
    Header revision: 0
    Header pad: 0
    Header length: 21
    Present flags
    Flags: 0x00
    Channel frequency: 2422 [BG 3]
    Channel flags: 0x0480, 2 GHz spectrum, Dynamic CCK-OFDM
    Antenna signal: -49dBm
    Antenna: 1
    RX flags: 0x0000
    MCS information
    [Data Rate: 65.0 Mb/s]
802.11 radio information
IEEE 802.11 QoS Data, Flags: .p.....T
Data (48 bytes)

协议

每一次接收到的 802.11 帧中只需要解析出 lengthairkiss 就是围绕 length 进行编码的协议, length802.11 数据帧长度,

配合开源工程 Airkiss 分析协议过程如下

  • Cap len 为读取携带 radiotap header 的原始数据长度,十进制
  • length 为计算之后 802.11 数据长度,且过滤不符合的数据帧,十六进制

length 为计算之后 802.11 数据长度,且过滤不符合的数据帧,十六进制

discover- 发现过程

协议规定发送前导码 {1, 2, 3, 4},这个值是差异值,在 wireshark 抓包如下

314    0.000342132    HuaweiTe_0e:74:56    Broadcast    802.11    100    795    QoS Data, SN=795, FN=0, Flags=.p.....T
318    0.000077578    HuaweiTe_0e:74:56    Broadcast    802.11    101    796    QoS Data, SN=796, FN=0, Flags=.p.....T
322    0.000007695    HuaweiTe_0e:74:56    Broadcast    802.11    102    797    QoS Data, SN=797, FN=0, Flags=.p.....T
326    0.000035866    HuaweiTe_0e:74:56    Broadcast    802.11    103    798    QoS Data, SN=798, FN=0, Flags=.p.....T

其中 radiotap header 长度为 21,代码判断如下

// 1 2 3 4
if((_akcontext.data.guide_code.length_record[1] - _akcontext.data.guide_code.length_record[0] == 1) &&
(_akcontext.data.guide_code.length_record[2] - _akcontext.data.guide_code.length_record[1] == 1) &&
(_akcontext.data.guide_code.length_record[3] - _akcontext.data.guide_code.length_record[2] == 1))
{
    _akcontext.base_len = _akcontext.data.guide_code.length_record[0] - 1;
    success = 1;
}

if(success)
{
    _akcontext.airkiss_state = AIRKISS_STATE_SRC_LOCKED;
    resest_airkiss_data();
    akconf->printf("airkiss_recv_discover success\n");
    akconf->printf("base len:%d\n", _akcontext.base_len);
}

调试打印

Cap len:100
length:4f --> 0x1
Cap len:46
length:1c
Cap len:34
length:10
Cap len:28
length:a
Cap len:101
length:50 --> 0x2
Cap len:46
length:1c
Cap len:44
length:1a
Cap len:28
length:a
Cap len:34
length:10
Cap len:28
length:a
Cap len:102
length:51 -> 0x3
Cap len:46
length:1c
Cap len:28
length:a
Cap len:34
length:10
Cap len:28
length:a
Cap len:103
length:52 --> 0x4
airkiss_recv_discover success
base len:78
Lock channel in 3

magic code 字段

magic code 由 4 个 9bits 组成,格式如下

第 1 个 9bits 0x0 length(high)
第 2 个 9bits 0x1 length(low)
第 3 个 9bits 0x2 ssid crc(high)
第 4 个 9bits 0x3 ssid crc(low)

length 为要发送数据的长度, ssid crc 为要发送 ssidcrc8

代码如下

if(((_akcontext.data.magic_code.record[0]&0x01f0)==0x0000)&&
    ((_akcontext.data.magic_code.record[1]&0x01f0)==0x0010)&&
        ((_akcontext.data.magic_code.record[2]&0x01f0)==0x0020)&&
        ((_akcontext.data.magic_code.record[3]&0x01f0)==0x0030))
{
    _akcontext.total_len = ((_akcontext.data.magic_code.record[0] & 0x000F) << 4) + (_akcontext.data.magic_code.record[1] & 0x000F);
    _akcontext.ssid_crc = ((_akcontext.data.magic_code.record[2] & 0x000F) << 4) + (_akcontext.data.magic_code.record[3] & 0x000F);
    //TODO:double check magic code
    _akcontext.airkiss_state = AIRKISS_STATE_MAGIC_CODE_COMPLETE;
    resest_airkiss_data();
    akconf->printf("airkiss_process_magic_code success\n");
    akconf->printf("total_len:%d, ssid crc:%x\n", _akcontext.total_len, _akcontext.ssid_crc);
}

调试打印信息

Cap len:100
length:4f --> 0x1
Cap len:46
Cap len:34
Cap len:34
Cap len:34
Cap len:28
Cap len:124
length:67 --> 0x19
Cap len:46
Cap len:119
Cap len:131
length:6e --> 0x20
Cap len:46
Cap len:162
length:8d --> 0x3f
airkiss_process_magic_code success
total_len:25, ssid crc:f

prefix code

prefix code 由 4 个 9bits 组成,格式如下

第 1 个 9bits 0x4 psw length(high)
第 2 个 9bits 0x5 psw length(low)
第 3 个 9bits 0x6 psw len crc(high)
第 4 个 9bits 0x7 psw len crc(low)

psw length 为要发送 psw 的长度, psw len crcpsw lencrc8

代码如下:

if((_akcontext.data.prefix_code.record[0]&0x01f0)==0x0040&&
    (_akcontext.data.prefix_code.record[1]&0x01f0)==0x0050&&
        (_akcontext.data.prefix_code.record[2]&0x01f0)==0x0060&&
        (_akcontext.data.prefix_code.record[3]&0x01f0)==0x0070)
{
    _akcontext.pswd_len = ((_akcontext.data.prefix_code.record[0] & 0x000F) << 4) + (_akcontext.data.prefix_code.record[1] & 0x000F);
    if(_akcontext.pswd_len > PASSWORD_MAX_LEN)
        _akcontext.pswd_len = 0;
    _akcontext.pswd_lencrc = ((_akcontext.data.prefix_code.record[2] & 0x000F) << 4) + (_akcontext.data.prefix_code.record[3] & 0x000F);
    if(calcrc_1byte(_akcontext.pswd_len)==_akcontext.pswd_lencrc)
    {
        _akcontext.airkiss_state = AIRKISS_STATE_PREFIX_CODE_COMPLETE;
    }
    else
    {
        akconf->printf("password length crc error.\n");
        resest_airkiss_data();
        return;
    }

    // only receive password and random
    _akcontext.need_seq = ((_akcontext.pswd_len + 1) + 3)/4;
    _akcontext.seq_success_map_cmp = (1 << _akcontext.need_seq) - 1;

    resest_airkiss_data();
    akconf->printf("airkiss_process_prefix_code success\n");
    akconf->printf("pswd_len:%d, pswd_lencrc:%x, need seq:%d, seq map:%x\n",
            _akcontext.pswd_len, _akcontext.pswd_lencrc, _akcontext.need_seq, _akcontext.seq_success_map_cmp);
}

调试信息

Cap len:163
length:8e --> ox40
Cap len:46
Cap len:158
Cap len:34
Cap len:28
Cap len:190
length:a9 --> 0x5b
Cap len:46
Cap len:185
Cap len:34
Cap len:34
Cap len:34
Cap len:28
Cap len:197
length:b0 --> 0x62
Cap len:46
Cap len:192
Cap len:34
Cap len:28
Cap len:211
length:be --> 0x70
airkiss_process_prefix_code success
pswd_len:11, pswd_lencrc:20, need seq:3, seq map:7

sequence header & data

将要发送的数据按照 4 字节为单位进行划分,每 4 个数据加上 sequence header 组成一个 sequence,以 sequence 为单位进行数据发送,如果最后一个 sequence 不够 4 字节,不用补全,格式如下

sequence header 格式如下

第 1 个 9bits 0 1 sequence crc8(低 7 位)
第 2 个 9bits 0 1 sequence index

data 格式如下

第 1 个 9bits 1 data(第 7-0bit)
第 2 个 9bits 1 data(第 7-0bit)
第 3 个 9bits 1 data(第 7-0bit)
第 4 个 9bits 1 data(第 7-0bit)

代码实现如下

if(((_akcontext.data.seq_code.record[0]&0x180)==0x80) &&
    ((_akcontext.data.seq_code.record[1]&0x180)==0x80) &&
    ((_akcontext.data.seq_code.record[2]&0x0100)==0x0100) &&
    ((_akcontext.data.seq_code.record[3]&0x0100)==0x0100) &&
    ((_akcontext.data.seq_code.record[4]&0x0100)==0x0100) &&
    ((_akcontext.data.seq_code.record[5]&0x0100)==0x0100) &&
    ((_akcontext.data.seq_code.record[1]&0x7F) <= ((_akcontext.total_len>>2)+1)))
{
    unsigned char tempBuffer[6] = {0};
    tempBuffer[0]=_akcontext.data.seq_code.record[0]&0x7F; //seq crc
    tempBuffer[1]=_akcontext.data.seq_code.record[1]&0x7F; //seq index
    tempBuffer[2]=_akcontext.data.seq_code.record[2]&0xFF; //data, same as following
    tempBuffer[3]=_akcontext.data.seq_code.record[3]&0xFF;
    tempBuffer[4]=_akcontext.data.seq_code.record[4]&0xFF;
    tempBuffer[5]=_akcontext.data.seq_code.record[5]&0xFF;

    if(tempBuffer[0] == (calcrc_bytes(tempBuffer+1,5)&0x7F) )
        ...
    }
}

调试信息

Cap len:408
Cap len:338
length:13d --> 0xef
Cap len:46
Cap len:34
Cap len:28
Cap len:229
length:d0 --> 0x82
Cap len:46
Cap len:42
Cap len:28
Cap len:42
Cap len:28
Cap len:34
Cap len:34
Cap len:28
Cap len:412
length:187 -> 0x139
Cap len:46
Cap len:34
Cap len:28
Cap len:408
length:183 -> 0x135
Cap len:46
Cap len:34
Cap len:28
Cap len:412
length:187 -> 0x139
Cap len:46
Cap len:28
Cap len:34
Cap len:34
Cap len:34
Cap len:34
Cap len:34
Cap len:34
Cap len:34
Cap len:34
Cap len:28
Cap len:416
length:18b -> 0x13d
[crc:6f][index:2]:39,35,39,3d; seq mapped:4

sequence header 数据为 0x13d-78 0xd0-78 –> 0xef 0x82

802.11/802.2

  • IEEE 802.11 定义了媒体访问控制层(MAC 层)和物理层。物理层
  • IEEE 802.2 是对数据链路层上层逻辑链路控制 (LLC) 连接的建立和管理的规范

几个概念:

  • PHY 物理层的芯片我们简称之为 PHY,物理层 Physical Layer
  • 数据链路层 Data Link LayerOSI 模型的第二层,负责建立和管理节点间的链路。该层通常又被分为介质访问控制 MAC 和逻辑链路控制 LLC 两个子层
    • MAC 数据链路层的芯片一般简称之为 MAC 控制器
    • LLC 子层的主要任务是建立和维护网络连接,执行差错校验、流量控制和链路控制

** WIFI MACPHY 层及协议在 OSI 位置**

Airkiss 需要关心的 length802.2 SNAP LLC 解析,数据格式

802.11 帧结构如下, airkissAddress1/Address2/Address3 字段进行了过滤

协议细节理解

前导码及发现过程

利用 802.2 SNAP 数据包中的 Length 字段进行通信。在实际应用中采用 UDP 广播包作为信息的载体。每一包的数据都是按照 Airkiss 通信协议进行编码。一个 UDP 包发送要经过 IP 层、数据链路层的封装,并且通过加密 ( WPA2、WPA、WEP ) 后才被发送出去,所以发送方发送 UDP 长度与接收方监听 SNAP 包长度存在差异,而且由于底层加密方式的差异,使得这个差异值也具有不确定性

因此需要监听信道计算差异值,这个差异值就是底层封装对 Length 的差异,后续传输的所有 Length 需要减去差异值

误识别

如果发送数据中包括递增值,例如 12344567abcd 会导致前导码识别错误,正式库中有处理?

应用数据组成

password + random + ssid

  1. passwordssid 可以发送经过 AES 加密后的数据, AES Key 私下协商, Airkiss 协议无规定?
  2. randomairkiss server 生成的随机数,在连接成功之后 airkiss client 将这个值发送回来以完成配网

端口的选择

  1. airkiss server 可以是 ethwlan
  2. airkiss client 可以是 ethwlan
  3. 可以使用 setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) 限制使用具体 interface

Ref

  1. AirKiss 库文件使用指南
  2. 揭开智能配置上网(微信 Airkiss)的奥妙面纱
  3. IEEE 802.11 的帧格式介绍
  4. Airkiss 协议详解
  5. Airkiss
  6. Radiotap 头信息解析
  7. 无线网络嗅探中的 Radiotap
  8. 基本 802.11 无线探测
  9. IEEE 802.11 Frame Types
  10. WIFI MAC 和 PHY 在 OSI 模型中的层次