Fernvale: The Path Not Taken
Today at 31c3, bunnie and I gave a talk on the Fernvale platform, the core
of which is a Mediatek MT6260 System-on-a-Chip. This chip is appealing
because it is a 364 MHz ARM chip with four megabytes of built-in flash and
eight megabytes of RAM. Additionally, it has the usual accoutrements such
as USB 1.1, I2C, LCD controller, and basic GPIO control. The talk centered
on how we ended up getting code execution on the chip and ultimately porting
an operating system to it. I won’t repeat that information here, you can
read more information on a blogpost put up by bunnie, or watch the talk
again on the 31c3 archives. Instead I’d like to document an approach to
reverse engineering that is interesting, but ultimately ended up not being
the approach we took.
In the beginning, the target phone was integrate directly into Novena. From
the perspective of the phone, its serial flash was visible in RAM at address
0x0000. Early on the bootloader jumped to address 0x3460, so we put our
code there. The FPGA in Novena emulated a SPI ROM, so address 0x3460 on the
MT6260 was actually a value in the block RAM of the FPGA.
Because the FPGA appears as a memory device to the Novena CPU, the same
memory region actually appears as normal RAM to Novena. That is, address
0x3460 on the MT6260 is actually the same address as offset 0x08013460 on
Novena. This means that we have a very tight loop on where the CPU is
executing, and a very current map of the MT6260's view of the world.
What we didn't have was a way to break into the debugger on the MT6260. In
theory it has JTAG, which should let us attach a debugger and break the
execution flow of the CPU. However, we never got it working, and it's
unclear what steps must be taken, or even which set of pins to use.
Instead, we have a UART connection running at 115200 bps. If we could use
this stable connection to help us act as a debugger, we'd be all set. We
needed a different approach.
qemu is a well-known system emulator. It is commonly used to emulate x86
PCs to do operating system development, or to run virtual servers. qemu is
capable of emulating a lot more than just x86, and has targets for PPC,
Sparc, and ARM. The ARM target is especially appealing, and it supports the
concept of emulating specific ARM boards Interestingly enough, it also
supports attaching a debugger using the GDB network protocl, which should
interface nicely with IDA Pro or Radare2.
We started by adding a "Fernvale" machine. This machine defined the basic
peripherals and memory spaces. We knew there the internal SRAM should be
located, and we knew where the internal PSRAM is on a real MT6260.
Additionally, we mapped the SPI chip where it would be on a real MT6260, and
loaded the SPI ROM we pulled out from our live machine into this emulated
area. Finally, we used the reference manual we had to implement a simple
UART register set using the same offsets as a real MT6260. This UART was
mapped to stdout, so that anything written to the UART would appear on the
Novena output.
We loaded everything up and set the program counter to the correct offset,
and set it running. Majestically, it actually started executing code! It
entered Thumb mode, jumped to the initialization vector, and crashed.
Well, it's a start at least.
We found that it was accessing unmapped areas of memory that were most
likely undocumented configuration registers. In order to figure out their
purpose, we needed to figure out what values the code was expecting.
Fortunately, we had a live MT6260 we could consult, and we had a way to
communicate with it.
So we wrote a simple peek/poke command loop for the MT6260 that took a byte
width (1- 2- or 4-bytes), an address, and optionally a value (for poke) and
ran it directly on the phone. We then hooked this up to the emulator, and
mapped undocumented memory accesses to real hardware. Areas where we could
confidently emulate the register set we handled directly. For example, we
quickly realized that the configuration register space had a hardcoded
product and revision IDs that we didn't even have to consult the hardware to
get.
Using this method, we found some clock registers, some power registers, and
some configuration registers. We found the ROM this way, though executing
code via a series of peeks and pokes across a UART is not efficient at all,
and could take untold minutes to complete. We started adding more exotic
features such as caching certain areas across accesses and modifying the
boot code to skip certain branches that caused the UART link to fail
(including the code that moved the SPI link up to quad-SPI mode), but
overall the system became too fragile.
Being able to attach a debugger such as IDA to a half-live system is a novel
approach, and may be useful in future endeavours in reverse engineering.
qemu is an amazing piece of software, and it is incredible to attach IDA to
a system that's currently running and be able to pull out values from the
emulated CPU's registers, manipulate the program counter, and view arbitrary
areas of memory. While ultimately we used a different approach to more
fully understand the system, this is an interesting method, and one which
I'm sure will come in handy in the future.