Neat Field Magnetic Inductance (NFMI) is a short range physical layer that communicates by coupling a tight non-propagating magnetic field between devices. Similar to radio waves but only for short distances. It is uses two coils to communicate to each other.
The DEFCON 27 badges communicated over NFMI. The MCU does the bulk of the work and the NFMI chip over UART does the communication with the other badges.
For debugging the badge, there is a JTAG interface, serial interface and a SWD that allows for doing whatever you want on the device. In particular, you can dump the firmware, read registers or do whatever you want.
While reverse engineering the firmware with IDA pro, the author found a horrible buffer overflow. The code writes bytes into a static buffer until it finds the character E. However, there is not limit on the amount of bytes we can write!
To run a quick POC, the author connected to the badge over SWD and added a large packet to the ring buffer on the transmission. Of course, this caused a crash!
But how do we write custom code to exploit this over NFMI? First, the center frequency is somewhere between 10.579MHz and 10.56MHz. From a few random sources, some things were found but a bunch of reverse engineering of the signals was required. The author goes into how the signal works but the notes for this are not included.
Eventually, they took to reversing the firmware of the NFMI chip itself. They needed to use SWD on the NFMI chip but the traces were in the middle of the board. After finding the reset line, the author scratched off a layer of the board, cut the line to the MCU from the chip and soldered a wire onto the line.
After connecting over SWD, the author tried a bunch of different configurations until one of them eventually worked. From reversing the firmware, there was code to drop all packets over 11 bytes. So, what happened? The badge had more buggy firmware!
When receiving the packet over UART from the NFMI chip, a few weird things are done:
- The badge copies the data from UART byte by byte. If this runs out of space, a partial packet is used without the proper delimiter.
- There is an off by 1 error that makes sure that two bytes are free when only one is being copied. This allows for an odd number size of packets.
By truncating data in the perfect way, we can convince the firmware that a packet is MUCH larger than it actually is! Even though a packet cannot be larger than 11 bytes, we can make something look like it's larger than 11 bytes. Now, the buffer overflow we originally saw it exploitable!
Since the data being sent out is limited in characters (because of encoding), it is possible to crash the badge but not get code execution. Still, this is super interesting!