view doc/TFC139-breakin @ 465:003e48f8ebe1

rvinterf/etmsync/fsnew.c: cast 0 to (char *) for execl sentinel I generally don't use NULL and use plain 0 instead, based on a "NULL considered harmful" discussion on the classiccmp mailing list many aeons ago (I couldn't find it, and I reason that it must have been 2005 or earlier), but a recent complaint by a packager sent me searching, and I found this: https://ewontfix.com/11/ While I don't give a @#$% about "modern" systems and code-nazi tools, I realized that passing a plain 0 as a pointer sentinel in execl is wrong because it will break on systems where pointers are longer than the plain int type. Again, I don't give a @#$% about the abomination of x86_64 and the like, but if anyone ever manages to port my code to something like a PDP-11 (16-bit int, 32-bit long and pointers), then passing a plain 0 as a function argument where a pointer is expected most definitely won't work: if the most natural stack slot and SP alignment unit is 16 bits, fitting an int, with longs and pointers taking up two such slots, then the call stack will be totally wrong with a plain 0 passed for a pointer. Casting the 0 to (char *) ought to be the most kosher solution for the most retro systems possible.
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 11 Feb 2019 00:00:19 +0000
parents e7502631a0f9
children
line wrap: on
line source

Maliciously locked bootloader
=============================

When Compal (Motorola's ODM who designed and built their C1xx phones for them)
designed the firmware architecture and flash memory layout for their phones,
they made a bad design decision by putting the boundary between their bootloader
and the main fw image at 0x2000, even though the flash erase block boundary
doesn't come until 0x10000 - thus every time the main fw needs to be reflashed
to a different version, the dangerous boot sector has to be reflashed too.

But then they made things even worse in the newer versions of their fw by
introducing a bootloader lock malfeature whereby the ability to interrupt boot
and load code serially may be artificially disabled.  This malfeature is
implemented as follows:

* In the original firmware layout (before the addition of the malfeature in
  question) the boot code occupies the flash range from 0 through 0x1FFF, then
  there are some ID strings at 0x2000, 0x2020 and 0x2040, and then the part of
  the firmware that used to be at 0x10000 in TI's reference fw starts at 0x20A0,
  with the entry point at 0x20F8 (corresponding to TI's 0x10058).

  With the addition of the bootloader lock malfeature the 32-bit word at 0x2060
  (previously unused and filled with 0xFFFFFFFF) became a control word telling
  the bootloader whether diversion of the boot path to serial code download
  should be allowed or not.

* When firmware images with this malfeature present are first built, the word
  at 0x2060 contains 0xDDDDDDDD.  (Does D stand for debug or development, or
  was the developer who implemented this malfeature fascinated by large bra
  cups?  We may never know.)  This word MUST read as 0xDDDDDDDD in order for
  the boot code to allow serial download: if it reads as any other value (e.g.,
  if it contains 0xFFFFFFFF because only the 8192 byte boot code has been
  programmed into flash sector 0, with blank flash from 0x2000 onward), no
  serial download opportunity will ever be offered and the phone is effectively
  bricked!

* For as long as the word at 0x2060 still contained 0xDDDDDDDD, Compal's
  developers could continue gaining access through the bootloader and reflashing
  their firmware.  But when phones were to be shipped to customers with the
  malicious bootloader lock activated, they probably sent some Test Mode command
  (see RVTMUX write-up) to their running fw that caused it to write 0x00000000
  into the flash word at 0x2060.  (Remember that any bit in a NOR flash memory
  can be programmed from 1 to 0 at any time in any combination, but changing
  bits from 0 back to 1 is only possible with full sector erasure.)

* Once the word at 0x2060 has been programmed (in the flash memory sense) from
  0xDDDDDDDD down to 0x00000000, the phone is irreversibly locked and has lost
  its ability to ever run a different firmware version, like a kamikaze pilot's
  plane that has discarded its landing gear and can only crash now.

Recovery procedure
==================

While it probably was Compal's, Motorola's and various carriers' intent that the
bootloader lock on their phones be truly irreversible, the unlocking community
has now developed a method for recovering these phones (restoring their ability
to run any firmware of the user's choice) which (we hope) will work with all of
the existing locked-down firmware versions.  It works as follows:

* Even though the bootloader is locked down, if one boots the full fw regularly,
  one can still access the RVTMUX interface which the TI-based fw implements
  for debug trace and factory programming functions.  One needs to key in the
  magic sequence **16379# into the running fw, and a hidden menu will appear,
  giving the operator the option to enable trace.  Selecting this option will
  cause the fw to switch the headset jack to the UART carrying RVTMUX.

* Mot/Compal's firmware is based on a quite old version of TI's chipset
  reference fw (relative to late TCS211 from the Openmoko/Pirelli era), and it
  does not feature the Enhanced Test Mode (ETM) component with which we are
  most familiar.  However, it does implement the older set of non-enhanced
  Test Mode commands, and these TM commands just happen to include raw memory
  read and write operations at an arbitrary address.  (For a while we were
  under a mistaken belief that these commands were Compal's inventions, until
  we discovered TI's original TM predating ETM.)

* The ability to write arbitrary bytes into arbitrary RAM locations while the
  phone firmware is running means that we can inject a piece of shellcode into
  an unused RAM location and then cause this shellcode to gain execution by
  overwriting a function return address on the stack.

* Once you can execute your own code on the Calypso, everything becomes possible
  once again.  At that point one can trivially reverse the bootloader lock by
  erasing flash sector 0 and rewriting it with 0xDDDDDDDD in the 0x2060 word,
  or even better, rewriting this boot sector with an older version of the boot
  code that lacks the locking malfeature altogether.

Procedure variations: old mot931c.exe vs. new tfc139
====================================================

We first became aware of the possibility of recovering locked-down phones as
described above in the spring of 2014 when FreeCalypso developer Space Falcon
became aware of the existence of Windows utility mot931c.exe (binary w/o source)
that performs a variant of this unlocking procedure specific to one particular
locked-down firmware version: C139 phones with TracFone branding, fw version
8.8.17.  At first we had replicated the operation of this Windows tool verbatim
in our own Unix/Linux-based tfc139 libre tool; this variant of the shellcode-
based unlocking procedure worked well on TFC139 units, but could not crack other
locked-down fw versions, e.g., Cingular-branded C139 phones with fw version
1.9.24.

Subsequent investigation revealed that whoever wrote that mot931c.exe Windows
tool had not studied the operation of Motorola/Compal's TI-based firmware deeply
enough, and implemented their shellcode injection quite suboptimally: the stack
smashing process is hitting the wrong stack (not the stack of the L1A task in
whose context the Test Mode commands sent over the UART are executing), and it
is only through dumb luck that this version of the break-in procedure worked
at all.  The limitation of working only with one specific fw version results
from this poor method of shellcode injection (mindless choice of the wrong stack
for smashing), and instead of adapting it in a version-specific manner to other
particular locked-down fw versions at hand, I (Space Falcon) reimplemented our
tfc139 utility to smash the right stack (that of the L1A task), and thereby
made it generic to all Mot C1xx firmware versions.

Our Compal firmware break-in utility is still called tfc139, but it is no longer
specific to TFC139 phones; instead it should work with all Mot C1xx firmwares.
The shellcode injected by tfc139 re-enables the Calypso chip's own boot ROM and
jumps to it; this boot ROM will endlessly wait for a serial download because
the word at 0x2000 contains neither 0 nor 1 (it is part of an identifying ASCII
string in Mot/Compal's fw), and the operator can then run fc-loadtool to
perform arbitrary flash operations.