CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(3)
2015-06-01 19:46
645 查看
Level1
Level1是和level0一样调用完getbuf以后我们不返回getbuf的调用者test而是去执行fizz函数,区别就是这个fizz函数要求我们传入参数,而且传入的参数必须是我们的cookie。所以在level0的方法我们轻松的知道了如何去执行fizz,就是用fizz函数的入口地址去覆盖返回地址,这里的关键就是找到fizz函数的参数从栈中的什么地方传入的,然后我们把我们的cookie写进这个fizz会获取参数的地方。一般参数都是从调用者的栈传到被调用者的栈中的,由实参传递给函数的形参,在我的文章底层实现理解函数传参,实参,形参中有讲解,可以去看看。
首先我们来看看一般函数调用的传参的底层汇编代码是实现:图片就是我之前那个文章中的图:为了方便就直接分析这个好了。可以看出一般函数的实参都是从栈顶指针开始保存的,esp开始,然后依次向上4i+4个地址,函数如果只有一个参数那么就是放在esp,如果有三个,第一个就放在esp,第二个放在esp+4,第三个在esp+8。然后参数有实参传递给形参的传参过程也就是,被调用的函数去调用者的函数中去取实参的值(参数从寄存器中压入了调用者的栈中了)再压入到自己的栈中,所以看到ebp都是加多少的,而不是减多少中取的,原第一个参数在原调用者函数的esp中,在被调用着栈中就是esp+8的位置处。
把这个函数传参的栈画出来:
在这里黄色是调用者函数的栈,蓝色的被调用者函数的栈,可以看到参数x在原调用者栈的esp处,y在esp+4,k在esp+8.然后红色代表被调用者func4函数的esp和ebp,可以看到第一个参数x在ebp+8,第二个y在ebp+c处等。ebp+4为调用者函数执行call指令后压入的返回地址。
搞懂了一般的参数传递的栈结构以后,我们回到这个level1中。
首先是test调用getbuf的栈结构:
我们首先通过篡改返回地址来执行fizz,也就是在原ret执行的返回地址用fizz函数的入口函数地址代替:
fizz入口函数地址为0x08048daf
getbuf执行leave指令之后:
执行ret语句后,pop eip的地址为fizz的入口地址,0x08048daf,也就是继续执行就是执行fizz函数了。
我们上面已经分析了,这里不是call指令,是直接执行函数,所以系统不会push 返回地址,接下来是执行fizz的栈结构:黄色为test的栈,蓝色是fizz的栈,红色为fizz的栈帧。
再看一下fizz函数的参数从调用者的那里取:
看到是fizz的ebp加8的地方,然后在对比我们第一次破坏的时候的图
我们看到在用fizz入口地址篡改掉返回地址,后在用4个00覆盖掉fizz ebp+4的地方,然后再用我们的cookie篡改fizzebp+8的地方,这样,执行fizz时传入的就是我们的cookie作为参数了。
覆盖效果图:
覆盖以后执行fizz。这个时候fizz取到的参数就是我们写进去的cookie
所以漏洞利用代码如下:solution
执行一下看看:
如果这里不是直接执行而是call是什么样的:
这样的话对比发现,我们以前篡改覆盖的到返回地址那一块是fizz的ebp+4,所以只需要在向上紧接着写上我们的cookie,就把我们的cookie写到了fizz取参数的地方ebp+8了。中间没有那4个00.还是有差别的。对比发现不管怎么样函数的参数都是去自己栈的ebp+8处去取,这个时候的solution变成了:
再来进一步考虑一下如果执行的fizz入口地址我们不是填的0x08048daf,而是0x8048db0,也就是不执行push ebp
这里发现如果要用cookie来覆盖fizz的参数,以前写44个零覆盖到getbuf保存的ebp,4个字节的fizz地址覆盖到原返回地址处,现在想覆盖到+8处,就要补两组4个0,再用cookie覆盖参数了。
这个时候的solution:
Level1是和level0一样调用完getbuf以后我们不返回getbuf的调用者test而是去执行fizz函数,区别就是这个fizz函数要求我们传入参数,而且传入的参数必须是我们的cookie。所以在level0的方法我们轻松的知道了如何去执行fizz,就是用fizz函数的入口地址去覆盖返回地址,这里的关键就是找到fizz函数的参数从栈中的什么地方传入的,然后我们把我们的cookie写进这个fizz会获取参数的地方。一般参数都是从调用者的栈传到被调用者的栈中的,由实参传递给函数的形参,在我的文章底层实现理解函数传参,实参,形参中有讲解,可以去看看。
首先我们来看看一般函数调用的传参的底层汇编代码是实现:图片就是我之前那个文章中的图:为了方便就直接分析这个好了。可以看出一般函数的实参都是从栈顶指针开始保存的,esp开始,然后依次向上4i+4个地址,函数如果只有一个参数那么就是放在esp,如果有三个,第一个就放在esp,第二个放在esp+4,第三个在esp+8。然后参数有实参传递给形参的传参过程也就是,被调用的函数去调用者的函数中去取实参的值(参数从寄存器中压入了调用者的栈中了)再压入到自己的栈中,所以看到ebp都是加多少的,而不是减多少中取的,原第一个参数在原调用者函数的esp中,在被调用着栈中就是esp+8的位置处。
把这个函数传参的栈画出来:
在这里黄色是调用者函数的栈,蓝色的被调用者函数的栈,可以看到参数x在原调用者栈的esp处,y在esp+4,k在esp+8.然后红色代表被调用者func4函数的esp和ebp,可以看到第一个参数x在ebp+8,第二个y在ebp+c处等。ebp+4为调用者函数执行call指令后压入的返回地址。
搞懂了一般的参数传递的栈结构以后,我们回到这个level1中。
首先是test调用getbuf的栈结构:
我们首先通过篡改返回地址来执行fizz,也就是在原ret执行的返回地址用fizz函数的入口函数地址代替:
fizz入口函数地址为0x08048daf
getbuf执行leave指令之后:
执行ret语句后,pop eip的地址为fizz的入口地址,0x08048daf,也就是继续执行就是执行fizz函数了。
我们上面已经分析了,这里不是call指令,是直接执行函数,所以系统不会push 返回地址,接下来是执行fizz的栈结构:黄色为test的栈,蓝色是fizz的栈,红色为fizz的栈帧。
再看一下fizz函数的参数从调用者的那里取:
看到是fizz的ebp加8的地方,然后在对比我们第一次破坏的时候的图
我们看到在用fizz入口地址篡改掉返回地址,后在用4个00覆盖掉fizz ebp+4的地方,然后再用我们的cookie篡改fizzebp+8的地方,这样,执行fizz时传入的就是我们的cookie作为参数了。
覆盖效果图:
覆盖以后执行fizz。这个时候fizz取到的参数就是我们写进去的cookie
所以漏洞利用代码如下:solution
执行一下看看:
如果这里不是直接执行而是call是什么样的:
这样的话对比发现,我们以前篡改覆盖的到返回地址那一块是fizz的ebp+4,所以只需要在向上紧接着写上我们的cookie,就把我们的cookie写到了fizz取参数的地方ebp+8了。中间没有那4个00.还是有差别的。对比发现不管怎么样函数的参数都是去自己栈的ebp+8处去取,这个时候的solution变成了:
再来进一步考虑一下如果执行的fizz入口地址我们不是填的0x08048daf,而是0x8048db0,也就是不执行push ebp
这里发现如果要用cookie来覆盖fizz的参数,以前写44个零覆盖到getbuf保存的ebp,4个字节的fizz地址覆盖到原返回地址处,现在想覆盖到+8处,就要补两组4个0,再用cookie覆盖参数了。
这个时候的solution:
相关文章推荐
- Linux网络编程:原始套接字编程及实例分析(3)
- Linux网络编程:原始套接字编程及实例分析(二)
- DHCP的配置及应用
- CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(2)
- CSAPP 深入理解计算机系统 Buflab实验,缓冲区溢出攻击实验(1)
- tomcat开启https
- MFC中的CAsyncSocket类实现网络通信
- https 的post数据
- 猫猫学iOS(五十五)多线程网络之图片下载框架之SDWebImage
- 卷积神经网络总结
- HttpServletRequest 常用返回值类型
- 学习数据结构的网站
- AsyncTask实现ListView中异步加载网络图片
- C++网络编程概述(精)
- PHP的cURL库:抓取网页,POST数据及其他,HTTP认证 抓取数据
- 网络分析工具
- 基于HTTP 协议认证介绍与实现
- android有关网络连接的方法
- Google网络框架Volley的使用,Cache-Control=no-cache时强制缓存的处理
- Go和HTTPS