how2heap_libc2.27_summary
\1. fastbin_dup:
填满Tcache后free(a),free(b),free(a)之后即可。
\2. fastbin_reverse_into_tcache:
(1)申请14个chunk,都释放掉0-6进入tcache,7-13进入fastbin中。(这14个chunk大小需相等)
(2)此时mallco掉7个chunk,就可以将tcache中的7个chunk都申请出来。
(3)再利用漏洞修改chunk7的fd为栈上的地址(任意地址),这时再malloc一次,就会从fastbin中申请chunk,由于fastbin先进后出的关系,会将chunk13申请出来。同时由于tcache机制,当fastbin中对应大小的bin中还存在chunk,就会将这些Chunk都拿出来放进对应大小的tcache中。
(4)由于先进后出的关系不变,拿出顺序为chunk12,chunk11…chunk7。进入tcache后的顺序为chunk7,chunk8….chunk12。
(5)这样又由于chunk7的fd被我们改掉了,所以实际的顺序为chunk7->chunk7.fd->chunk8…
(6)同时释放可以向栈上写入堆地址,之后再连续申请就可以将从栈上申请chunk。
\3. house_of_botcake(只能在double free前提下使用):
(1)申请chunk0-chunk6用于填充tcache,然后申请chunk7,chunk8,chunk9,其中chunk9用于防止和topchunk合并
(2)释放chunk0-chunk6填充tcache,释放chunk7,chunk8,发生合并进入unsortedbin中,称为chunk_U。
(3)malloc一次,将chunk6从tcache中申请出来,然后再释放chunk8(double free),这样chunk8就会进入tcache中。现在chunk8就会既在tcache中,又被包含在unsortedbin的chunk_C中。
(4)再申请一次大小大于以上chunk_size的chunk_C,这个chunk_C就会将chunk_U切割,同时使得chunk_C包含chunk8,这样就可以从chunk_C修改chunk8的fd指针。
(5)由于chunk8同时还在tcache中,那么再连续两次chunk8大小的size就可以将chunk8和chunk8.fd申请出来,实现任意地址申请堆块。
\4. house_of_einherjar(需要泄露堆地址):
(1)申请3个chunk,chunka,chunkb,chunkc,c的真实size大于0x100;
(2)然后通过chunkb的堆溢出(off by one/null),修改chunkc的in_use位为0,并且在chunkc的prev_size处伪造fake_prev_size=chunkb+chunka-0x10;
(3)在chunka中伪造chunk,满足要求:
&Fake_chunk = chunka+0x10
Fake_chunk->size = sizeof(chunka) -0x10+sizeof(chunkb)
Fake_chunk->fd = Fake_chunk
Fake_chunk->bk = Fake_chunk
用以绕过unlink的检查。
(4)随后申请7个与chunkc同大小的chunk,释放填充tcache;
(5)释放chunkc,因为chunkc的prev_inuse位被置为0,所以会向上合并,通过fake_prev_size找到前一个堆块,即fake_chunk,并比较fake_prev_size与fake_chunk的size是否相等,如果相等则发生堆合并,进入unlink脱链。
(6)此时合并的堆块,会被放入unsortedbin中,而此时的chunkb还处于使用状态,释放chunkb(因为其大小与前面tcache大小不同,会被放入新的tcachebin中)。
(7)再申请一个大于chunkc大小的chunk,会直接从unsortedbin中去寻找划分,该chunk就是fakechunk+chunkb,且合理配置chunka和chunkc的大小使得能够覆盖到chunkb的数据,随后通过申请回来的该chunk改写chunkb的fd指针,将chunkb申请回来,再次申请就能够实现tcache poisoning攻击。
这里和2.23有点不太一样,这里利用的是再释放chunkb从而使得其进入tcache,修改fd制造tcache poisoning,因为tcache不会检查size,只要fd就可以任意申请。
\5. house_of_force:一样的,没多大差别
6.house_of_lore:和2.23差不多,没多大差别
7.large_bin_attack:和2.23基本一样。
\8. overlapping_chunks(能够溢出修改size位):
只有free之后修改size的了.
\9. poison_null_byte:
与2.23差不多,不过需要考虑到tcache的影响,有时候需要先填满tcache。一般情况是4个chunk,最后一个chunk防止合并,前三个chunk用来制造堆块重叠,但是中间其实可以插入较多的堆块,制造多个堆块重叠,方便利用。
\10. tcache_dup:基本没啥用,现在2.27也基本都修复了这个问题,不过做题的时候可以尝试一下看行不行。2.28就已经增加了key字段检查
11.tcache_ house_of_spirit:
与house_of_spirit一样,修改栈上的的chunk指针为栈上的地址,在栈上伪造chunk,只需要伪造size即可,注意in_use位的设置。同时由于tcache在free的时候不会依据chunk的size来对下一个chunk做检查,所以这里不需要伪造下一个chunk的size。
\12. tcache_poisoning:
已经在tcache链表中的chunk,如果修改了fd,那么直接两次malloc即可获得fd对应地址的chunk,不需要构造字节错位,而且malloc之后得到的chunk其pre_size和size都是0。
\13. Tcache Stashing Unlink Attack(需要calloc申请chunk,能够控制smallbin的bk指针):
(1)申请9个chunk,chunk1-chunk9,释放chunk4-chunk9进入tcache中,释放chunk2进入tcache,再顺序释放chunk1和Chunk3进入unsortedbin中。
(2)申请一个largebin大小的chunk,使得chunk1和chunk3被整理到smallbin中。
(3)申请两个chunk,将chunk2和chunk9从Tcache中申请出来,使得tcache中存在两个空位。
(4)利用UAF之类的漏洞修改chunk3的bk指向fake_chunk,这里的chunk3是smallbin中的第一个chunk:
即为图中的0x602390的bk指针,指向一个fake_chunk,栈上的地址。
(5)同时由于smallbin按照FIFO的顺序,所以依据bk指针进行寻找,那么如果从smallbin中申请chunk,申请顺序应该是0x602250 —▸ 0x602390 —▸ 0x7fffffffdd10。
(6)调用calloc,使得chunk不从tcache中申请,从smallbin中申请,那么就会触发下列在使用smallbin时,只在use tcache的宏定义中的代码:
1 | while ( tcache->counts[tc_idx] < mp_.tcache_count |
这样就会将tc_victim,也就是这里的0x602390,通过tcache_put放入到tcache中,同时tcache_put这个函数中没有任何的安全检查,所以可以直接放入。那么由于tcache的FILO关系,依据fd来申请,0x602390的fd为0x7fffffffdd10(fakechunk),所以会将fakechunk提到tcache的头部。同时又由于tcache中的指针指向的是chunk头部+0x10,那么在tcache中的顺序就是
这里的0x7fffffffdd20就是fakechunk,再次申请0xa0大小的chunk就可以将fakechunk给申请出来。同时又由于从smallbin链表中的unlink中的bck->fd = bin的赋值操作,会导致0x7fffffffdd20+0x10处会被赋值上smallbin的libc地址:
这样Tcache Stashing Unlink Attack修改bk为target_addr,malloc后会控制target_addr-0x10,会在target_addr+0x10处写入main_arena_addr。
14.unsafe_unlink:和2.23差不多,就只是申请的chunk使之大于0x410,从而不使用tcache。
15.unsorted_bin_attack:申请较大的chunk使得从unsortedbin中重新申请chunk时不会将该大小的chunk放入对应的tcache中。或者修改tcache结构体的counts域,使得系统认为该tcache已经满了,那么就不会放入了。
\16. unsorted_bin_into_stack_attack:和2.23差不多,只要满足chunk的大小大于0x408从而不使用tcache即可,或者能够修改tcache结构体的count域。