gets() 会忽略'\0'吗?

Does gets() ignore '\0'?

我正在使用此源代码了解缓冲区溢出运行:

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

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

首先,在 gdb 中,我在第 6 行设置断点,在 gets() 函数和 运行 函数之后 r <<< $(python -c 'print "[=18=]"*11 + "AAAA"')

当我探索堆栈时,我意识到它只将 "AAAA" 写入 buf。会发生什么?

(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 ""*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

So the gets() function will not receive the Null character or the stdin will ignore it ?

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" + "[=14=]"*6 + "AAAA"'| ./j_stack 
buf @ 0xffffcfbc
41 41 41 41 00 00 00 00 00 00 41 41 41 41 00 ffffffff

But how do I provide input which contains '[=26=]' to buf in gdb program

不,gets不忽略'[=18=]'

我更改了你的程序以包含

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

调用后 gets。我运行程序就输入

abc\n

看到了

61626300000000000000000000000000

如我所料。然后我运行程序就输入

ab[=13=]c\n

看到了

61620063000000000000000000000000

这也是我所期望的。


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

echo abc | a.out

echo 616200630a | unhex | a.out

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

不,不是。

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

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

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

# echo $(python -c 'print "[=10=]"*11 + "AAAA"') | wc -c
5

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

python -c 'print "[=11=]"*11 + "AAAA"' | ./myProgram