本篇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 |







