10

基本的に私が利用している機能はこれです:

int getbufn()
{
     char buf[512];
     Gets(buf);
     return 1;
}

メインプログラムを実行すると、関数は5回実行され、bufの場所が変わるたびに、%ebpの場所も変わります。私がすることになっているのは、特定の16進値(たとえば0xFFFFFFFF)を変数に配置することです。メインプログラムは、その変数が存在するかどうかを毎回チェックします。そうである場合は、5回すべてが完了し、プログラムが静かに終了するまで、再度実行されます。

私が抱えている問題は、16進値のチェックの直前に、定数である別の値、たとえば0x12345678のチェックがあることです。0x12345678が破損していて、そこにない場合、プログラムが爆発します。

0x12345678が-0x10(%ebp)に格納されていることがわかったので、%ebpに基づいており、毎回%ebpのアドレスを知っていますが、エクスプロイトを機能させることができるのは初めてです。これを行うには、基本的に496バイトをnopsledし、このマシンコードをバイト形式にします。

mov  0xFFFFFFFF, %eax
movl address old ebp, %ebp
push correct return adress in function main
ret

これは最終的に5ワードになり、リターンロングのバイトになります。これを0x313131で埋めて、6ワードの長さにします。この時点で、私のエクスプロイト文字列は520バイトの長さであり、これはバッファが%ebpを下回っている正確な量です。したがって、古いebpのアドレスと、nopsled内のどこかにアドレスを追加して、%ebpの現在の値とリターンを上書きします。 getbufnのアドレス。

問題は、プログラムが2回目に実行されるときに、%ebpが前のアドレスよりも0x10低いアドレスにあるため、%ebpを破損しない方法が機能せず、mainが0x12345678が-0x10(%ebp)にないことを検出することです。%ebpを破損しないようにするにはどうすればよいですか?

4

1 に答える 1

5

pmjordanは正しいです。%ebpが%espとの関係でどこにあるかを計算できるはずです。%espは現在のスタックポインターであり、%ebpは前の関数のスタックポインターがあった場所であることを忘れないでください。静的な%ebpを使用する代わりに、%espから計算された動的な%ebpを使用する必要があります(または、実際には、スタック変数によってオフセットされた%espにあるメモリに格納されているものを確認するだけです)。擬似コードは次のようになります。

  1. %espから%ebpのオフセットを計算します
  2. そのメモリ位置に保存されている値を読み取り、自分で保存します
  3. エクスプロイトを行う
  4. 手順2で保存された%ebpの古い値を復元します
  5. ret
于 2011-11-29T04:29:34.183 に答える