首页
社区
课程
招聘
[原创]TAMUCTF 2018 pwn writeup
发表于: 2018-3-27 08:30 8722

[原创]TAMUCTF 2018 pwn writeup

2018-3-27 08:30
8722

首先先看一些简单的栈溢出,TAMUCTF的五题pwn全是由gets引起的栈溢出,五题分别代表了栈溢出最基本的题型以及利用方式,值得看一看。

本篇主要针对于最基础的内容,所以尽可能详细的作出解释

pwn1是通过溢出覆盖局部变量,从而达到某个正常程序流达不到的分支,通过IDA可以非常直观的看出来哪里可以溢出,以及溢出点在哪里,而且我们要达到的分支在哪里

对于本题来说,gets(&s)即溢出点所在,而所溢出的对象就是跟s变量同样在栈中的变量v5,而当v5通过溢出修改数值==0xF007BA11时,就可以达到我们想要达到的分支。

所以溢出点就是v5在栈中的位置,就是[ebp-Ch]的位置,由于gets内容是从s处开始读入栈中,所以,在相对于s偏移0x23-0x0C=0x17的位置。

即我们可以构造0x17个其他字符,后面跟着0xF007BA11即可获得flag,由于某些十六进制数无法通过字符的形式直接输入,所以建议通过脚本形式来将构造的数据写入

跟pwn1相比,pwn2就没有那么直观和简单了,不过依然是栈溢出最基本的题型,通过IDA点进echo函数看看


gets函数,凡是有gets函数的地方一定会产生溢出,区别仅仅是能否利用以及怎么利用,这里与上一题不同,有栈溢出经验的都知道,这里的gets可以造成控制程序流的效果,可以让程序执行到指定的位置,这是栈溢出最常见也是利用效果最好的方式

下面来看看溢出点,同样是s变量,位于[ebp-EFh]的位置,所以ret地址,也就是我们想要控制的程序流地址,就是相对于s在(0xEF+0x04)的位置,加上的那个0x04时ebp所占的空间,因为ebp始终在ret地址的上方,所以是一个很好的计算偏移的基准。

所以我们构造形如(0xF3*'a'+addr)的数据,addr就是我们的程序流可以到达的地方,其中'a'代指任意数据,不同的题目这里填充的数据可能有所不同,针对这一题则可以填充任意数据。

接下来就要看看我们要让这个程序执行到哪个地方,通过IDA的函数窗口可以看到有哪些函数可以利用



很明显,我们看到了在上一题遇到的相同的函数,所以可以直接跳转到该函数处,从而获得flag,我们可以通过IDA查看该函数的地址


显然0x0804854B就是该函数的地址,也是我们通过控制程序流要达到地方,所以我们构造的最终输入字符串应该是:

通过脚本输入即可获得flag

乍一看,pwn3和pwn2像是一样的题目,同样,我们点进echo看看


这里除了多了两个printf就没有明显的差别了,同样也是gets产生溢出,同样也是通过栈溢出控制程序流,所以我们看看可以控制程序流到达什么地方


很遗憾,这里没有获得flag的函数,所以就不能通过现成的函数来达到我们的目的了,所以我们采取大多数pwn题型最常用的思路,getshell,说明白点就是通过控制程序流获得对方系统的root权限,从而达到读取对方主机上flag文件的目的

那么如何通过控制程序流获得root权限呢,不同题型、不同漏洞、不同解题思路各有不同方式,这个以后慢慢讲解。

针对这个题目,我们可以首先看看echo函数的指令,第一个printf通过%p打印出来了s的地址,而我们又可以通过gets控制程序流,那么我们就可以控制程序执行到s所在的地址,至于地址中应该是什么指令,我们就可以通过shellcode填充,来getshell。

所以我们的shellcode的功能就应该是在linux x86下,打开/bin/bash,文章最后会附上简单的shellcode生成方式。

所以我们最终要在s处填充的数据应该就是:

pwn4看起来就要比前三题要复杂得多,一般的pwn题思路则应该是大致的了解程序的结构功能和所用的数据结构,然后发现哪里可能会出现问题,寻找问题所在的最简单的思路就是关注危险函数,其中最危险的函数就是gets

本题显然也是由于gets产生的栈溢出,而且很明显溢出点在s偏移0x20的地方,可以控制程序流,这一般来说是对于这个程序的假设,我们可以通过GDB去调试验证这个假设还有我们所计算的溢出点是否有误。

而对于本题来说,后续的执行流程并未影响栈结构,也并没有使得s在栈中的布局发生变化,所以,在这一题中,我们依然可以通过gets的溢出漏洞控制程序流。

接下来就是我们的重点了,怎么通过控制程序流getshell

通过题目分析就可以发现,我们可以通过直接调用system函数来getshell,即执行system("/bin/sh")

那么该如何调用函数呢,根据之前的经验,只要ret处写上system的地址,即可调用system函数,那么该如何配置参数呢

很简单,通过内存查找找到"/bin/sh"字符所在的内存地址,然后因为在x86模式下,第一个参数往往放在ret之后的栈空间内,所以,将"/bin/sh"地址填充在ret之后,即可成功调用getshell

system函数的地址我们同样可以采用与之前相同的方式查看

"/bin/sh"的查找则可以通过IDA的字符串查找功能来实现



[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-2-1 20:10 被admin编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 1218
活跃值: (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
学习到了,谢谢啦
2018-3-28 21:17
0
游客
登录 | 注册 方可回帖
返回
//