scapy之ap信息收集

百家 作者:OPPO安全应急响应中心 2019-10-15 09:37:05


1

以上文章由作者【syaber】有赏投稿,也欢迎广大朋友继续投稿,详情可点击OSRC重金征集文稿!!!了解~~



前言

对于无线攻击的第一步,通常是信息搜集,我们可以直接使用aircrack套件中的airodump-ng工具进行信息收集,但本文不介绍airodump-ng的使用方法,而是从较为底层的方式去实现信息搜集这一目的,从而能更好地理解对于无线信息搜集的原理,由于目的是掌握原理,所以一些地方讲得比较基础,但也不是面面俱到,小白向,望大佬轻喷。本文主要针对2.4GHz频段,不涉及5GHz。

环境/工具

kali或ubuntu16.04/18.4系统(作者使用的是ubuntu18.04,由于windows,mac系统对无线攻击的支持不完善,不建议使用windows/mac系统进行无线攻击)一张外置无线网卡


Scapy

scapy是python的一个库,主要用于各种协议的数据包发送或嗅探,也可以自己构造一个协议。由于kali自带的scapy版本过老,如果使用kali,需要更新下scapy库。安装scapy:

pip install https://github.com/secdev/scapy/archive/master.zip


手动信息收集

我们先手动对ap进行信息搜集,从而了解信息搜集的原理。

在开始信息搜集之前,先大致了解下802.11协议的一些理论知识,这里主要介绍下Beacon帧。

对于ap的信息搜集主要来源便是Beacon帧,Beacon帧又称信标帧,在很多协议中都有Beacon帧这一概念,在802.11协议中,Beacon帧主要用于宣告ap的存在。Beacon帧中携带许多重要的信息,比如说ap的mac地址、ssid、信道、加密方式等等。

用手机打开wifi开关后,在wifi列表中便可以看到存在的ap,这个过程可以理解为手机不断切换信道去接收各个信道上的Beacon帧,实际上也是一个信息搜集的过程。

为了在wireshark中分析Beacon帧,我们先把网卡设置为监听模式:

sudo airmon-ng start wlx70f11c1f9108

激活网卡:

sudo ifconfig wlan0mon up

(网卡名称通过iwconfig命令查看)

Beacon帧属于管理帧,type为0,子帧类型subtype为8,在wireshark中可以用

wlan.fc.type_subtype==8

或者

wlan.fc.type==0 and wlan.fc.subtype==8

来过滤Beacon帧:

Beacon帧头:

在Beacon帧头部可以看到Beacon的目的地址(Destination address)为:

ff:ff:ff:ff:ff:ff

即广播地址,Beacon帧的源地址(Source address)为:

68:a0:3e:**:**:**

即ap的mac地址

802.11协议帧通过信息元素(IE)来携带一些信息,802.11协议的信息元素架构为:

信息元素由ID来标识,如ID=0,即代表此信息元素为SSID,Length表示信息元素的长度,范围为0~0xff字节,每个信息元素携带的信息则放在Info中。

wireshark中的Beacon帧:

前面的固定参数:Timestamp,Beacon Interval,Cap info分别表示ap的存活时间,Beacon帧的发送间隔以及一些flag标志位。

我们主要注意下面的信息元素。

SSID:

学名服务集标识,通俗讲就是wifi的名字。约定俗称ssid的长度最多为32字节,但802.11协议规定信息元素的长度最多为255字节,这里曾经出现过ssid长度溢出漏洞,后来被默默修复了。

Channel:

用来表示当前ap的信道。2.4Ghz主要使用1至14信道。

RSN:

802.11i新引入的信息元素,表示一些关于安全的信息,比如加密方式,认证方式。
加密方式的对应关系为:

'0':'Use group cipher suite''1':'WEP-40''2':'TKIP''3':'Reserved''4':'CCMP''5':'WEP-104'

认证方式的对应关系为:

'0':'reversed''1':'IEEE 802.1X / PMKSA caching''2':'PSK'

802.1x主要用于企业wifi认证,我们平时用的wifi主要是PSK认证。


到目前为止,我们用人工的方式进行了信息搜集,显然是个比较繁琐的过程,而且不能批量信息搜集,对于别的信道的ap,还需要更改网卡信道,下面我们使用scapy来代替人工操作。


使用Scapy进行信息收集

这里我们主要使用scapy的嗅探功能。

先贴上最简单的脚本:

from scapy.all import *
class sniffer():def __init__(self,iface):self.iface=ifaceself.cipher_suites={'x00':'Use group cipher suite','x01':'WEP-40','x02':'TKIP','x03':'Reserved','x04':'CCMP','x05':'WEP-104'}self.akm_suites={'x00':'reversed','x01':'802.1X','x02':'PSK'}self.run()def PacketHandler(self,pkt): ap_mac=pkt[Dot11].addr3if ap_mac not in self.ap:self.ap.append(ap_mac) print "%s | beacon"%ap_mac pkt.show()
def run(self): sniff(iface=self.iface,prn=self.PacketHandler,filter="type mgt subtype beacon")
if __name__ == "__main__": sniffer('wlan0mon')

参数填入网卡接口的名称即可。

scapy嗅探函数sniff底层调用的是tcpdump,所以sniff的过滤规则和tcpdump一致(参考https://www.tcpdump.org/manpages/pcap-filter.7.html)

filter="type mgt subtype beacon"

表示过滤管理帧,并且子帧类型为beacon。

sniff函数的prn参数可以将嗅探到的数据包交给prn参数进行处理。

def PacketHandler(self,pkt):    ap_mac=pkt[Dot11].addr3if  ap_mac not in self.ap:self.ap.append(ap_mac)        print "%s | beacon"%ap_mac        pkt.show()

PacketHandler用来处理嗅探到的Beacon帧,scapy会解析Beacon帧,可以使用pkt.show()查看Beacon的各个layer,运行此脚本:

在Dot11层可以看到Beacon帧头的一部分信息,其中addr3即为Beacon帧的源地址。

如果不熟悉scapy的layer命名,可以用下面定义的函数查看:

def expand(x):yield xwhile x.payload:        x = x.payloadyield xprint list(expand(pkt))

我们需要从scapy解析的帧中将mac地址,ssid,信道,加密方式,认证方式提取出来。

但由于scapy的信息元素的layer全都是Dot11Elt,想要遍历所有的Dot11Elt,可以在读取第一个Dot11Elt后将其舍弃,从而自顶向下遍历:

elt=pkt[Dot11Elt]while elt.payload:                                            ......elt=elt.payload

获取ssid:

if elt.ID==0: #ssid    ssid=elt.info

获取信道:

elif elt.ID==3: #channel    ch=ord(elt.info)

解析RSN有些复杂:

pkt.show()

虽然scapy已经解析出加密以及认证方式,但我们取出仍是字节,取出pairwise_cipher_suites以及akm_suites的最后一个字节,再到字典比对:

elif elt.ID==48: #ciper and authcipher_type=str(elt[Dot11EltRSN].pairwise_cipher_suites[0])[-1:]akm_type=str(elt[Dot11EltRSN].akm_suites[0])[-1:]cipher=self.cipher_suites[cipher_type]auth=self.akm_suites[akm_type]

当前脚本:

from scapy.all import *
class sniffer():def __init__(self,iface):self.iface=ifaceself.ap=[]self.cipher_suites={'x00':'Use group cipher suite','x01':'WEP-40','x02':'TKIP','x03':'Reserved','x04':'CCMP','x05':'WEP-104'}self.akm_suites={'x00':'reversed','x01':'802.1X','x02':'PSK'}self.run()def promt(self,arg1,arg2,arg3,arg4,arg5):return "%17s%30s%10s%10s%10s"%(arg1,arg2,arg3,arg4,arg5)def PacketHandler(self,pkt): ap_mac=pkt[Dot11].addr3if ap_mac not in self.ap: ssid=None ch=None cipher=None auth=Noneself.ap.append(ap_mac) elt=pkt[Dot11Elt]while elt.payload:if elt.ID==0: #ssid ssid=elt.info elif elt.ID==3: #channel ch=ord(elt.info) elif elt.ID==48: #ciper and auth cipher_type=str(elt[Dot11EltRSN].pairwise_cipher_suites[0])[-1:] akm_type=str(elt[Dot11EltRSN].akm_suites[0])[-1:] cipher=self.cipher_suites[cipher_type] auth=self.akm_suites[akm_type] elt=elt.payload print self.promt(ap_mac,ssid,ch,cipher,auth)
def run(self): print self.promt('mac','ssid','channel','cipher','auth') sniff(iface=self.iface,prn=self.PacketHandler,filter="type mgt subtype beacon")
if __name__ == "__main__": sniffer('wlan0mon')

运行结果:

 (最后一个是隐藏wifi)

这时我们发现嗅探到的都是一信道的ap,因为我们的网卡在第一信道,扫描全信道需要不断更改网卡信道,我们使用多线程每0.5秒切换下信道,最终脚本:

from scapy.all import *from threading import Threadimport osimport time
def change_ch(iface): ch=0while 1: ch+=1 cmd="sudo iwconfig {iface} channel {channel}".format(iface=iface,channel=(ch%14+1)) os.system(cmd) time.sleep(0.5)

class sniffer():def __init__(self,iface):self.iface=ifaceself.ap=[]self.cipher_suites={'x00':'Use group cipher suite','x01':'WEP-40','x02':'TKIP','x03':'Reserved','x04':'CCMP','x05':'WEP-104'}self.akm_suites={'x00':'reversed','x01':'802.1X','x02':'PSK'}self.run()def promt(self,arg1,arg2,arg3,arg4,arg5):return "%17s%30s%10s%10s%10s"%(arg1,arg2,arg3,arg4,arg5)def PacketHandler(self,pkt): ap_mac=pkt[Dot11].addr3if ap_mac not in self.ap: ssid=None ch=None cipher=None auth=Noneself.ap.append(ap_mac) elt=pkt[Dot11Elt]while elt.payload:if elt.ID==0: #ssid ssid=elt.info elif elt.ID==3: #channel ch=ord(elt.info) elif elt.ID==48: #ciper and auth cipher_type=str(elt[Dot11EltRSN].pairwise_cipher_suites[0])[-1:] akm_type=str(elt[Dot11EltRSN].akm_suites[0])[-1:] cipher=self.cipher_suites[cipher_type] auth=self.akm_suites[akm_type] elt=elt.payload print self.promt(ap_mac,ssid,ch,cipher,auth)
def run(self): print self.promt('mac','ssid','channel','cipher','auth') sniff(iface=self.iface,prn=self.PacketHandler,filter="type mgt subtype beacon")
if __name__=="__main__": t1=Thread(target=change_ch,args=('wlan0mon',)) t1.daemon=True t1.start()
t2=Thread(target=sniffer,args=('wlan0mon',)) t2.start() t2.join()

最终结果:





关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接