网络安全之溢出利用FILE结构体

2016-12-04 08:12:00 作者:红黑联盟 分类 : 比特网

  最近的上海大学生网络安全赛就只出了一题pwn450,对于还不是很会的我,瞬间懵逼,不过大佬还是大佬,最后还是挺多大佬做出来了,不过反正我没做出来,最后看题解,用到了两个点,一个是堆溢出,另一个就是利用这个FILE结构体做文章;菜鸡的我只有一个一个学,堆溢出的这点后面再学,先学习了如何利用FILE结构体,也就写出了这篇文章。学习的过程主要也是看大牛的博客文章写出来的,在最后也会附上相应的文章。

  一、结构体介绍

  首先介绍下FILE结构体,下面图就是FILE结构体:

\

  平常我们正常使用FILE结构体的情景是:

\

  此时,系统会给应用程序申请一段空间将相应数据赋值好后然后将地址返回给fp。事实上,系统并不是直接分配的FILE(_IO_FILE)结构体,而是名字为_IO_FILE_plus结构体,这个结构体包含了_IO_FILE结构体,还包含了一个虚函数表指针,其定义为:

\

  这个结构体里面的_IO_jump_t指针类似于C++中的虚函数表,而其结构中具体虚函数名称定义如下:

\

  二者之间的整个关系结构图如下:

\

  二、利用原理

  我们平常在应用程序中调用fclose、fputs这些函数的时候系统最终都会通过_IO_jump_t这个函数表指针对函数进行调用(如fclose会调用close函数等)。

  在知道了这一点后,试想如果我们想办法利用其他各种溢出方式覆了应用程序的文件指针,使其指向我们可控区域,在该区域伪造相应的_IO_FILE_plus头(主要是_IO_jump_t表或者是表中函数的指针),最终在程序调用fclose函数或其它函数的时候,就可以控制程序去执行我们想要它执行的地址,control the eip, control the world。

  比较常见的是利用strcpy,strcat等覆盖了文件指针然后进一步利用,下面会举两个例子来进一步理解如何实现,一个是利用UAF来覆盖修改指针,一个是利用strcpy栈溢出。

  三、实例

  1)UAF利用

  直接贴出源代码:

\

  可以看到,程序首先申请_IO_FILE_plus (sizeof(_IO_FILE+sizeof(void)) 结构体大小的内存块,接下了free掉,紧接着打开一个文件,此时系统会将刚刚释放掉的内存空间分配给文件指针(不懂可以先去看下UAF的相关资料)即此时str与fp指向同一块内存空间,这时利用str将fp结构体的_IO_jump_t指针指向我们伪造的funcs数组,同时再系统最后调用fclose的时候,即调用_IO_jump_t里面的close函数的时候最终变成了调用我们定义的pwn函数,最终程序执行截图如下:

\

  2)栈溢出利用

  先贴出源码(看了别人的文章以后改编的)

\

  程序的意思是将”abc…..”这个字符串写进到aa.txt中,编译。

  首先是漏洞的发现,可以输入最多1046个字符,最后strcpy拷贝到stage缓冲区中,会造成缓冲区溢出,拖进IDA中,如下图

\

  可以看到stage为bp-0x41A而fp指针则为bp-0x8,也就是说在输入长度大于0x41a-0x8=0x412(1042)的时候就可以覆盖fp指针,最大允许输入为0x416,多四字节,刚好可以覆盖fp指针,为了降低难度只体现利用FILE结构体的思想,程序中没有要求我们自己泄露栈地址什么的,而是直接给出了buff地址,所以可以直接覆盖fp指针,指向buff中的地址。最后在调用fputs(源代码是fprintf,编译的时候优化成了fputs)的时候,我们把它调用_IO_jump_t结构中对应的函数地址改写成get_flag函数的地址即可。

  在写exp的时候还遇到了不少的困难,下面说我是怎样一步一步解决的。大牛的文章是将stderr指针中的数据拷贝到我们输入的内存中(详细情况可以参考http://www.evil0x.com/posts/13764.html),可是我想文件指针里面的数据要不都是地址要不都不怎么用,如果我们事先使用gdb将stderr里面数据拷出来,由于地址随机化的影响,数据很大肯能性已经变得不可访问了,这样容易出错,在看了一遍_IO_FILE结构体后我决定直接将fp里面的数据全都覆盖成stage的地址。前面我又已知了系统的_IO_FILE结构体大小为0x94(148),所以在0x94后面的数据我把_IO_jump_t函数表指针的值设置成了stage+180的地址,在stage+180的地方伪造_IO_jump_t的函数表,并将函数表里面的地址都指向get_flag函数。这样最初写出来的exp代码如下:

\

  执行脚本…….

\

  没有任何反应,gdb附载程序,看下哪里出错,断点下在fputs函数调用前。重新执行脚本

\

  可以看到执行fputs时,此时的fp指针是0xbf9e3c76,而打印出来的stage地址为:

\

  二者相同,说明第一 步我们已经成功,即将fp指针覆盖成我们输入的地址,可以看下此时stage地址中的数据内容

\

  全都是stage的地址,到这一步还没错,接下来按c继续执行看哪出错。程序崩了,重新再来一次,这次不下断点,直接看哪里出错

\

  程序错在fupts+141这里,也就是call[eax+0x1c]这里,查看eax寄存器里面的内容

\

  发现和stage的地址很像,只是错位了两个字节

\

  往上追溯,看eax是在哪赋值的,由于之前的调试,现在我直接去看fputs+120的地方。

\

  看到在fputs+123的地方将eax赋值,查看esi寄存器

\

  发现是stage的地址,其实也就是文件指针,fputs+123代码将文件指针+0x94(_IO_FILE大小就是0x94),刚好是_IO_jump_t函数表指针的地址,不过这里还多加了个eax*1,继续往前翻,看eax来自于哪里

\

  可以看到eax寄存器中的内容来自于esi+0x46,突然想起之前的_IO_FILE结构图,

\

  里面有个offset字段,也就是说通过_IO_FILE指针寻找_IO_jump_t函数表指针的时候不是直接+0x94得到的,而是通过+0x94+offset得到的,之前我们输入的offset可能会很大,导致访存错误,所以下一步修改我们输入的offset字段,也就是偏移0x46处的内容,由于strcpy会截断,故该字段值不能为’\x00’,为了方便,我把它直接改成了0x4,同时此时需要将伪造的_IO_jump_t函数表指针地址往后移四个字节。修改后的exp如下:

\

  同时在执行的时候,在fputs+109处下断点,观察eax寄存器中的值

\

  可以看到此时esi+0x46的值正是我们所控制的0x4,继续跟,直到跟到取出_IO_jump_t函数表指针地址的地方,在我这里也就是fputs+123的地方

\

  可以看到此时计算esi+0x94+eax后所指向的地址,正是我们写的指向get_flag函数的地址,进一步查看它偏移0x1c的地址

\

  仍然为get_flag函数的地址(因为我在脚本里将整个_IO_jump_t表函数地址都写成get_flag的地址)。最后在call的时候,就会跳到get_flag函数那里去执行。从而得到shell

\

  到这里就算完成了利用,最后结果如下

\

  最后再提一下,在这里fputs首先调用的是_IO_jump_t+0x1c的地址,

\

  (JUMP_INIT_DUMMY 8个字节),也就是先调用xsputn函数(我也不知道干什么用,之前我猜的是会调用write函数,不过可能是初始化调用这个函数,后面可能还是会调用write,有兴趣的可以继续跟下去),在这里提一下是后面如果遇到,在不覆盖全部指针的情况下,仍然知道如何处理。

  到这里,就算写完了。还有就是脚本跑个五六次可能会有一俩次出错,重新跑一次就行了,猜测是stage地址刚好包含’\x00’,导致strcpy直接截断,而不复制,最后无果而终,地址随机化开了,多试个一两次就好。

  四、 小结

  利用FILE结构体,最主要的就是那个函数表,控制了它就可以控制函数的流程,linux系统也没有进行检查,可能后面会进行修补吧,不过修了也没关系,大牛们总会有办法的,不过这就和我没什么关系了。现在想想,这个其实也不是很难,只是一个知识点还可以接受,上海的比赛把这个和堆结合起来有有点蒙圈了。

  学了这个之后,下一步可能会针对上海的那题再学下堆的利用,再把二者结合起来再总结一下。

最近更新
科普

科普图集
带着朋友和机器人上月亮散步

带着朋友和机器人上月亮散步>>详情

比食人鱼更恐怖:长着人类牙齿的鱼

比食人鱼更恐怖:长着人类牙齿的鱼>>详情

邮件订阅

软件信息化周刊
比特软件信息化周刊提供以数据库、操作系统和管理软件为重点的全面软件信息化产业热点、应用方案推荐、实用技巧分享等。以最新的软件资讯,最新的软件技巧,最新的软件与服务业内动态来为IT用户找到软捷径。
商务办公周刊
比特商务周刊是一个及行业资讯、深度分析、企业导购等为一体的综合性周刊。其中,与中国计量科学研究院合力打造的比特实验室可以为商业用户提供最权威的采购指南。是企业用户不可缺少的智选周刊!
网络周刊
比特网络周刊向企业网管员以及网络技术和产品使用者提供关于网络产业动态、技术热点、组网、建网、网络管理、网络运维等最新技术和实用技巧,帮助网管答疑解惑,成为网管好帮手。
服务器周刊
比特服务器周刊作为比特网的重点频道之一,主要关注x86服务器,RISC架构服务器以及高性能计算机行业的产品及发展动态。通过最独到的编辑观点和业界动态分析,让您第一时间了解服务器行业的趋势。
存储周刊
比特存储周刊长期以来,为读者提供企业存储领域高质量的原创内容,及时、全面的资讯、技术、方案以及案例文章,力求成为业界领先的存储媒体。比特存储周刊始终致力于用户的企业信息化建设、存储业务、数据保护与容灾构建以及数据管理部署等方面服务。
安全周刊
比特安全周刊通过专业的信息安全内容建设,为企业级用户打造最具商业价值的信息沟通平台,并为安全厂商提供多层面、多维度的媒体宣传手段。与其他同类网站信息安全内容相比,比特安全周刊运作模式更加独立,对信息安全界的动态新闻更新更快。
新闻中心热点推荐
新闻中心以独特视角精选一周内最具影响力的行业重大事件或圈内精彩故事,为企业级用户打造重点突出,可读性强,商业价值高的信息共享平台;同时为互联网、IT业界及通信厂商提供一条精准快捷,渗透力强,覆盖面广的媒体传播途径。
云计算周刊
比特云计算周刊关注云计算产业热点技术应用与趋势发展,全方位报道云计算领域最新动态。为用户与企业架设起沟通交流平台。包括IaaS、PaaS、SaaS各种不同的服务类型以及相关的安全与管理内容介绍。
CIO俱乐部周刊
比特CIO俱乐部周刊以大量高端CIO沙龙或专题研讨会以及对明星CIO的深入采访为依托,汇聚中国500强CIO的集体智慧。旨为中国杰出的CIO提供一个良好的互融互通 、促进交流的平台,并持续提供丰富的资讯和服务,探讨信息化建设,推动中国信息化发展引领CIO未来职业发展。
IT专家网
IT专家新闻邮件长期以来,以定向、分众、整合的商业模式,为企业IT专业人士以及IT系统采购决策者提供高质量的原创内容,包括IT新闻、评论、专家答疑、技巧和白皮书。此外,IT专家网还为读者提供包括咨询、社区、论坛、线下会议、读者沙龙等多种服务。
X周刊
X周刊是一份IT人的技术娱乐周刊,给用户实时传递I最新T资讯、IT段子、技术技巧、畅销书籍,同时用户还能参与我们推荐的互动游戏,给广大的IT技术人士忙碌工作之余带来轻松休闲一刻。