用Python访问802.11无线管理帧

8

我想从Linux的Python中嗅探802.11管理“探测请求”帧。可以使用Scapy来实现:

# -*- coding: utf-8 -*-
from scapy.all import *

def proc(p):
        if ( p.haslayer(Dot11ProbeReq) ):
                mac=re.sub(':','',p.addr2)
                ssid=p[Dot11Elt].info
                ssid=ssid.decode('utf-8','ignore')
                if ssid == "":
                        ssid="<BROADCAST>"
                print "%s:%s" %(mac,ssid)

sniff(iface="mon0",prn=proc)

或者像这样从tshark:

tshark -n -i mon0 subtype probereq -R 'wlan.fc.type_subtype eq 4' -T fields -e wlan.sa -e wlan_mgt.ssid

我们可以将tshark的输出重定向,并使用一些Python代码来读取它(不太美观,但很有效)。
然而,这两个选项都有GPL许可证,这使得潜在的商业项目变得棘手。因此,我正在尝试为这个具体问题找到一个Python中的“低级”解决方案。从谷歌上,我已经找到了两个潜在的方向:
1. Pcap库:似乎有三个可用于Python的pcap库:pylibpcappypcappcapy。我不太确定如何将上述功能合并到这些库中。任何示例代码或解决方案都将是极好的。
2. 原始套接字:PF_PACKET:“数据包套接字用于在设备驱动程序(OSI第2层)级别接收或发送原始数据包。它们允许用户在物理层之上的用户空间中实现协议模块。”
这似乎可以是另一个选择,完全绕过pcap。我听说过的评论甚至认为这可能是更好的方法,去除pcap库的开销。不过,我不确定从哪里开始解决这个问题。任何帮助解决这个问题都将不胜感激。
1个回答

8
我已经理解了这个问题。以下是我进行的步骤:

我成功地解决了这个问题。下面是我经历的过程:

  1. Capture some 802.11 management 'probe-request' frames:

    tshark -n -i mon0 subtype probereq -c 5 -w probe.pcap
    

  2. Understand RadioTap

    Reading RadioTap documentation, I realised that RadioTap frames are comprised of the following fields:

    it_version (2 bytes) - major version of the radiotap header is in use. Currently, this is always 0
    it_pad (2 bytes) - currently unused 
    it_len (4 bytes) - entire length of the radiotap data, including the radiotap header
    it_present (8 byte) - bitmask of the radiotap data fields that follows the radiotap header
    

    Therefore the it_len allows us to locate the beginning of the 802.11 frame that follows the radiotap data.

  3. Coding solution in Python

    I chose to use pylibpcap from three pcap library options I found in my previous post, and discovered the dpkt module for parsing 802.11 frames. Documentation was very thin, so by playing in the Python interpreter I managed to work out the following code to extract MAC, probe SSID, and signal strength from our capture file:

    f = open('probe.pcap')
    pc = dpkt.pcap.Reader(f)
    dl=pc.datalink()
    if pc.datalink() == 127: #Check if RadioTap
            for timestamp, rawdata in pc:
                    tap = dpkt.radiotap.Radiotap(rawdata)
                    signal_ssi=-(256-tap.ant_sig.db)        #Calculate signal strength
                    t_len=binascii.hexlify(rawdata[2:3])    #t_len field indicates the entire length of the radiotap data, including the radiotap header.
                    t_len=int(t_len,16)                     #Convert to decimal
                    wlan = dpkt.ieee80211.IEEE80211(rawdata[t_len:])
                    if wlan.type == 0 and wlan.subtype == 4: # Indicates a probe request
                        ssid = wlan.ies[0].info
                        mac=binascii.hexlify(wlan.mgmt.src)
                        print "%s, %s (%d dBm)"%(mac,ssid,signal_ssi)
    


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接