前言
终于抽出时间对glibc动态内存管理部分源码进行初略的探究,试着从源码和动调来分析free函数执行过程和一些pwn的攻击技巧,分析的不是很全面,有错误的地方望提出指正,共同进步。ps:欢迎白帽子们关注 涂鸦智能安全响应中心
Malloc的执行流程
情况3:申请mmap
测试代码
#include <stdio.h>
#include <stdlib.h>
int main()
{
malloc(0x20);
malloc(0x24000);
return 0;
}
申请的size 大于 av->top
执行调用链: Malloc -> int_malloc -> sysmalloc
Nb = 0x24010 > mp.mmapthreshold 且 (mp.nmmaps < mp.n_mmaps_max,满足条件进入mmap()的调用。
计算出满足页对齐的size后调用 MMAP()
申请的size大小为 0x24030 满足页对齐的size是 0x25000
执行后申请到的mmap 空间
之后对mmap 空间写入 size头,并在标志位上 打上 Mmap标志 0x2
执行效果
calloc执行流程
测试代码
#include<stdio.h>
#include<stdlib.h>
int main(){
int *p1 = calloc(0x20, 1);
int *p2 = calloc(0x20, 1);
free(p1);
calloc(0x20, 1);
return 0;
}
堆初始化执行流程
libc_calloc() -> _int_malloc(),和libc_malloc()一样的堆初始化流程,之后通过malloc_hook跳转 malloc_hook_ini(),与malloc()的区别在于会将申请的堆空间全部置零。
之后有关main_arena取chunk的申请也是通过int_malloc(),最后都会置空堆空间
整体上看calloc是一个malloc的调用接口,输出前加上了置空堆空间
realloc执行流程
测试代码
#include<stdio.h>
#include<stdlib.h>
int main(){
int *p1 = malloc(0x10);
int *p2 = malloc(0x10);
int *p_realloc = realloc(p1, 0x30);
return 0;
}
realloc调用流程 realloc->realloc_hook_ini(通过realloc_hook跳转)
清空 malloc_hook,__realloc_hook之后跳转 _libc_realloc()执行
之后进入_int_realloc()
_int_realloc()函数是一个_int_free()和_int_malloc()的结合体,释放剩余旧堆块,若申请新堆块,则复制堆块内容
先对新申请的堆块与原先堆块进行比对
若新申请堆块大于原先堆块
若新申请的size大于原先的size,尝试向top_chunk申请堆块
新申请堆块的话,需要进行数据复制,将原先堆块的数据拷贝到新申请堆块中
之后释放原先堆块
若新申请堆块小于原先堆块
若新申请的堆块小于原先堆块分割原先堆块,并且位于原先堆块中,释放剩余部分,
整体来看realloc是个功能丰富的缝合怪属于是。
realloc可以通过构造制定大小修改,实现free 特定size的remainder_chunk
realloc(0, size) 可以当做malloc(size)使用
realloc(chunk_ptr, 0) 可以当做free(chunk_ptr)使用
本文作者:Jambolt@涂鸦智能安全实验室
漏洞悬赏计划:涂鸦智能安全响应中心(https://src.tuya.com) 欢迎白帽子来探索。
招聘内推计划:涵盖安全开发、安全测试、代码审计、安全合规等所有方面的岗位,简历投递sec@tuya.com,请注明来源。
发表评论
您还未登录,请先登录。
登录