Smuggler - An interactive 802.11 wireless shell without the need for authentication or association
I've always been fascinated by wireless communications. The ability to launch seemingly invisible packets of information up into the air without even the need to consider aerodynamics itself seems like some kind of magic.
In my quest to become a wireless wizard I started looking at the 802.11 wireless protocol to find out a little more about it. I had always noticed when looking at wireless management frames in various packet dumps that a wealth of additional (and somewhat optional) information is sent between stations. Much of this additional information is not all that useful from a security perspective.
This additional information that I speak of is known as "Information Elements" (IE), which are contained in 802.11 wireless management frames . The Dot Eleven wiki states, "IEs are a device's way to transfer descriptive information about itself inside management frames. There are usually several IEs inside each such frame, and each is built of type-length-values mostly defined outside the basic IEEE 802.11 specification."
With regards to IEEE 802.11, these information elements are as follows: (0) SSID, (1) Rates, (2) FHset, (3) DSset, (4) CFset, (5) TIM, (6) IBSSset, (16) challenge, (42) ERPinfo, (46) QoS Capability, (47) ERPinfo, (48) RSNinfo, (50) ESRates, (221) vendor and (68) reserved.
I wanted to experiment with these IEs directly. Scapy is a powerful tool that allows such access to this layer via Dot11Elt . Using Scapy I wrote some code to extract the SSID and rates IEs as a proof of concept, the code for this is below.
[receiver.py - note: if you copy/paste from this blog the indentations will need to be fixed]
# -- coding: utf-8 --
# wireless information elements receiver POC – Tom Neaves <firstname.lastname@example.org>
from scapy.all import *
if pkt.haslayer(Dot11) :
if pkt.type == 0 and pkt.subtype == 8 and pkt.info == "" : # if management frame and beacon and SSID is blank
print "AP MAC: %s | SSID: %s | Rates: %s" % (pkt.addr2, pkt.info, (pkt[Dot11Elt:2].info))
sniff(iface="mon0", prn = packets)
This would extract the "SSID" and the "rates" IEs from all beacon management frames discovered which had a blank SSID.
I then put together some code to act as the sender. Note that I am using an additional wireless card on mon1 to send packets. The receiver is using a different wireless card on mon0 to listen out for our packets.
[sender.py - note: if you copy/paste from this blog the indentations will need to be fixed]
# -- coding: utf-8 --
# wireless information elements sender PoC – Tom Neaves <email@example.com>
from scapy.all import *
conf.iface="mon1" # second wireless card
ssid=sys.argv # takes ssid from the command line
rates=sys.argv # takes "rates" from the command line
# python sender.py "" rateshere
The command above will result in a beacon management frame sent into the airwaves with a blank SSID and a "rates" information element of "rateshere". The receiver will parse the frame and print the rates content out to the screen, in this case "rateshere".
I just utilised an IE in a way not originally intended to pass a message. At this point I did a little digging to determine if I was the first to stumble on this little gem.
Turns out yes and no.
Chandra, et al.  in 2007 explored hacking up the 802.11 protocol in order to broadcast additional information without the need for association. This was in the form of SSID and BSSID concatenation and adding in additional IEs to broadcast "coupons" for advertising purposes. The paper did not, however, discuss modifying using it as a two-way communications channel.
Gupta V. and Rohil M.K.  in 2013 hacked up the 802.11 protocol to transmit information within the "Length" fields of the IEs. However, again this is only for broadcast purposes.
So it seems that I am a little late to the party, however it also appears that I am doing things a little different – I am injecting into the actual IE. Furthermore, the research falls short on being restricted to a one way broadcast. What if I could create a two-way covert communications channel? Furthermore, what could I create without the fuss of association and authentication that is usually required in wireless networks before such communications can begin? What if an attacker could send commands and receive the output on this channel? That would be magic++ and then some.
Ladies and gentlemen, I present you Smuggler.
I expanded on the proof of concepts already discussed to create a tool called Smuggler. It is a two-way covert communications channel, which consists of an interactive wireless shell without the need for association or authentication, and it works like this:
An attacker compromises a machine and starts up a receiver (client.py), much like the proof of concept. The receiver listens to management beacon frames with a blank SSID and, when spotted, extracts the rates IE. The evolution here from the proof of concept (v2.0 if you like…) is that the receiver has the operating system parse the rates IE as a command. The attacker leaves the compromised machine with the receiver running and heads off to grab some lunch. Enter the next act.
The attacker comes back the next morning, sitting in the car park with a latte. The attacker uses Smuggler (smuggler.py) to create a management beacon frame (with a blank SSID) and a rates IE with their very own command.
Now here comes the clever bit - the receiver parses the command found in the rates IE as already discussed, but wait, it then invokes clientprobe.py to construct management probe requests with the output of the command as the SSID. Smuggler on the attacker's machine is listening out for these management probe requests and extracts the SSID, hence the output. The information is presented in an attractive looking shell not unlike bash. ;)
So, to summarise:
If management and beacon frame (AND blank SSID) seen, read rates (attackers_command) IE and send to the OS to parse.
Attacker send commands (smuggler.py):
Construct management beacon frame (AND blank SSID) with a custom rates IE.
Rates = attackers_command
Management frame, probe request, SSID = outputofcommand
As a proof of concept the same machine is being used with two wireless cards, however, this would work exactly the same on two computers. The example below shows the attacker issuing the "who" command wirelessly (in the "rates" IE) through the wireless card on mon1 in a management beacon frame. The receiver parses this command and sends the output back wirelessly over another wireless card on mon0 via the SSID of a management frame probe request.
What happens "under the hood" within the airwaves is shown below.
Another proof of concept for your viewing pleasure. A number of text files which exist on the victim machine:
The attacker recreates these commands over the wireless airwaves, all without association or authentication.
I am not going to release Smuggler just yet - that is not the objective of this blog post. The objective of this post is that I wanted to share my findings of abusing a protocol in a way not intended and use it for bad things, such as creating this covert two-way communications channel without associating or authenticating. I have also created Anti-Smuggler to demonstrate that it is possible to detect such attacks. However, the proof of concept I have demonstrated is pretty basic in that it does not utilise any form of encryption. You would imagine such convert channels would be reinforced with several layers of security, encryption being just one of them.
For the final treat; Anti-Smuggler detecting extraction of credit cards.
The regular expressions can be expanded to cover all manner of things – directory listings, extraction of the passwd file, etc.
 Chandra R., Padhye J., Ravindranath L., Wolman A. "Beacon-Stuffing: Wi-Fi without Associations", In Proceedings of the Eighth IEEE Workshop Mobile Computing Systems and Applications (Tucson, Arizona, February 26-27, 2007)
 Gupta G., Rohil M.K., "Bit-Stuffing in 802.11 Beacon Frame: Embedding Non-Standard Custom Information", International Journal of Computer Applications (0975 – 8887), Volume 63 – No. 2 (February 2013)