gets()忽略'\ 0'吗?

时间:2016-12-22 15:43:29

标签: c gcc buffer-overflow

我正在学习有关此源代码的缓冲区溢出:

#include <stdio.h>
int main()
{
    char buf[16];
    gets(buf);
    printf("buf @ %8p\n", (void*)&buf);
    return 0;
}

我尝试将Null字符('\ 0')写入buf变量。

首先,在gdb中,我在gets()函数之后的第6行设置断点并使用r <<< $(python -c 'print "\0"*11 + "AAAA"')

运行它

当我探索堆栈时,我意识到它只向buf写了“AAAA”。会发生什么?

(gdb) x/16xw &buf
0xffffcf80: 0x41414141  0xffffd000  0xffffd04c  0x080484a1
0xffffcf90: 0xf7fb43dc  0xffffcfb0  0x00000000  0xf7e1a637
0xffffcfa0: 0xf7fb4000  0xf7fb4000  0x00000000  0xf7e1a637
0xffffcfb0: 0x00000001  0xffffd044  0xffffd04c  0x00000000

但是,当我使用r <<< $(python -c 'print "\1"*11 + "AAAA"')运行该程序时,buf将是:

(gdb) x/16xw &buf
0xffffcf80: 0x01010101  0x01010101  0x41010101  0x00414141
0xffffcf90: 0xf7fb43dc  0xffffcfb0  0x00000000  0xf7e1a637
0xffffcfa0: 0xf7fb4000  0xf7fb4000  0x00000000  0xf7e1a637
0xffffcfb0: 0x00000001  0xffffd044  0xffffd04c  0x00000000
  

因此gets()函数不会收到Null字符,或stdin会忽略它吗?

P / S:我在gcc(Ubuntu 5.4.0-6ubuntu1~16.04.4)5.4.0 20160609上使用gcc -m32 -fno-stack-protector -g stack.c -o stack构建它。

更新:经过一些建议,我试试这个:

#include <stdio.h>
int main()
{
    char buf[16];
    gets(buf);
    printf("buf @ %8p\n", (void*)&buf);
    for (int i = 0; i < 16; ++i) // this is for loop all the buf
    {
        printf("%02x ", buf[i]);
    }
    return 0;
}

适用于'\ 0'

$ gcc -g j_stack.c -o j_stack
$ python -c 'print "AAAA" + "\0"*6 + "AAAA"'| ./j_stack 
buf @ 0xffffcfbc
41 41 41 41 00 00 00 00 00 00 41 41 41 41 00 ffffffff
  

但是如何在'\0'程序中提供包含bufgdb的输入

2 个答案:

答案 0 :(得分:3)

不,它没有。

此行为与gets()或Python字符串无关;这是由于你为程序提供输入的方式,使用子shell和Bash“herestring”语法(performs some manipulations on whatever you give it,显然包括删除空字节):

# python -c 'print "\0"*11 + "AAAA"' | wc -c
16
# python -c 'print "\0"*11 + "AAAA"' | hexdump
0000000 0000 0000 0000 0000 0000 4100 4141 0a41
0000010

# cat <<< $(python -c 'print "\0"*11 + "AAAA"') | wc -c
5
# hexdump <<< $(python -c 'print "\0"*11 + "AAAA"')
0000000 4141 4141 000a
0000005

# echo $(python -c 'print "\0"*11 + "AAAA"') | wc -c
5

如果使用简单的管道运行程序,您应该看到预期的结果:

python -c 'print "\0"*11 + "AAAA"' | ./myProgram

答案 1 :(得分:2)

不,gets不会忽略'\0'

我将您的计划更改为

for(i = 0; i < 16; i++) printf("%02x", buf[i]);
printf("\n");

致电gets后。我在输入

上运行程序
abc\n

并看到了

61626300000000000000000000000000

正如我所料。然后我在输入

上运行程序
ab\0c\n

并看到了

61620063000000000000000000000000

这也是我的预期。

P.S。我不确定你为什么看到你所做的行为,但我承认我不确定你在使用<<<和那些python片段做什么。我,我用了

echo abc | a.out

echo 616200630a | unhex | a.out

其中unhex是我在bin目录中的一个小程序,好吧,显而易见。