曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 9695|回复: 0
打印 上一主题 下一主题

段错误与堆栈溢出

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2010-11-16 12:50:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
段错误的产生一般是:

1. 用户程序访问一个虚拟地址,MMU 对这个地址进行检查,确定无权访问。

2. MMU 产生异常,CPU 从用户模式切换到特权模式,然后跳转到内核代码中执行异常服务程序。

3. 内核将这个异常解释为段错误,并把引发异常的进程终止掉。

下面的程序会产生段错误:
#include <stdio.h>
void return_input (void)
{
char array[30];
gets (array);
printf ("%s
", array);
}
int main()
{
return_input();
return 0;
}

编译程序方法:
# cc -mpreferred-stack-boundary=2 -g stack.c -o stack
/tmp/ccgRJGyd.o: In function `return_input':
/root/shellcode/stack.c:7: warning: the `gets' function is dangerous and should not be used.

使用 -mpreferred-stack-boundary=2 选项表示优先栈边界编译,这里 2 表示栈以双字节为单位递增或递减,在 x86 体系结构里,堆栈是递减的。
程序编译后,可以生成可执行文件,但有警告 gets() 是个不安全的函数,它的不安全在于它是不对边界进行检查的,但这里正是想利用这个函数进行栈溢出的研究。

下面运行程序使发生段错误:

[root@centos shellcode]# ./stack
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
段错误

程序里,数组只能容纳 30 个字符,但我们输入了 40 个字符,越界后会发生的段错误预示着什么呢?在调试里查明这它。

(gdb) disas return_input
Dump of assembler code for function return_input:
0x080483d4 <return_input+0>:    push   %ebp
0x080483d5 <return_input+1>:    mov    %esp,%ebp
0x080483d7 <return_input+3>:    sub    $0x24,%esp
0x080483da <return_input+6>:    lea    -0x1e(%ebp),%eax
0x080483dd <return_input+9>:    mov    %eax,(%esp)
0x080483e0 <return_input+12>:   call   0x80482c4 <[email=gets@plt]gets@plt[/email]>   # 这里调用了 gets() 函数
0x080483e5 <return_input+17>:   lea    -0x1e(%ebp),%eax
0x080483e8 <return_input+20>:   mov    %eax,(%esp)
0x080483eb <return_input+23>:   call   0x80482e4 <[email=puts@plt]puts@plt[/email]>
0x080483f0 <return_input+28>:   leave
0x080483f1 <return_input+29>:   ret  # 这里 return_input 函数返回
End of assembler dump.

对于上面的汇编代码,分别在 0x080483e0 和 0x080483f1 下断点:

(gdb) break *0x080483e0
Breakpoint 1 at 0x80483e0: file stack.c, line 7.
(gdb) break *0x080483f1
Breakpoint 2 at 0x80483f1: file stack.c, line 9.

继续运行程序,程序会落在第一个断点处,在接受我们的输入后,会继续走到第二个断点处:

(gdb) run
Starting program: /root/shellcode/stack
Breakpoint 1, 0x080483e0 in return_input () at stack.c:7
7               gets (array);

不忙往下走输入数据,先看一下 main() 函数的代码和栈布局。
main() 函数汇编代码

(gdb) disas main
Dump of assembler code for function main:
0x080483f2 <main+0>:    push   %ebp
0x080483f3 <main+1>:    mov    %esp,%ebp
0x080483f5 <main+3>:    call   0x80483d4 <return_input>
0x080483fa <main+8>:    mov    $0x0,%eax
0x080483ff <main+13>:   pop    %ebp
0x08048400 <main+14>:   ret
End of assembler dump.

栈布局

(gdb) x/20x $esp
0xbfffcc8c:     0xbfffcc92       0x0012d175      0xbfffcd4c          0xbfffccb8
0xbfffcc9c:     0x00258ff4      0x00d50600      0x08048420      0x00000000
0xbfffccac:     0x00258ff4      0xbfffccb8          0x080483fa       0xbfffcd18
0xbfffccbc:     0x00116e9c     0x00000001      0xbfffcd44          0xbfffcd4c
0xbfffcccc:     0x00d5e810     0x00000000      0x00000001      0x00000001

上面的堆栈内容中,0xbfffccb8 是保存的 EBP,0x080483fa 正是 return_input() 返回的地址,也就是它的下一条指令。关于堆栈布局方面的内容参考:http://www.groad.net/bbs/read.php?tid-2602.html

现在可以执行上面的程序了:

(gdb) c
Continuing.
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
Breakpoint 2, 0x080483f1 in return_input () at stack.c:9
9       }

这时候,来到了第二个断点处,也就是 ret 指令,如果一切正常,它会返回到上面的 0x080483fa 这个地址处!现在再看一下栈上的情形:

(gdb) x/20x 0xbfffcc8c
0xbfffcc8c:     0xbfffcc92      0x4141d175      0x41414141      0x41414141
0xbfffcc9c:     0x42424242      0x42424242      0x43434242      0x43434343
0xbfffccac:     0x43434343      0x44444444      0x44444444      0xbf004444
0xbfffccbc:     0x00116e9c      0x00000001      0xbfffcd44      0xbfffcd4c
0xbfffcccc:     0x00d5e810      0x00000000      0x00000001      0x00000001

唉哟,原来的返回地址 0x080483fa 不见了!取而代之的是 0x44444444 --- 正是大写字符 DDDD 十六进制形式。到了这里,我们知道,MMU 经过检查此地址发现这个地址对于我们这个应用程序是无权访问的,所以触发了段错误!

综上可见,这就是栈溢出!对于这样的溢出,或许是可以搞点事情的。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-2 22:57 , Processed in 0.083319 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表