SmartConfig 3
From: http://depletionregion.blogspot.com/2013/10/cc3000-smart-config-and-keyphrase.html
CC3000 Smart Config and keyphrase recovery
Having previously described how the SSID and keyphrase are transmitted to a
CC3000 enabled device I thought I should put my money where my mouth is and
prove that it's possible to create an application capable of recovering such
information.
This proved a bit more difficult than expected but ultimately the code required
turned out to be fairly simple.
Capturing wifi packets
While sniffing ethernet packets on a wired network is something pretty much any
computer can do the same is not true for looking at wifi packets. To be able to
look at all packets, not just ones involving the machine doing the sniffing, one
has to be able to enable what's called monitor mode. The ease with which this
can be done seems to depend on the wifi chipset, the OS and other factors. Even
if one can enable monitor mode one may be able to see the headers for packets
without being able to see the data portion, again this seems to be dependent on
chipset and other factors.
After much unsuccessful experimentation on Linux I eventually found it was
actually easier to get things working without any issues or special tricks on my
Mac. I did eventually get things to work on my Linux box and this is described
later, but as it's rather more involved I'll stick with describing the Mac setup
initially.
I just downloaded and installed the latest Mac version of Wireshark (the
de-facto standard packet analysis tool). After installation the command line
version, called tshark, and other tools could be found in /usr/local/bin. Note:
when I installed Wireshark it created /usr/local/bin such that it belonged to a
userid that did not exist and with 0700 permissions, so I did:
$ sudo chmod 755 /usr/local/bin
First I found the wifi device like so:
$ tshark -D
It was en0, then I tested that I could capture packets including the data
portion like so:
$ tshark -i en0 -I -V
The options tell tshark to capture packets from en0 (-i en0), using monitor
mode (-I) and to produce verbose output (-V). Verbose output will show the
binary contents of the data portions of any packets that have data. The fact
that the data is encrypted isn't important.
Filtering for relevant packets and
outputting relevant information
The -V options shows way more detail than is actually needed and without filters
one sees information about many packets that aren't of interest.
After some experimentation I came up the following:
$ tshark -o 'wlan.enable_decryption:FALSE' \
-i en0 -I -f 'subtype qos-data' \
-Y 'wlan.fc.retry==0' -T fields \
-e wlan.bssid -e radiotap.channel.freq -e wlan.sa -e wlan.da -e data.len
As we can't decrypt the packet data we can't look at the higher level protocol
information, so we can't simply filter for UDP traffic. But we can ignore all
packets that can't possibly contain the UDP traffic we're interested in. We do
this by excluding all packets that are not of subtype QoS data (-f 'subtype
qos-data'). And we ignore all retransmitted packets (-Y 'wlan.fc.retry==0'),
this may not sound intuitive but handling them in a meaningful manner is
difficult and on the whole they tend to duplicate data that we actually already
have rather than providing data that has somehow been missed (which was my
initial assumption).
The -T fields and subsequent -e arguments are our replacement for -V and only
output the very limited set of fields values that we are interested in:
BSSID - the numeric address behind the human readable SSID - see Basic
service set identification.
Channel frequency - see WLAN channels (and more on channel hopping later).
Source address - the address of the sender of a given packet.
Destination address - the destination address of a given packet.
Data length - the length of the encrypted data portion of a given packet.
BBSID and channel frequency are just output for reference - they are not
actually required by any of the SSID or keyphrase recovery logic.
Note: wireshark and tshark can actually decrypt wifi packets if you provide the
necessary information. If you've already configured and enabled decryption then
tshark will pick this up from your ~/.wirehark file and automatically decrypt
packets. Above I've actively disabled this behavior with the
-o 'wlan.enable_decryption:FALSE' option, if you don't have decryption already
configured you don't need this.
SSID and keyphrase recovery application
I've written an application in Java that parses the output of tshark and
recovers the SSID and keyphrase information from this data. If you've got git
installed you can just clone the relevant repository from GitHub like so:
$ git clone
https://github.com/george-hawkins/betaengine
If you don't have git you can just download the repository contents as a zip
file from here:
https://github.com/george-hawkins/betaengine
The code is fairly simple and short (700 lines in total) and just consists of
the following classes:
Consumer - contains the main method and reads and parses the output from
tshark.
Analyzer - maintains a LinkManager per source/destination pair seen.
LinkManager - looks for data length differences that might indicate Smart
Config data.
LengthDecoder - finds SSID and keyphrase sequences.
Solver - attempts to combine partial SSID and keyphrase sequences to
generate and decode complete sequences.
EncodedData and Link - trivial support classes.
The files come with a README.md that briefly outlines how to compile and run the
application (for the run instructions look at the "Decoder" section). Basically
you just run tshark and pipe its output directly into the application. If you
then use a Smart Config application to communicate an SSID and keyphrase to a
CC3000 enabled devise you should soon see something like:
Solved SSID: [MyPlace]
Solved keyphrase: [LetMeIn]
Scan succeeded
This shows that we succeeded in recovering the SSID, in this case "MyPlace", and
the keyphrase, in this case "LetMeIn". Note that it may find the SSID or
keyphrase long before the other.
Any characters that are not printable character in the Unicode range 0x20 to
0xFF are printed as Unicode escapes, e.g. the € symbol would appear as "\u20AC".
If you don't succeed in recovering the password then it maybe that you are not
listening on the right wifi channel - see the channel hopping section later.
However generally you will be on the right channel already as a result of having
being previous connected to the relevant wifi access point (AP).
Note that while tshark is running in monitor mode your machine will be
disassociated from your AP and other applications on the machine will not be
able to access the network.
If you used AES encryption then the keyphrase displayed will be the still
encrypted version and will probably appear largely as Unicode escapes due to
non-printing characters etc. I haven't added AES decryption logic, this is left
as an exercise for the reader, it's simple actually if you create a cipher using
AES Electronic Cook Book transformation with no padding as described briefly in
the middle of this post. Obviously any such logic will need the relevant AES key
to decrypt a given keyphrase.
Important update Dec 8th, 2014: please see this comment from Mark and my reply.
I have not updated my code to reflect any recent changes such as this and do not
plan to do so.
Implementation issues
So what were the main difficulties encountered in creating the application?
When I started I thought it would be easier to filter the packets I was
interested in from all the other packets and I assumed I would see cleaner runs
of packets corresponding to the SSID and keyphrase.
However while one can group packets by source and destination, when one cannot
decrypt the packets one can only do so much to distinguish between Smart Config
related packets and other similar traffic between a given source and destination.
Using what we know about Smart Config it's possible to filter out many packets
but we still end up with a combination of extra invalid values and missing
values between the packets that delimit the SSID and keyphrase. I refer to the
invalid extra values as spam and the missing values as holes in my code. The
holes are presumably the product of packet collision, the spam the product of
unrelated traffic that can't be distinguished from Smart Config traffic due to
encryption. And remember that the packets that have an appropriate data length
such that they appear to be Smart Config tags, separators etc. may themselves
just be the result of unrelated traffic that coincidentally involves packets
that have the lengths being looked for.
Note: packet collision shouldn't be the issue it is on wired ethernet networks
due to the need to use CSMA/CA on wifi networks.
The Smart Config application transmits the same sequences over and over again.
The Solver class takes multiple received sequences, each probably containing
spam and holes, and tries to construct a clean sequence of the required length
that obeys the upper nibble rules etc., described in my previous post, that we
know have to apply.
The current Solver is just one possible implementation, one could imagine
taking completely different approaches with different pros and cons. It should
certainly possible to come up with more complex logic that can recover the SSID
and keyphrase from fewer repeats of the underlying sequences in the face of
greater amounts of spam and collisions.
Note: the current solver tries hard to patch pieces from multiple sequences
together to create a complete clean sequence. Sometimes it will actually produce
multiple valid solutions and you'll see output like this:
Solved SSID: [MyPlacf]
Solved SSID: [MyPlace]
Obviously only one solution is the right one - with a little extra effort it
would be possible to generate statistics for each solution, on e.g. things like
how much patching was involved, to give some indication as to how likely a given
solution is to be the right one. Sometimes if an SSID or keyphrase tag gets lost
in transmission the current solver can occasionally produce a largish number of
very poor solutions.
Channel hopping
The tshark logic described above will only listen on whatever channel your wifi
device is currently configured for, typically channel 1, 6 or 11. The CC3000
must presumably do channel hopping to find the relevant channel. Tshark and
related utilities don't directly support channel hopping - but it's relatively
easy to setup channel hopping - see the channel hopping section of the Wireshark
wiki page on capture setup.
On Mac things are even easier - one can use the standard, but well hidden,
airport application that can be found here:
/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport
With this command you can scan for nearby networks and see what channel they're
using, you can disassociate from your current network and change the current
channel of your wifi device. See e.g. CNET's overview of various Mac network
related CLI commands for more details.
Setting up aircrack and tshark on Linux
As outlined above it proved to be easier getting tshark working on Mac. I did
eventually get it working on my Ubuntu 12.04 machine. The main issue was
enabling monitor mode. To do this I required airmon-ng, a tool that's part of
Aircrack-ng. Aircrack wasn't available via apt-get so I had to download and
compile it. On doing make install it installed airmon-ng to /usr/local/sbin.
Then I was able to enable monitor mode like so, where wlan0 is the name of my
wifi device as reported by ifconfig (it may have a different name on your system):
$ sudo /usr/local/sbin/airmon-ng start wlan0 11
It output "monitor mode enabled on mon0" - mon0 is a pseudo device created by
airmon-ng that tshark will listen to rather than wlan0. However the command also
outputs a warning about processes that may interfere with its operation. They do
indeed interfere but it's not as simple as killing the suggested PIDs as some of
them are related to services that will simply restart them if they're seen to
die. So I had to stop the relevant services like so:
$ sudo service network-manager stop
$ sudo service avahi-daemon stop
$ sudo service upstart-udev-bridge stop
I then stopped monitor mode - note that this needs to done on mon0 rather than
wlan0:
$ sudo /usr/local/sbin/airmon-ng stop mon0
Then I started monitor mode, as above, again and this time it only warned about
one process and I killed the listed PID with a normal kill (using sudo).
Note that stopping the above services will disconnect you from your wifi network
, even before you use tshark with the monitor mode enabled pseudo device mon0.
If you need to reconnect, e.g. if you find initially as I did that you don't
have tshark installed and need to apt-get it, then just redo the service
commands above with start instead of stop.
OK - now we're ready to start tshark almost as above on the Mac:
$ tshark -o 'wlan.enable_decryption:FALSE' \
-i mon0 -f 'subtype qos-data' \
-R 'wlan.fc.retry==0' -T fields \
-e wlan.bssid -e radiotap.channel.freq -e wlan.sa -e wlan.da -e data.len
Note that I use the mon0 pseudo device and use -R rather than -Y as the version
of tshark available via apt-get for Ubuntu 12.04 is older than the version I
have on my Mac and doesn't support the -Y flag. And I don't use -I as mon0 is
already in monitor mode (and trying to use -I will cause tshark to fail).
Unlike on the Mac, where no special steps need to be taken once one you've
finished capturing packets with tshark, one should stop the pseudo device as
shown above and restart the various services (also as described above).
Note that in the airmon-ng start command above we explicitly specify what
channel we want to monitor, in the example it's channel 11. If you wanted to do
channel hopping see the Wireshark wiki page (also mentioned above).
Extra features of the Smart Config library
In a previous post I covered details of the TI Smart Config library that may
(most likely) be historical left overs from TI's development process or may
possibly be useable in combination with some non-default configuration of a
CC3000 device. The only one of these that could affect the ability of the code
I've written to recover SSIDs and keyphrases is being able to set the length of
the two separator value. Currently my code looks for packets that differ in
length by the difference between these two values, so this logic would no longer
work if these values were changed. However it would be simple to adjust the
logic to look for values that reoccur frequently and deduce that they were the
separator values being used in this particular situation.