Discovering Hidden SSIDs with Wireshark and Scapy

25 Mar 2013

The goal of this post is to demonstrate a simple Python script I wrote which uses Scapy to detect BSSIDs and SSIDs and use this in conjunction with Wireshark to resolve the SSID. It's relatively easy to detect hidden SSIDs and there are other tools that allow you to this as well like inSSIDer. However I wanted to try out Scapy and do a bit of DIY.

Get yourself a copy of the latest Backtrack 5 or its successor Kali and update it, we will be using airmon-ng, aireplay-ng, wireshark, scapy and python to discover hidden SSIDs. Make sure you have an antenna capable of being put into monitoring mode (I'm using the AWUS036H). Use airmon-ng to put your wireless card (in my case wlan0) into monitoring mode, so we can capture all wireless traffic:

airmon-ng start wlan0

This should normally become mon0, you can check with ifconfig to see what monitoring interface number your received. From there launch Wireshark and select your monitoring interface to sniff, in my case this is mon0. Wireshark comes with different filters, below you can find a small overview of frames you can filter in regards to wireless traffic:

wlan.fc.type == 0           Management frames
wlan.fc.type == 1           Control frames
wlan.fc.type == 2           Data frames
wlan.fc.typesubtype == 0   Association request
wlan.fc.typesubtype == 1   Association response
wlan.fc.typesubtype == 2   Reassociation request
wlan.fc.typesubtype == 3   Reassociation response
wlan.fc.typesubtype == 4   Probe request
wlan.fc.typesubtype == 5   Probe response
wlan.fc.type_subtype == 8   Beacon
I made a simple Python script that uses Scapy to detect probe answers and requests to identify Access Points with a hidden SSID. It will capture wireless traffic, analyze it and write unique BSSIDs with the corresponding SSID to a CSV file:

from scapy.all import *
from csvCreator import CSV
aps = dict()
headers = ['channel','enc','bssid','ssid'] #The headers for the CSV file
csvFile = CSV('sniffed.csv',headers) #Create a new CSV file with the previously defined headers
def sniffAP(p):
    detectAP(p)
def detectAP(p):
    if ( (p.haslayer(Dot11Beacon) or p.haslayer(Dot11ProbeResp))
                 and not aps.has_key(p[Dot11].addr3)):
        ssid       = p[Dot11Elt].info
        bssid      = p[Dot11].addr3
        channel    = int( ord(p[Dot11Elt:3].info))
        capability = p.sprintf("{Dot11Beacon:%Dot11Beacon.cap%}\
                {Dot11ProbeResp:%Dot11ProbeResp.cap%}")
        # Check for encrypted networks
        if re.search("privacy", capability): enc = 'Y'
        else: enc  = 'N'
        # Save discovered AP
        aps[p[Dot11].addr3] = enc
        # Write the results to the CSV file
    csvFile.addToCSV( [int(channel), enc, bssid, ssid] )
sniff(iface = "mon0",prn = sniffAP)

The CSV class csvCreator.py:

class CSV(object):
    csvFile = None
    fileName = ''
    def __init__(self,fileName,headers):
        self.fileName = fileName
        self.prepareCSVFile(headers)
    def prepareCSVFile(self,headers):
        self.csvFile = open(self.fileName, 'w')
        headerString = self.prepareValues(headers)
        self.writeToCSV(headerString)
    def prepareValues(self,valueList):
        line = str()
        x = len(valueList)
        for item in valueList:
            print x
            line = line + str(item)
            if x != 1:
                line = line + ','
            else:
                line = line + '\n'
            x = x - 1
        return line
    def addToCSV(self,valueList):
        valueLine = self.prepareValues(valueList)
        self.writeToCSV(valueLine)
    def writeToCSV(self,line):
        self.csvFile.write(line) 

The script uses Scapy to monitor all traffic and filters packets on beacon and probe packets. Launch the script and let it run for about a minute, you can break it with CTRL+c. Now check sniffed.csv, this file contains all uniquely discovered BSSIDs with a corresponding SSID, a hidden SSID will have an empty SSID field. For the sake of the example, let's say the BSSID of the AP we are trying to identify is 00:01:02:03:04:05. Now to identify the SSID of the AP we will use Wireshark, you can either wait for a client to connect to the AP or you can force clients to deauthenticate from the AP. Once they try to reconnect you can capture the request and look up the SSID. Add a filter to wireshark to filter on WLAN packets directed to the AP only and to exclude all beacon frames.

wlan.bssid == 00:01:02:03:04:05 && (wlan.fc.type_subtype != 8)
Now force a deauthentication by broadcasting a message to all stations connected to this particular AP by using aireplay-ng:

aireplay-ng --deauth 0 -a 00:01:02:03:04:05 mon0

Let's break it down:

  • --deauth => Deauth attack
  • 5 => amount of packets to send
  • -a => BSSID to send the deauthentication packages for, if set to 0 you will continuously send deauthentication packets
  • mon0 => our monitoring interface
It might be on Backtrack that you get an error, then you need to add an extra parameter so the command equals:

aireplay-ng --deauth 0 -a 00:01:02:03:04:05 mon0 --ignore-negative-one

Now once you have sent the packets, keep looking at wireshark you should get clients re-authenticating, sending along the SSID of the AP.

wiresharkj

Look at the depiction, on the last column on the bottom you can see a client reconnecting using the "Wireless Lab" SSID. You can also filter to only display probe responses towards the specific SSID by using:

wlan.bssid == 00:01:02:03:04:05 && wlan.fc.type_subtype == 5
So now you know how to discover hidden SSIDs using Python, Scapy and Wireshark. Have fun!