11

スタックオーバーフローを制御しようとしています。gcc -fno-stack-protector -ggdb -o first first.cまず、x32 VM Linux ( ) でコンパイルした C コードの例を次に示します。

#include "stdio.h"

int CanNeverExecute()
{
    printf("I can never execute\n");
    return(0);
}

void GetInput()
{
    char buffer[8];

    gets(buffer);
    puts(buffer);
}

int main()
{
    GetInput();
    return(0);
}

次に、デバッガー (Intel フレーバー): 関数のアセンブラー コードのダンプGetInput:

0x08048455 <+0>:    push   ebp
0x08048456 <+1>:    mov    ebp,esp
0x08048458 <+3>:    sub    esp,0x28
0x0804845b <+6>:    lea    eax,[ebp-0x10]

ここで、sub esp、0x28 がバッファ変数用に 40 バイトを予約していることがわかります (そうですか?)。 CanNeverExecutefunction は address にあります0x0804843c。したがって、CanNeverExecute関数を実行するには、40 バイトをバッファー変数に入れる必要があります。次に、格納されたベース ポインター用に 8 バイト、変更したいリターン ポインター用に 8 バイトを使用します。

したがって、48 個の ASCII 記号と\x3c\x84\x04\x08末尾 (CanNeverExecute関数のアドレス) の文字列が必要です。それは理論上です。しかし実際には、リターン ポインターのアドレスの前に 20 バイトしか必要ありません。

~/hacktest $ printf "12345678901234567890\x3c\x84\x04\x08" | ./first
12345678901234567890..
I can never execute
Illegal instruction (core dumped)

48 バイトではなく 20 バイトしか必要ないのはなぜですか? 私の間違いはどこですか?

4

2 に答える 2

9

まず、アセンブリは 32​​ ビットです。保存された EBP と戻りアドレスはそれぞれ 4 バイトです。

第 2 に、buffer変数はスタック トップ (ESP) で開始されず、ebp-0x10 で開始されます。これは、戻りアドレスから 20 バイト離れています。0x10 は 16 バイトで、保存された EBP 用にさらに 4 バイトです。

于 2013-03-12T21:38:40.040 に答える
2

逆アセンブルの大部分を行うと、次のように表示されます。

08048445 <GetInput>:
8048445:    55                      push   %ebp
8048446:    89 e5                   mov    %esp,%ebp
8048448:    83 ec 28                sub    $0x28,%esp
804844b:    8d 45 f0                lea    -0x10(%ebp),%eax
804844e:    89 04 24                mov    %eax,(%esp)
8048451:    e8 9a fe ff ff          call   80482f0 <gets@plt>
8048456:    8d 45 f0                lea    -0x10(%ebp),%eax
8048459:    89 04 24                mov    %eax,(%esp)
804845c:    e8 9f fe ff ff          call   8048300 <puts@plt>
8048461:    c9                      leave  
8048462:    c3                      ret   

ebp が保存され、esp が ebp に移動され、esp から 40 が減算されます (スタック フレーム、あなたが書いたように) が、バッファーへのポインターが eax レジスター経由で get に渡され、eax は ebp-0x10 で読み込まれます!

lea    -0x10(%ebp),%eax

したがって、バッファをオーバーフローさせるのに 20 バイトしか必要ありません (16 予約済み + 32 ビット システムの格納されたベース ポインタ用に 4)

于 2013-03-12T22:03:29.793 に答える