我正在学习有关此源代码的缓冲区溢出:
#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'
程序中提供包含buf
到gdb
的输入
答案 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目录中的一个小程序,好吧,显而易见。