If this code is functioning properly, it will read back only the USB descriptor tables, and nothing else. If there’s a bug in the size calculation, you may be able to request more data. If there isn’t already a bug, you can introduce one via clock or power glitching.
Introducing a bug at just the right time can be tricky, so this is where it helped to build a new tool. Well, a tiny add-on for a masterful existing tool: the ChipWhisperer-Lite by Colin O’Flynn. The ChipWhisperer is an open source platform for side-channel power analysis and glitching. The joy of having both power analysis and glitching in the same platform is that they can be on the same reference clock. With one oscillator, you can deterministically step your target device through its paces, measure its activity via the power consumption waveform, and deliver glitches to specific clock cycles. By removing as many sources of jitter as possible, glitches can be delivered more reliably to the intended operation within the target’s firmware.
My humble addon is the FaceWhisperer, a USB host controller based on the MAX3421E chip, inspired of course by Travis Good-speed’s Facedancer21 tool. Whereas the USB host controller in your PC will be subject to many influences far outside your control, the USB host in the FaceWhisperer can be precisely synchronized with both the target device and the ChipWhisperer itself.
Putting everything on the same clock is necessary but not sufficient for cycle-accurate timing repeatability. The LC87, like many microcontrollers, will boot from a free-running RC oscillator before switching to the external clock under software control. This means it’s necessary to synchronize with the running firmware somehow before starting up the USB host. In this case, I’m using a comparator input on the FaceWhisperer to precisely wait on a debug signal that indicates the beginning of a tablet scanning cycle.
The GET_DESCRIPTOR request we’re interested in comes in several parts: a SETUP token that describes what descriptor we’d like to read, some IN tokens that each ask the device to send back one more packet, and finally an OUT for acknowledgment. These phases each drive a forgetful state machine that wakes up on each interrupt and leaves notes to itself for what needs to be done to the next packet. Unlike antique asynchronous serial ports, USB devices can never speak to the host unless they’re offered a timeslot with an IN token, so no matter how badly we glitch the firmware we do need to follow this flow in order to read back data from the device.
This firmware extraction glitch works by disrupting the calculation and/or storage of the descriptor length, between that SETUP and the first IN. To extract as much data as possible, the SETUP can have a length limit of 0xFFFF and the FaceWhisperer can continue spamming IN tokens until something fails. With this infrastructure in place, the ChipWhisperer’s Glitch Explorer can hone in on timing offsets and glitch parameters that give us longer than usual descriptor responses. By briefly interrupting power at slightly different timing offsets after the SETUP packet, a variety of glitched behavior can be observed.
The descriptor we’ll be reading is the USB Configuration Descriptor, typically one of the longest descriptors a device will provide. This device has a 34-byte descriptor that we’ll be trying to glitch into something much longer. Usually the whole thing comes back in one packet:
Sometimes our glitches occur while copying the IN data itself. These aren’t useful on their own, but they can give some feedback on how well the glitch is working:
When you’re getting close, you start to see non-corrupted descriptors that have a longer than expected length:
Only a little more of that, and we find a glitched configuration descriptor that’s 65,534 bytes long, more than enough to reconstruct the entire 32 kB firmware ROM. You only get the memory prior to the descriptor if the address space wraps, but fortunately for us this was the case. All that’s left is to determine the address offset by looking for clues like an IVT at the beginning or unused memory near the end of the image, and correctly align the resulting 32 kB image.
If you’d like to try this technique on your own devices with the ChipWhisperer, you can grab the PCB design and source for FaceWhisperer to play along.15
This sort of side-channel analysis still requires a bit of PCB surgery in order to set up the device’s power rails and clock for glitching and monitoring. It also helps to have a reset signal and some sort of GPIO that can be used as a timing reference. It would be interesting future work to see how far this setup could be reduced. Could the glitching be performed solely via the USB port, even through whatever power regulation and conditioning the device includes?
Coding in Disappearing Ink
The documentation for the LC87 architecture is sparse. I eventually found an instruction encoding table buried in some product-line-specific appendix, but for a while the only resource I could find was a freeware toolchain, including a compiler and an on-chip debugger. I had already taken a look at this debugger in an attempt to awaken the debug port on my tablet. It wouldn’t do much without this mysterious TCB87-TypeC dongle, but I tried simulating the TCB87 with a GreatFET that mostly just pretends things are okay and tells this RD87 debugger whatever it wants to hear. When I get the debugger to start up, it begins populating the hex views with zeroes. After a quick look with the USB analyzer, I easily find the requests that are the same size as the device’s memory and begin answering those with my firmware dump. Now I have a debugger that I can use for static analysis!
I was looking for some kind of update mechanism. I would later discover that this tablet (firmware 1.16) used mask ROM whereas many earlier tablets (1.13) used flash memory. Those 1.13 tablets do seem to have a bootloader of some kind available, but I haven’t looked into it yet. With the 1.16 tablet I had been analyzing, though, I became fairly certain there was no intended way to modify the device’s program memory. This gave me a new constraint, which turns out to be interesting anyway: Turn the tablet into an RFID reader without modifying its firmware. We’ll do this entirely via RAM and return-oriented programming.
The next step was much easier than expected. There was plenty of hidden functionality in the firmware. These are things that aren’t part of any standard and aren’t used by the official drivers, but presumably exist for factory test purposes. There’s a mode you can put the tablet in which enables an additional USB endpoint that returns loads of timers and internal debug info. Oh, and there’s a HID request that will just write exactly 16 bytes into RAM anywhere you like!
I think this was used in conjunction with another routine that isn’t called anywhere, which tests the custom silicon Sanyo added for Wacom. Oh, custom silicon. I was hoping not to find that here. Newer tablets have chips that are obviously designed by Wacom to be complete analog frontends. I wanted to start with an older tablet that would have fewer custom parts. But perhaps the “W” in LC871W32 stands for Wacom. The analog frontend is made from discrete components in this tablet; multiplexers to select from an array of coils, op-amps to integrate the received signals, a buffer to excite the coils with a carrier wave. When I first looked at the circuit, it seemed like the 750 kHz carrier wave itself as well as the other timing signals would be generated using general-purpose peripherals on the micro. But when I look for the corresponding GPIO pins, nothing. More reverse engineering, and it was clear that I was facing custom hardware. I’ve been calling it FEB0h, after its I/O address. At first I thought it was a serial engine of some sort that was being misused to run the tablet, but now it’s clear that this hardware is purpose-built. More on that later. For now, it’s enough to know that the hardware or the mask ROM itself had enough engineering risk that they thought it prudent to include such a powerful test feature.
This is enough to start testing the waters and building up more and more complex ROP code. The ROM is only 32kB, and barely half full, but there are some useful gadgets. We can make function calls, do memcpy, RAM-to-RAM and ROM-to-RAM. Interrupts are tricky. I tried coexisting with them for a while, but had to give up on that due to USB packet corruption issues I couldn’t track down. Write an ar
bitrary byte? Look up where we’d find that in ROM and do a memcpy. Loops are the slowest. These ROP stack frames can only execute once before they’re corrupted, so we must copy the code each time it’s run. It’s slow, but we’re doing arbitrary things to this peripheral that we haven’t even written any code to. We can even return it to normal operation if we like, by jumping back to the main loop and restoring a normal stack.
This is not typically the sort of operation your OS requires elevated privileges for. The underlying Send Feature Report operation is typically associated with harmless device-specific features like toggling your keyboard LEDs, not with writing arbitrary instructions to a Turing-complete processor that is trusted by the OS just as much as you are. Applications can typically reserve access to any HID device that doesn’t already have a driver loaded. It’s easy to imagine some desktop malware that unloads or subverts the default driver long enough to load some malware into a peripheral’s RAM without subsequent detection by either the user or the driver.
Amplitude Modulation Alchemy
Wacom pens and passive RFID cards are broadly similar, in that they both use a resonant LC circuit to pick up some energy from the reader’s changing magnetic field, then they send back data bits with backscatter modulation, selectively shorting out the coil. The specific mechanism is a bit different though, and it will make our job harder. A typical 125 kHz RFID reader is sending out either a continuous carrier, or perhaps sending long bursts a few times a second to save energy. During this burst, the reader is continuously listening for a modulated response, with hardware filters specifically tuned to this job.
Wacom tablets, by contrast, are all about sequentially scanning an array of coils. This CTE-450 tablet has 12 short and wide horizontal coils on the front side (Y00 through Y11) and 17 tall and thin vertical coils on the back side (X00 to X16). When it has no idea where the pen might be, it has to scan everywhere. After locating the pen, it can adjust the scanning pattern to take differential measurements from the tablet coils nearest the pen coil. Instead of transmitting and receiving simultaneously, the filtering can be simplified by toggling between two modes. When transmitting, a 74HC125 buffer drives the coil with the tablet’s carrier wave. During this time, the analog integrator is zeroed. Then the tablet switches modes, and begins integrating the received signal.
These resonant LC circuits are like electromagnetic tuning forks. An RFID tag or a Wacom pen have a tuning fork at a specific frequency, and some circuitry that communicates each bit by either damping the oscillations or letting them ring. The Wacom tablet shouts at the tuning fork’s frequency, quickly and abruptly, and immediately listens for the reverberation. The whole protocol is designed around this mode switch. Gaps in the carrier indicate the bit boundaries, and longer bursts divide packets.
The trick here is to use this mechanism to read some common RFID access card. Between the slow return-oriented programming and the limited analog frontend, I picked an easy target for the PoC. The EM4100 is a common 125 kHz tag with a fixed 40-bit ID. It’s no more secure than a pin tumbler lock for sure, but it isn’t too far from the tags used in many access control systems.
The EM4100 pads the 40-bit code out to a 64-bit repeating pattern with the addition of a 9-bit header and a matrix of parity bits. Each bit is Manchester encoded; 0 becomes 10, 1 becomes 01. Each half-bit lasts 32 clock cycles, giving us a conveniently slow data rate.
The pulsed carrier is a problem. The RFID card does have its little tuning fork, and it keeps ringing a little bit, but not as much as you might think, especially when the EM4100 chip is trying to power itself from this stored energy and the external carrier has disappeared. A clock cycle or two, but not nearly as long as the tablet’s A/D conversion takes. This little bit of unpredictability, though, has so far foiled every plan of mine to stay in sync with the signal in order to sample it at or below the bit rate. My workaround has been to use a short enough carrier pulse in order to have multiple samples per bit, allowing me to occasionally use a pile of filters and heuristics to recover the correct bits with appropriate deference to Nyquist. The problem with using a shorter carrier pulse is that it lowers our carrier duty cycle, delivering less power to the RFID card. So, there’s a delicate balance: long enough to power the card, short enough for the resulting data to be intelligible through this intermittent sampling.
The returned signal is quite weak, since the tablet’s filters are looking for resonance at a very different frequency. This is an area where I’ve seen much difference between individual RFID tags. Under unrealistic conditions, with the RFID tag placed directly on the tablet circuit board, many tags read successfully without much trouble. With an unmodified and fully assembled tablet, I’ve had very difficult to reproduce results, occasionally reading only one of the several tags I tried the setup with.
If you want to try this experiment or others, you can find my simple ROP toolkit and signal processing for the CTE-450 and try your luck with the return-oriented analog hacking.16
More to do
Although so far I’ve only managed to transform this tablet into an extremely bad RFID reader, I think this shows that the overall approach may lead somewhere. The main limitations here are in the reliance on slow ROP, and the relatively low quality A/D converter on the LC871. I’ve done my best to try and separate the signal from the noise, but I’m no DSP guru. It’s possible that a signal processing expert could be snooping tags with a better success rate than I’ve been seeing. As a proof of concept, this shows that the transformation from tablet to RFID reader is theoretically doable, though without a significant improvement in range it’s hard to imagine this approach succeeding at reading access cards casually left against a victim’s graphics tablet.
It could be interesting to examine newer tablets. The custom silicon in FEB0h turned out to be one of the best things about the CTE-450 tablet, making it relatively easy to change the timing and carrier frequency. If newer tablets have a nicer A/D converter and a programmable filter on the receive path, they could make a decent RFID reader indeed. A brief look at my newer Intuos Pro tablet shows a Renesas processor that likely has reprogrammable flash.
There’s certainly more work to do in discovering the scope of devices vulnerable to glitched GET_DESCRIPTOR requests. What other devices that we usually think of as black-box peripherals might have firmware that can be read out, or RAM that we can temporarily hide code in?
It may be possible to mitigate these glitched GET_DESCRIPTOR firmware readouts by adding additional verification steps in the device’s USB stack, which would each also need to be glitched. Reducing the number of invalid states that eventually result in spilling data will make the glitching process much more tedious.
In practice, though, I would argue that the best security is not to rely on secret firmware at all. Algorithms shouldn’t need secrecy to keep them secure. Debug features that are too dangerous to leave should be disabled, not hidden. If any sensitive data must be reachable from the CPU, it should be unmapped whenever possible, especially when some USB controller asks for your life story.
13:5 Decoding AMBE+2 in MD380 Firmware in Linux
by Travis Goodspeed KK4VCZ, with kind thanks to DD4CR, DF8AV and AB3TL.
Howdy y’all,
In PoC‖GTFO 10:8, I shared with you fine folks a method for extracting a cleartext firmware dump from the Tytera MD380. Since then, a rag-tag gang of neighbors has joined me in hacking this device, and hundreds of amateur radio operators around the world are using our enhanced firmware for DMR communications.
AMBE+2 is a fixed bit-rate audio compression codec under some rather strict patents, for which the anonymously-authored Digital Speech Decoder (DSD) project is the only open source decoder.17 It doesn’t do encoding, so if you’d like to convert your favorite Rick Astley tunes to AMBE frames, you’ll have to resort to expensive hardware converters.
In this article, I’ll show you how I threw together a quick and dirty AMBE audio decompressor for Linux by wrappin
g the firmware into a 32-bit ARM executable, then running that executable either natively or through Qemu. The same tricks could be used to make an AMBE encoder, or to convert nifty libraries from other firmware images into handy command-line tools.
This article will use an MD380 firmware image version 2.032 for specific examples, but in the spirit of building our own bird feeders, the techniques ought to apply just as well to your own firmware images from other devices.
Suppose that you are reverse engineering a firmware image, and you’ve begun to make good progress. You know where plenty of useful functions are, and you’ve begun to hook them, but now you are ready to start implementing unit tests and debugging chunks of code. Wouldn’t it be nicer to do that in Unix than inside of an embedded system?
As luck would have it, I’m writing this article on an aarch64 Linux machine with eight cores and a few gigs of RAM, but any old Raspberry Pi or Android phone has more than enough power to run this code natively.
Be sure to build statically, targeting arm-linux-gnueabi. The resulting binary will run on armel and aarch64 devices, as well as damned near any Linux platform through Qemu’s userland compatibility layer.
Dynamic Firmware Loading
First, we need to load the code into our process. While you can certainly link it into the executable, luck would have it that GCC puts its code sections very low in the executable, and we can politely ask mmap(2) to load the unpacked firmware image to the appropriate address. The first 48kB of Flash are used for a recovery bootloader, which we can conveniently skip without consequences, so the load address will be 0x0800c000.
PoC or GTFO, Volume 2 Page 36