原地址: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;
}
执行结果截图如下: