admin

Malloc两种内存获取方式的区别

admin 安全防护 2022-12-17 383浏览 0

既然你正在看这篇文章,那么你就应该知道malloc函数是通过syscall调用从操作系统获取内存的。 如下图所示,malloc是通过调用brk或mmap这两种syscall之一来获取内存的。

Malloc两种内存获取方式的区别

1.brk方式

brk:brk是通过增设程序断点来从内核获取内存(非清零)的。最初堆段的起点(start_brk)和堆段终点(brk)是指向相同的位置的。当ASLR关闭时,start_brk和brk将指向data/bss段(end_data)的末尾。当ASLR打开时,start_brk和brk的值将等于data/bss段(end_data)的结尾加上一个随机的brk偏移。

Malloc两种内存获取方式的区别

正如上面的“进程虚拟内存布局”图展示的,start_brk是堆段的开始,brk(程序中断)是堆段的结尾。

例程如下:

/*sbrkandbrkexample*/
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>

intmain()
{
void*curr_brk,*tmp_brk=NULL;

printf("Welcometosbrkexample:%d\n",getpid());

/*sbrk(0)返回此进程的断点位置*/
tmp_brk=curr_brk=sbrk(0);
printf("ProgramBreakLocation1:%p\n",curr_brk);
getchar();

/*brk(addr)递增/递减程序的断点位置*/
brk(curr_brk+4096);

curr_brk=sbrk(0);
printf("ProgrambreakLocation2:%p\n",curr_brk);
getchar();

brk(tmp_brk);

curr_brk=sbrk(0);
printf("ProgramBreakLocation3:%p\n",curr_brk);
getchar();

return0;
}

输出分析:在增设程序中断之前,通过下面的输出,我们可以看到并没有堆段。

因此:• start_brk = brk = end_data = 0x804b000

sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$./sbrk
Welcometosbrkexample:6141
ProgramBreakLocation1:0x804b000
...
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$cat/proc/6141/maps
...
0804a000-0804b000rw-p0000100008:01539624/home/sploitfun/ptmalloc.ppt/syscalls/sbrk
b7e21000-b7e22000rw-p0000000000:000
...
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$

在增设了程序断点后:在下面的输出我们可以观察到有堆段。

因此:• start_brk = end_data = 0x804b000• brk = 0x804c000

sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$./sbrk
Welcometosbrkexample:6141
ProgramBreakLocation1:0x804b000
ProgramBreakLocation2:0x804c000
...
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$cat/proc/6141/maps
...
0804a000-0804b000rw-p0000100008:01539624/home/sploitfun/ptmalloc.ppt/syscalls/sbrk
0804b000-0804c000rw-p0000000000:000[heap]
b7e21000-b7e22000rw-p0000000000:000
...
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$

其中0804b000-0804c000是此堆段的虚拟地址范围

rw-p是Flags(可读,可写,不可执行,私有)

00000000是文件偏移 – 由于不存在文件映射,所以这里为零

00:00是主要/次要设备号 – 由于不存在文件映射,所以这里为零

0是Inode编号 – 由于不存在文件映射,所以这里为零

[heap]表示是堆段

2.mmap方式

mmap:malloc使用mmap去创建一个私有的匿名映射段。映射这个私有匿名段的主要目的是为了分配新的内存(已清零),并且这个新的内存将被调用进程独占使用。

例程:

/*Privateanonymousmappingexampleusingmmapsyscall*/
#include<stdio.h>
#include<sys/mman.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>

voidstaticinlineerrExit(constchar*msg)
{
printf("%sfailed.Exitingtheprocess\n",msg);
exit(-1);
}

intmain()
{
intret=-1;
printf("Welcometoprivateanonymousmappingexample::PID:%d\n",getpid());
printf("Beforemmap\n");
getchar();
char*addr=NULL;
addr=mmap(NULL,(size_t)132*1024,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
if(addr==MAP_FAILED)
errExit("mmap");
printf("Aftermmap\n");
getchar();

/*Unmapmappedregion.*/
ret=munmap(addr,(size_t)132*1024);
if(ret==-1)
errExit("munmap");
printf("Aftermunmap\n");
getchar();
return0;
}

输出分析:

mmap调用前:在下面的输出中,我们只能看到属于共享库libc.so和ld-linux.so的内存映射段

sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$cat/proc/6067/maps
08048000-08049000r-xp0000000008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
08049000-0804a000r--p0000000008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
0804a000-0804b000rw-p0000100008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
b7e21000-b7e22000rw-p0000000000:000
...
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$

mmap调用后:在下面的输出中,我们可以看到我们的内存映射段(b7e00000 – b7e21000,大小为132KB)与已映射的内存映射段(b7e21000 – b7e22000)拼接在一起了。

sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$cat/proc/6067/maps
08048000-08049000r-xp0000000008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
08049000-0804a000r--p0000000008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
0804a000-0804b000rw-p0000100008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
b7e00000-b7e22000rw-p0000000000:000
...
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$

其中b7e00000-b7e22000是此段的虚拟地址范围

rw-p是Flags(可读,可写,不可执行,私有)

00000000是文件偏移 – 由于不存在文件映射,所以这里为零

00:00是主要/次要设备号 – 由于不存在文件映射,所以这里为零

0是Inode编号 – 由于不存在文件映射,所以这里为零

munmap调用后:在下面的输出中,我们可以看到我们的内存映射段是未映射的,就是说其相应的内存已经释放到操作系统了。

sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$cat/proc/6067/maps
08048000-08049000r-xp0000000008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
08049000-0804a000r--p0000000008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
0804a000-0804b000rw-p0000100008:01539691/home/sploitfun/ptmalloc.ppt/syscalls/mmap
b7e21000-b7e22000rw-p0000000000:000
...
sploitfun@sploitfun-VirtualBox:~/ptmalloc.ppt/syscalls$

注意:在我们的示例程序中ASLR是关闭的。

继续浏览有关 安全 的文章
发表评论