more info in readme, fix dump mode
This commit is contained in:
parent
b97e026d9a
commit
b1c1aa0806
27
README.md
27
README.md
|
@ -92,6 +92,8 @@ described near the end, the article is quite large.
|
|||
1. Even when returning from an interrupt serviced during BSL execution, it is
|
||||
not possible to return from this interrupt directly back to BSL code, as
|
||||
this counts as a jump-to-arbitrary-BSL-location.
|
||||
1. DMA transfers cannot read from the BSL region at all (not from the Z-area,
|
||||
not from the BSL region during BSL execution).
|
||||
|
||||
## Vulnerabilities of the BSL against a readout attack
|
||||
|
||||
|
@ -182,13 +184,34 @@ normally return into the BSL from user code, doing this would cause a reset.
|
|||
Luckily, it is still possible to change the program counter on the stack of the
|
||||
address returned to, so the experiment can be restarted from the beginning.
|
||||
|
||||
`0x1b00` halts the CPU by writing some code into tiny RAM (at address `0`) that
|
||||
sets the CPU in a low power mode and performs an infinite loop. It then jumps
|
||||
to that code.
|
||||
|
||||
`0x1b02` and `0x1b04` eventually converge to address `0x1bea`, where NMI
|
||||
tracing starts failing for a yet unknown reason. It does not seem to be an "NMI
|
||||
disable" instruction (by writing to an SFR or SYS register), as using DMA to
|
||||
continuously rewrite these registers with values that enable these signals,
|
||||
doesn't seem to work. It does not disable the UART, as LEDs used in debugging
|
||||
stop blinking at this moment as well.
|
||||
|
||||
At this point in, the second BSL code has not performed any stack accesses or
|
||||
memory-to-register reads.
|
||||
|
||||
As `0x1b02` is called from the main BSL code as part of the "mass-erase FRAM"
|
||||
command, it most likely implements this functionality, and hardly anything
|
||||
else.
|
||||
|
||||
## Proof of concept
|
||||
|
||||
The code in `src/main.c` will dump the content of the BSL to `eUSCI_A0` in UART
|
||||
mode. Tested on an MSP430FR5994, but no other chips.
|
||||
mode, at 9600 baud. Tested on an MSP430FR5994, but no other chips.
|
||||
|
||||
By setting the `DUMP_MODE` preprocessor definition to 0, it can instead be used
|
||||
as an instruction tracer, accompanied by `logtracer.py`.
|
||||
as an instruction tracer, accompanied by `logtracer.py`. Setting `USE_NMI` to 1
|
||||
will use an NMI-based tracer instead of a `Timer_A`-based one. The address to
|
||||
jump to (to trace) will still have to be changed manually in the `do_trace()`
|
||||
function body.
|
||||
|
||||
## Useful shellcode
|
||||
|
||||
|
|
33
src/main.c
33
src/main.c
|
@ -75,12 +75,12 @@ static void pico_wait_ack(void) {
|
|||
/*#define SKIP_CYC_OFF 5*/
|
||||
|
||||
// DUMP_MODE == 0 => insn trace mode
|
||||
#define DUMP_MODE 0
|
||||
#define DUMP_MODE 1
|
||||
#define DUMP_CYC_OFF 14
|
||||
#define DUMP_ADDR_START (0x1000+2) /* there's an off-by-4 error */
|
||||
#define DUMP_ADDR_END 0x1800
|
||||
#define DUMP_ADDR_START (0x1000) /* there's an off-by-4 error */
|
||||
#define DUMP_ADDR_END 0x17fc
|
||||
|
||||
#define USE_NMI 1
|
||||
#define USE_NMI 0
|
||||
|
||||
#if USE_NMI
|
||||
#define STORAGE
|
||||
|
@ -116,7 +116,9 @@ __attribute__((
|
|||
, __no_inline__, __used__))
|
||||
void do_trace(void) {
|
||||
const bool nmi = USE_NMI;
|
||||
#if USE_NMI
|
||||
P1OUT ^= BIT1;
|
||||
#endif
|
||||
|
||||
// TODO: chain 2 timers for 32 bit tick number
|
||||
// TODO: continue instead of restarting?
|
||||
|
@ -174,12 +176,8 @@ void do_trace(void) {
|
|||
#endif
|
||||
#if USE_NMI
|
||||
// send trigger
|
||||
"mov.w #0xa5a5, 0x1c00\n"
|
||||
"bis.w #0x10, P1OUT\n"
|
||||
#else
|
||||
//TA1CTL = TASSEL__SMCLK | ID__1 | MC__UP | TACLR | TAIE;
|
||||
"mov.w #0x0216, TA1CTL\n"
|
||||
"eint\n"
|
||||
#endif
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
"nop\n"
|
||||
|
@ -214,9 +212,15 @@ void do_trace(void) {
|
|||
"push.w r13\n"
|
||||
"mov.w #2, r12\n"
|
||||
"br #0x1b02\n" // CHANGEME (address to trace insn flow of)
|
||||
#else
|
||||
//TA1CTL = TASSEL__SMCLK | ID__1 | MC__UP | TACLR | TAIE;
|
||||
"mov.w #0x0216, TA1CTL\n"
|
||||
"eint\n"
|
||||
"br #0x1002\n"
|
||||
#endif
|
||||
//#if !USE_NMI
|
||||
"1: jmp 1b\n"
|
||||
//#endif
|
||||
//#endif*/
|
||||
);
|
||||
//#if !USE_NMI
|
||||
while (1) ;
|
||||
|
@ -251,14 +255,14 @@ void do_collect(uint16_t* sp) {
|
|||
uint16_t v1 = sp[2*(12-4)];
|
||||
uint16_t v2 = sp[2*(13-4)];
|
||||
|
||||
if ((curaddr & 0xf) == 0x2) {
|
||||
iprintf("%04x: ", curaddr-2/*correct off-by-2 error*/);
|
||||
if ((curaddr & 0xf) == 0x0) {
|
||||
iprintf("%04x: ", curaddr-0/*correct off-by-2 error*/);
|
||||
}
|
||||
iprintf("%02x %02x %02x %02x ",
|
||||
v1 & 0xff, (v1 >> 8) & 0xff,
|
||||
v2 & 0xff, (v2 >> 8) & 0xff
|
||||
);
|
||||
if ((curaddr & 0xf) == 0xe) {
|
||||
if ((curaddr & 0xf) == 0xc) {
|
||||
iprintf("\r\n");
|
||||
}
|
||||
#else
|
||||
|
@ -311,7 +315,6 @@ next_iter:
|
|||
++curticks;
|
||||
#endif
|
||||
#if USE_NMI
|
||||
//P1OUT ^= BIT1;
|
||||
// return...
|
||||
#else
|
||||
do_trace();
|
||||
|
@ -501,8 +504,8 @@ CODESP int main(void) {
|
|||
#if USE_NMI
|
||||
pico_send_cmd('0');
|
||||
pico_wait_ack();
|
||||
#endif
|
||||
dma_init();
|
||||
#endif
|
||||
do_trace();
|
||||
/*while(1);*/__builtin_unreachable();
|
||||
|
||||
|
|
Loading…
Reference in New Issue