1.5.8 glibc malloc

下载文件

glibc

glibc 即 GNU C Library,是为 GNU 操作系统开发的一个 C 标准库。glibc 主要由两部分组成,一部分是头文件,位于 /usr/include;另一部分是库的二进制文件。二进制文件部分主要是 C 语言标准库,有动态和静态两个版本,动态版本位于 /lib/libc.so.6,静态版本位于 /usr/lib/libc.a

这一章中,我们将阅读分析 glibc 的源码,下面先把它下载下来,并切换到我们需要的版本:

  1. $ git clone git://sourceware.org/git/glibc.git
  2. $ cd glibc
  3. $ git checkout --track -b local_glibc-2.23 origin/release/2.23/master

下面来编译它,首先修改配置文件 Makeconfig,将 -Werror 注释掉,这样可以避免高版本 GCC(v8.1.0) 将警告当做错误处理:

  1. $ cat Makeconfig | grep -i werror | grep warn
  2. +gccwarn += #-Werror

接下来需要打上一个 patch:

  1. $ cat regexp.patch
  2. diff --git a/misc/regexp.c b/misc/regexp.c
  3. index 19d76c0..9017bc1 100644
  4. --- a/misc/regexp.c
  5. +++ b/misc/regexp.c
  6. @@ -29,14 +29,17 @@
  7. #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23)
  8. -/* Define the variables used for the interface. */
  9. -char *loc1;
  10. -char *loc2;
  11. +#include <stdlib.h> /* Get NULL. */
  12. +
  13. +/* Define the variables used for the interface. Avoid .symver on common
  14. + symbol, which just creates a new common symbol, not an alias. */
  15. +char *loc1 = NULL;
  16. +char *loc2 = NULL;
  17. compat_symbol (libc, loc1, loc1, GLIBC_2_0);
  18. compat_symbol (libc, loc2, loc2, GLIBC_2_0);
  19. /* Although we do not support the use we define this variable as well. */
  20. -char *locs;
  21. +char *locs = NULL;
  22. compat_symbol (libc, locs, locs, GLIBC_2_0);
  23. $ patch misc/regexp.c regexp.patch

然后就可以编译了:

  1. $ mkdir build && cd build
  2. $ ../configure --prefix=/usr/local/glibc-2.23
  3. $ make -j4 && sudo make install

如果我们想要在编译程序时指定 libc,可以像这样:

  1. $ gcc -L/usr/local/glibc-2.23/lib -Wl,--rpath=/usr/local/glibc-2.23/lib -Wl,-I/usr/local/glibc-2.23/lib/ld-2.23.so test.c
  2. $ ldd a.out
  3. linux-vdso.so.1 (0x00007ffcc76b0000)
  4. libc.so.6 => /usr/local/glibc-2.23/lib/libc.so.6 (0x00007f6abd578000)
  5. /usr/local/glibc-2.23/lib/ld-2.23.so => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f6abdb1c000)

然后如果希望在调试时指定 libc 的源文件,可以使用 gdb 命令 directory,但是这种方法的缺点是不能解析子目录,所以推荐使用下面的命令在启动时加载:

  1. gdb `find ~/path/to/glibc/source -type d -printf '-d %p '` ./a.out

malloc.c

下面我们先分析 glibc 2.23 版本的源码,它是 Ubuntu16.04 的默认版本,在 pwn 中也最常见。然后,我们再探讨新版本的 glibc 中所加入的漏洞缓解机制。

相关结构

堆块结构

  • Allocated Chunk
  • Free Chunk
  • Top Chunk

Bins 结构

  • Fast Bins
  • Small Bins
  • Large Bins
  • Unsorted Bins

Arena 结构

分配函数

_int_malloc()

释放函数

_int_free()

重分配函数

_int_realloc()

参考资料