堆栈随机化是一项安全增强,它允许对系统调用发生时,内核使用的堆栈添加一个随机偏移。这给基于stack的攻击增加了难度,因为stack攻击通常要求stack有个固定的layout。现在每次系统调用,stack的layout都变化的话,攻击就无规律可寻了。
首先以系统调用为主线,看一下Linux内核ARM64架构堆栈随机化的实现方式:
在ARM64上,主要在系统调用的链条中增加了invoke_syscall()这个函数来实现堆栈随机化:
linux-5.4.175未增加堆栈随机化的实现:
linux-5.16.4增加堆栈随机化的实现:
我们模仿上面的逻辑,写一个demo来分析其原理:
#include <stdio.h>
#include <stdlib.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
int __attribute__((noinline)) bar(void)
{
unsigned int abc = 0;
DBG("stack var addr %p.", &abc);
return 0;
}
int __attribute__((noinline)) foo(void)
{
int offset = rand()%256;
void *ptr = __builtin_alloca(offset);
bar();
return 0;
}
int main(void)
{
int i = 0;
for(i = 0; i < 10; i ++)
{
DBG("loop %d.", i);
foo();
}
return 0;
}
去掉随机化之后,和上面对比,你会发现,堆栈地址在每次调用是都保持了不变。