Sunday, December 4, 2011

Introduction to Bluetooth RFCOMM Reverse Engineering

by Travis Goodspeed <travis at>
with thanks to Alexei Karpenko

Spot Connect (cropped)

Reverse engineering a Bluetooth device is rather straightforward, but quite a few good neighbors don't know where to begin. This article demonstrates exactly how an Android client was reverse engineered in order to produce open source clients in Python and QT Mobility. I'm writing with the assumption that you are trying to reverse engineering your own device, which is similar but not identical to mine. As this is an introductory guide, I'll stay clear of any code reverse engineering, sticking only to network traffic.

The subject of this article is the Spot Connect, which transmits one-way text messages and GPS coordinates by L-band to the GlobalStar satellite constellation. These messages are then forwarded by email or SMS. Except in its emergency mode, the device is operated through Bluetooth by a smart phone. Thanks to Android's use of the Bluez bluetooth stack, it is rather easy to get the necessary traffic dumps.

Kind thanks are due to Alexei Karpenko (Natrium42) for his article on SPOT Reverse Engineering, which covers the original SPOT unit in excellent and thorough detail. It was his article that got me looking at the Spot Connect, and his description of the GPS format saved me quite a bit of travel for sample collection.

GlobalStar Beacon

Sniffing RFCOMM

The first step is to load the official client onto a rooted Android phone, in my case a Nexus S. I had to swap SIM cards as my Brazilian one put me in a region of the Android market that didn't have the application. Switching to a Swiss card fixed this, and a moment later the app was installing.

SPOT Connect

The Spot Connect uses RFCOMM, which is Bluetooth's alternative to a TCP socket or a UART. As it is easy to prototype and always delivers packets in order, RFCOMM has become the standard way of implementing custom protocols. To sniff the traffic before knowing the mode, we'll use hcidump running in a debugging shell of the phone. For this, run adb shell hcidump -X | tee spotlog.txt on your workstation, send a transmission, and watch the result in the log.

The message being sent stands out as ASCII, of course, so it's the first thing to look for. With no knowledge of the HCI protocol, you can still be sure that you have a cleartext recording.

HCIDump Screenshot

35 00 40 00 0b ef 63 aa 31 26 01 00 01 00 01 4d  5.@...c.1&.....M
72 2e 20 57 61 74 73 6f 6e 2c 20 63 6f 6d 65 20 r. Watson, come
68 65 72 65 2e 20 49 20 77 61 6e 74 20 74 6f 20 here. I want to
73 65 65 20 79 6f 75 2e 9a see you..

From Alexei's article, you can expect that frames inside of RFCOMM will begin with 0xAA, followed by a length, followed by a verb and the objects. These bytes will be wrapped in padding on the outbound end, and they'll be fragmented on the inbound end. Sure enough, these are the bytes that come before the word ``Watson'':
aa Preamble
31 Length
26 Verb
01 00 01 00 01 Flags (OK, Check In)
4d 72 2e 20 57 ASCII Message (abbreviated)

Counting 0x31 bytes out, notice that the packet ends exactly on a byte of the ASCII message, without a checksum! By looking for bytes of AA and searching for length, with allowances for packet fragmentation and the RFCOMM wrapper, it becomes possible to decode every command and its matching response.

Be aware that responses will be fragmented more than transmissions. If you need to reverse engineer longer transactions or have a more complete log, it will be handy to have a script to reassembly from the HCI frames. In those cases, toss together a proper HCI decoder to get a more accurate interpretation of the records.

Looking through the entire log, it the protocol appears to be as follows. First, the client queries the Device ID with verb 0x01, using the exact same format as Alexei's article. Then it uses verb 0x25 to query the last known position of the device, which will be returned in the style that Alexei reverse engineered from the original unit. Use pen and paper to decode these transactions from my Python client.
Location Query

First Implementation

With these recordings in hand, the complete language can now be described and implemented. Luckily, three verbs make for a quick implementation!

I use py-bluez for prototyping such implementations, as its example is simple enough to get a working client in minutes. As py-bluez is specific to Linux, Mac users might prefer lightblue.

For simplicity, cut the UUID code or switch it to RFCOMM's UUID, which is 00001101-0000-1000-8000-00805F9B34FB. For a list of all services on a device, run 'sdptool records $adr'. This only lists those which are publicly announced by SDP, the Service Discovery Protocol. To scan for unadvertised services, try BT Audit from Collin Mulliner.

0x01 -- Get ID
A minimal test client will just test the serial number of the device. To do this, simply send "\xAA\x03\x01" and then catch the reply with verb 0x01. Bytes 3, 4, 5, and 6 of the reply will contain the serial number in Big Endian notation. For this first implementation, commands and their responses may be handled synchronously for simplicity.

Where self.tx() takes a frame as its input and returns the response, this is implemented in Python as the following. What could be simpler?

0x25 -- Get Last Position
Similar in calling convention, the 0x25 verb requests the last known GPS position of the device. The coordinate format is exactly the same as in Alexei Karpenko's Spot Hacking article, consisting of three bytes apiece to describe latitude and longitude. The following is my C++ code for parsing the position data, which has already been requested as "\xAA\x03\x25".


0x26 -- Transmit Text
Transmitting text is just as easy, with the Spot Connect handling all the work after a message has been loaded. The following is Python code to transmit a short text message with the OK message-code. This lacks length checks and doesn't support the changing of flags, but it will work perfectly well for a test.


After the device receives this command, it will reply with an acknowledgment and then begin to attempt transmissions at irregular intervals. Each transmission consists of a number of fragments, such that the packet can be reassembled so long as one copy of each fragment makes it through. If you have a clear view of the sky and have configured the first destination to be your email address, you should receive a notification within a few minutes. If you don't receive a notification by the time the mailbox icon has ceased blinking, then the transmission failed.

Other Verbs
These three verbse--0x01, 0x25, and x026--are sufficient to implement a minimal client for the Spot Connect. If you'd care to help out, it would be useful to have more documentation for the flags of the 0x26 verb, as well as documentation for 0x52, 0x40, and 0x38. By scanning and listening for error codes, it should be possible to get a complete list of those verbs that are unused by the Android application.

You can find my Python client at . It ought to run as-is on Linux with py-bluez, including the Nokia N900.

A Graphical Client

Now that the protocol has been sufficiently well documented to have a Python implementation, it is worthwhile to rewrite it as a GUI. In my case, I wanted a QT Mobility client for my Nokia N9. You can find my work in progress at

Pacific Ocean

Other Methods

If hcidump isn't available for your platform, you might try Sniffing with a USRP or reflashing a dongle to become a commercial sniffer. For a jailbroken iPhone, see the iPhone Wiki's documentation.

Another option would be to create a Bluetooth proxy, relying on the slim authentication performed in the protocol. In this case, the proxy would open all relevant port to the device being reverse engineered, ferrying commands back and forth as a way to record them. You might also need to experiment with changing the device class and, in the case of iOS devices, there is also a lockout sequence that must be implemented.

If none of that works for your device, you could sniff the UART lines that come from the bluetooth module, shown here on the left board. This particular module happens to be a BT23, and Page 8 of BT23_Datasheet.pdf shows that pins 14 and 13 should be tapped to get a communications log.
SPOT Connect

As a last resort, you could always ask for documentation. I didn't bother with this because of my own impatience, but for some devices, such as the Metawatch, documentation is freely available. More than once, a neighborly vendor has been so kind as to give me the source code or documentation just to be neighborly.

Future Work

This article will be followed with one on the physical layer protocol of the SPOT, which I've been able to sniff thanks to some kind help from Michael Ossmann. For a preview of that technique, you are welcome to stalk my SPOT Connect Set on Flickr. The most neighborly of these shows individual bits from a FunCube Dongle recording of the transmission. It's cleartext, of course.
Bits from SPOT Connect

Replacement firmware is also a possibility. The Spot Connect uses an MSP430F5xx microcontroller with the standard USB bootloader, using a Java client on Windows and an Objective C client on OS X. The firmware itself is downloaded by HTTPS, and a copy could be acquired either by a MITM attack on HTTPS or by asking the bootloader politely, using the password that is to be found within the firmware update. Be careful when doing this to test on a unit without a service contract, as service cannot be moved from one unit to another and bricking is a distinct possibility.


I hope that this article has given you a decent overview of the methods for reverse engineering Bluetooth RFCOMM devices. While my subject was the Spot Connect, these methods would apply equally well to something like a GPS, the Metawatch, Bluetooth chat applications, and multiplayer games. Other brands of Bluetooth satellite communicators are available, and open documentation for them would be quite handy. For a list of a few thousand potential targets, search the Bluetooth SIG's Gadget Guide.

Tuesday, September 6, 2011

A Bluetooth GoodFET for the N900

by Travis Goodspeed <travis at>
continuing Promiscuity is the NRF24L01+'s Duty
with kind thanks to @fbz, @skytee, and their Hacker Hostel.

Bluetooth GoodFET

Since building my packet sniffer for the Microsoft 2.4GHz keyboards, I've frequently wanted to demo it without having to drag out a laptop. Laptops are heavy, they are inconvenient, and cables just make matters worse. While it is possible to port it to a standalone board or to add an LCD to the Next Hope Badge, I'd rather have the entire GoodFET client library available over bluetooth to my Nokia N900. Pictured above is my prototype build, which reliably sniffs keyboard traffic on battery power for a more than an hour. Rather than serving as a build tutorial, this article will chronicle the bugs that cropped up during the port, in the hope that they'll help other neighbors trying to port the GoodFET firmware to new devices.

This sniffer was assembled from a Next Hope Badge running the GoodFET firmware with hardwired DCO calibrations, a Roving Networks RN41 module, and three NiMH batteries. The client uses py-bluez at the moment, but I might port it to LightBlue for OS X support. Future models will use a GirlTech IMME or Telos B in place of the Next Hope Badge, to allow me to play with APCO P25 or ZigBee networks without a laptop.

Compiling the Firmware

Most of the GoodFET devices are built around an FT232RL and MSP430, with the FTDI taking care of USB to serial conversions. The client software just opens /dev/ttyUSB0 or its local equivalent through py-serial, then uses the DTR and RTS lines to reset the MSP430 into either the GoodFET application or a masked-ROM bootloader, the BSL. The client and the hardware do a little initialization dance in which the GoodFET is reset until the clock configuration register within the device matches 16MHz. So when you run 'goodfet.monitor info' and it replies with "Clocked at 0x8f9e", the devices has rebooted several times until it finds by chance that 0x8F9E is a stable clock configuration for 16MHz.

When replacing the FTDI with a Bluetooth module, the DTR and RTS lines are unavailable with the timing resolution that is necessary to enter the BSL. Rather than rely upon them, I left them disconnected and instead ran only the TX and RX lines from the RN41 to the NHBadge. The !RST signal is also disconnected, so the GoodFET will boot when power is applied and cannot be rebooted except by the appropriate software command.

Bluetooth GoodFET

This creates a number of complications in the client, which I'll get to later, but the important thing for firmware is that the clock configuration must be explicitly known by the firmware at compile or link time. To specify this at compile time, set CFLAGS="-DSTATICDCO=0x8F9E". To specify it at link time, just flash the image without erasing the INFO flash that resides from 0x1000 to 0x1100 in the MSP430X chips.

Additionally, the firmware must be told which pins to use and which microcontroller to target. These are specified by exporting platform="nhb12b" and mcu="msp430x2618". If an NHB12 were used instead of the NHB12B, then the platform would be redefined appropriately. Finally, the firmware size (and thus the flashing time) can be significantly reduced by exporting config="monitor nrf spi" to reduce the set of applications to only the Monitor, Nordic RF, and SPI applications.

To ease in reconfiguring my build environment, I left a script to create these settings in trunk/firmware/configs/examples/ . Be sure to change the STATICDCO value to that of your own hardware when building it.

Next Hope Badge Flashing

Finally, the firmware had to be flashed by JTAG, rather than BSL. This was done the same way the Next Hope Badges were originally programmed at the factory, by wedging the board into a GoodFET programmer and running 'goodfet.msp430 flash goodfet.hex', then verifying with 'goodfet.msp430 verify goodfet.hex'.

Patching the Client

Recalling that the client was initially designed to use py-serial, a few changes were required to make it function through py-bluez.

Before writing a proper client, I wrote a quick py-bluez script to connect to the GoodFET and print any string that is received. Briefly touching the !RST signal on the JTAG connector to its GND pin resets the device, causing it this client to print "". If the default GoodFET firmware is flashed, with no STATICDCO or Info Flash, the string will be printed as garbage most times, with one attempt in ten producing a legible string.

Having verified that the timing and baud rate were correct, I continued by writing a communications module, GoodFETbtser(), that emulates the read() and write() functions of serial.Serial() used by the rest of the application. Additionally, the function is written so as to always return the exact number of bytes requested by the receiver, as Bluetooth buffering sometimes breaks apart packets that would otherwise reliably be received as contiguous chunks.

The following is a screenshot (with GoodFET.verbose=1) of a transmission being split in half because of a read() request returning too few bytes.
Bluetooth Packetization Bug

Additionally, the initialization routine was modified such that if the GOODFET environment variable is set to a six byte MAC address. Setting it to "bluetooth" causes the firmware to search for Bluetooth devices by name, then exit with instructions for setting the MAC. Later revisions might attempt to use the first observed RFCOMM adapter.


The final client is already mainstreamed into the GoodFET's subversion repository, and it looks a little like the following when packet sniffing encrypted OpenBeacon traffic. It can also sniff Turning Point Clickers, Microsoft Keyboards, and anything else that uses the 2.4GHz Nordic chips.

Bluetooth GoodFET OpenBeacon Sniffing

I've already ordered parts to build Bluetooth versions of the Girltech IMME and the Telos B for mobile sniffing of APCO P25 and ZigBee. My rebuilds will include integrated battery charging from USB and the option of running standalone with the bluetooth module disabled, in order to greatly increase battery life. The client ought to run unmodified on rooted Android devices by use of SL4A and py-bluez. Additionally, I'm planning a firmware port to the OpenBeacon USB 2 module from Bitmanufaktur GmbH.

As a final note, I would like to remind all good neighbors that there is no reason why offensive security can't be fun for the whole family.
Bluetooth GoodFET

Thursday, September 1, 2011

Remotely Exploiting the PHY Layer

or, Bobby Tables from 1938 to 2011

by Travis Goodspeed <travis at>
concerning research performed in collaboration with
Sergey Bratus, Ricky Melgares, Rebecca Shapiro, and Ryan Speers.


The following technique is a trick that some very good neighbors and I present in Packets in Packets: Orson Welles' In-Band Signaling Attacks for Modern Radios (pdf) at Usenix WOOT 2011. As the title suggests, Orson Welles authored and implemented the attack in 1938 as a form of social engineering, but our version acts to remotely inject raw frames into wireless networks by abuse of the PHY layer. As that paper is limited to a formal, academic style, I'd like to take the opportunity to describe the technique here in my people's native language, which has none of that formal mumbo-jumbo and high-faluttin' wordsmithin'. This being just a teaser, please read the paper for full technical details.

The idea is this: Layer 1 radio protocols are vulnerable injections similar to those that plague naively implemented SQL websites. You can place one packet inside of another packet and have the inner packet drop out to become a frame of its own. We call the technique Packet-in-Packet, or PIP for short.

As I've mentioned in my article on promiscuously sniffing nRF24L01+ traffic, every modern digital radio has a Layer 1 form that consists of a Preamble, followed by a Sync, followed by a Body. The Body here is Layer 2, and that is the lowest that a normal packet sniffer will give you. (Keykeriki, Ubertooth, and GoodFET/NRF give a bit more.)

In the specific case of IEEE 802.15.4, which underlies ZigBee, the Preamble consists of the 0 symbol repeated eight times, or 00000000. The Sync is A7. After that comes the Body, which begins with a byte for the length, a few bytes for flags, the addresses, and some sort of data. Suppose that an attacker, Mallory, controls some of that data, in the same way that she might control an HTTP GET parameter. To cause a PIP injection of a Layer 2 packet, she need only prepend that packet with 00000000A7 then retransmit a large--but not unmanageably large--number of times. I'm not joking, and I'm not exaggerating. It actually works like that.

Below is a photograph of the first packet capture in which we had this technique working. The upper packet capture shows those packets addressed to any address, while the lower capture only sniffs broadcast (0xFFFF) messages. The highlighted region is a PIP injection, a broadcast packet that the transmitter intended to only be data within the payload of an outer packet.

How it works.

When Alice transmits a packet containing Mallory's PIP to Bob, Bob's interpretation can go one of three ways, two of which are depicted in the diagram below. In the first case, as shown in the left column, Bob receives every symbol correctly and interprets the packet as Alice would like him to, with Mallory's payload sitting harmlessly in the Body. In the second case, which is not depicted, a symbol error within the Body causes the packet's checksum to fail, and Mallory's packet is dropped along with the rest of Alice's.

802.15.4 PIP

The third interpretation, shown above in the right column, is the interesting one. If a symbol error occurs before the Body, within the Preamble or the Sync, then there's no checksum to cause the packet to be dropped. Instead, the receiver does not know that it is within a packet, and Mallory's PIP is mistaken as a frame of its own. Mallory's Preamble and Sync will mark the start of the frame, and Mallory's Body will be returned to the receiver.

In this way, Mallory can remotely inject radio frames from anywhere on the network to which she can send her payload. That is, this is a PHY-Layer radio vulnerability that requires no physical access to the radio environment. Read the WOOT paper for complications that arise when applying this to IEEE 802.11, as well as the conditions under which a PIP injection can succeed on every attempt.

War of the Worlds

In 1938, Orson Welles implemented a similar exploit as a form of social engineering in order to cause panic with his War of the Worlds (mp3, transcript) performance.

Recall that PIP injection works by having the victim miss the real start of frame marker, then fraudulently including another start of frame marker inside of the broadcast. As per the FCC requirements of his time, Orson begins with a real start of broadcast marker:

ANNOUNCER: The Columbia Broadcasting System and its affiliated stations present Orson Welles and the Mercury Theatre on the Air in The War of the Worlds by H. G. Wells.


ANNOUNCER: Ladies and gentlemen: the director of the Mercury Theatre and star of these broadcasts, Orson Welles . . .

ORSON WELLES: We know now that in the early years of the twentieth century this world was being watched closely by intelligences greater than man's and yet as mortal as his own. We know now that as human beings busied themselves about their various concerns they were scrutinized and studied, perhaps almost as narrowly as a man with a microscope might scrutinize the transient creatures that swarm and multiply in a drop of water. With infinite complacence people went to and fro over the earth about their little affairs, serene in the assurance of their dominion over this small spinning fragment of solar driftwood which by chance or design man has inherited out of the dark mystery of Time and Space. Yet across an immense ethereal gulf, minds that to our minds as ours are to the beasts in the jungle, intellects vast, cool and unsympathetic, regarded this earth with envious eyes and slowly and surely drew their plans against us. In the thirty-ninth year of the twentieth century came the great disillusionment.
It was near the end of October. Business was better. The war scare was over. More men were back at work. Sales were picking up. On this particular evening, October 30, the Crosley service estimated that thirty-two million people were listening in on radios.

That introduction is two minutes and twenty seconds long, and it was scheduled to begin while a popular show on another station was still in progress. Many of the listeners tuned in late, causing them to miss the Sync and not know which show they were listening to, just as in a PIP injection! What follows is thirty-eight minutes of a first act, without a single word out of character or a single commercial message from a sponsor. The play begins in the middle of a weather report, followed by repeated false station and show announcements, a few of which follow.

We now take you to the Meridian Room in the Hotel Park Plaza in downtown New York, where you will be entertained by the music of Ramón Raquello and his orchestra.
From the Meridian Room in the Park Plaza in New York City, we bring you the music of Ramón Raquello and his orchestra.
Ladies and gentlemen, we interrupt our program of dance music to bring you a special bulletin from the Intercontinental Radio News.
We are now ready to take you to the Princeton Observatory at Princeton where Carl Phillips, or commentator, will interview Professor Richard Pierson, famous astronomer.
Good evening, ladies and gentlemen. This is Carl Phillips, speaking to you from the observatory at Princeton.
Just a moment, ladies and gentlemen, someone has just handed Professor Pierson a message. While he reads it, let me remind you that we are speaking to you from the observatory in Princeton, New Jersey, where we are interviewing the world- famous astronomer, Professor Pierson.

By repeatedly lying to the listeners about the station and the program, Welles was able to convince them that they were listening to legitimate news broadcasts of an alien invasion. Ensuring that the listener missed the starting broadcast announcement breaks the encapsulation that was intended to prevent such confusion, just as a PIP injection relies upon the start of frame to be missed in order to break OSI model encapsulation.

How the hell did this happen?

This class of vulnerability is a really, really big deal. An attacker can use it to inject raw frames into any wireless network that lacks cryptography, such as a satellite link or an open wifi hotspot. Not only that, but because the injection is remote, the attacker needs no radio to perform the injection! Not only that, but this vulnerability has sat unexploited in nearly every unencrypted digital radio protocol that allows for variable frame length since digital radio began! So why did no one notice before 2011?

Packet in Packet injection works because when Bob forwards a wrapped string to Alice over the air, he is trusting Mallory to control the radio symbols that are broadcast for that amount of time. The potential for abusing that trust wasn't considered, despite communications experts knowing full well that sometimes a false Sync was detected or a true Sync missed. This is because a symbol error in the Sync field causes the packet to be implicitly dropped, with the same behavioral effect that would be had if the error were later in the packet and it were explicitly dropped. Except when faced with a weaponized PIP injection, nothing seems strange or amiss. Sync errors were just a nuisance to communications engineers, as we security guys were staying a few layers higher, allowing those layers of abstraction to become boundaries of competence.

That same trust is given in wired networks and busses, with the lesser probability of missing a Sync being the only defense against PIP injection. Just as PIP has shown that unencrypted wireless networks are vulnerable even when the attacker is not physically present, I expect wired networks to be found vulnerable as soon as an appropriate source of packet errors is identified. Packet collisions provide this in unswitched Ethernet networks, and noisy or especially long links might provide it for more modern wired networks.

If I've not yet convinced you that this attack is worth studying, I probably won't be able to. For the rest of you, please print and read the paper and extend this research yourself. There's a hell of a lot left to be done at the PHY layer, and it might as well be you who does it.

Thank you kindly,
--Travis Goodspeed

Tuesday, May 24, 2011

Practical MC13224 Firmware Extraction

by Travis Goodspeed <travis at>
as presented at CONFidence Krakow, 2011.


Pictured above is a Freescale MC13224 chip, having been partially decapped with nitric acid in my lab. This is the chip used in the Defcon 18 Ninja Badge and the Redwire Econotag. This brief demonstrates two methods for extracting the firmware from an MC13224 or MC13226 which has been read-protected by placing "SECU" as the first four bytes of Flash memory.

Rather, pictured above are the three chips and a few discrete components that comprise the MC13224. The smallest chip is a radio balun, while the largest is a CPU+radio and the third chip is Flash memory. This brief article will present two methods for forcibly extracting firmware from a locked MC13224, the latter of which is non-invasive and requires only a bit of soldering skill.

For a more thorough discussion of the MC13224, read Akiba's MC13224 Review. In short, the strong point of this chip is its radio, which integrates analog components on chip. Literally everything except for the antenna is included, so a 50Ω trace antenna is the only external radio component. Most of these components aren't on-die, just in-package. You can see the 0402 components used in this in the photo below, which is slightly less etched than the one at the beginning of this article.


Unlike many competing microcontrollers, the MC13224 is unable to execute code directly from Flash. Rather, a ROM bootloader copies a working image from Flash into RAM. If the security word "OKOK" is seen, then JTAG access is enabled before the bootloader branches into RAM. If the security word is instead set to "SECU", then JTAG access is not enabled and the chip remains in its default, locked state.

MC13224 CPU
MC13224 LittleMC13224 Flash (SST25WF010)

The final chip shown above is the Flash memory. Its badge is in the corner near a bonding wire, clearly identifying the chip as an SST25WF010, a SPI flash chip that aside from its low voltage is easily interfaced with a GoodFET or Arduino.
SST25WF010 Badge

The first method for recovery requires access to some rather--but not terribly--expensive equipment. First, use HNO3 or H2SO4 to remove the packaging and expose the SST25WF010 die. Then use a wedge wire-bonder to place the chip into a new package. The die has ten bonding pads while only eight pins are documented, but these can be guessed quickly enough if it is supposed that the sides of the chip are kept constant.

A second extraction technique takes advantage of the fact that, while the SPI bus is not bound out to external pins, the power and ground lines are exposed. Still better, the supply line to the SST25 has its own pin! Pin #133, NVM_REG, is the voltage regulator output for the flash memory, which is exposed in order to allow an external voltage regular to replace the internal one. In ZigBee applications, power could be saved by shutting down the SST25 after booting. This pin is highlighted below.


Given that a local attacker can control power to just the SST25 Flash chip, what would happen if he disabled the chip by cutting its power? MC1322xRM.pdf explains in Figure 3-22 on page 93 that the MC13224 will enable JTAG access then try to boot from UART1, as a SPI slave, as a SPI master, or as an I2C master. If none of these methods work, the chip will hang in an infinite loop.

So all that is needed to recover a copy of an MC13224's flash memory is a board that holds Pin 133 too low during a reset, then loads a new executable into RAM that--when Pin 133 is allowed to swing high--will read firmware out of the SST25WF010 and exfiltrate it through an I/O pin.

Toward that end, I've made a small batch of modified Econotag boards that expose this pin to a jumper. A pair of tweezers can then hold the line low during a reboot in order to unlock JTAG. Once the tweezers are removed, a client for the internal SST25 flash chip can be used through the board's built-in OpenOCD implementation to dump the firmware.

RedBee w/ SECU Bypass

Please note that the MC13224 and MC13226 are the only Freescale 802.15.4 chips with an ARM and external flash die. Both older and more recent devices use an 8-bit HCS08 microcontroller with built-in flash memory.

Freescale could certainly patch the boot behavior, but this would bring its own complications. Mandating an erase and erase-check on failure would cause the chip to self-destruct when being supplied with noisy power. Not mandating that erase would make the chip difficult to recover if improperly flashed.

But even if they were to patch the ROM behavior, successfully, the first vulnerability would still remain. The SST25WF010 chip can still be rebonded into a new package. Further, MC1322x family appears to be an evolutionary dead-end. There have been no new releases since the initial pair of chips, and Freescale's more recent designs have abandoned the ARM7 for the less expensive HCS08 core they maintain in-house.

Tuesday, March 1, 2011

GoodFET on the TelosB, TMote Sky

by Travis Goodspeed <travis at>
with kind thanks to Sergey Bratus, Ryan Speers, and Ricky Melgares,
for contributions of code, conversation, and general neighborliness.

Telos B

As I was recently reminded that the Crossbow Telos B and Sentilla TMote Sky devices litter most universities, left over from wireless sensor network research, it seemed like a perfect target. As such, I'm happy to announce that the GoodFET firmware now fully supports the Telos B and TMote, and also that support for the Zolertia Z1 mote will be coming soon. KillerBee integration should come in the next few weeks, but there's plenty of fun to be had in the meantime.

This brief tutorial will walk you through cross-compiling the GoodFET firmware for the Telos B or TMote Sky, as well as simple packet sniffing and injection. As the GoodFET project is always being refactored in one way or another, you can expect a bit of this to change.

Compiling the Firmware

A port of the GoodFET firmware is defined by three things. First, the $platform environment variable defines the header file from which port definitions come. Most platforms just use platforms/goodfet.h, which is loaded when $platform is undefined or set to 'goodfet'. Some devices, such as the two varieties of the Next Hope Badge and the Telos B, use ports which are not the same as the standard GoodFET's layout. In particular, it's rather common for the Slave-Select (!SS) line to be unique to the hardware layout of a particular board. Setting $platform to 'telosb' takes care of this.

Additionally, the Telos B uses the MSP430F1611 chip, so $mcu must be set to 'msp430x1611'. (That's with an 'x', as the linker doesn't care whether the chip is in the F, G, or C variants.)

Finally, a normal GoodFET includes a lot of modules for things like JTAG and similar protocols that the Telos B does not include wiring for. Although leaving them in doesn't hurt, it does make the firmware larger, which is annoying when repeatedly recompiling and reflashing during firmware development. To restrict support to just the monitor, the SPI Flash chip, and the Chipcon SPI radio, it is handy to set $config to 'monitor spi ccspi'.

export platform=telosb
export mcu=msp430x1611
export config='monitor ccspi spi'
make clean install

Accessing the SPI Flash

The Telos B is reset in a manner very different from the GoodFET, courtesy of a bit-banged I2C controller. Someday we'll figure out how to auto-detect this, but until then you will need to have $platform set to 'telosb' just as you did when compiling.

The Telos B contains a Numonyx M25P80 SPI Flash chip, which is compatible with the goodfet.spiflash client. Unfortunately, most units use a variety of this chip that does not respond to a request for its model number. (According to the datasheet, this feature is only available in the 110nm version. Datasheets have a way of phrasing bugs as if they were just optional features.) On those lucky units with a properly behaving chip, run 'goodfet.spiflash info' to get its capacity and model number. Upgrading to a larger chip or replacing the SMD unit with a socketed one will cause no problems, as the client will automatically adapt.

GoodFET for the Telos B

You may also use the standard peek, erase, dump, and flash verbs to access the contents of the chip. When the chip refuses to identify itself, the GoodFET will default to a size of 8Mb, so explicit ranges needed be given for things like 'goodfet.spiflash dump telosb_m25p80.bin'.

As the M25P80 chip is not access-controlled in any way, it's a handy way to grab old data from a node. On some academically-sourced devices, you might find leftover data or code from LogStorage or Deluge. On commercial devices, these chips sometimes keep hold more interesting things.

Sniffing ZigBee, 802.15.4

While the Flash chip is a neat little toy and handy for forensics, most users of the Telos B port will be interested in the CC2420 radio. As a final collaboration between Ember and Chipcon, the '2420 was one of the first popular 802.15.4 chips, and it is still quite handy for reversing and exploit ZigBee devices. Just as before, you must set $platform to be 'telosb' or the client will not connect.

To sniff raw 802.15.4 packets on channel 11, just call 'goodfet.ccspi sniff 11'. This enables promiscuous mode, so you will see traffic from all PANs and to all MACs in the region. If you are only interested in broadcast traffic, use 'goodfet.ccspi bsniff 11' instead.
goodfet.ccspi sniff 11

As much fun as it is to sit with the 802.15.4 and ZigBee protocol documentation to figure out what a packet means the first time, white-washing this particular fence quickly becomes boring. For that reason, Ryan Speers and Ricky Melgares at Dartmouth tossed together a Scapy module for dissecting these sorts of packets. It's in the scappy-com Mercurial repository, so check it out with "hg clone" then run "sudo python install" after the prerequisite packages have been installed.

Once the community build of Scapy has been installed, you can run 'goodfet.ccspi sniffdissect 11' to print the Scapy dissections of various packets. As this code is less than a week old, there are a few kinks to work out, so ignore the warning messages that pop up at the beginning of the log. (Scapy likes to initialize the operating system's networking stack even though we're using a GoodFET instead. This is infuriating on OpenBSD, but merely an annoyance on OS X and Linux.)

802.15.4 Scapy

If you have no other 15.4 equipment to play with, you can do a transmission test with 'goodfet.ccspi txtest 11'. In the following section, I'll show you to how to send and receive packets in a Python script, which is useful for talking to the myriad of wireless sensors that have less than serious security.

Scripting the CC2420

The GoodFET project is built as a number of client scripts which are written in spaghetti code, features from which are slowly moved out of spaghetti and into classes. That is to say, the heavy lifting should be in, while short and sweet client scripts will be found in goodfet.ccspi. As an example, this section will cover the functioning of 'goodfet.ccspi txtoscount' which implements the radio protocol spoken by the TinyOS RadioCountToLeds application.

Rather than go into too much detail, I'll just point out the lines that are most instructive. Just like sing-along cartoons, this only works if you read the code, so please open up your favorite editor and follow along. While you're at it, use 'svn blame' to figure out which new GoodFET developer wrote that routine. If too much time has passed, you'll also need to back up to the revision that was current when I wrote this review. Then jump back a few more revisions to figure out which bugs of mine had to be fixed before his code worked. Isn't revision control nifty?

By default, the CC2420 only receives packets addressed to the local PAN and MAC as well as those sent to the broadcast address. In order to receive promiscuously, allowing the client to automatically identify any devices on the channel, it is necessary to enable promiscuous mode with 'client.RF_promiscuity(1)'. You might also want to tune away from the default channel with 'client.RF_setchan()'.

Also, as checksums must be correct in any outbound traffic, it is necessary to enable the AUTOCRC mode with 'client.RF_autocrc(1)'. This appends a checksum to every outbound packet, and it also rejects any inbound packets with invalid checksums, which is helpful to reduce noise but would sometimes accidentally rejects packets from non-compliant devices during sniffing. (TinyOS always uses the AUTOCRC feature, so it isn't an issue in this particular application.)

Packet reception, as is standard among the radio modules, is performed by 'client.RF_rxpacket()'. This method returns None if no packet has been received, so a synchronous application ought to spin in a loop until something else is returned.

Finally, the routine needs to broadcast its own reply, either from a stock template or from the sniffed packet. This is accomplished by passing an array of bytes to 'client.RF_txpacket(packet)'.

That's really all there is to it.


The GoodFET is primarily a tool for reverse engineering, and integration with other tools is a priority. KillerBee and Kismet plugins are already in development, and clients for all sorts of 802.15.4 devices will be written as hardware becomes available. Support for the CC2420's AES engine will also be added, so that encrypted packets can be sniffed once keys are sniffed from the air or by syringe with a bus analyzer.

That's all folks. Grab a Telos B or TMote and start poking at devices. Good targets might include Z-Wave door locks and ZigBee thermostats.

Monday, February 7, 2011

Promiscuity is the nRF24L01+'s Duty

by Travis Goodspeed <travis at>
extending the work of Thorsten Schröder and Max Moser
of the KeyKeriki v2.0 project.

NHBadge and a Keyboard

Similar to Bluetooth, the protocols of the Nordic VLSI nRF24L01+ chip are designed such that the MAC address of a network participant doubles as a SYNC field, making promiscuous sniffing difficult both by configuration and by hardware. In this short article, I present a nifty technique for promiscuously sniffing such radios by (1) limiting the MAC address to 2 bytes, (2) disabling checksums, (3) setting the MAC to be the same as the preamble, and (4) sorting received noise for valid MAC addresses which may later be sniffed explicitly. This method results in a rather high false-positive rate for packet reception as well as a terribly high drop rate, but once a few packets of the same address have been captured, that address can be sniffed directly with normal error rates.

As proof of concept, I present a promiscuous sniffer for the Microsoft Comfort Desktop 5000 and similar 2.4GHz wireless keyboards. This vulnerability was previously documented at CanSecWest by Thorsten Schröder and Max Moser, and an exploit has been available since then as part of the KeyKeriki v2.0 project. My implementation differs in that it runs with a single radio and a low-end microcontroller, rather than requiring two radios and a high-end microcontroller. My target hardware is the conference badge that I designed for the Next Hope, running the GoodFET Firmware.

Part 1: or, Why sniffing is hard.

nRF24L01 Die

Radio packets usually begin with a preamble, followed by a SYNC field. In the SimpliciTI protocol, the SYNC is 0xD391, so the radio packets will begin with {0xAA,0xD3,0xD91} or {0x55,0xD3,0x91}. The AA or 55 in the beginning is a preamble, which is almost universally a byte of alternating 1's and 0's to note that a packet is beginning, followed by the SYNC field which makes sure that the remainder of the packet is byte-aligned.

In the case of the Nordic radios, there is no SYNC pattern unique to the radio. Instead, the MAC address itself serves this purpose. So an OpenBeacon packet will begin with {0x55, 0x01, 0x02, 0x03, 0x02, 0x01} while a Turning Point Clicker's packets will begin with {0x55, 0x12, 0x34, 0x56}. The preamble in this case will be 0x55 if the first bit of the SYNC/MAC is a 0 and 0xAA if the first bit is a 1. To make matters worse, the chip does not allow a MAC shorter than three bytes, so previously it was believed that at least so many bytes of the destination address must be known in order to receive a packet with this chip.

Moser and Schröder solved this problem by using an AMICCOM A7125 chip, which is a low-level 2FSK transceiver, to dump raw bits out to an ARM microcontroller. The ARM has just enough time to sample the radio at 2Mbps, looking for a preamble pattern. If it finds the pattern, it fills the rest of register memory with the remaining bits and then dumps them to the host by USB. In this manner, every prospective MAC address can be found. Once the address is known, KeyKeriki places that address in its second radio, an nRF24L01+, which is used to sniff and inject packets.

A similar solution is used in Michael Ossmann's Project Ubertooth sniffer for Bluetooth. See that project's documentation and Ossmann's Shmoocon 2011 video for a more eloquent explanation of why sniffing without a known SYNC is so hard.

Part 2: or, Sniffing on the cheap.
My trick for sniffing promiscuously involves a few illegal register settings and the expectations of background noise. You can find code for this in the AutoTuner() class of the goodfet.nrf client.

First, the length of the address to sniff must be reduced to its absolute minimum. The datasheet claims that the lowest two bits of register 0x03 are responsible for address width, and that the only valid lengths at 3 bytes (01b), 4 bytes (10b), or 5 bytes (11b). Setting this value to 00b gives a 2 byte match, but when checksums are disabled, this results in a deluge of false-positive packets that appear out of background noise.
nRF Address Width

Second, it is necessary to begin receiving before the SYNC field appears, as the Nordic chips drop the address of incoming packets, leaving only the payload. By looking at the noise returned when the address is at its shortest length, it is clear that background noise includes a lot of 0x00 and 0xFF packets as well as 0xAA and 0x55 packets, which are likely feedback from an internal clock. What then would happen if the address were to be 0x00AA or 0x0055?

What happens is that noise activates the radio a bit early, which then syncs to the real preamble, leaving the SYNC field as the beginning of the packet payload! This is because the preamble and SYNC do not need to be immediately adjacent; rather, the SYNC can be delayed for a few bytes from the preamble in order to allow for longer preambles in noisy environments.

As a concrete example, an OpenBeacon packet looks something like the following. The SYNC field is 0x0102030201, so the packet will be cropped from that point backward. 0xBEEF is all that will be returned to the application, with everything prior to that cropped.
nRF24L01+ Promiscuous Mode

By making the address be 0x0055 and disabling checksums, that same packet will sometimes be interpreted as shown on the bottom. The preamble will be mistaken for a SYNC, causing the real SYNC value to be returned as the beginning of the payload. In that way, I am able to determine the SYNC/MAC field without any prior knowledge or brute force exploration.

This does depend upon the preamble being preceded by 0x00, which occurs often in background noise but is not broadcast by the attacker. So the odds of receiving a packet, while significantly worse than we'd like, are much better than the 1/2^16 you might assume. In experiments, one in twenty or so real packets arrive while a significant number of false positives also sneak in.

Recalling that the MAC addresses are three to five bytes long, and that radio noise is rather distinct, it stands to reason that noise can easily by separated from real packets by either manually checksumming to determine packet correctness or simply counting the occurrences of each address and taking the most popular. You will find an example log of OpenBeacon packets and false positives at Sorting the list reveals that the MAC address 0x0102030201 is the most popular, which is in fact the address used by OpenBeacon tags.

Rather than rely on packet dumps and sorts, there is an autotune script that identifies network participants and prints their MAC addresses. Simply run 'goodfet.nrf autotune | tee autotune.txt' and go out for a coffee break while your device is transmitting. When you come back, you'll find logs like the following, which has identified a nearby OpenBeacon transmitter.

goodfet.nrf autotune

As low data-rate devices require significantly more time than high-rate devices to identify, such devices will either require undue amounts of patience or a real KeyKeriki. In the case of a Nike+ foot pod, I'm resorting to using loud hip hop music to trigger the sensor, which is left inside a pair of headphones. My labmates are not amused, but it is a great way to reveal the radio settings when syringe probes aren't convenient.

Part 3: or, Sniffing a keyboard effectively.

Having a class to identify channels and MAC addresses is most of the problem, but there are remaining issues. First, the packets themselves are encrypted, and that cryptography must be broken.

Fear not! We won't need to do any fancy math to break this cryptography, as the key is included at least once in every packet. Moser and Schröder's slides explain that the packet's header is cleartext, while the payload is XOR encrypted with the MAC address.
XOR Crypto!

Applying an XOR to the proper region yields decrypted packets such as the following. Because these contain USB HID events, key-up HID events quite often include long strings of 0x00 bytes. When XOR'ed with the key, those zeroes produce the key, so some packets contain the XOR key not just once, but twice!
MSKB5k Traffic

Finally, the USB HID events need to be deciphered to get key positions. Mapping a few of these yields meaningful text, with bytes duplicated in the case of retransmissions and omitted in the case of lost packets. Disabling checksums will allow the dropped packets to be converted to a smaller number of byte errors, while tracking sequence numbers will prevent retransmitted keys from being displayed twice. Regardless, the results are quite neighborly, as you can make out the sentence typed below in its packet capture.
NHBadge Key Sniffer

Part 4; or, Reproducing these results.

All of the code for this article is available in the GoodFET Project's repository, as part of and its goodfet.nrf client script. The hardware used was an NHBadge12, although an NHBadge12B or a GoodFET with the SparkFun nRF24L01+ Transceiver Module will work just as well.

To identify a nearby Nordic transmitter, run 'goodfet.nrf autotune'. Keyboards can be identified and sniffed with 'goodfet.nrf sniffmskb', while a known keyboard can be sniffed and decoded by providing its address as an argument, 'goodfet.nrf sniffmskb aa,c10ac074cd,17,09'. The channel--0x17 in this case--will change for collision avoidance, but channel hopping is slow and resets to the same starting channel. Identification of the broadcast channel is faster when the receiver is not plugged in, as that causes the keyboard to continuously rebroadcast a keypress for a few seconds.

All code presently in the repository will be refactored and rewritten, so revert to revision 885 or check the documentation for any changes.


Contrary to prior belief, the nRF24L01+ can be used to promiscuously sniff compatible radios, allowing for keyboard sniffing without special hardware. It's also handy for figuring out the lower levels of the otherwise-documented ANT+ protocol, and for reverse engineering vendor-proprietary protocols such as Nike+.

Additionally, it should be emphasized that the security of the Microsoft keyboards in this family is irreparably broken, and has been since Moser and Schröder published the vulnerability at CanSecWest. (It's a shame, because the keyboards are quite nicer than most Bluetooth ones, both in pairing delay and in battery life.) Do not purchase these things unless you want to broadcast every keystroke.

While I have not yet written code for injecting new keystrokes, such code does exist in the KeyKeriki repository and would not be difficult to port. Perhaps it would be fun to build stand-alone firmware for the Next Hope badge that sniffs for keyboards, broadcasting Rick Astley lyrics into any that it finds?

Please, for the love of the gods, use proper cryptography and double-check the security your designs. Then triple-check them. There is no excuse for such vulnerable garbage as these keyboards to be sold with neither decent security nor a word of warning.

Monday, January 24, 2011

Generic CC1110 Sniffing, Shellcode, and iClickers

Chipcon CC1110 Logo

Howdy y'all,

I haven't the time to write individual posts on these subjects, but I do have plenty of new features for the CC1110 that are worth sharing. Rather than explain how they were written in too much detail, I invite you to read the source code, which is mostly Python and C shellcode.

In order to follow along with these examples, you will need to have SmartRF Studio installed to /opt/smatrf7. While this requirement will go away in a few weeks, the GoodFET client temporarily needs SmartRF Studio for machine documentation about the CC1110. You can find more details on SmartRF requirements in the client page.

(1) Packet sniffing, and other neighborly scripts.

GoodFETCC now has packet sniffing support for the SimpliciTI protocol used by the Chronos watch. Not only that, but it implements the protocol well enough to act as an access point for the watch, collecting accelerometer data and deciphering it for the host.
GoodFET Simpliciti Sniffing!

Run an access point with ' simpliciti [band]'. (This command will likely change names soon, as it is a rather ugly hack which only supports the Chronos accelerometer feature.) The optional parameter should be us, eu, or lf for the American, European, and Low Frequency versions of the watch.
GoodFET SimpliciTI Client

Not only protocols intended for the GoodFET, but also others which are coincidentally compatible, are supported. Thanks to some register settings contributed by Mike Ossman, you can sniff and decipher i<clicker traffic with ' iclicker'. iclicker

The i<clicker uses a Xemics XE1203F (PDF) radio chip, shown below. The XE1203F is nearly as configurable as the CC11xx parts, except that it is limited to 2FSK encoding. Previously, this protocol could be sniffed with the GR-Clicker project and a USRP, but the highly-versatile CC1110 chip allows this to be done with neither a software defined radio nor a chip identical to that used by the transmitter.

If you find it handy to see when a device is broadcasting, you can produce an ASCII-art plot of signal strength with ' rssi [freq]':
GoodFET CC1110 RSSI Graph

Care to jam another transmitter? Just like with the Next Hope Badge's GoodFET mode, it takes a single command to hold a carrier wave.
' carrier [freq]'
Chipcon Carrier

(2) Shellcode, now for quiche-eaters!

At the risk of appearing to facilitate quiche-eating, I'd like to quickly explain the new shellcode interface for placing code fragments on a Chipcon 8051 target, such as the CC1110.

The Chipcon radios have certain functions which are timing sensitive, chief among these being the rewriting of flash memory and the use of the digital radio core. If flash memory is not pulsed with the correct timing, mis-writes will occur. If the radio is read too slowly, bytes will be missed and a buffer underflow will ruin the transaction. Similarly, a transmission might fail if the single-byte transmission buffer isn't refilled quickly enough. I've also had trouble, for reasons that I can poorly explain, configuring the crystal oscillator through the debugging interface without shellcode.

As I described in my CC2430 Debugging Notes, the recommended method of flashing memory is to write a small block of code into XDATA RAM which does the actual write, then to branch to this code, waiting for a HALT (0xA5) opcode to return control to the debugger. This routine is provided in SWRA124 as machine code with assembly comments, beginning with the fragment shown below.
CC2430 Flash Routine

While this is fine and dandy for code that works, it's a bit infuriating to debug code in machine language. (Is that opcode supposed to be 0xA5 or 0xA6? Is the length of this instruction correct? Similar frustration abounds.) To correct for this, the GoodFET project now has a trunk/shellcode directory in addition to trunk/firmware and trunk/client. Shellcode is compiled for target microcontrollers, in this case just the CC1110 by SDCC, the Small Device C Compiler.

For example, this is the code that used to configure the crystal oscillator on the CC1110, a prerequisite for any radio operations:
Chipcon Shellcode

That ugly mess becomes the following little fragment of C. It is compiled by 'sdcc --code-loc 0xF000 crystal.c' in order to place the code squarely within RAM, which is executable in this 8051 clone's unified memory architecture. (It's a Harvard chip that acts Von Neumann, or the other way around.)
CC1110 Crystal Shellcode

For inputs to these functions, and also for their return values, I find it more convenient to declare arrays at known locations than to read the symbol files to find them. The syntax for placing an array in XDATA memory at 0xFE00 is 'char __xdata at 0xfe00 packet[256];'. You can find examples of this in txpacket.c and rxpacket.c in the GoodFET repository.

(3) Care to join the fun?

There are a number of features remaining to be implemented in shellcode. Among them in a completed port of Ossmann's $15 Spectrum Analyzer, which I began in CC1110 Instrumentation in Python and you can find in the contrib/ directory of the GoodFET repository. By dropping the GUI interface and replacing it with timing delays, full spectrum scans can be made in decent time without requiring that anything in flash memory be changed.

Another handy tool would be an OOK sniffer that over-samples, using the infinite-packet-length trick described in the CC1110 datasheet to fill ram with a recording. Triggering on RSSI allows the beginning of the packet to be reliably timed, with oversampling allowing for correction on all later bits. I've begun to implement this as ' sniffook [freq]', but an enterprising neighbor should be able to start sniffing garage door remotes in short order.

A Morse-code library in combination with an external amplifier would also be neighborly for the licensed amateur bands. The ability of the microcontroller to quickly return and channel hop might be able to account for, among other things, the Doppler shift experienced in EME moon-bounce experiments, without losing backward compatibility with 19th century radio technology.

As a prize, I offer one ale apiece for GoodFET patches implementing these features.

Stay neighborly,
--Travis Goodspeed
<travis at>