off-by系列
- 参考资料:
前提介绍
- off-by系列不单单只有
off-by-one
和off-by-null
还有Off-by-Two
、Off-by-Many
、Off-by-Half
、Off-by-Block
,但是off-by-one
和off-by-null
是最为常见的,off-by-one
是溢出一个字节,该字节可以是任意的,而off-by-null
也是溢出一个字节,但是它溢出的字节只能是\x00
,所以off-by-null
其实是off-by-one
的一种特殊情况,比off-by-one
的利用条件更苛刻。 - 这里的
off-by-one
等并不是只用于打堆,其他方面的pwn也可以利用该漏洞,但是打堆时这类漏洞会可以花式利用。可以进行堆布局(堆风水)和进行堆叠。例如,off-by-one
,指非预期溢出1个字节,这样就可以修改堆块的标志位和Size
的大小。再如off-by-null
,非预期的溢出\x00
也可以修改堆块的标志位(常用于堆叠)。这种都被称之为堆布局(堆风水)
堆叠
-
堆叠其实就是unlink这一机制,具体的机制我就讲了,已经放在
unlink
那边讲过了 -
堆叠(overlap)一般指的就是将两个内存大小比较小的堆块,合并成一个大的堆块。将ptmalloc这一管理机制进行漏洞的理由,对堆进行一定的布局。堆叠有两种叠法,一种是向前合并,另一种是向后合并。
- 向前合并的逻辑比较多,可以比较好的利用。直接修改下一个堆块的
prev_size
即可。 - 而后向合并的逻辑,并不是很好利用,也没有模版化的利用,一般要用
perfect fit
来绕过。
- 向前合并的逻辑比较多,可以比较好的利用。直接修改下一个堆块的
off-by利用方式
-
off-by
有俩种利用方式:- 第一种是利用是对
unlink
机制进行攻击(主要是off-by-null的利用) - 第二种是通过堆溢出,然后修改堆中
SIZE
的P
标志位,然后导致前面的堆块的use_size
能覆盖到后面一个堆块的位置,造成堆叠,我们将通过一些实验来展示堆叠的利用。(主要是off-by-one的利用即)
- 第一种是利用是对
-
本篇文章主要是介绍第二种的
off-by
利用方式(因为第一种的unlink攻击已经在unlink中介绍过了)
堆知识回顾
p标志位
- p=0 时,表示前一个 chunk 为空闲,prev_size 才有效
- p=1 时,表示前一个 chunk 正在使用,prev_size 无效 p 主要用于内存块的合并操作;ptmalloc 分配的第一个块总是将 p 设置为 1,以防止程序引用到不存在的区域
- 放入fast_bin链表和放入tcache_bin链表里面的堆块,与它相邻的高地址堆块的
p
位也设置为1
chunk空间复用
- chunk 的大小要 align 到 8bytes。当一个 chunk 处于使用状态时,它的下一个 chunk 的 prev_size 域肯定是无效的。这个域可以被当前 chunk 使用
示例代码
- 这些实验只是堆叠的方法,具体的利用方法还是要根据题目来利用,而且堆叠只是pwn中的一种技巧,仅仅只用堆叠是没有什么机会
getshell
的,还需要和其他利用方法结合才能
实验一
- 在ubuntu16.04glibc2.23中编译如下c程序,并详细描述堆叠的过程。
1 |
|
分析1.1
- 使用gdb进行动态调试,使用
ni
命令将程序运行到第4个malloc
之后的位置
- 使用
heap -v
命令查看堆块,发现有5个堆块,且第二个堆块的size位大小为0x41
- 再使用
ni
命令,将程序运行到第一个free
之前
- 使用
heap -v
再次查看堆块,发现此时只有4个堆块,而且第二个堆块的size
位已经变成了0x81
- 使用
ni
命令将该程序运行到第二个free
之后
- 使用
heap -v
命令查看堆块,发现被释放的俩个堆块都被放入了fast_bin
中
- 使用
fastbins
命令查看fastbin
链表,我们会看到,fastbin中管理俩个不同大小的堆块,一个是0x40
大小的(原来申请的),另一个是0x80
大小(利用off-by-one
堆叠而成的)
分析1.2
- 按照分析1.1动态调试给出的地址和值,画出堆叠的过程。刚开始堆块的结构如下。
- 之后我对
chunk0
进行写入操作,然后造成off-by-one
溢出,修改了chunk1
的size
- 所以发生了堆叠,堆叠后的chunk图如下
总结1
-
我们在
Chunk A
处触发Off-by-one
漏洞,将Chunk B
的size
域篡改为Chunk B + Chunk C
的大小,然后释放Chunk B
,再次取回,我们此时就可以对Chunk C
的内容进行任意读写了。 -
申请三个chunk
chunA
、chunkB
、chunkC
,对chunkA
写入造成off-by-one漏洞,修改chunkB
的size
位,从而造成堆叠 -
篡改
Chunk B
的size
域时,需要保证将Chunk C
完全包含,否则将无法通过以下所述的验证。
1 | // /glibc/glibc-2.23/source/malloc/malloc.c#L3985 |
- 注意:篡改
Chunk B
的size
域时,仍要保持prev_issue
位为1
,以免触发堆块合并。
实验二
- 在ubuntu16.04glibc2.23中编译如下c程序,并详细查看第二种堆叠的方式
1 |
|
分析2.1
- 使用
gdb
进行动态调试,使用ni
命令将程序运行到第4个malloc
之后,free
之前
- 使用
heap -v
命令查看,发现有5个堆块
- 然后使用
ni
命令将程序运行到free之后
- 再使用
heap -v
查看堆块,发现第二个堆块被释放了
- 再使用
ni
命令将程序运行到最后一个malloc
之前
- 再使用
heap -v
命令查看,发现发生了堆叠
实验三
- 在ubuntu16.04glibc2.23中编译如下c程序,并详细查看第三种堆叠的方式,该堆叠方式是利用off-by-null漏洞
1 |
|
分析3.1
例题
off_by_level_1
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 iyheart的博客!
评论