You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

栈内存读取与缓冲区溢出疑问:为何未读到相邻buf2的值?

问题描述

我写了一段带缓冲区溢出漏洞的代码,当输入小于16的参数时,程序会输出超出预期的内容。我定义了三个栈上的缓冲区buf、buf2和buf3,认为它们是连续存储的,但程序输出的是随机值而非我预期的buf2的值(我本以为能得到buf2里的1)。试了不同输入值,程序始终输出全0,这是为什么?栈上的缓冲区难道不是连续的吗?

附代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 16

unsigned char *isThisVulnerable(unsigned char* src, int size)
{
    unsigned char* retval = (unsigned char*)malloc(size*sizeof(unsigned char));
    return memcpy((void*)retval, (const void*)src, (size_t)size);
}

int main(int argc, char **argv)
{
    int size = SIZE, i = SIZE, k = 0;
    if(argc > 1)
    {
        size = atoi(argv[1]);
    }

    unsigned char buf2[size];
    unsigned char buf[size];
    unsigned char buf3[size];

    for(k=0;k<size;k++){
        buf[k] = 0;
        buf2[k] = 1;
        buf3[k] = 2;
    }
    
    unsigned char *result = (unsigned char*)isThisVulnerable(buf, i);
    printf("%02X", result[0]);
    for(k=1;k<i;k++)
    {
        if(k%16 == 0)
            printf("\n");
        else if(k%4 == 0)
            printf("\t");
        printf("%02X", result[k]);
    }
    printf("\n\n");
    return 0;
}
问题分析与解答

1. 你没触发栈上的缓冲区溢出

你的代码里所谓的“溢出”根本不是发生在栈上。isThisVulnerable函数是用malloc在堆上分配内存,然后把buf的内容拷贝过去——当你传入小于16的size时,memcpy会从buf开始拷贝16字节,这时候溢出的是堆上的retval缓冲区,和栈上的buf2完全不沾边。你打印的是堆上的result内容,自然看不到buf2的值。

2. 栈上变量的存储顺序无保证

就算你真的在栈上做溢出,栈上局部变量的排列顺序也不是你想的那样。C标准没有规定局部变量在栈上的存储顺序,编译器会根据优化规则、内存对齐要求调整顺序,甚至可能在变量之间插入填充字节。你定义的buf2、buf、buf3,实际在栈上可能是反向排列,或者中间隔了空字节,完全没法按“连续相邻”来假设。

3. 输出全0只是巧合

当size小于16时,buf只有前size个字节是0,后面的字节是栈上的未知数据。memcpy把这些数据拷贝到堆上的result里,你看到全0只是因为buf后面的栈区域刚好是0(可能是栈帧初始化后的残留值),这是环境相关的巧合,换个编译器或系统就会输出随机值。而buf2的数据根本没被拷贝过来,因为它和buf在栈上的位置不一定相邻,就算相邻,顺序也可能和你想的相反。

4. 测试栈溢出的正确方式

如果想测试栈上的缓冲区溢出,得直接操作栈上的缓冲区。比如在main里定义一个固定大小的数组,然后用memcpy往里面写超过它长度的数据,或者修改isThisVulnerable让它直接操作栈上的变量。但要注意,这种行为属于C语言的未定义行为,不同环境下结果差异极大,甚至可能直接崩溃。

内容的提问来源于stack exchange,提问作者cipos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 01:47:43