地址 space C 中的布局随机化和结构
Address space layout randomization and structures in C
我有这样的结构:
struct Books {
char title[50];
char author[50];
};
假设我知道如果我将 arg1
传递给程序,在代码的某些部分,它会在 $title+52
方向添加一些字符,所以 author
值被覆盖(缓冲区溢出)。
现在我将 ASLR 添加到我的二进制文件中。这样一来,有些方向是随机的,所以我认为我之前描述的缓冲区溢出是不可能的。
这是真的吗?或者即使我添加 ASLR 结构成员的方向在一起并且缓冲区溢出可能是可能的?
你说的具体溢出还是有可能的。
除位域外,结构的域在内存中按顺序依次排列(中间可能有一些填充)。这在 C standard:
的第 6.7.2.1p15 节中有详细说明
Within a structure object, the non-bit-field members and the
units in which bit-fields reside have addresses that increase in
the order in which they are declared. A pointer to a structure
object, suitably converted, points to its initial member (or
if that member is a bit-field, then to the unit in which it
resides), and vice versa. There may be unnamed padding within
a structure object, but not at its beginning.
因此在这种情况下,author
字段将 始终 跟在 title
字段之后,无论 [=12= 类型的对象的具体地址是什么] 位于。唯一可能的区别可能是填充量,但除非您在结构中添加或删除字段,否则这可能不会改变。
ASLR 不影响编译时的内容。编译器在编译时选择结构的布局,并将其硬编码在生成的目标代码中。
此外,C 标准要求连续的结构成员按照它们在结构定义中出现的顺序在内存中布局(成员之间有未指定的填充,但这在编译时也是固定的)
我认为你误解了ASLR (Address Space Layout Randomization)的作用:ASLR随机排列进程不同虚拟内存区域(可执行文件、堆栈、堆、数据、库等)的位置) 在每次执行中都不同。不改变同一虚拟内存区域中元素的相对位置。
以下面的简单程序为例:
int main(void) {
struct {
char a[10];
char b[10];
} myvar;
printf("a: %p\n", &myvar.a);
printf("b: %p\n", &myvar.b);
return 0;
}
这是程序的虚拟内存,ASLR 禁用:
0x555555554000 0x555555555000 r-xp 1000 0 /home/marco/test/test [executable segment]
0x555555754000 0x555555755000 r--p 1000 0 /home/marco/test/test [read only data]
0x555555755000 0x555555756000 rw-p 1000 1000 /home/marco/test/test [bss (global variables)]
0x7ffffffde000 0x7ffffffff000 rw-p 21000 0 [stack] <-- myvar is here
输出(禁用 ASLR):
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
这是启用了 ASLR 的同一个程序:
0x559fefcbe000 0x559fefcbf000 r-xp 1000 0 /home/marco/test/test [executable segment]
0x559fefebe000 0x559fefebf000 r--p 1000 0 /home/marco/test/test [read only data]
0x559fefebf000 0x559fefec0000 rw-p 1000 1000 /home/marco/test/test [bss (global variables)]
0x7ffe3bb5e000 0x7ffe3bb7f000 rw-p 21000 0 [stack] <-- myvar is here
输出(启用 ASLR):
$ ./test
a: 0x7ffe3bb5e080
b: 0x7ffe3bb5e08a
$ ./test
a: 0x7ff4abdeea80
b: 0x7ff4abdeea8a
$ ./test
a: 0x7efa6b8fa080
b: 0x7efa6b8fa08a
您的变量仍将位于某个连续虚拟内存块内,并且相对位置 的字段根本不会改变。使用 ASLR 时,连续数组仍然是连续的:它们只是从内存中的不同位置开始。
由于 struct
字段在内存中是连续的(并遵循它们的声明顺序),这意味着 缓冲区溢出仍然是一个潜在的问题,即使使用 ASLR。
我有这样的结构:
struct Books {
char title[50];
char author[50];
};
假设我知道如果我将 arg1
传递给程序,在代码的某些部分,它会在 $title+52
方向添加一些字符,所以 author
值被覆盖(缓冲区溢出)。
现在我将 ASLR 添加到我的二进制文件中。这样一来,有些方向是随机的,所以我认为我之前描述的缓冲区溢出是不可能的。
这是真的吗?或者即使我添加 ASLR 结构成员的方向在一起并且缓冲区溢出可能是可能的?
你说的具体溢出还是有可能的。
除位域外,结构的域在内存中按顺序依次排列(中间可能有一些填充)。这在 C standard:
的第 6.7.2.1p15 节中有详细说明Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
因此在这种情况下,author
字段将 始终 跟在 title
字段之后,无论 [=12= 类型的对象的具体地址是什么] 位于。唯一可能的区别可能是填充量,但除非您在结构中添加或删除字段,否则这可能不会改变。
ASLR 不影响编译时的内容。编译器在编译时选择结构的布局,并将其硬编码在生成的目标代码中。
此外,C 标准要求连续的结构成员按照它们在结构定义中出现的顺序在内存中布局(成员之间有未指定的填充,但这在编译时也是固定的)
我认为你误解了ASLR (Address Space Layout Randomization)的作用:ASLR随机排列进程不同虚拟内存区域(可执行文件、堆栈、堆、数据、库等)的位置) 在每次执行中都不同。不改变同一虚拟内存区域中元素的相对位置。
以下面的简单程序为例:
int main(void) {
struct {
char a[10];
char b[10];
} myvar;
printf("a: %p\n", &myvar.a);
printf("b: %p\n", &myvar.b);
return 0;
}
这是程序的虚拟内存,ASLR 禁用:
0x555555554000 0x555555555000 r-xp 1000 0 /home/marco/test/test [executable segment]
0x555555754000 0x555555755000 r--p 1000 0 /home/marco/test/test [read only data]
0x555555755000 0x555555756000 rw-p 1000 1000 /home/marco/test/test [bss (global variables)]
0x7ffffffde000 0x7ffffffff000 rw-p 21000 0 [stack] <-- myvar is here
输出(禁用 ASLR):
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
$ ./test
a: 0x7ffffffde080
b: 0x7ffffffde08a
这是启用了 ASLR 的同一个程序:
0x559fefcbe000 0x559fefcbf000 r-xp 1000 0 /home/marco/test/test [executable segment]
0x559fefebe000 0x559fefebf000 r--p 1000 0 /home/marco/test/test [read only data]
0x559fefebf000 0x559fefec0000 rw-p 1000 1000 /home/marco/test/test [bss (global variables)]
0x7ffe3bb5e000 0x7ffe3bb7f000 rw-p 21000 0 [stack] <-- myvar is here
输出(启用 ASLR):
$ ./test
a: 0x7ffe3bb5e080
b: 0x7ffe3bb5e08a
$ ./test
a: 0x7ff4abdeea80
b: 0x7ff4abdeea8a
$ ./test
a: 0x7efa6b8fa080
b: 0x7efa6b8fa08a
您的变量仍将位于某个连续虚拟内存块内,并且相对位置 的字段根本不会改变。使用 ASLR 时,连续数组仍然是连续的:它们只是从内存中的不同位置开始。
由于 struct
字段在内存中是连续的(并遵循它们的声明顺序),这意味着 缓冲区溢出仍然是一个潜在的问题,即使使用 ASLR。