原地址:https://blog.csdn.net/qq_31481187/article/details/73612451
原作者代码是基于linux系统的演示代码,因为windows和Linux 内存管理机制上略有不同,该程序在Windows需要稍微做些改动。
- Windows上执行free释放malloc函数分配的内存后,内存地址一般不被收回,从Windows7到Windows11都是这样,这一点根Linux完全相同。
- Linux上再一次调用malloc后,返回的是上一个fee掉的内存地址;而window不同,free执行后再一次执行malloc,两次的内存地址不同。
- 基于第二点,代码没有再次申请内存,而是直接在free掉的内存地址上修改函数指针,达到了同样的效果。
源码如下:
#include <Windows.h>#include <stdio.h>
#include <cstdlib>
#include <string.h>#include <stdlib.h>
#include <conio.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]((char*)"hello world\n");free(p1); //在这里free了p1,但并未将p1置空,导致后续可以再使用p1指针p1[3]((char*)"hello again\n"); //p1指针未被置空,虽然free了,但仍可使用.p1[3] = evil_fuc; //在这里将p1指针里面保存的echo函数指针覆盖成为了evil_func指针.p1[3]((char*)"cmd /c calc.exe");_getch();return 0;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]((char*)"cmd /c calc.exe");return 0;
}
执行结果截图如下: