0%

Ptmalloc算法:hook劫持

Ptmalloc算法:hook劫持

利用hook机制,把某个函数的hook劫持为shellcode

这种技术在堆利用中很常见,想要了解它,必须先了解hook机制


钩子hook

hook直意为钩子又叫做回调函数,是一种特殊的消息处理机制,它可以监视系统或者进程中的各种事件消息,截获发往目标窗口的消息并进行处理

在程序中设置钩子,用来在 mallocreallocfree 的时候,对其进行检查,可以看到对应的函数调用后的地址是什么

原理:

hook本质上就是一个函数指针,可以指向不同的函数,从而完成不同的功能

设计理念:

我们在写main函数的时候,可能还不知道它会完成什么功能,这时候留下函数指针作为接口,可以挂上不同的函数完成不同的功能,究竟执行什么功能由钩子函数的编写者完成,钩子的出现体系了程序模块化的思想

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "stdio.h"

void fun1(void)
{
printf("i am fun1\r\n");
}

void fun2(void)
{
printf("i am fun2\r\n");
}

int main(int argc, char const *argv[])
{
void (* fun)(void); //定义一个函数指针

fun = fun1; // 让fun指向fun1(首地址)
fun(); // 执行fun

fun = fun2; // 让fun指向fun2(首地址)
fun(); // 执行fun

return 0;
}
1
2
3
➜  [/home/ywhkkx/桌面] ./test
i am fun1
i am fun2

这里的函数“fun1”和函数“fun2”就是hook把函数指针fun指向fun1和fun2的过程称为“挂钩子”

libc中的hook

libc中最常见,也是堆利用中最常见的两种hook:malloc_hook,free_hook

接下来以“malloc_hook”为例,分析一下hook的具体实现:

ptmalloc 定义了一个全局钩子 malloc_hook,这个钩子会被赋值为 malloc_hook_ini 函数

1
2
void *weak_variable (*__malloc_hook)
(size_t __size, const void *) = malloc_hook_ini;

而函数malloc会调用 malloc_hook ,那么在 第一次调用malloc函数 时会执行 malloc_hook,也就是执行了 malloc_hook_ini

1
2
3
4
5
6
7
static void *
malloc_hook_ini (size_t sz, const void *caller)
{
__malloc_hook = NULL;
ptmalloc_init ();
return __libc_malloc (sz);
}

可见在 malloc_hook_ini 会把 malloc_hook 置空,然后调用 ptmalloc_init 函数,完成对 ptmalloc 的初始化,最后再次调用 malloc_hook,但是这次的 malloc_hook 已经置空,从而继续执行剩下的代码

第一次调用:

1
malloc(__libc_malloc) -> __malloc_hook(malloc_hook_ini) -> ptmalloc_init -> __libc_malloc -> _int_malloc

再次调用:

1
malloc(__libc_malloc) -> _int_malloc
  • malloc_hook_ini:对malloc_hook进行初始化的函数,代码已给出
  • ptmalloc_init:对整个ptmalloc框架进行初始化的函数,以后分析
  • __libc_malloc:用于初始化malloc,以后分析
  • _int_malloc:用于内存分配的函数,是ptmalloc的核心点,以后分析

最后,malloc_hook会指向一个“检查函数”

1
void * function(size_t size, void * caller)

caller:表示用malloc申请空间的“可写入地址”( fd&bk 所在处)

使用malloc的时候就可以返回其“可写入地址”了

hook劫持

hook劫持的基本操作就是:在hook的地址中写入shellcode的地址,可以把hook地址写在某个固定地址上,然后在这个地址中写入shellcode,这样就挂钩完毕了

那么问题的关键就是找hook的地址:

一,如果知道libc版本,可以直接引入libc库,用ELF工具进行查找

1
2
free_hook = libc_base + libc.sym['__free_hook']
malloc_hook = libc_base + libc.sym['__malloc_hook']

这种方法需要泄露libc基地址

二,还可以用“main_arena”来定位“malloc_hook”

malloc_hook位于main_arena上方16字节

当small chunk被释放时,它的fd、bk指向一个指针,这个指针指向top chunk地址,这个指针保存在“main_arena+0x58”

找到合适的small chunk再free掉,然后通过“main_arena”获取“malloc_hook”

​ // 等到分析 Unsortedbin attack 的时候,再分析这种hook劫持技术