我一直在阅读The Shellcoder's Handbook (2e),并一直试图重现第18-23页的堆栈溢出实验。
我有这个代码
void return_input (void)
{
char array[30];
gets (array);
printf(“%sn”, array);
}
main()
{
return_input();
return 0;
}
编译:gcc -fno-stack-protector -o overflow overflow.c
main函数的汇编代码转储:
0x080483ea <main+0>: push %ebp
0x080483eb <main+1>: mov %esp,%ebp
0x080483ed <main+3>: call 0x80483c4 <return_input>
0x080483f2 <main+8>: mov $0x0,%eax
0x080483f7 <main+13>: pop %ebp
0x080483f8 <main+14>: ret
我们可以用return_input()
的调用地址覆盖保存的返回地址
$ printf
"AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDxedx83x04x08" | ./overflow
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDí
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDò
这将导致我们的输入被打印两次。但是,没有提示我第二次输入。第二次呼叫return_input()
不应该导致第二次呼叫gets()
吗?
这可能与gets()从stdin读取的内容有关。
稍微修改过的程序版本:
#include <stdio.h>
int n = 1;
void return_input(void)
{
char array[30];
gets (array);
printf("%sn", array);
if (n--) return_input();
}
int main(void)
{
return_input();
return 0;
}
如果我只是运行它,我可以输入2个短字符串(每个后跟回车键),像这样:
C:gets.exe
qwe
qwe
123
123
这里qwe和123都在屏幕上重复出现(第一次是在我输入它们时,第二次是在它们被打印时)。
当我在Windows上使用echo命令管道程序输入时,我得到了以下内容,没有机会输入第二个字符串,gets()在第二次调用时不知何故设法获得垃圾作为输入:
C:echo qwe|gets.exe
qwe
№ ☺
所以,gets()读取管道输入的方式有问题,这与堆栈溢出无关。