readme update
This commit is contained in:
parent
cb7386bc6f
commit
60a5e08c7e
71
README.md
71
README.md
|
@ -5,40 +5,51 @@ Tools to try to dump the MSP430FR BSL, mainly targetting the [MSP430FR5994
|
|||
|
||||
## The idea
|
||||
|
||||
The 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 MSP430FR bootloader ('BSL') resides at `0x1000`. This memory cannot be
|
||||
read, and user code can only jump to `0x1000` or `0x1002`, called the "Z-area",
|
||||
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, as that is often needed to store eg. structs, lookup tables, and so on.
|
||||
Several other "execute-only" memory implementations function in a similar way,
|
||||
such as the Nintendo GameBoy Advance and DS boot ROMS ("BIOS"es, citation
|
||||
below), as well as in other systems analyzed by Schink and Obermaier,
|
||||
publication also linked below.
|
||||
|
||||
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
|
||||
interrupts. That means that, while the BSL is executing, it is possible to
|
||||
interrupt this execution flow to
|
||||
jump to code controlled by the user. An interrupt can inspect and modify
|
||||
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).
|
||||
having it dump the register and stack contents after a certain interval increasing
|
||||
by one cycle every iteration, it is possible to trace the instruction flow of
|
||||
the CPU, as well as which registers and stack contents it is accessing, and how,
|
||||
even though the code itself is not visible. Furthermore, the MSP430 CPU uses a
|
||||
variable-length instruction set and instructions can use a variable amount of
|
||||
cycles, therefore these traces can also be used to infer more infromation about
|
||||
which instructions are executed, as the `pc` CPU register will never point to
|
||||
the middle of an instruction, and will only advance to the next instruction
|
||||
depending on how long the current instruction takes to execute.
|
||||
|
||||
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.
|
||||
Function epilogues typically first pop a number of values off the stack and
|
||||
load these back into registers, and then return. By controlling the stack
|
||||
pointer value, these can be used as a way to perform arbitrary reads. However,
|
||||
as we are targetting nonwritable memory, an interrupt needs to happen before
|
||||
the return occurs, otherwise CPU execution becomes very unpredictable.
|
||||
|
||||
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.
|
||||
Alternatively, by timing an interrupt or 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 as well as the program counter. Then, CPU
|
||||
execution can be redirected to another code snippet performing the memory read
|
||||
before returning. With control over the address it reads from, this can be used
|
||||
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
|
||||
|
@ -64,7 +75,8 @@ described near the end, the article is quite large.
|
|||
|
||||
1. When the CPU is executing the BSL, it can perform data accesses to other BSL
|
||||
areas. Thus, if an arbitrary read gadget is found, it can be used to dump
|
||||
the entire BSL region.
|
||||
the entire BSL region. This is the same issue as present in the Nintendo
|
||||
DS ARM7 boot ROM.
|
||||
1. The routine at `0x1002` provides such a gadget, *as indicatd in SLAU550AA*.
|
||||
1. The BSL execution is allowed to be interrutped, thus the instruction flow
|
||||
can be traced by dumping CPU register values throughout the BSL execution.
|
||||
|
@ -101,3 +113,14 @@ described near the end, the article is quite large.
|
|||
1. DMA: can a DMA transfer be used to change the stack contents during BSL
|
||||
execution? (Most likely, just like interrupts can, I simply haven't checked.)
|
||||
|
||||
## Hashes
|
||||
|
||||
This is the hash of the memory region `0x1000` to `0x17FF`, on an MSP430FR5994,
|
||||
with BSL 00.08.35.B3:
|
||||
|
||||
| Hash function | value |
|
||||
| MD5 | `4bb3bb753face80fffe1fef7a762884a` |
|
||||
| SHA-1 | `1b4c13e006121a9b1c1ebcd4fbc6ec7c96cc017f` |
|
||||
| SHA-256 | `e4d0d171013f847a357eebe5467bcd413ecb41dc01424b7e4ee636538d820766` |
|
||||
| SHA-512 | `fed28a7e9643a551789075b79d9b04fa6e8cdca74d783c1c3830ece07e5c9141dda9532b3c442416a1ddab90d752e679c6918c0d5333ac6da9fd23ab6c33d1bb` |
|
||||
|
||||
|
|
Loading…
Reference in New Issue