RCTF2017 Pwn



RCTF2017的Pwn writeup,赛后复现的,对于我这种刚刚接触heap的新手,是一套不错的练手题目,感谢ROIS的各位大佬!

Rcacl

64位elf,只开启了NX,虽然没有开启canary,但是有意思的是程序实现了一套自己的SSP,对部分关键函数进行了栈保护

能够发现存在一个很明显的栈溢出,但是由于ssp的存在无法利用,我们需要想办法Bypass ssp
整个ssp是存在漏洞的,因为所有ssp生成的随机值都存在堆中,而每一次cacl计算运算的结果也存在一个相邻的heap中,如下:

存放运行结果的heap只有0x100大小,当运算结果过多超过0x100后就会覆盖到存放Canary的chunk
我们改写canary,绕过ssp,实现栈溢出

栈溢出之后,因为只有一次利用机会,所以需要进行一步stack pivot到一块可读写的内存上,bypass ASLR后进行ret2libc即可
在写exp的时候,注意sacnf函数比较麻烦,他对所有的” “0x20 即空格字符截断,而我们利用的很多函数plt与got都有0x20,利用x64下的通用csu_init这个通用ropgets,需要避免该截断,所以在利用地址的过程中,使用到了一些计算避免出现0x20

Recho

漏洞是一个很明显的栈溢出,我们需要控制read的返回值为0,从而劫持程序控制流
所以,题目只能做ROP,并且由于没有给出libc,做ret2libc不实际
于是通过系统调用来做Rop
观察到bss段中给出了flag字符串
想必是题目的hint,降低难度,于是rop的思路就有了

下面的难点在于找到syscall,在GOT中寻找一个syscall
通过add byte ptr [rdi], al ; ret来修改got表,指向一个syscall
我们不能够修改read和write函数,其他的atoi,setvbuf在libc的实现中不一定有系统调用
所以alarm成为了我们不多的选择,修改got{‘alarm’}–>syscall,从而调用open完成rop即可

RNote

首先分析题目的数据结构:
Note的管理结构建在BSS段中

其中漏洞在于在输入Title时,能够输入17个字节的数据,这样就形成了一个off by one漏洞

溢出的一个字节刚好能够修改*Content最后指针一个字节的内容,虽然在delete note时,判断了flag是否等于0来判断note是否被删除过,但是通过修改Content指针,我们能够轻松造成double free
利用该double free做FastBin Attack,修改__malloc_hook为one_gadgets,最终spawn shell
新手可参考:RNote(pwn)
整个过程讲述十分详细

RNote2

首先,题目建立了note的数据结构如下:

其中edit_flag 在edit或者expand操作后置为1
利用next与prev指针,将所有的Note串成了一个双向链表
我们能够指定Content的大小
shi
其中包含五种操作:add,delete,edit,list都是常规操作
但是在读入数据时:

字符串结尾没有接”\0″,可以利用该漏洞泄露libc_base(smallbin)与heap_base(fastbin)地址

在expand操作中,其操作的本意是在一个已有的note后面追加内容,用relloc函数
void *realloc(void *p, size_t size) 将p所指向的对象的大小改为size个字节.

如果新分配的内存比原内存大, 那么原内存的内容保持不变, 增加的空间不进行初始化.
如果新分配的内存比原内存小,那么新内存保持原内存的内容, 增加的空间不进行初始化. 返回指向新分配空间的指针;
若内存不够,则返回NULL, 原p指向的内存区不变.

漏洞点在relloc没有对区域初始化,利用strncat进行追加时,strncat函数判断的是从”\0″的位置开始追加内容,所以如果relloc返回的chunk区域本身有值,就可能造成strnact追加时HOF,堆溢出字节数具体看实际的chunk中的情况

如上图,relloc追加该矩形区域chunk中的内容,由于该区域未初始化,还含有free后的内容,若从0x555555757060开始追加内容,可以溢出heap 9个字节,最终能够覆盖到箭头所指的下一个chunk的Size位

漏洞利用的基本思路:
就是利用expand中的heap overflow,修改一个chunk的Size=0xff,delete后再add就能分配到overlap chunk中利用add overwrite一个该note的管理结构Note中的内容,将content指针改成free_hook地址(malloc_hook与relloc_hook都不容易触发,相比,free_hook直接删除时就会触发,不会有任何限制),之后edit该note,将free_hook中改为one_gadgets,delete即可spawn shell

同样,不用one_gadgets,将__relloc_hook中更改为system,expand一个名称”/bin/sh”的note,同样可行
具体参考官方wp:RCTF 2017 官方Writeup

script:

此外,在本地,利用本地高版本的glibc进行测试时,上述方法会报错,应该在新版本的glibc中加入了相应的patch,具体原因没有深究

aiRcraft

题目复杂在题目的情景比较多
首先,关于飞机和飞机场建立了一下两个数据结构

plane使用双向链表进行链接

planes是停靠在该Airport的plane的指针数组

四类操作分别是:

1.buy:购买一架飞机
2.build:建造一座飞机场
3.enter:进入飞机场,enter_list显示所有分机的情况,enter_sell卖掉飞机场和停靠在飞机场上所有飞机
4.select:选择分机,select_fly选择该分机飞到指定的飞机场,select_sell卖掉改飞机

其中漏洞有两处:

1.在enter_sell时,没有释放飞机场的char *Name
2.在enter_sell时,没有清空飞机场中的分机plane的指针数组,可以用来做double free

首先,我们需要泄露出heap_base,libc_base,proc_base
能够泄露的操作只有enter_lise函数

heap_base容易泄露,直接利用fastbin_dup即可

利用sell_plane释放一个0x51的chunk,之后建造一个0x48 Name大小的新机场(0x91不是fastbin),实现Uaf
在uaf的chunk中填入满足条件的地址以及我们想要泄露的地址(注意分机停靠在飞机场A中),之后利用enter_list(A)就可以泄露出libc_base,proc_base

之后,我们发现在heap中有函数指针,如果修改在sell_plane处的函数指针就能够实现system("/bin/sh")

首先我们可以利用泄露内存时的uaf,申请一个0x48大小name的新机场实现函数指针的修改
但是发现在顺利uaf后,sell_plane时,由于在enter_sell机场时已经将该plane从plane_lise这个双向链表中删除,所以无法再次选择到该plane进行sell操作

究其原因是因为我们不能只对一个plane进行修改,而要在不free的情况下,直接修改一个该plane的指针,这就需要用到uaf的fastbinAttack
思路:首先构造一个名为”/bin/sh”的plane作为fastbinAttack的目标,利用fastbinAttack修改该plane的(plane+ 64) 为system地址,之后再次sell_plane(‘/bin/sh)即可spawn shell

发表评论