Выполнение кода эксплойт Cortex M4
Для тестирования MPU и игры с эксплойтами я хочу выполнить код из локального буфера, работающего на моей плате разработчиков STM32F4.
int main(void)
{
uint16_t func[] = { 0x0301f103, 0x0301f103, 0x0301f103 };
MPU->CTRL = 0;
unsigned int address = (void*)&func+1;
asm volatile(
"mov r4,%0\n"
"ldr pc, [r4]\n"
:
: "r"(address)
);
while(1);
}
В основном у меня первая очередь из МПУ. В func хранятся мои инструкции. В части ASM я загружаю адрес (0x2001ffe8 +1 для большого пальца) в регистр счетчика программ. При пошаговом выполнении кода с помощью GDB в R4 правильное значение сохраняется и затем передается в регистр ПК. Но тогда я окажусь в HardFault Handler.
Редактировать: стек выглядит так:
0x2001ffe8: 0x0301f103 0x0301f103 0x0301f103 0x2001ffe9
Инструкции верны в памяти. В "Полном руководстве по Cortex" сказано, что регион 0x20000000–0x3FFFFFFF - это SRAM, и "этот регион является исполняемым, поэтому вы можете скопировать здесь программный код и выполнить его".
1 ответ
Вы назначаете 32-битные значения 16-битному массиву.
Ваши инструкции не заканчиваются, они продолжают сталкиваться с тем, что найдено в ОЗУ, так что это может привести к сбою.
Вы не загружаете адрес в массив в счетчик программы, вы загружаете первый элемент в массиве в счетчик программы, это приведет к сбою, вы создали уровень косвенности.
Посмотрите на инструкцию BX для этого, а не ldr pc
Вы не объявили массив как статический, поэтому массив можно оптимизировать как мертвый и неиспользуемый, что может привести к его аварийному завершению.
Компилятор также должен жаловаться, что вы присваиваете void* переменной без знака, так что здесь требуется тип-трансляция.
По привычке я рекомендую адрес |=1, а не +=1, в этом случае любой из них будет работать.