Off By One & chunk_extend
Off By One
概念
单字节缓冲区溢出:
- 循环次数设置错误
- 字符串操作不合适
strlen不考虑\x00来计算长度,但是strcpy会把\x00一起复制if(strlen(buffer) == 24){ strcpy(arr,buffer); }如果
arr的大小是24,但是实际上会拷贝25个数据。
又叫栅栏错误。
是差一错误的一种。
应用
应用广泛(大概),这道题里用的他更改下一个chunk的size域,达到overlap的效果。
chunk_extend
如何获得各个chunk位置
在ptmalloc中,chunk_header是定位前后chunk的重要依据。
- 获取下一chunk
当前指针加上header中size的大小。 - 获取前一chunk
当前指针减去header中pre_size的大小。
判断是否在使用
- 判断前一chunk是否在使用当中
size中的pre_inuse标志。 - 判断当前chunk是否在使用当中
查看下一个chunk的pre_inuse标志。 - 判断下一chunk是否在使用当中
查看下下一个chunk的pre_inuse标志。
原理
通过更改chunk_header的数据,可以让一个chunk中包含另一个chunk,从而实现跨越chunk的操作——overlapping。
trick
- 当需要malloc的长度(size)没有和
0x8对齐时(64位),实际分配到的chunk大小将会是size & (~0xf)。少的内存由相邻下一个chunk的pre_size补上。
思路
流程
是一个常见的分配堆,释放堆的题目。
-
分配
首先malloc(0x10)创建一个结构体,里面存储size和指向content的指针。此后的操作都是在这个结构体里面获得数据。然后用户指定大小分配内存存储
content。 -
释放
会把结构体和
content的内存释放,并将结构体的指针置空。 -
提供编辑和打印功能
漏洞
在删除函数中人为地创造了一个off_by_one的漏洞。
利用
-
分配两个
content,content_0大小见trick,content_1大小需要和结构体大小相同【原因见后】,程序会分配4个chunk。其中两个是结构体。
注意这里struct_1和content_1的大小和地址。 -
编辑
content_0,使struct_1的size大小为struct_1和content_1的大小之和。
在更改了struct_1的size之后,gdb解析的heap中就没有content_1了 -
delete(1)
fastbin中的原有struct_1被放进了0x40的bin中。 - 分配
0x30大小的content
系统会先在fastbin找有没有0x20和0x40大小的chunk来作为struct和content,于是原有struct_1&content_1就被分配给了新的struct和content。content_1大小要和struct相同的原因但是这两个实际大小都是
0x20。

当向
content_2写入数据,就可以覆盖到struct_2。
【题目中编号仍为1,此处只为容易分辨】构造chunk如图。

-
打印
content_2
前面说到所有有关content的操作都是根据struct中存的数据来的。
打印是打印struct中存的地址指向的位置。在此处改为free_got计算后即可得到libc基址。 - 编辑
content_2
其实已经成为改got表的操作了。
将free的got表改为system的地址。
调用free的时候,参数是struct的存的地址,也就是*(struct->addr)。
所以我们可以在一开始构造content_0的时候,就把内容改成/bin/sh\x00,当delete(0)的时候就是system("/bin/sh");。
exp
1 | |
atoi
这里也可以改atoi,在choice:的时候限制4个字节,输入sh\x00就可以了。
一个问题
- 为什么在glibc2.27里面跑的时候,fastbin里面是空的。但是getshell是可以的?