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
我正在使用此源代码了解缓冲区溢出运行:
#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 theNull
character or thestdin
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=]'
tobuf
ingdb
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