I am trying to write a proof of concept in C that demonstrates the execution of code from a memory buffer on a stack on an ARM Cortex-M3. It will be useful to demonstrate that using the ARM MPU correctly can prevent such an attack. I decided that a quick and dirty way to get the code on the stack is to copy it from a regular function, and then use goto to jump to it like this:
static void loopit(void) { printf("loopit\n"); while (1); } void attack(void) { uint8_t buffer[64] __attribute__((aligned(4))); memcpy(buffer, loopit, sizeof(buffer)); goto *((void *) (int) buffer); }
I would expect that when I call the attack function, it will copy the code onto the stack, jump to it, print a message and go into an endless loop. However, instead, I get an exception with the following values ββin the error registers:
HFSR = 0x40000000 CFSR = 0x00020000 PSR = 0x60000000
This seems to be an INVSTATE bit in UFSR that indicates "illegal use of EPSR", which I read, usually because of a BX instruction trying to go to an address with LSB set to 0, which the processor interprets as a function with non-Thumb- with code in it, but Cortex-M processors only allow Thumb code. I see that memcpy gets an odd address for the loopit function, since I assume that the ORing compiler for the real memory address is using 1 . Therefore, the fix I would think would be to rewrite my attack function like this:
void attack(void) { uint8_t buffer[64] __attribute__((aligned(4))); memcpy(buffer, ((int) loopit) & ~1, sizeof(buffer)); goto *((void *) ((int) buffer) | 1); }
However, after that I get another exception from the error registers:
HFSR = 0x40000000 CFSR = 0x00080000 PSR = 0x81000000
This does not seem to mean that the UFSR bit set 3 means that "the processor tried to access the coprocessor." Looking at the PC, this time it seems that the jump succeeded, and it's great, but then something went off the rails, and the processor seems to follow strange instructions and does not enter into an endless loop. I tried to disable interrupts before goto and comment out the listing, but no luck. Any clue what is going wrong and how to make it work?