堆的UAF(use after free)利用

学长介绍了某CTF大佬聚集的交流群,但是入群需要做题,题目本来不是我这个段位可以搞定的,但是怎么说?有压力就有动力:)抱着入群的信念,
先看了misc,结果需要修复pyc文件,按流程走的时候出现了无法解决的一个奇怪问题,遂放弃;之后看了下pwn,感觉甚难;在看了逆向完全不会之后,
只能看了下pwn的tips,开始现学现卖。

原理

就像它的名字一样,即一个内存块被释放后再次被使用;主要利用的是一个指针对应的内存块被释放后,对应的指针没有被设为NULL;
而如果在这个指针在下一次被使用之前对应的内存块仍未被修改,程序可能还会正常运转;而若被已经修改,则有可能被利用,UAF就是利用该漏洞。

  • 根本原因:应用程序调用free()释放内存时,如果内存块小于256kb,dlmalloc并不马上将内存块释放回内存,而是将内存块标记为空闲状态。这么做的原因有两个:一是内存块不一定能马上释放会内核(比如内存块不是位于堆顶端),二是供应用程序下次申请内存使用(这是主要原因)。当dlmalloc中空闲内存量达到一定值时dlmalloc才将空闲内存释放会内核。如果应用程序申请的内存大于256kb,dlmalloc调用mmap()向内核申请一块内存,返回返还给应用程序使用。如果应用程序释放的内存大于256kb,dlmalloc马上调用munmap()释放内存。dlmalloc不会缓存大于256kb的内存块,因为这样的内存块太大了,最好不要长期占用这么大的内存资源。

漏洞的简单利用

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
#include <stdio.h>
#include <stdlib.h>
typedef void (*func_ptr)(char *);
void evil_fuc(char command[])
{
system(command);
}
void echo(char content[])
{
printf("%s",content);
}
int main()
{
func_ptr *p1=(func_ptr*)malloc(4*sizeof(int));
printf("malloc addr: %p\n",p1);
p1[3]=echo;
p1[3]("hello world\n");
free(p1); //在这里free了p1,但并未将p1置空,导致后续可以再使用p1指针
p1[3]("hello again\n"); //p1指针未被置空,虽然free了,但仍可使用.只是其内存块是被标记为空闲状态
func_ptr *p2=(func_ptr*)malloc(4*sizeof(int));//malloc在free一块内存后,再次申请同样大小的指针会把刚刚释放的内存分配出来.
printf("malloc addr: %p\n",p2);
printf("malloc addr: %p\n",p1);//p2与p1指针指向的内存为同一地址
p2[3]=evil_fuc; //在这里将p1指针里面保存的echo函数指针覆盖成为了evil_func指针.
p1[3]("/bin/sh");
return 0;
}

最终运行效果:

result

to

漏洞的利用方法原理上与其相同,之后会再加上入群题的解题过程

学习借鉴文章来源:https://blog.csdn.net/qq_31481187/article/details/73612451?locationNum=10&fps=1