add readme

This commit is contained in:
Triss 2022-04-09 03:56:33 +02:00
parent 7f1c85134d
commit b43120968d
1 changed files with 65 additions and 0 deletions

65
README.md Normal file
View File

@ -0,0 +1,65 @@
# MSP430FR BSL dumper
Tools to try to dump the MSP430FR BSL, mainly targetting the [MSP430FR5994
](https://www.ti.com/product/MSP430FR5994) (on an MSP-EXP430FR5994 devboard).
## How
Mhe MSP430FR bootloader ('BSL') resides at 0x1000, this memory cannot be read,
and user code can only jump to 0x1000 or 0x1002 to run certian functions of the
BSL. Though, it is very likely that when the CPU is running from inside this
memory region, it can access this memory as data, because that's often needed
to store eg. complex integer values, structs, lookup tables, and so on.
The BSL (according to [the datasheet
](https://www.ti.com/lit/ug/slau550aa/slau550aa.pdf)) doesn't disable
interrupts. That means that you can still jump to it, and then interrupt it to
jump to code controlled by the user. As this is an interrupt, it can inspect
the registers of the BSL code at the time when the interrupt happened, as well
as the stack contents. Having a timer at the same frequency as the CPU, and
having it dump the register+stack contents after a while, and doing that over
and over again while advancing the time-until-interrupt delay by one cycle
every iteration, you can get a view of what the CPU is doing while executing
this hidden code (also, the MSP430 CPU is multicycling and uses variable-length
instructions, so instruction timings and pc deltas can also be used as a side
channel to figure out which instruction is which).
Function epilogues typically first pop a bunch of values off the stack and load
these back into registers, and then return. Additionally, if you're lucky, you
may also find a memory read right before the end of such an epilogue.
You can find these epilogues by staring at many, many execution traces
(obtained from these timer interrupts) and thinking really hard (this is the
hard, time-consuming and labor-intensive part).
Then, by timing a DMA transfer such that it happens after a function is called
but before it returns, it is possible to overwrite the memory popped off the
stack when an epilogue executes, thereby gaining control of a few register
values, and the program counter. Then you could redirect it to another piece of
code that does the memory read before returning. As you now (hopefully) have
control over the address it reads from, you can use this as an arbitrary read
to read one word of the BSL, then return to use code to do the next iteration.
The "using interrupts to figure out what execute-only code is doing" trick was
first (afaik) used by Martin Korth to find such a gadget inside the Nintendo DS
ARM7 boot ROM to read it out (and dump some keys), see [here
](http://problemkaputt.de/gbatek-bios-dumping.htm) and [here
](http://problemkaputt.de/gbatek-ds-memory-control-bios.htm), but is also
described in the academic literature, eg. [here
](https://www.usenix.org/system/files/woot19-paper_schink.pdf).
The "use DMA to get ROP" trick comes from [here
](https://hexkyz.blogspot.com/2021/11/je-ne-sais-quoi-falcons-over-horizon.html),
described near the end, the article is quite large.
## What has been found
1. `0x1000` is a jump to `0x1014`.
1. `0x1002` is a jump to `0x1028`.
1. The other code in the Z-Area are infinite loops (to itself, instruction `ff 3f`).
### 0x1014 (BSL_main())
1. `0x1014` sets `sp` to `0x3c00`.
1. It then calls `0x16fa` which fills a lot of RAM