首页 > 解决方案 > C中自发的缓冲区溢出

问题描述


我想知道是否有可能以编程方式生成缓冲区溢出,我的意思是,无需任何用户输入。

我一直在尝试使用该memcpy函数导致缓冲区溢出,将缓冲区的内容复制到另一个较小的缓冲区中。现在,分段错误仅在源缓冲区初始化时触发,如下所示:

char * overflow = "\x40\40\x40...";

或者:

char * overflow = {"\x40\40\x40..."};

如果我将此缓冲区复制到另一个较小的变量中,它会成功溢出。但是这种声明使源缓冲区只读,所以我想知道是否可以动态生成缓冲区的内容,例如,程序可以在运行时生成一个缓冲区,可以将指令指针重定向到某个内存地址也在运行时计算。所以我尝试将其更改为:

char overflow[] = {"\x40\x40\x40\x40..."}

但是,由于某种我不太了解的原因,无论缓冲区有多长,此声明都不会触发分段错误。

为什么只读常量字符串可以触发缓冲区溢出,而变量不能?

这是我正在使用的代码:

int WINAPI mainCRTStartup(){
  char buffer[100];
  char * overflow = {   "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x64\x63\x62\x61\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
    "\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40\x40"
  };

  printf("Ready:\n");
  // 117
  memcpy(buffer, overflow, 117);
  //strcpy(buffer, overflow);
  printf("String: %s\n", buffer);
  return 0;
}

我编译它:

i686-w64-mingw32-gcc -O2 -s -DNDEBUG -static \
    -nostdlib -m32 \
    -o deleteme.exe deleteme.c \
    -lkernel32 -lmsvcrt -fno-stack-protector

此代码成功地将指令指针设置为地址 0x61626364。
我知道这可能没有任何实际用途,我只是对这种行为感到好奇。

标签: c

解决方案


当您使用char overflow[]时,数组的内存与overflow位于同一堆栈帧中buffer,并且它可能位于它之后。因此,当您超出 的范围时buffer,您将回写到overflow,而不是覆盖堆栈帧中的返回地址字段。

制作它static char overflow[],或制作overflow一个全局变量。然后它不会在堆栈帧中。您也可以尝试更改两个变量声明的顺序。


推荐阅读