我正在尝试用 C 语言编写概念验证,演示从 ARM Cortex-M3 堆栈中的内存缓冲区执行代码。这将有助于证明正确使用 ARM MPU 可以防止此类攻击。我认为将一些代码放入堆栈的一种快速而肮脏的方法是从常规函数复制它,然后使用 goto 跳转到它,如下所示:
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);
}
我希望当我调用攻击函数时,它会将代码复制到堆栈中,跳转到堆栈,打印消息并进入无限循环。然而,我却得到了一个异常,故障寄存器中包含以下值:
HFSR = 0x40000000
CFSR = 0x00020000
PSR = 0x60000000
这似乎是 UFSR 中的 INVSTATE 位,它指示“非法使用 EPSR”,我读到的这通常是由于 BX 指令试图跳转到 LSB 设置为 0 的地址,处理器将其解释为函数其中包含非 Thumb 代码,但 Cortex-M 处理器只允许 Thumb 代码。我看到 memcpy 被赋予了一个奇怪的地址loopit
函数,因为我假设编译器正在将实际内存地址与1
。所以我认为的修复方法是重写我的攻击函数,如下所示:
void attack(void)
{
uint8_t buffer[64] __attribute__((aligned(4)));
memcpy(buffer, ((int) loopit) & ~1, sizeof(buffer));
goto *((void *) ((int) buffer) | 1);
}
然而,在这样做之后,我得到了一个与故障寄存器不同的异常:
HFSR = 0x40000000
CFSR = 0x00080000
PSR = 0x81000000
这似乎没有任何意义,UFSR 位 3 设置意味着“处理器已尝试访问协处理器”。这次看看 PC,似乎跳转成功了,这很好,但随后有些东西脱离了轨道,CPU 似乎正在执行奇怪的指令,并且没有进入无限循环。我尝试在 goto 之前关闭中断并注释掉 printf 但没有成功。知道出了什么问题以及如何让它发挥作用吗?