Largebin_attack初探
Largebin_attack初探
Largebin相关知识
largebin 是指在 glibc 的堆管理中用于管理较大的堆块的数据结构。x64下largebin 的范围是 size > 0x400(x64)如果是libc 2.27及以上,其实0x400到不了largebin,而是tcache的范围,所以,在libc 2.27中,一般使用0x420,但是如果可以将0x400的tcache填满,也是可以申请到largebin的
large bin采取了分段的存储,比如第一个范围就是0x400到(48<<6),即0x400到0xc00,而其中,每个链表之间大小差为(1<<6)=0x40,结果如下:
如何获得largebin
我们释放一个大chunk时,它不会直接进入largebin,而是先进入unsortedbin中,接下来如果我们申请一个更大的堆块,这个释放进unsortedbin的chunk无法满足需求时,就会被释放进largebin
largebin内部:
因为largebin,一个bin内部并不是一个size,所以需要fd_nextsize与bk_nextsize将其串起来。
首先fd_nextsize指向比他小的最大heap,而bk_nextsize指向比他大的最小的heap,最后将两条链条首尾相连。而fd和bk和其原来的任务一样,都是指向和其大小相同的堆块

如果bin里的大小都一样的话,那么第一个释放的堆块作为此bin链的链首(这个和fastbin和tcache都不一样),fd_nextsize与bk_nextsize都指向自己,其余的大小相同的堆块free的时候,fd_nextsize与bk_nextsize就都为0了。
而fd和bk与原本作用一样,指向上一个释放的堆块,但是,这里的链头始终为第一个释放的chunk。
看个例子
1 | add(0x40) |
建了3个largebin中间建chunk防止free后合并,先将chunk1释放随后是3和5,此时再申请一个size>0x480的chunk,这三个chunk都会被放进largebin中,那么根据上述情况,此时largebin的链首是chunk1,接着是chunk3,最后是chunk2
链首chunk的fd_nextsize和bk_nextsize都指向自己,其余的chunk对应位置为0
largebin_attack
插入时利用
glibc2.29 及以下版本,可以利用 Large Bin Attack 来写两个地址。
但是在 glibc2.30 及以上版本中,只能利用 Large Bin Attack 来写一个地址。
这里拿how2heap上的例子,参考hollk师傅的文章:https://blog.csdn.net/qq_41202237/article/details/112825556
1 | // gcc -g -no-pie largebin.c -o largebin |
编译好运行一下看看:
stack_var1和stack_var2被写入了同一个较大的数,是不是感觉和unsortedbin_attack有点相似呢
下面看这一过程是如何被实现的
先在23行下断点,也就是申请p4之前
p1和p2被送进unsortedbin中
接着断在25,申请了p4
这里的过程直接引用hollk师傅写的:
1 | 1.从unsorted bin中拿出最后一个chunk(P1) |
接着释放p3进unsortedbin,为让其进largebin做准备
接下来修改p2
1 | 1.size部分由原来的0x411修改成0x3f1(要小于进入largebin的p3的size) |

这个图很直观地体现了p2,stack1,stack2之间的关系
1 | P2 --> bk --> fd = stack_var1_addr |
接下来malloc(0x90)和之前一样,把p3挂进largebin
看一下glibc2.23中malloc.c源码的3565行
victim是要被放进的p3,fwd是原来的p2,我们希望走else内的语句,那么就需要让p3.size > p2.size
1 | p3 ->bk_nextsize = p2 ->bk_nextsize = stack2-0x20 |
走完这个流程也就把p3的堆地址的值写进了stack2的地址中
接下来制定bk,bck是p2的bk指针
1 | p3->bk = p2 -> bk |
走完这个过程也就把p3的堆地址的值写进了stack1的地址中
到此&stack1和&stack2都被写进了一个堆地址p3的头指针
申请时利用
上述情况是插入时的利用,可以向任意两个地址写入堆地址
我们还可以在申请时利用
在申请largebin的时候,从最小的heap开始,利用bk_nextsize寻找合适的heap,如果找到了合适的heap,就将其取出,那么如果我们将bk_nextsize指向其他地方,就可以申请到其他地方。看下源码:
那么有两种方式:
1 | 直接将bk_nextsize指向B的头 |
第二种还可以利用unlink

此时申请large bin ,就会得到fake B的内存区域。


