|
|
楼主 |
发表于 2019-8-1 14:20:04
|
显示全部楼层
咕了两个星期,更新一点
关于 packet injection 与 radiotap header
由于这玩意儿实在搜不到什么连鸽子都能看懂的中文版的解释所以按照自己的理解随便写点 可能有误请指出
当把支持 monitor mode 下称监听模式 的网卡设置成监听模式后,它就可以监听在你设定的频率上能被这网卡认出来的包
有很多网卡支持这个模式 如原项目的ar9271/rtl8812之类 也有一些网卡不支持如 ath6k ath10k那些
这些不支持常见原因是因为没有支持这个功能的firmware
firmware就是字面意思 可以当作是初始化网卡时主机传给网卡内部cpu运行的程序
有的firmware开源了 如ar9271那个 上面有提到 更多的没有开源
firmware的有些行为会无法预测 如ar9271在注入的时候不管你填什么速率 g还是n 都会按1mbps发送 因为顺序写死在firmware里了
还有rtl8192啥的忘了一个 发data包全部默认mcs7 发rts包全部默认1mbps = =...还改不了
所以给图传选个能用的网卡比较难= =
监听模式下同时也可以按照你的要求绕过协议栈发送一些自定义的包 叫做 packet injection 注入
对于这个项目而言 好处是绕过了协议栈的确认重传等等一大堆复杂的问题 底层可以由自己控制 可以降低延迟 等等
在用户态的应用程序告诉驱动该怎么发送这个包的时候 除了包的本体 还需要带上一些额外的信息 常见的如 速率 频率 guard interval 等等
这些信息在注入时需要你自己确定好 按照格式写在头部传递给内核 然后驱动会读取这些内容并按照你的设定发送
同样在收包的时候 驱动会按照相同的格式填好信息并返回给用户态的应用程序
这套描述附加信息并写在头部的方式叫 radiotap
下面会简单描述一下这东西在ez-wifibroadcast项目里怎么玩的
先以我用wireshark随便抓到的一个包(接收)为例解释一下它的包头结构
0x00, // Header revision
0x00, // padding (for (uint16)length )
0x24, 0x00, // Length, (le)uint16
0x2f, 0x40, 0x00, 0xa0, // Present flags word (bit31=1, has next present flag)
0x20, 0x08, 0x00, 0x00, // Second Present flags word
0x00, 0x00, 0x00, 0x00, // padding (timestamp uint64)
0xf1, 0x18, 0xc2, 0x3f, 0x00, 0x00, 0x00, 0x00,
// Timestamp, uint64, 1069684977
0x10, // flags (See enum ieee80211_radiotap_flags)
0x30, // Data rate (500kHz unit)
0x85, 0x09, // 0x0985, 2437, Channel frequency MHz
0xc0, 0x00, // Channel flags (See enum ieee80211_radiotap_channel_flags)
0xcb, // Signal, int8, -53, dBm
0x00, // Antenna 0
0x00, 0x00, // RX Flags (See enum ieee80211_radiotap_rx_flags)
// Second Present flags word
0xcb, // Signal, int8, -53, dBm
0x00, 0x00, // Antenna 1
结构都写了注释 应该很好看懂
present flag 用每一bit指示后面是否有出现相应的数据项
可以存在多个 present flag 若某一个present flag 转大端后的最高位为1 则指示紧接着的四个字节是下一个present flag
这段数据中的第一个 present flag如下 (仅写出了为1的位)
1010 0000 0000 0000 0100 0000 0010 1111
.... .... .... .... .... .... .... ...1 = TSFT: Present
.... .... .... .... .... .... .... ..1. = Flags: Present
.... .... .... .... .... .... .... .1.. = Rate: Present
.... .... .... .... .... .... .... 1... = Channel: Present
.... .... .... .... .... .... ..1. .... = dBm Antenna Signal: Present
.... .... .... .... .1.. .... .... .... = RX flags: Present
..1. .... .... .... .... .... .... .... = Radiotap NS next: True
1... .... .... .... .... .... .... .... = Ext: Present
最高位指示有下一个present flag,如下:
0000 0000 0000 0000 0000 1000 0010 0000
.... .... .... .... .... .... ..1. .... = dBm Antenna Signal: Present
.... .... .... .... .... 1... .... .... = Antenna: Present
关于padding在radiotap的规范里有提到 由于每项数据的大小都是不同的 所以在确认是否需要padding 的时候 看下一个数据的大小 把下一个数据对齐到该大小的整数倍 与前一项中间的空位就都填0
比如第一个数据uint8在0x0,第二个放uint32的话就要在前面补3个0x00,这样这个uint32就是对齐的
每个数据占用的大小见Linux内核源码的 include/net/ieee80211_radiotap.h 数据排列顺序按照 present flags 字段中先转为大端序后 从低位到高位的顺序
数据本体为小端序
所以按照上面两个present flag 的解析,后面的数据顺序应该如下:
TSFT +Flags +Rate +Channel +dBm Antenna Signal +RX flags +Radiotap NS next +dBm Antenna Signal(2) +Antenna(2) (并按需padding)
然后对着注释就能看明白了。。
至于发送的时候,摘取原项目tx_measure中一点 见 https://github.com/rodizio1/EZ-WifiBroadcast/blob/1.6RC6/root/wifibroadcast/tx_measure.c#L160
packet_header_init() 这个函数负责填写发送缓冲区的radiotap头部与ieee80211头部
具体做的事是 把 u8aRadiotapHeader 以及 u8aIeeeHeader_rts, u8aIeeeHeader_data_short, u8aIeeeHeader_data中(看你的配置)的一个复制到缓冲区的开头
并按照配置填写rate与port
摘录如下
static u8 u8aRadiotapHeader[] = { 0x00, 0x00, // <-- radiotap version 0x0c, 0x00, // <- radiotap header length 0x04, 0x80, 0x00, 0x00, // <-- radiotap present flags 0x00, // datarate (will be overwritten later in packet_header_init) 0x00, 0x00, 0x00};
结构完全可以用上面提到的解释 就不写了
值得注意的是这个在使用ar9271(ath9k_htc)网卡时填写rate也没用,因为他们是靠搞了一堆不同的firmware切换来达成发送速率切换的
另外 上面提到的rate字段仅对802.11abg起作用
如果想要通过radiotap指定发送802.11n或是802.11ac的包 甚至开启ldpc抠2个dbm出来的话
需要网卡驱动支持按照radiotap发包(atk9k就没毛病。。)ldpc需要网卡硬件支持
并在present flag中 设定 mcs 或 vht 的位 并在对应位置增加数据
具体可以见我写的 https://github.com/libc0607/YJSNPI-Broadcast/blob/op/root/wifibroadcast/tx_test.c 是一个可以拿来发测试包的小程序 写了注释
参考资料
https://github.com/torvalds/linux/blob/master/include/net/ieee80211_radiotap.h
https://warmcat.com/git/packetspammer/tree/packetspammer.c
https://github.com/torvalds/linux/blob/master/Documentation/networking/radiotap-headers.txt
https://github.com/torvalds/linux/tree/master/Documentation/networking/mac80211-injection.txt
|
| |