在ARM Cortex-M3上编写一个简单的C任意代码执行漏洞?

sat*_*ine 5 c exploit cortex-m

我正在尝试在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);
}
Run Code Online (Sandbox Code Playgroud)

我希望当我调用攻击函数时,它会将代码复制到堆栈中,跳转到它,打印消息并进入无限循环.但是,我在故障寄存器中使用以下值获得异常:

HFSR = 0x40000000
CFSR = 0x00020000
PSR  = 0x60000000
Run Code Online (Sandbox Code Playgroud)

这似乎是UFSR中的INVSTATE位,表示"非法使用EPSR",我读到的通常是由于BX指令试图跳转到LSB设置为0的地址,处理器将其解释为函数其中包含非Thumb代码,但Cortex-M处理器仅允许Thumb代码.我看到memcpy被赋予了loopit函数的奇数地址,因为我假设编译器正在使用实际内存地址进行ORing 1.所以我认为解决方法是重写我的攻击函数,如下所示:

void attack(void)
{
    uint8_t buffer[64] __attribute__((aligned(4)));
    memcpy(buffer, ((int) loopit) & ~1, sizeof(buffer));
    goto *((void *) ((int) buffer) | 1);
}
Run Code Online (Sandbox Code Playgroud)

但是在这之后我得到了一个与故障寄存器不同的异常:

HFSR = 0x40000000
CFSR = 0x00080000
PSR  = 0x81000000
Run Code Online (Sandbox Code Playgroud)

这似乎没有任何意义,UFSR第3位设置意味着"处理器已尝试访问协处理器".看看PC,这次看起来跳跃成功了,这很好,但后来有些东西掉了轨道,CPU看起来正在执行奇怪的指令,而不是进入无限循环.我尝试在goto之前关闭中断并注释掉printf,但没有运气.有什么问题以及如何使其发挥作用?

A.K*_*.K. 1

很抱歉滥用答案表格,我对您的代码进行了一些修改,并且它从堆栈中闪烁了 LED:

void (*_delay_ms)(uint32_t) = delay_ms;

static void loopit(void)
{
    while (1)
    {
        GPIOC->ODR ^= 1 << 13;
        _delay_ms(125);
    }
}

void attack(void)
{
    volatile uint8_t buffer[64] __attribute__((aligned(4)));
    memcpy(buffer, (void *)((uint32_t) loopit & ~1), sizeof(buffer));
    goto *(void *)((uint32_t) buffer | 1);
}
Run Code Online (Sandbox Code Playgroud)

我想知道我多久会收到关于 UB 的投诉。