简体   繁体   English

为什么在 python 中使用套接字嗅探 wifi 帧时我得到以太网帧(不是 802.11)

[英]Why when sniffing wifi frames using sockets in python I get ethernet frames (not 802.11)

I am trying to write a program that will display all wifi networks and their clients.我正在尝试编写一个程序来显示所有 wifi 网络及其客户端。 The code looks as follows:代码如下所示:

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))

I do not know why, but "unpack_ethernet_frame" function receives Ethernet frames, not MAC frames.我不知道为什么,但是“unpack_ethernet_frame”函数接收以太网帧,而不是 MAC 帧。 If I receive wireless frames then I should rather get MAC frames?如果我收到无线帧,那么我应该获得 MAC 帧吗? Mostly what I am trying to do is to find out which frames are beacon frames and get their SSID.大多数情况下,我想要做的是找出哪些帧是信标帧并获取它们的 SSID。

EDIT : I am trying this code with Monitor mode enabled编辑:我正在尝试启用监控模式的代码

When you are getting your data from a socket , the IEEE802 -frame has already been unpacked and the Ethernet -frame within it is what you see.当您从socket获取数据时, IEEE802帧已经解包,其中的Ethernet帧就是您所看到的。 There are historical reasons why this is done and the whole IEEE802 -layer is usually not visible even to the OS.这样做是有历史原因的,整个IEEE802层通常甚至对操作系统都不可见。 In order to receive unmodified IEEE802 -frames, you need to为了接收未修改的IEEE802帧,您需要

  • turn your WiFi-device into "Monitor mode", which not all devices support.将您的 WiFi 设备转为“监控模式”,并非所有设备都支持这种模式。 This will cause all Ethernet- (and by extension, all TCP/UDP-) connections to get dropped.这将导致所有以太网(以及所有 TCP/UDP-)连接被丢弃。
  • receive your data not from a socket but directly from the device, eg via libpcap .不是从socket而是直接从设备接收数据,例如通过libpcap

Also see this answer and this link regarding scapy .另请参阅答案和有关scapy 的链接

You've connected to the wrong interface.您连接到了错误的接口。 You shall specify which network interface you want to connect.您应指定要连接的网络接口。

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)

This worked for me这对我有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM