扫描溢出("%8s",字符串)?

Fig*_*igo 4 c scanf buffer-overflow

我知道溢出普通代码是可能的:

char string [9];

scanf("%s",string).

但是有可能溢出scanf("%8s",字符串)?图8只是一个例子.

我知道"%8s"的作用类似于分隔符,但我也注意到当我输入超过8个字符的字符串时,程序将因以下原因而终止:

*堆栈粉碎检测*:./a.out终止

======= Backtrace:=========

...

显然,有一个标志可以检测GCC默认启用的堆栈粉碎.由于这是一个堆栈粉碎,我的猜测是仍然可以溢出并执行任意代码.

与正常溢出相反,会破坏scanf的调用者("%s"),如果scanf("%8s")可能溢出,它将在scanf函数内溢出,以便当scanf尝试返回时,获得控制权.

但是scanf是一个需要模式切换的系统调用(从用户模式切换到内核模式),并且在内部它会调用诸如read之类的东西到stdin等.所以不确定我们是否可以在内核模式或其他东西溢出.

欢迎评论!!

更新>>

在上面的例子中假设了char字符串[9].以下实际代码中的字符串[8].

问题实际上是关于安全扫描("%8s")和GCC流产之间由于堆栈粉碎而看似矛盾的故事.

简化代码:

void foo(pass some pointer) {
char input[8];
int input_number = 0;

while (1) { // looping console
   printf some info;
   scanf("%8s", input);

   input_number = atoi(input);

   if ((strlen(input) == 1) && (strncmp(input, "q", 1) == 0)) {
       input_number = -1;
   }
   switch (input_number) {
       case -1: to quit the console if input = 'q';
       default: to print info that pointer refers to;
       ...
   } 

}

}
Run Code Online (Sandbox Code Playgroud)

注意:

  1. foo被别人叫.
  2. 虽然字符串是实际代码中的8个字节,带有"%8s",但我认为这不会导致粉碎.

yst*_*sth 8

http://www.opengroup.org/onlinepubs/009695399/functions/scanf.html:

每个指令由下列之一...一个可选的非零十进制整数,指定最大场的宽度.

s
匹配不是空格字符的字节序列.应用程序应确保相应的参数是指向char,signed char或unsigned char数组的初始字节的指针,其大小足以接受序列和终止空字符代码,这些代码应自动添加.

所以它不会溢出9字节的字符串缓冲区.