randomized layout

在Linux Kernel的结构体声明中,经常会看见最后带了一个_randomizelayout标识。 此标记含义为 : 随机化布局。

地址随机化

栈和 mmap 映射区域并不是从一个固定地址开始,并且每次的值都不一样,这是程序在启动时随机改变这些值的设置,使得使用缓冲区溢出进行攻击更加困难。当然也可以让程序的栈和 mmap 映射区域从一个固定位置开始,只需要设置全局变量 randomize_v a_space 值为 0 ,这个变量默认值为 1

[root@iz2zecj7a5r32f2axsctb9z logs]# sysctl -a | grep randomize
kernel.randomize_va_space = 2

用户可以通过设置 /proc/sys/kernel/randomize_va_space 来停用该特性, 0表示禁用随机化

结构体随机化

不管是地址随机化,还是结构体随机化,其目的都是增强内核安全性。结构体随机化也是GCC编译器的一个重要特性,使能后将在编译时随机排布结构体中元素的顺序,从而使攻击者无法通过地址偏移进行攻击。

结构体随机化在编译时根据随机数种子打乱排布顺序,但一旦编译完成,结构体内容即确定。

只存储函数指针的结构体,是默认开启结构体随机化的,如果不需要,需要添加no_randomize_layout进行排除。另一方面,如果特定结构体希望主动开启保护,需要添加randomize_layout标识

结构体随机化后的差异

  • 既然已经开启了结构体随机化,在进行赋值或初始化时,就需要按照元素名称进行赋值,否则会出现非预期结果。(designated initializers)

  • 不要对开启了随机化的结构体指针或对象进行强制数据转换,因为内存排布是不可预测的。

  • 涉及到远程调用的结构体,如果需要保证结构体内容的一致性,需要添加例外。

  • 调试时,根据dump推算结构体内容将极为麻烦,因为每个版本、每个平台的布局都将不同。

  • 部分以模块形式添加到Kernel中的驱动,为保持结构体一致性,在编译时需要采用与kernel相同的随机数种子,这带来了极大的安全风险

文档更新时间: 2021-03-14 19:18   作者:周国强