__libc_free详解(tcache 略)
1. 检查是否存在 hook函数,如果有就执行
void
__libc_free (void *mem)
{
mstate ar_ptr;
mchunkptr p; /* chunk corresponding to mem */
/*
1. 关于__free_hook,释放时会检查其会否为NULL,否的话就执行相应的函数
2. __free_hook指向的函数,其调用的参数,为chunk中的内容
3. 将__free_hook,改为system时,需要在chunk中写入 /bin/sh
4. 将__free_hook,改为onegadget时,有时需要调整rsp
5. 貌似是在__malloc_hook下面的realloc_hook,通过push调整
*/
void (*hook) (void *, const void *)
= atomic_forced_read (__free_hook);
if (__builtin_expect (hook != NULL, 0)) //hook函数不是null,就执行__free_hook对应的函数并返回
{
(*hook)(mem, RETURN_ADDRESS (0));
return;
}
if (mem == 0) /* free(0) has no effect */
return;
/*
1. 用户指向的空间在chunk头下方0x10处,chunk头对用户是不可见的,free处理的就是chunk头
2. 因此,需要获得chunk头的指针
*/
p = mem2chunk (mem); //将指向user data 的指针转化为指向 chunk的指针
/*
1. 一般使用 mmap分配的chunk都非常的大,且chunk的地址在libc_base的上方固定偏移,因此可以用来泄漏libc的地址
2. 一般在没有size检查时使用
*/
if (chunk_is_mmapped (p)) //如果chunk是mmap分配的,就用munmap_chunk()函数释放 /* release mmapped memory. */
{
/* See if the dynamic brk/mmap threshold needs adjusting.
Dumped fake mmapped chunks do not affect the threshold. */
if (!mp_.no_dyn_threshold
&& chunksize_nomask (p) > mp_.mmap_threshold
&& chunksize_nomask (p) <= DEFAULT_MMAP_THRESHOLD_MAX
&& !DUMPED_MAIN_ARENA_CHUNK (p))
{
mp_.mmap_threshold = chunksize (p);
mp_.trim_threshold = 2 * mp_.mmap_threshold;
LIBC_PROBE (memory_mallopt_free_dyn_thresholds, 2,
mp_.mmap_threshold, mp_.trim_threshold);
}
munmap_chunk (p);
return;
}
MAYBE_INIT_TCACHE ();
/*
1. ar_ptr实际上不在heap数据段中,在libc中,是一个全局的变量
2. 当释放small chunk是,ustored bin中指向的是main_area + 88
3. 在ubuntu 16.04中,libc_base = main_area - 88 - 0x3c4b20
*/
ar_ptr = arena_for_chunk (p); //获得指向arena的指针
_int_free (ar_ptr, p, 0); //调用init函数进行释放
}
2. _int_free()函数,对chunk进行检查
static void
_int_free (mstate av, mchunkptr p, int have_lock)
{
INTERNAL_SIZE_T size; /* its size */
mfastbinptr *fb; /* associated fastbin */
mchunkptr nextchunk; /* next contiguous chunk */
INTERNAL_SIZE_T nextsize; /* its size */
int nextinuse; /* true if nextchunk is used */
INTERNAL_SIZE_T prevsize; /* size of previous contiguous chunk */
mchunkptr bck; /* misc temp for linking */
mchunkptr fwd; /* misc temp for linking */
size = chunksize (p);
/* Little security check which won't hurt performance: the
allocator never wrapps around at the end of the address space.
Therefore we can exclude some size values which might appear
here by accident or by "design" from some intruder. */
//第一个条件筛选掉一些特别大的size,第二个条件检查chunk是否对齐
if (__builtin_expect ((uintptr_t) p > (uintptr_t) -size, 0