先简单说明下,在非monitor模式时,内核会将802.11帧封装成普通网络帧传递给上层;而在monitor模式时,内核会直接将802.11帧传递给上层,不再进行封装,这样用户层通过接口就可以得到802.11的raw包了。
1.查看设备芯片
有以下几种方法:
1)lsmod 可以看到目前使用的驱动模块 (有些统一名称是wlan.ko,路径在/system/lib/modules/)
2)dmesg 查看内核启动打印信息着,根据打印信息直接搜索内核源码,找到相应的驱动代码
3) cat /sys/class/rkwifi/chip 显示为RTL8188EU,这个是android wifi模块中kobj的标准接口
2.查看是否支持monitor模式
在著名的aircrak-ng的官方网站上有支持的网卡列表。
http://www.aircrack-ng.org/doku.php?id=compatibility_drivers
另外,kismet是一款比较综合的无线协议包解析的软件,包括蓝牙\GPS\WIFI,其中wifi部分主要在 phy_80211_dissectors.cc中PacketDot11dissector函数实现。
而
3.iwconfig
该命令主要实现配置网卡的模式。
iwconfig wlan0 mode Monitor
iwconfig开源源码可以在以下网站上得到:
http://www.labs.hpe.com/personal/Jean_Tourrilhes/Linux/Tools.html
其实现原理是借助内核底层的 ioctl:
- ret = ioctl(skfd, SIOCSIWMODE, &wrq);
SIOCSIWMODE表明配置的是网卡的模式,而具体的配置位,在wrq中定义。
另外,ioctl的第一个形参fd是由以下调用得到,即一个AF_INET的套接字
socket(AF_INET, SOCK_DGRAM, 0);
4.基本原理和流程
在内核中,hostap_80211_rx 函数是IEEE 802.11 接收无线skb的 tasklet函数,其作用是处理802.11网卡传递过来的数据包。
我们也可以猜想到,倘若网卡被设置成monitor模式,该函数中应当做了特别的处理。事实也正是如此:
- if (local->iw_mode == IW_MODE_MONITOR) {
- monitor_rx(dev, skb, rx_stats);
- return;
- }
当本地网卡设置为MONITOR时,将直接调用moitor_rx,而不进行下面的处理。
这里所述的处理,包括mac提取,包类型的判断等等。
在monitor函数中,主要是prism2_rx_80211函数,实现将带有802.11头的skb直接发送给netif。所谓的netif即linux内核网络数据包的标准框架。
这里具体代码就不贴出来了,看起来是比较简单易懂的。不过有一点需要补充的是,在prism2_rx_80211中,在skb中补充了一个抓包的头,其目的是为了给用户提供更多的包信息。
这个头对应的数据结构为linux_wlan_ng_cap_hdr,具体声明如下:
struct linux_wlan_ng_cap_hdr {
__be32 version;
__be32 length;
__be64 mactime;
__be64 hosttime;
__be32 phytype;
__be32 channel;
__be32 datarate;
__be32 antenna;
__be32 priority;
__be32 ssi_type;
__be32 ssi_signal;
__be32 ssi_noise;
__be32 preamble;
__be32 encoding;
} __packed;
显然,这与我们用wireshark抓到的包是相吻合的。如下图的
4.1 驱动更换问题
version不匹配问题,类似以下的内核打印。
- version magic '2.6.32.2 mod_unload modversions ARMv4 ' should be '2.6.32.2-FriendlyARM'
1)使用 modinfo可以看到相关的模块信息 以及目标机的内核:
vermagic:3.0.8-perf-00464-ga326fac SMP preempt mod_unload modversions ARMv7
cat /proc/version
Linux version 3.0.8-perf-00464-ga326fac (builder@taishan) (gcc version 4.4.3 (GCC) ) #1 SMP PREEMPT Tue Jan 8 11:46:49 CST 2013
这里,目标机器的gcc版本为4.4.3,编译模块或者应用程序的gcc需要小于该版本,否则会出现fuck的错误。
2)在menuconfig中将 moudle version检查关闭
先下载对应的内核版本(注:systemtype 选择相应的架构就好)。修改ARCH和CROSS_COMPILE 环境变量。
另外,
- Enable loadable module support --->
- [*] Module versioning support
去掉version support。
3)修改kernel 的 vermagic
先对比现有内核对应的宏。
vermagic: 2.6.39+ mod_unload ARMv5
①内核版本字符为 UTS_RELEASE "3.0.8-perf-00464-ga326fac" 位置 include/linux/generated/utsrelease.h
② 去除组合 VERMAGIC_STRING 的MACRO,位置 include/linux/vermagic.h 。这里直接修改VERMAGIC_STRING ,不用管前面的一堆信息(注意每个标记后面有一个空格)
注1:只编译执行目录的模块可以使用以下方式
- make modules SUBDIRS=drivers/net/wireless/bcmdhd
- make modules SUBDIRS=drivers/net/wireless/bcm4329
注2:获取android官方内核
$ git clone https://android.googlesource.com/kernel/common.git
$ git clone https://android.googlesource.com/kernel/exynos.git
$ git clone https://android.googlesource.com/kernel/goldfish.git
$ git clone https://android.googlesource.com/kernel/msm.git
$ git clone https://android.googlesource.com/kernel/omap.git
$ git clone https://android.googlesource.com/kernel/samsung.git
$ git clone https://android.googlesource.com/kernel/tegra.git
git branch -a
msm是高通,包含ADP1\ADP2\Nexux One\Nexus 4的源码。
omap是德州仪器,包含了PandaBoard、Galaxy Nexus的源码。
goldfish包含了适用于模拟器平台的源码。
tegra是英伟达系列。包含了Xoom和Nexus 7的源码。
exynos三星猎户座芯片组。包含了Nexus 10的源码。
然后clone下切换分支(后面的数字即为kernel版本,而非android版本)。
注3:编译文件格式,目标文件格式
- ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), BuildID[sha1]=9797a8add3ead38b191e5d7fc99150c33d5f4c7e, not stripped
- ELF 32-bit LSB relocatable, ARM, version 1, BuildID[sha1]=750621f8c1cc6e748f78527f1dbdaecac31087e0, not stripped
其中,模块可能没有EABI5,需要选中内核的CONFIG_AEABI
注4:insmod出现"no symbol version for module_layout"
这是由于内核源码目录没有Module.symvers所导致的,源码编译下就可以了。
注5:工具链可以下载谷歌官方的,也可以直接下载arm-eabi
- git clone https://android.googlesource.com/platform/prebuilt