【问题标题】:Why when sniffing wifi frames using sockets in python I get ethernet frames (not 802.11)为什么在python中使用套接字嗅探wifi帧时我得到以太网帧(不是802.11)
【发布时间】:2020-09-29 14:16:13
【问题描述】:

我正在尝试编写一个程序来显示所有 wifi 网络及其客户端。 代码如下:

import os
import socket
import struct

def unpack_ethernet_frame(data):
    dest_mac, src_mac, proto = struct.unpack('! 6s 6s H', data[:14])  # Big-endian, 6bytes, 6bytes, 1 short
    return format_mac(dest_mac), format_mac(src_mac), socket.htons(proto), data[14:]

def format_mac(bytes_addr):
    bytes_s = map('{:02x}'.format, bytes_addr) 
    return ":".join(bytes_s).upper()

def format_ip(bytes_addr):
    return ".".join(map(str, bytes_addr))

def unpack_ipv4_frame(data):
    header_len = (data[0] & 15) * 4  # last 4 bits of first byte * 4
    ttl, prot, src, dst = struct.unpack("! 8x B B 2x 4s 4s", data[:20])
    return format_ip(src), format_ip(dst), prot, data[header_len:]

def unpack_tcp(data):
    src_port, dst_port = struct.unpack("! H H", data[:4])
    return src_port, dst_port

def unpack_udp(data):
    src_port, dst_port, size = struct.unpack("! H H 2x H", data[:8])
    return src_port, dst_port, size, data[8:]

if __name__ == '__main__':
    conn = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(3))

    while True:
        raw_data, addr = conn.recvfrom(65536)
        dest, src, prot, data = unpack_ethernet_frame(raw_data)
        if prot == 8:  # IP
            print("Dest {0}, Src {1}, prot {2}".format(dest, src, prot))
            src_id, dst_ip, prot, data = unpack_ipv4_frame(data)
            print("From {0} to {1}".format(src_id, dst_ip))
            if prot == 6:  # TCP
                src_port, dst_port = unpack_tcp(data)
                print("src_port {0} dst_port {1}".format(src_port, dst_port))
            if prot == 17:  # UdP
                src_port, dst_port, size, data = unpack_udp(data)
                print("src_port {0} dst_port {1} size {2}".format(src_port, dst_port, size))

我不知道为什么,但是“unpack_ethernet_frame”函数接收以太网帧,而不是 MAC 帧。如果我收到无线帧,那么我宁愿获得 MAC 帧吗?大多数情况下,我要做的是找出哪些帧是信标帧并获取它们的 SSID。

编辑:我正在尝试启用监控模式的这段代码

【问题讨论】:

  • “MAC 帧”是什么意思?
  • 我认为原始套接字不允许您访问链接层以下。
  • 我的意思是 IEEE802 帧,以便能够从信标访问 SSID 和有关 AP 的其他信息

标签: python sockets ethernet wireless


【解决方案1】:

当您从socket 获取数据时,IEEE802-frame 已经被解包,而其中的Ethernet-frame 就是您所看到的。这样做是有历史原因的,而且整个IEEE802-layer 通常即使对操作系统也是不可见的。为了接收未修改的IEEE802-frames,您需要

  • 将您的 WiFi 设备设置为“监控模式”,并非所有设备都支持。这将导致所有以太网(以及所有 TCP/UDP)连接断开。
  • 不是从socket 而是直接从设备接收数据,例如通过libpcap

关于scapy,另请参阅this 答案和link

【讨论】:

  • 嗨,这里也有类似的代码:hackoftheday.securitytube.net/2013/04/…
  • 那么套接字不能做到这一点吗?
  • 我不确定,但我不会指望它。请注意,securitytube.net 上的代码接收来自mon0 的数据包,在某些驱动程序堆栈上,这是一个处于监控模式的特殊设备,它接收IEEE802-frames,而eth0 和类似的接收到捆绑的Ethernet-frames。
  • 但实际上我也在使用监控模式接口并获取以太网帧:/
  • 那么信标帧应该在哪里呢?我假设我收到了有 IP 帧的 eth 帧,有 TCP 帧等等。我应该在哪一层获得信标?
【解决方案2】:

您连接到错误的接口。您应指定要连接的网络接口。

if __name__ == '__main__':
    conn = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(3))
    conn.bind(("wlan0mon", 0x0003))
    while True:
        raw_data, addr = conn.recvfrom(65536)

这对我有用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    • 2013-07-22
    • 2014-02-21
    • 2023-01-26
    相关资源
    最近更新 更多