C语言 为什么以下代码容易受到堆溢出攻击



我是网络安全新手,我试图理解为什么以下代码容易受到堆溢出攻击......

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超过struct datachar name分配的缓冲区大小吗?

任何帮助都会很棒

堆溢出攻击类似于缓冲区溢出攻击,不同之处在于攻击者不会覆盖堆栈中的值,而是践踏堆中的数据。

请注意,在代码中有两个动态分配的值:

d = malloc(sizeof(struct data));
f = malloc(sizeof(struct fp));

因此,d现在在堆中保存 128 字节内存块的地址,而f保存 8 字节(假设是 64 位计算机)内存块的地址。从理论上讲,这两个地址可能彼此不靠近,但由于它们都相对较小,因此操作系统可能会分配一个较大的连续内存块,并为您提供彼此相邻的指针。

所以一旦你运行f->fp = printName;,你的堆看起来像这样:

注意:每行宽 8 个字节

|                        |
+------------------------+
f -> | <Address of printName> |
+------------------------+
|           ▲            |
|      11 more rows      |
|       not shown        |
|                        |
d -> |  <Uninitialized data>  |
+------------------------+
|                        |

您对漏洞来源的初步评估是正确的。d指向 128 字节的内存,但您允许用户将 256 字节写入该区域。C 没有边界检查机制,因此编译器非常乐意让您写过d内存的边缘。如果f就在d旁边,你会从d的边缘掉下来,掉进f。现在,攻击者只需写入d即可修改f的内容。

为了利用此漏洞,攻击者通过对所有 256 字节的输入重复输入来提供他们写入d的某些代码的地址。如果攻击者在地址0xbadc0de存储了一些恶意代码,他们会向 stdin 输入 32 次0xbadc0de(256 字节),以便堆被覆盖。

|  0xbadc0de  |
+-------------+
f -> |  0xbadc0de  |
+-------------+
|     ...     |
|  0xbadc0de  |
|  0xbadc0de  |
d -> |  0xbadc0de  |
+-------------+
|             |

然后,您的代码到达该行

f->fp();

这是使用存储在f中的地址的函数调用。计算机转到内存位置f并检索存储在那里的值,该值现在是攻击者恶意代码的地址。由于我们将其调用为函数,因此机器现在跳转到该地址并开始执行存储在那里的代码,现在您手上有一个可爱的任意代码执行攻击媒介。

相关内容

  • 没有找到相关文章

最新更新