我是网络安全的新手,我试图理解为什么以下代码容易受到堆溢出攻击......
struct data {
char name[128];
};
struct fp {
int (*fp)();
};
void printName() {
printf("Printing function...\n");
}
int main(int argc, char **argv) {
struct data *d;
struct fp *f;
d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
f->fp = printName;
read(stdin,d->name,256);
f->fp();
}
是因为read(stdin, d->name, 256)
因为128
中的char name
读取的struct data
缓冲区大小超过heap overflow attack?
任何帮助都会很棒
buffer overflow attack类似于d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));
,除了不覆盖堆栈中的值,攻击者践踏堆中的数据。
请注意,在代码中有两个动态分配的值:
d
所以f
现在保存堆中128字节内存块的地址,而f->fp = printName;
保存8字节(假设64位机器)内存块的地址。从理论上讲,这两个地址可能无处可靠,但由于它们都相对较小,因此操作系统可能会分配一大块连续内存,并为您提供彼此相邻的指针。
所以一旦你运行 | |
+------------------------+
f -> | <Address of printName> |
+------------------------+
| ▲ |
| 11 more rows |
| not shown |
| |
d -> | <Uninitialized data> |
+------------------------+
| |
,你的堆看起来像这样:
注意:每行宽8个字节
d
您对漏洞来源的初步评估是正确的。 d
指向128字节的内存,但是让用户将256字节写入该区域。 C没有边界检查的机制,所以编译器非常乐意让你写出f
内存的边缘。如果d
就在d
旁边,那么你将落在f
的边缘并进入f
。现在,攻击者只需写入d
即可修改d
的内容。
为了利用此漏洞,攻击者通过重复输入所有256字节的输入来提供他们写入0xbadc0de
的一些代码的地址。如果攻击者在地址0xbadc0de
上存储了一些恶意代码,则会将 | 0xbadc0de |
+-------------+
f -> | 0xbadc0de |
+-------------+
| ... |
| 0xbadc0de |
| 0xbadc0de |
d -> | 0xbadc0de |
+-------------+
| |
提供给stdin 32次(256字节),以便堆被覆盖。
f->fp();
然后,您的代码到达该行
f
这是使用存储在f
中的地址的函数调用。机器进入内存位置arbitrary code execution并检索存储在那里的值,该值现在是攻击者恶意代码的地址。由于我们将其称为函数,机器现在跳转到该地址并开始执行存储在那里的代码,现在你手上有一个可爱的qazxswpoi攻击向量。