IEEE802.11数据帧在Linux上的抓取(3)

这样,我们知道了为何无法使用tcpdump抓取802.11帧了,接下来就是想办法抓取到这种帧。最关键的事情就是找到在哪里802.11帧转化为了以太帧以及相反的转化,而这很容易,在2.6.32内核中,ieee80211_invoke_rx_handlers函数里面取到的就是802.11帧,不过注意,一定要在__ieee80211_data_to_8023调用之前,对于其它的内核版本,也是类似的。找到了这个之后,接下来需要将以下的代码添加到你找到的位置:

list_for_each_entry_rcu(ptype, &ptype_all, list) {       if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||           ptype->dev == orig_dev)           ret = deliver_skb(skb, ptype, skb->dev);       }   }  

ptype_all并没有导出,那么可以通过/boot/System.map-2.6.32-5-amd64这个文件中取得,这样就可以使得tcpdump抓取到802.11的数据帧,原汁原味的。同样的方法也可以用于抓取发出的802.11数据帧。        到此为止,不得不插一句,来看看依靠802.11适配层也就是wireless框架如何来实现抓包,正如tcpdump的手册上写的那样,注意这只能在高版本的内核上才行得通,我手上的2.6.37则刚好。在框架内部,实现了ieee80211_rx函数,该函数被驱动调用,接收来自驱动的802.11数据帧,其中调用了ieee80211_rx_monitor来实现802.11数据帧直接上传到“网卡设备接口”,从而越过了适配层将802.11帧适配到以太帧这一步,ieee80211_rx_monitor中式这么实现的:

list_for_each_entry_rcu(sdata, &local->interfaces, list) {       if (sdata->vif.type != NL80211_IFTYPE_MONITOR)           continue;       if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)           continue;       if (!ieee80211_sdata_running(sdata))           continue;       if (prev_dev) {           skb2 = skb_clone(skb, GFP_ATOMIC);           if (skb2) {               skb2->dev = prev_dev;               netif_receive_skb(skb2);  //直接调用设备接口层的函数实现之           }       }       prev_dev = sdata->dev;       sdata->dev->stats.rx_packets++;       sdata->dev->stats.rx_bytes += skb->len;   }  

这种方式看起来和我的方法没什么两样,实则更妙,hack一个链表头总显得不那么正规,而导出一个函数却很显而易见。然而如果驱动不遵照这个框架来写,框架里面再好的东西也没法使用,事实上现有的Linux无线网卡驱动很多都是基于ndiswrapper的,这样可以直接加载windows上的驱动程序,如果事情是这样,那还好,糟糕的是,有人写的驱动竟然是个四不像。下文分解。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pxgxg.html