私は 1 つのスタック オーバーフローの例で遊んでいます。この例は次のようになります。
void return_input (void){
char array[30];
gets (array);
printf("%s\n", array);
}
main() {
return_input();
return 0;
}
このコードはすべて、overflow.c というファイルにあります。return_inputという脆弱な関数があり、特に 30 バイトの char 配列です。私はそれをコンパイルし、 gdbで脆弱な関数を開き、次の出力を得ました:
(gdb) disas return_input
0x08048464 <+0>: push %ebp
0x08048465 <+1>: mov %esp,%ebp
0x08048467 <+3>: sub $0x48,%esp
0x0804846a <+6>: mov %gs:0x14,%eax
0x08048470 <+12>: mov %eax,-0xc(%ebp)
0x08048473 <+15>: xor %eax,%eax
0x08048475 <+17>: lea -0x2a(%ebp),%eax
0x08048478 <+20>: mov %eax,(%esp)
0x0804847b <+23>: call 0x8048360 <gets@plt>
0x08048480 <+28>: lea -0x2a(%ebp),%eax
0x08048483 <+31>: mov %eax,(%esp)
0x08048486 <+34>: call 0x8048380 <puts@plt>
0x0804848b <+39>: mov -0xc(%ebp),%eax
0x0804848e <+42>: xor %gs:0x14,%eax
0x08048495 <+49>: je 0x804849c <return_input+56>
0x08048497 <+51>: call 0x8048370 <__stack_chk_fail@plt>
0x0804849c <+56>: leave
0x0804849d <+57>: ret
End of assembler dump.
関数のプロローグからわかるように、ローカル変数用にスタックに hex48 (dec 72) バイトを予約しました。最初に、脆弱な配列がスタック上で始まるアドレスを見つけようとしていました。-0x2a(%ebp) だと思いますが、そうですか? Hex2a は 10 進数で 42 です。私が理解しているように、スタックに保存された EBP を上書きし始める前に、安全に 42 バイトを書き込むことができるということです。しかし、この例を実行すると、セグメンテーション違反が発生するのは 37 バイトだけで十分です。
rustam@rustam-laptop:~/temp/ELF_reader$ ./overflow
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault (core dumped)
バッファをオーバーフローさせるのに37バイトで十分ですか? ローカルの char 配列が保存された EBP から -42 バイトの場合