airkiss
用于智能配网,基于 802.11
协议,本文记录相关知识点
概述
airkiss
首先需要网卡有监听空中无线包的能力,包括 监听
和 混杂
两种模式,并以 802.11
格式从数据链路层截取数据(要求的是不带 radiotap header
的 802.11
数据帧)
radiotap header
radiotap
包含了信号强度、噪声强度、信道、时间戳等信息。 radiotap
比传统的 Prism
或 AVS
头更有灵活性,成为 ieee802.11
事实上的标准。在 WLAN
无线网络抓包的时候不管是用 wireshark
、 tcpdump
还是 scapy
都会出现 Radiotap
、 LLC
、 SNAP
协议层。典型数据帧如下
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
帧中只需要解析出 length
, airkiss
就是围绕 length
进行编码的协议, length
为 802.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
为要发送 ssid
的 crc8
值
代码如下
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 crc
为 psw len
的 crc8
值
代码如下:
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 Layer
是OSI
模型的第二层,负责建立和管理节点间的链路。该层通常又被分为介质访问控制MAC
和逻辑链路控制LLC
两个子层MAC
数据链路层的芯片一般简称之为 MAC 控制器LLC
子层的主要任务是建立和维护网络连接,执行差错校验、流量控制和链路控制
** WIFI
MAC
和 PHY
层及协议在 OSI
位置**
Airkiss
需要关心的 length
从 802.2 SNAP LLC
解析,数据格式
802.11
帧结构如下, airkiss
对 Address1/Address2/Address3
字段进行了过滤
协议细节理解
前导码及发现过程
利用
802.2 SNAP
数据包中的Length
字段进行通信。在实际应用中采用UDP
广播包作为信息的载体。每一包的数据都是按照Airkiss
通信协议进行编码。一个UDP
包发送要经过IP
层、数据链路层的封装,并且通过加密 (WPA2、WPA、WEP
) 后才被发送出去,所以发送方发送UDP
长度与接收方监听SNAP
包长度存在差异,而且由于底层加密方式的差异,使得这个差异值也具有不确定性
因此需要监听信道计算差异值,这个差异值就是底层封装对 Length
的差异,后续传输的所有 Length
需要减去差异值
误识别
如果发送数据中包括递增值,例如 1234
、 4567
或 abcd
会导致前导码识别错误,正式库中有处理?
应用数据组成
password
+ random
+ ssid
password
和ssid
可以发送经过AES
加密后的数据,AES Key
私下协商,Airkiss
协议无规定?random
为airkiss server
生成的随机数,在连接成功之后airkiss client
将这个值发送回来以完成配网
端口的选择
airkiss server
可以是eth
或wlan
airkiss client
可以是eth
或wlan
- 可以使用
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)))
限制使用具体interface