Friday, February 8, 2013

Infiltrate Preview - The Chameleon: A cellphone-based USB impersonator.

If you've ever been part of a Call For Papers committee you know that the information provided in the submission's abstract is generally vague and ambiguous. A talk could be a total Fail or THE talk that will define your conference and ensure it will return next year. That's why we ask for a draft version of the research and involve our technical team in asking questions and vetting submissions.

As an attendee of a conference you of course have to decide which conferences to attend. Immediate financial costs, scheduling time off, logistical details, these are all headache inducing aspects of going to a conference. You read a vague abstract on a conference website but you are not allowed to ask questions. You understand the Windows 8 heap, but does this presenter really know what they're talking about or will this be a waste of your time? In the past folks have had to base their attendance decision on how well the conference has been reviewed in the past (reviews which are sometimes are paid for by the organizers) and on speaker reputation (another criteria used by CFP committee).

At Infiltrate, we like you, heck we understand you because we've gone through that ourselves. So in order to change this annoying process in the infosec community, we're offering something different :). We are encouraging our selected speakers to be guest bloggers here, to provide more in depth information on their topics and to field questions.

The ball is now in your court, the shoe on your foot, the ace is in your sleeve. As an attendee you should take the time to research the subject and try to get the most out of each of each talk. We generally like to brag that our audience poses the most difficult questions to presenters, let's try to keep that up! Without further ado:

Matias Soler on:

The Chameleon: A cellphone-based USB impersonator

Fuzzing or auditing USB stuff has been around for a while but doing it from the device's perspective is a relatively unexplored area. This is mostly because of the complications that are involved in pretending to be a USB device to attack a USB host. The simplest method involves some hackish modifications on QEMU, where you can write a driver for QEMU for your emulated device and it will appear as real to the virtualized OS.

Unfortunately you cannot run everything interesting inside a virtual machine (think smart TVs, music centers, etc), and even if you could operating systems may behave differently on real hardware. And even more important your real target probably won't be inside QEMU.

Travis Goddspeed has done an amazing job on building a small device with two USB ports that will solve this problem. One end goes to your computer and the other one to the target machine. By using python he is able to control the device such that it will appear as a real USB gadget to the target. Although this is awesome, building this device requires building the PCB and more importantly SMD soldering skills (that I don't have).

So our goal was to build a device that allowed us to quickly prototype USB gadgets and make it easy to assemble. We decided to use a Teensy board, which it's not much more that an AVR micro controller with built-in USB support. All the basic components needed to work, a USB boot-loader so you can reprogram it using this port and of course it had to come pre-assembled :)

Things we love about this board:
  • Is a small board with a relatively powerful microprocessor
  • This processor has built-in USB controller
  • Has a handy bootloader that allows for programming the microprocessor via USB very easily
The Teensy's USB controller is managed entirely by setting and reading a couple of specific registers which makes life wonderfully simple. For example, sending data from the device to the host would be something like this:

There are lots on examples on the Internet about using this device to emulate different USB gadgets such as: keyboards, mice, mass storage, etc. Although there are some drawbacks:

  • There is no easy way to debug: You can always send data trough USB, but you will be interfering with the emulation
  • You have to code in C/C++
  • For each test you need to recompile and re-flash.

The last issue too may not seem very important but when you are doing hundreds of tests it adds a lot of time overhead. Also if you are testing on real hardware, you will need to unplug the Teensy and connect it to your development machine for reprogramming.

So what we did was instead of emulating the whole Gadget on the Teensy, we just use it as a proxy. And this proxy is controlled from a Python script where all the USB logic was implemented. This allow us to move all the complexity of coding USB stuff from the hardware device to the host side, using python code which is much more friendly. We also designed our library in layers so the upper layers do not depend on our actual hardware this gives us the ability to port the library to different hardware if needed.

For this we needed another communication channel from the Teensy to our development computer, so we added a generic USB-Serial adapter connected to the host's serial port:

  • USB device that emulates a serial port on the host
  • RX and TX outputs are in TTL level
  • 0v to 0.8v = 0
  • 2.2v to 5v = 1
  • Native support on Linux

Now the developer's computer communicates via the USB-serial line to the Teensy, where it can interact with the USB controller. On the other side the Target machine is connected directly to the USB port of our device.

We built a very basic firmware for the Teensy that reads commands from the serial line and based on the value received it will either read or write a register from the USB controller. The first byte transmitted either from the host to the Teensy or from the Teensy to the host has the following format:

Where opcodes can be SET_REGISTER, READ_REGISTER or PING, and the register value is 5 bits that represent what register will be read or written to. In the case of a SET_REGISTER operation a second byte is sent indicating the value that should be written to the register. In the case of READ_REGISTER the value will be returned by the Teensy to the host.

PING is just for debugging, a PING_REPLY is answered every time we send this request and lets us know if some part of the chain has died. Just to be more clear here is part of the firmware code (it has been trimmed so it can fit nicely on the blog post):

And finally here's what it looks like on my desk:

As you can see the device is very simple to build, just need to attach tree wires and it's done!

The firmware is also very simple, but the whole complexity is moved to Python on the host side, where you need to understand and handle almost raw USB requests.

Despite all the good features of this project, it has its limitations. When you are emulating stuff that requires a lot of data transfers, like USB-storage for example, it results are pretty slow. The bottleneck right now is the serial line, although some improvements can be made to the protocol like handling bulk data transfers instead of byte by byte, it will at most double the speed which is still not enough.

At this point we were forced to look for new alternatives and we decided to move to using a Cellphone as the base hardware. Surprisingly a cellphone is a perfect platform for this task, they have powerful processors, big screens, Wi-Fi and more important a guest-capable USB controller. In particular we have chosen Samsung S2, as it is very popular and relatively easy to replace the kernel.

If you want to see more on this new approach you should came to Infiltrate and see my talk, "Chameleon, a cellphone-based USB impersonator" :)

~ Matias Soler


No comments: