Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 堆溢出攻击_C_Buffer Overflow - Fatal编程技术网

C 堆溢出攻击

C 堆溢出攻击,c,buffer-overflow,C,Buffer Overflow,我正在学习堆溢出攻击,我的教科书提供了以下易受攻击的C代码: /* record type to allocate on heap */ typedef struct chunk { char inp[64]; /* vulnerable input buffer */ void (*process)(char *); /* pointer to function to process inp */ } chunk_t; void showlen(char

我正在学习堆溢出攻击,我的教科书提供了以下易受攻击的C代码:

/* record type to allocate on heap */
typedef struct chunk {
    char inp[64];            /* vulnerable input buffer */
    void (*process)(char *); /* pointer to function to process inp */
} chunk_t;

void showlen(char *buf)
{
    int len;
    len = strlen(buf);
    printf("buffer5 read %d chars\n", len);
}

int main(int argc, char *argv[])
{
    chunk_t *next;

    setbuf(stdin, NULL);
    next = malloc(sizeof(chunk_t));
    next->process = showlen;
    printf("Enter value: ");
    gets(next->inp);
    next->process(next->inp);
    printf("buffer5 done\n");
}

然而,教科书没有解释如何修复此漏洞。如果有人能解释一下这个漏洞和修复它的方法,那就太好了。(部分问题是我来自Java,而不是C)

代码使用
get
,这因其潜在的安全问题而臭名昭著:无法指定传递给它的缓冲区的长度,它只会一直从
stdin
读取,直到遇到
\n
EOF
。因此,它可能会溢出您的缓冲区,并写入缓冲区之外的内存,然后会发生不好的事情-它可能会崩溃,它可能会继续运行,它可能会开始播放色情


要解决此问题,您应该改为使用。

您可以通过设置
进程的地址,在下一步中填充超过64个字节。因此,人们可以插入自己想要的任何地址。地址可以是指向任何函数的指针


要修复simple,请确保只将63个字节(一个为空)读入数组
inp
-使用
fgets

问题在于
gets()
将一直读入缓冲区,直到它读取换行符或到达EOF。它不知道缓冲区的大小,所以它不知道当它达到极限时应该停止。如果行为64字节或更长,则会超出缓冲区,并覆盖
进程
。如果输入的用户知道这一点,他可以在第64位键入正确的字符,以将函数指针替换为指向他希望进行程序调用的其他函数的指针

修复方法是使用除
get()
之外的函数,因此您可以指定要读取的输入量的限制。而不是

gets(next->inp);
您可以使用:

fgets(next->inp, sizeof(next->inp), stdin);

fgets()
的第二个参数告诉它在
next->inp
中最多写入64个字节。因此,它将从
stdin
读取最多63个字节(需要为空字符串终止符允许一个字节)。

函数get不会限制来自
stdin
的文本量。如果超过63个字符来自
stdin
,则会出现溢出。 gets丢弃LF字符,这将是一个[Enter]键,但它在末尾添加了一个null字符,因此限制为63个字符

如果
inp
处的值填充了64个非空字符,因为它可以直接访问,
showlen
函数将触发访问冲突,因为
strlen
将搜索
inp
之外的空字符以确定其大小

使用
fgets
可以很好地解决第一个问题,但它也会添加一个LF char和null,因此可读文本的新限制为62


对于第二种情况,只需注意在
inp

上写入的内容,您的
inp
是64字节。因此,输入65个字节,您就溢出了…要修复它,@orangesoda这是哪本书?例如,通过输入精心编制的字节序列,很可能是非ascii的,长度为68个字节,您可以用另一个函数的已知地址覆盖函数指针,然后执行该函数(在更大的程序中,例如,office软件包中). 但这与堆没有直接关系,它同样适用于堆栈上的结构。为了做一些特定于堆的事情,您可以将目标数据放在堆上,或者操作存储在内存块之间的簿记信息(但我不确定这将如何做,但会使程序崩溃)