6

私は 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 バイトの場合

4

1 に答える 1

6

関数の分解全体を見ないとわかりません。

ただし、私の推測では、 -0xc(%ebp) に保存されている %gs:0x14 は、スタックの破損が検出された場合にクリーンな終了を引き起こすスタック カナリアである可能性があります。したがって、この値は -0xc(%ebp) に保存されます。これは、バッファが実際には 30 バイトしかなく、その後に続くものであることを意味します。

于 2012-06-17T07:51:34.337 に答える