当前位置: 代码网 > 服务器>网络安全>加密解密 > 缓冲区溢出解密二

缓冲区溢出解密二

2008年10月08日 加密解密 我要评论
缓冲区溢出解密二 而如果ESP被PUSH到堆栈,这是堆栈的表示: |_parametre_I___| EBP 12 |_parametre II__| EBP 8 |_return adress_| EBP 4 |___saved_ESP___| EBP ESP |_loc... 08-10-08

好,让我们看另外一个例子:
b.c :
void f(int a, int b, int c)
{
char foo1[6];
char foo2[9];
}
void main()
{
f(1,2,3);
}
编译并且启动gdb,解析f:
[murat@victim murat]$ gcc -g b.c -o b
[murat@victim murat]$ gdb -q ./b
(gdb) disas f
dump of assembler code for function f:
0x8048440 : pushl 雙
0x8048441 : movl %esp,雙
0x8048443 : subl $0x14,%esp
0x8048446 : leave
0x8048447 : ret
end of assembler dump.
(gdb)
可以看出,从esp中减去了0x14(20字节),尽管foo1和foo2的总长度只有9 6=15。这样的原因是,内存,还有堆栈,在4字节框架下编址。这意味着,你不能简单的push 1字节数据到堆栈中。或者4字节或者为空。 f()北调用时,堆栈将象这样:
|_______$1_______| ebp 16
|_______$2_______| ebp 12
|_______$3_______| ebp 8
|_return address_| ebp 4
|___saved_esp____| ebp esp
|______foo1______| ebp-4
|______foo1______| ebp-8
|______foo2______| ebp-12
|______foo2______| ebp-16
|______foo2______| ebp-20
你可以相信,当我们对f001装载超过8个字节对和对foo2超过12个字节,我们将溢出他们的空间。如果你对foo1写入超过4个字节,你将重写被保护的ebp,而且……如果你写入超过4个字节,你将重写返回地址……而这不正是我们都想要的吗?这是内存溢出的基础……让我设法用一段简单的代码稍微阐明一下这种现象,假设我们有这样的代码:
c.c :
#include
void f(char *str)
{
char foo[16];
strcpy(foo, str);
}
void main()
{
char large_one[256];
memset(large_one, 'a', 255);
f(large_one);
}
[murat@victim murat]$ make c
cc -w -wall -pedantic -g c.c -o c
[murat@victim murat]$ ./c
segmentation fault (core dumped)
[murat@victim murat]$
我们在上面做的是简单的写255字节到一个只能容纳16字节的数组里。我们传递了一个256字节的大数组作为一个参数给f()函数。在函数内部,没有边界检测我们拷贝了整个large_one到foo,溢出了foo和其它数据。因此缓冲区被填写了,同样的strcpy()用a填写了内存的其它部分,包括返回地址。
这里是用gdb生成核文件代码的检查:
[murat@victim murat]$ gdb -q c core
core was generated by `./c'.
program terminated with signal 11, segmentation fault.
find_solib: can't read pathname for load map: input/output error
#0 0x41414141 in ?? ()
(gdb)
可以看出,cpu在eip中看到0x41414141(041是字母a的十六进制ascii码),试图存储和执行此处的指令。然而,0x41414141不是我们的程序被允许存储的内存地址。最后操作系统发了一个sigsegv(segmentation violation)段侵犯信号给程序并且停止了任何进一步的操作。
我们调用f()时,堆栈看起来象这样:
|______*str______| ebp 8
|_return address_| ebp 4
|___saved_esp____| ebp esp
|______foo1______| ebp-4
|______foo1______| ebp-8
|______foo1______| ebp-12
|______foo1______| ebp-16
strcpy()从foo1的开头,ebp-16开始,拷贝large_one到foo,没有边界检查,用a填充了整个堆栈。
现在我们能够重写返回地址,如果我们放一些其它的内存段地址,我们能在那里执行指令码?答案是肯定的。假如我们放了一些 /bin/sh spawn出的指令在一些内存地址中,而我们把这个地址放到我们溢出的这个函数返回地址中,我们就能spawn出一个shell,而且很有可能,既然你已经对setuid二进制程序感兴趣了,我们将spawn出一个root shell。
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com