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 库的开销。不过,我不确定从哪里开始解决这个问题。

解决此问题的任何帮助将不胜感激。

4

1 回答 1

8

我设法解决了这个问题。这是我经历的过程:

  1. 捕获一些 802.11 管理“探测请求”帧:

    tshark -n -i mon0 subtype probereq -c 5 -w probe.pcap
    
  2. 了解 RadioTap

    阅读RadioTap文档,我意识到 RadioTap 帧由以下字段组成:

    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
    

    因此,it_len 允许我们定位在 radiotap 数据之后的 802.11 帧的开头。

  3. Python中的编码解决方案

    我从我在上一篇文章中找到的三个 pcap 库选项中选择使用pylibpcap,并发现了用于解析 802.11 帧的dpkt模块。文档非常薄,因此通过在 Python 解释器中运行,我设法编写了以下代码,以从我们的捕获文件中提取 MAC、探测 SSID 和信号强度:

    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)
    
于 2013-03-06T00:25:51.200 回答