continuing Promiscuity is the NRF24L01+'s Duty
with kind thanks to @fbz, @skytee, and their Hacker Hostel.
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.
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/bluetooth-nhb12b.sh . Be sure to change the STATICDCO value to that of your own hardware when building it.
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 "http://goodfet.sf.net/". 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 GoodFETbtser.read() 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.
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.
Conclusions
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.
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.