本篇writeup已收录进pwn解题本. Link
ACTF2020的两道堆体,当时还不会做,现在补上。
一共有两道,分别是SCP_Foundation_Secret和SCP_Foundation_Attack,Secret可以直接打印出flag,Attack则需要getshell,其余部分两题都一样,我只做了更难的getshell法。
SCP_Foundation_Secret
题目描述:
忘记了
题目附件:
考察点:fastbin attack (
uaf
+double free
)难度:中等
分值:300
程序分析
glibc heap
相关的菜单题,主函数如下:
1 | void main(void){ |
创建SCP的时候会连续malloc三次,主要代码如下:
1 | void Creat_SCP(void){ |
删除SCP的时候连续free三次,但是并未清空数据,主要部分如下:
1 | void Delete_SCP(void){ |
从上面俩函数中,可以分析出SCP的结构体如下:
1 | struct SCP{ |
查看SCP会打印name
和description
中的数据,主要部分如下:
1 | void View_SCP(void){ |
解题思路
总体思路就是先利用uaf
泄漏libc,然后double free
,改free
的got
表为system
函数,最后通过free('/bin/sh')
拿到shell
创建SCP时,三次malloc依次为
- SCP结构体,大小
0x20
name
,大小自定description
,大小自定
UAF
利用fastbin LIFO的特性,先创建两个SCP,再删除它们,获得两个0x20
的fastbin
这两个SCP的
name
和description
的大小需要都不在0x20
范围内
然后再创建一个SCP,name
的大小等于0x18
,这时name
的chunk
就会被分派到已经释放了的0号节点的位置,向name
中写入任意地址,只要查看0号节点,就可以打印出该地址中的数据
我的做法是向name
中写free
的got
表,然后打印出libc
中free
的地址:
1 | add(0x28,'AAAAAAAA',0x58,'aaaaaaaa') #0 |
Double Free
题目有限制,只能添加10个SCP,因此要节约使用,刚刚泄漏libc时创建的两个节点可以重复使用,uaf只是在0x20
的fastbin
上做手脚,其余的fastbin
不受影响。
虽然创建一次会连续malloc
三次,但是只要这三次malloc
出的chunk
大小不一样,就不会互相影响。
这里有一点需要注意,要想成功malloc
到free
的GOT
表,必须要先伪造chunk
的size
,通过调试,顺着GOT
表中free
的地址往前找,在第14
字节找到了0x60
,因此往这里可以分配0x50-0x60
的chunk
1 | pwndbg> got |
具体的操作如下:
1 | add(0x28,'AAAAAAAA',0x58,'aaaaaaaa') #0 |
getshell
1 | # system('/bin/sh') |
exp
1 | #!/usr/bin/python |