SEED缓冲区溢出实验笔记——Return_to_libc

参考:http://www.cis.syr.edu/~wedu/seed/Labs_12.04/Software/Return_to_libc/

     http://drops.wooyun.org/tips/6597

     Bypassing non-executable-stack during exploitation using return-to-libc by c0ntex | c0ntex[at]gmail.com

     ROP轻松谈

     《程序员的自我修养》(虽然我没看完,但是对于理解这一切很有帮助)

在已经了解了缓冲区溢出的基本原理后,使用R2Libc方法需要获得最关键三个参数:system()、exit()、“/bin/sh”的地址,其中system()和exit()是libc.so中的函数,我们想要调用system并传入“/bin/sh”,并且返回到exit()的地址正常退出,以免留下错误日志。

要取得字符串的地址,教程中给出了一个方法,即通过自己程序的环境变量的地址来寻找漏洞程序的SHELL环境变量地址,因为他们的地址相近。但是程序的环境变量地址往往难以猜测,不如利用libc.so里的字符串,采用gdb如下指令可以查找到该地址。其中0xb7e5f430是system的地址。

通过反汇编正常的system()调用(自己写一个例子程序),可以从下图看出,是将参数字符串”/user/bin”的地址入栈来进行传递参数的。调用完system()后,程序同样会返回。正常调用函数是使用call命令,该命令首先将下一条指令的地址入栈,然后再跳转至目标地址执行。所以,我们在让程序的eip直接指向system()时,需要构建所谓的“伪栈”(fake frame)才能让溢出正常的进行,即栈让中依次存储”/usr/bin”地址、返回地址(exit()的地址)。esp指向的是返回地址。如图所示。为什么是这样的呢?其实,在溢出之后,对比参考图(b)就容易知道,上述要求的栈结构和调用call命令之后是一样的,故所谓的fake frame就完成了;而我们溢出是直接让eip指向了system,没有调用call。需要注意,溢出让ebp原来的值丢了,破坏了栈帧的结构。

下面来看一看细节。反观我们溢出后程序的栈,在执行leave、ret命令后,ebp变为原值,esp指向原来的参数位置。通过调试溢出的程序,发现程序转到system()地址后,没有像一般函数那样push ebp,所以esp继续指向0xbfffff200地址,即溢出前存放参数的位置。同样可以看到,0xb7e5f49b直接返回ret,并没有leave指令,而ret指令功能就是pop eip(这样的说法是否准确?),所以在调用完system()后eip会变成0xbfffff200存放的内容,故教程中的fake_ret位置是正确的。从0xb7e5f437指令可以看出,对参数的引用就是根据esp的偏移,将0xbffff204的内容放到了esi中。虽然ebp被我们“丢掉”了,但是system()没有用到ebp。

接着一步步的执行,会发现程序跳转到了不知名的地址0xb7e5ee70中,并且再也不会回到之前的f4**的地址,但是,最后仍然会使用0xaaaaaaaa返回,即调用system()前设置的返回地址(过程中都发生了什么?)。但是,如果把system看做一个黑盒的话,这么做确实可以成功的攻击。

其实在实验的时候,我花了很久才理解为何这样构建所谓的fake frame是正确的。原因在于分析问题的粒度:我一步步汇编跟进了system函数,而没有从调用函数黑盒的角度来理解。这也算是走了弯路的收获吧。

漏洞程序代码:

 By Ascii0x03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏MasiMaro 的技术博文

Python处理正则表达式超时的办法

最近在项目中遇到一个问题,就是需要采用正则匹配一些疑似暗链和挂马的HTML代码,而公司的老大给的正则表达式有的地方写的不够严谨,导致在匹配的时候发生卡死的现象,...

1883
来自专栏顶级程序员

50 行代码教你爬取猫眼电影 TOP100 榜所有信息

对于Python初学者来说,爬虫技能是应该是最好入门,也是最能够有让自己有成就感的,今天,恋习Python的手把手系列,手把手教你入门Python爬虫,爬取猫眼...

1333
来自专栏北京马哥教育

编写Linux Shell脚本的最佳实践

来自:Myths的个人博客 作者:myths 链接:https://blog.mythsman.com/2017/07/23/1/(点击尾部阅读原文前往) 前言...

4149
来自专栏Java帮帮-微信公众号-技术文章全总结

回顾Java 8 9 10的新特性,展望即将来临的11和明年的12【大牛经验】

1997年4月2日,JavaOne会议召开,参与者逾一万人,创当时全球同类会议纪录;

1.6K3
来自专栏大数据和云计算技术

MongoDB系列8:MongoDB集合的增量更新

在关系型数据库中,经常会遇到这样的场景:用某张表或是多张表的关联产生的结果集,然后持续地更新另外一张表的数据,有时为了方便,只更新变化的数据,即增量更新。那么在...

1943
来自专栏Golang语言社区

Go语言并发编程总结

Golang :不要通过共享内存来通信,而应该通过通信来共享内存。这句风靡在Go社区的话,说的就是 goroutine中的 channel …….

1434
来自专栏java一日一条

Java线程面试题 Top 50

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚...

1212
来自专栏诸葛青云的专栏

C语言被忽视的一些小东西!C语言基础教程之错误处理

C 语言不提供对错误处理的直接支持,但是作为一种系统编程语言,它以返回值的形式允许您访问底层数据。在发生错误时,大多数的 C 或 UNIX 函数调用返回 1 或...

1050
来自专栏Python入门

使用Python这么多年,才发现Python还有这些实用的功能和特点

在使用Python多年以后,我偶然发现了一些我们过去不知道的功能和特性。一些可以说是非常有用,但却没有充分利用。考虑到这一点,我编辑了一些你应该了解的Pytho...

951
来自专栏技术博客

编写高质量代码改善C#程序的157个建议[用抛异常替代返回错误、不要在不恰当的场合下引发异常、重新引发异常时使用inner Exception]

  自从.NET出现后,关于CLR异常机制的讨论就几乎从未停止过。迄今为止,CLR异常机制让人关注最多的一点就是“效率”问题。其实,这里存在认识上的误区,因为正...

1152

扫码关注云+社区

领取腾讯云代金券