使用 Scapy 在 Python 中构建一个 Wi-Fi 扫描器,它可以查找并显示附近可用的无线网络及其 MAC 地址、dBm 信号、信道和加密类型。
Python如何构建WiFi扫描仪?你是否曾经想构建一个工具来显示附近的无线网络及其 MAC 地址和其他一些有用信息?好吧,在本教程中,我们将使用 Python 中的 Scapy 库构建一个 Wi-Fi 扫描仪,包括Python构建WiFi扫描仪示例。
如果你在这个领域工作了一段时间,你可能已经看到airodump-ng实用程序,它可以嗅探、捕获、s 和解码802.11 帧以以一种很好的格式显示附近的无线网络,在本教程中,我们将做一个类似的。
入门
如何使用Scapy构建WiFi扫描仪?首先,你需要安装 Scapy,我已经克隆了开发版本,你也可以使用pip安装它:
pip3 install scapy
或者你可以在 Github 中克隆当前的开发版本:
git clone https://github.com/secdev/scapy.git
cd scapy
sudo python setup.py install
注意:本教程假设你使用任何基于 Unix 的环境,也建议你使用Kali Linux。
在那之后,我们将使用pandas来以一种很好的格式打印(显然你可以改变它):
pip3 install pandas
现在,如果你没有在网络接口中启用监控模式,本教程的代码将无法工作,请安装aircrack-ng(Kali 预装)并运行以下命令:
现在你可以使用iwconfig检查你的接口名称:
如你所见,我们的界面现在处于监控模式,名称为"wlan0mon"。
你还可以使用iwconfig本身将你的网卡更改为监控模式:
sudo ifconfig wlan0 down
sudo iwconfig wlan0 mode monitor
编写Python构建WiFi扫描仪示例代码
让我们开始吧,打开一个新的 Python 文件并导入必要的模块:
from scapy.all import *
from threading import Thread
import pandas
import time
import os
接下来,我们需要初始化一个空的数据帧来存储我们的网络:
# initialize the networks dataframe that will contain all access points nearby
networks = pandas.DataFrame(columns=["BSSID", "SSID", "dBm_Signal", "Channel", "Crypto"])
# set the index BSSID (MAC address of the AP)
networks.set_index("BSSID", inplace=True)
因此,我将BSSID(接入点的 MAC 地址)设置为每一行的索引,因为它对于每个设备都是唯一的。
如何使用Scapy构建WiFi扫描仪?如果你熟悉Scapy,那么你肯定知道我们将使用sniff()函数,该函数采用在嗅探数据包时执行的回调函数,让我们实现这个函数:
def callback(packet):
if packet.haslayer(Dot11Beacon):
# extract the MAC address of the network
bssid = packet[Dot11].addr2
# get the name of it
ssid = packet[Dot11Elt].info.decode()
try:
dbm_signal = packet.dBm_AntSignal
except:
dbm_signal = "N/A"
# extract network stats
stats = packet[Dot11Beacon].network_stats()
# get the channel of the AP
channel = stats.get("channel")
# get the crypto
crypto = stats.get("crypto")
networks.loc[bssid] = (ssid, dbm_signal, channel, crypto)
这个回调确保嗅探到的数据包上有一个信标层,如果是这样,那么它将提取BSSID、SSID(接入点名称)、信号和一些统计信息。Scapy 的Dot11Beacon类具有很棒的network_stats()函数,它可以从网络中提取一些有用的信息,例如通道、速率和加密类型。最后,我们将这些信息添加到以BSSID作为索引的数据帧中。
你会遇到一些没有 SSID 的网络(ssid等于""),这表明它是一个隐藏网络。在隐藏网络中,接入点将信息字段留空以隐藏网络名称的发现,你仍然可以使用本教程的脚本找到它们,但没有网络名称。
Python如何构建WiFi扫描仪?现在我们需要一种方法来可视化这个数据框。由于我们将使用sniff()函数(它会在主线程中阻塞并开始嗅探),因此我们需要使用一个单独的线程来打印网络数据帧的内容,以下代码执行此操作:
def print_all():
while True:
os.system("clear")
print(networks)
time.sleep(0.5)
现在到主要代码:
if __name__ == "__main__":
# interface name, check using iwconfig
interface = "wlan0mon"
# start the thread that prints all the networks
printer = Thread(target=print_all)
printer.daemon = True
printer.start()
# start sniffing
sniff(prn=callback, iface=interface)
还学习: 如何在 Python 中进行 SYN 泛洪攻击。
改变频道
现在,如果你执行此操作,你会注意到并非所有附近的网络都可用,这是因为我们仅在一个WLAN 信道上进行侦听。我们可以使用iwconfig命令来改变频道,这里是它的 Python 函数:
def change_channel():
ch = 1
while True:
os.system(f"iwconfig {interface} channel {ch}")
# switch channel from 1 to 14 each 0.5s
ch = ch % 14 + 1
time.sleep(0.5)
例如,如果你想更改为频道2,则命令为:
iwconfig wlan0mon channel 2
Python构建WiFi扫描仪示例 - 太好了,所以这将每0.5秒从1到14递增地更改通道 ,生成运行此函数的 守护线程:
# start the channel changer
channel_changer = Thread(target=change_channel)
channel_changer.daemon = True
channel_changer.start()
注意:低功耗模式下允许使用通道 12 和 13,而通道 14 被禁止且仅在日本允许使用。
如何使用Scapy构建WiFi扫描仪?请注意,我们将daemon
线程的属性设置为True
,因此该线程将在程序退出时结束,有关守护线程的更多信息,请查看本教程。
在此处查看完整代码。
这是我执行的屏幕截图:
结论
Python如何构建WiFi扫描仪?在本教程中,我们使用 Scapy 库编写了一个简单的 Wi-Fi 扫描器,它嗅探和解码每次由接入点传输的信标帧,它们用于宣布无线网络的存在。