2

バッファオーバーフローで遊んでみます。ここで eip の値で何が起こっているのかわかりません。

Cコードは次のとおりです。

void copy(char *arg) {
  char msg[256];
  strcpy(msg,arg);
}

それのためのアセンブリ:

0x804847d <copy+25>:    call   0x8048368 <strcpy@plt>
0x8048482 <copy+30>:    leave  
0x8048483 <copy+31>:    ret    

「 _ \xAA\xBB\xCC\xDD」のような文字列を引数として入力し、最後の4バイトが$ebp以降の4バイトになるようにサイズを計算して入力します(実際のリターンアドレスを上書きするため)。そしてそれはうまくいくようです。

gdb で:

(break before strcpy)
x/2wx $ebp
0xbffffb38: 0xbffffb58  0x080484d2
n
(just after strcpy execution)
x/2wx $ebp
0xbffffb38: 0x80cdd189  0x080484b6
...
n
...
x/2wx $ebp
0xbffffb38: 0x80cdd189  0x080484b6

したがって、リターンアドレスは0x080484d2で、オーバーフローした後は0x080484b6です。これが私が望むものです。しかし、プログラムは終了します:「アドレス0x80cdd18dのメモリにアクセスできません」。

なぜ $eip が自分のアドレスに設定されなかったのかはわかりません。コードのアドレスが 0x08048 にあるためです... $ebp+4 がリターン アドレスを含む場所であると確信しています。

4 バイト小さい文字列でもう一度試してみたところ、今度は $ebp+4 ではなく $ebp が上書きされ、返された後、$eip は $ebp+4 に含まれる値に設定されました。

説明はありますか?

4

2 に答える 2

1

わかりました、ありがとう@Wumpus Q. Wumbley、これは私が物事を理解するのに役立ちました.

ジャンプnextをしてleaveret完全に。retは変更される命令でeipあり、 と同等でなければなりませんpop eip。ただしleave、スタックポインターespとそのebp前を変更します(特に、ebp + 4を上書きするときにebpに含まれる値を変更するため)

TLDR : ebp で値を上書きしないと、正常に機能します。

于 2013-11-03T20:12:33.420 に答える
0

これが x86 の場合 (x86-64 とは対照的に)、通常の関数プロローグでは、プッシュebpしてから の値を割り当てますesp。これにより、リターン アドレスはスタックの に残されebp+4ます。

関数の逆アセンブリを見て、最初の命令が次のようになっているかどうかを確認します。

pushl   %ebp
movl    %esp, %ebp

もしそうなら、これがオフセットの原因です。

于 2013-11-03T19:12:45.983 に答える