首页
社区
课程
招聘
[原创]看雪TSRC_2017秋季赛第四题---------WriteUp
发表于: 2017-11-7 00:42 8251

[原创]看雪TSRC_2017秋季赛第四题---------WriteUp

2017-11-7 00:42
8251

这是一道pwn题,需要利用程序的漏洞来getshell然后读取存放在远程服务器上的flag文件。

使用checksec club可以查看到以下信息。(用python的pip工具安装pwntools包后就可以使用checksec了,安装命令为 pip install pwntools 下载慢可以找下清华园的镜像)

简单介绍一下含义:

小结: 需要找程序基址,GOT表可以利用。

用ida进行静态分析,可以看到流程很清晰,首先程序菜单如下:

分别来看下每个选项的做用

先看1号功能get a box

IDA F5后代码如下,相关全局变量的做用已经在分析后rename了

可以看出,这个功能号就是用来申请一个堆空间,不过这里对大小有限制,分别由calcMinSizcalcMaxSize来计算当前申请的堆空间是不是满足条件。

在看申请堆大小限制前先去看下这些全局变量的部局。

boxSize数组有7个元素,第0跟第6个元素已经被设定了初始值,第1到第5为0 这5个元素就是用来记录申请到的box的大小。 而第0跟第6是用来限制堆大小的,等下看到calcMinSizecalcMaxSize就会明白。
boxBuff没有特殊,第1到第5总共5个元素用来记录申请的box的堆地址。
boxUsed没有特殊,第1到第5总共5个元素用来记录5种box类型哪些已经被使用了。

接着来看一下堆大小的限制。

由以上代码可以看出,申请的当前空间要比排它前面的大0x10比排在它后面的小0x10,又由于boxSize的第0与第6个元素被初始化为了8和0x1000所以我们可以申请的堆大小范围在0x18 ~ 0xFF0之间。

get a box中的代码功能分析完毕,并且没有发现漏洞存在。继续看下一个功能。

2号功能destory a box

这里出现了一个新的全局变量isCanRelease

结合程序逻辑可以看出,只有smallnormal类型的box可以被free。并且由于free后没有重置boxUsed的值,所以每种类型的box只能使用一次,这里还有一个很明显的漏洞存在,free后的buffer指针没有被清空,所以可能导致double free的利用。

3号功能leave me a message in box

向box中写入数据,这里也有一个漏洞,写入次数比buffer多了一字节,所以可以用off-by-one,我没有用这种方式来利用,所以这里给一个off-by-one相关资料

4号功能show message in box

这里到没有什么多说的,很单纯的显示buffer内容,可以用来泄露地址。

5号功能guess a random number

很好玩的小游戏,预测伪随机数,猜中了返回随机种子,猜错了会告诉你正确的随机数,这里的随机种子就是seed的全局变量的地址,由于程序开启了PIE所以这里是获取程序基址的地方。

6号功能exit

输入个名字,打印信息并退出,没有利用点。

小结: 可以通过猜随机数获取程序基址,利用free时不清空buffer指针来构造堆中数据和使用double free

这部分主要是给自己做个记录,第一次玩堆,看了很多文章,这几篇不错的记录一下备忘。

相关知识了解了以后,就要根据本题的实际情况来构造payload了

首先先通过猜伪随机数来获取程序的加载基址,怎么去预测伪随机数,这里有篇文章写的很好。Linux随机数分析

看过文章可以得到一个公式 r[i] = (r[i-3] + r[i-31]) & 0x7fffffff

获取基址的代码如下:

由于只有smallnormal的box可以free,所以先创建normalbig,然后释放掉normal,之后再创建littlesmall,并通过normal的指针来构造fake chunk,下面结合实际代码与内存来演示如何构造fake chunk

首先申请400与450大小的normal boxbig box,释放normal box,再申请150与200大小的little boxsmall box,这样normal boxlittle box的指针是同一个地址,又由于本程序中写入数据只看指针与box大小,所以此时的normal box的指针可以同时操作little boxsmall box的内存,这样就可以来构造fake chunk, 代码如下:

以上代码执行后内存数据如下:

开始布置fake chunk的内存数据,就用上面的地址来描述,fake chunkprev sizesize放在0x0000558DC84DA4200x0000558DC84DA428处,0x0000558DC84DA430处开始写入fdbk,由于unlink新增加的检测,所以这里需要分别写入一个指向fake chunk头部的指针的地址减0x18和0x14,这样就能满足FD->bk == p && BK->fd == p,p表示当前chunk,FD表示当前chunkfd指向的chunk, BK表示当前chunkbk指向的chunk,所以这里选择全局变量boxBuff - 0x18boxBuff - 0x10的地址来写入。

然后还要修改0x0000558DC84DA4B0处的prev size0x0000558DC84DA4B8处表示前chunk是否空闲的最低位为0这样当释放此处的堆时会因为向前合并而调用unlink,所以这里根据实际情况,写入0x900xD0,构造fake chunk后内存布局如下(A为填充数据,不影响结果):

完整的利用脚本如下:

 
 
 
Arch:     amd64-64-little
RELRO:    Partial RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 1
支持
分享
最新回复 (6)
雪    币: 206
活跃值: (108)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
2
分析的好清楚,符合我胃口,顶一个
2017-11-10 17:15
0
雪    币: 6818
活跃值: (153)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
不错!!
2017-11-10 19:27
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
整体过程很清晰,学习中
2017-11-26 22:07
0
雪    币: 6
活跃值: (124)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
学习了!
2017-12-5 22:55
0
雪    币: 6
活跃值: (124)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
还想问下师傅,如何学习pwn
2017-12-5 22:56
0
雪    币: 870
活跃值: (2264)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
写的很好
2018-7-21 16:58
0
游客
登录 | 注册 方可回帖
返回
//