劫持__mlloc_hook和__free_hook
参考资料:PWN入门(3-14-1)-劫持__malloc_hook和__free_hook (yuque.com)
附件下载:
链接:https://pan.baidu.com/s/1-o9N0IPi3bpB-6mUIGjH6w
提取码:ti3t
–来自百度网盘超级会员V3的分享
若修改__malloc_hook和__free_hook的内容,就会在malloc或free的时候执行其中的内容(函数)。
实验环境
![image-20230812111742538](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230812111742538.png)
Ubuntu版本为16.04.4,libc版本为2.23。
Demo1–__free_hook
首先看一下glibcc中__free_hook源码(libc版本为2.23):
![](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230812112818359.png)
1 2
| void weak_variable (*__free_hook) (void *__ptr, const void *) = NULL;
|
这就是__free_hook的定义。也可以看出当__free_hook中的内容不为空时,就会去执行里面的地址。
源码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#include<stdio.h> #include<stdlib.h> #include<string.h>
extern void (*__free_hook) (void *__ptr,const void *);
int main() { char *str = malloc(160); strcpy(str,"/bin/sh"); printf("/bin/sh的地址为:0x%016X\n",str); printf("__free_hook的地址为:0x%016X\n",&__free_hook); printf("system函数的地址为:0x%016X\n",&system); __free_hook = system;
free(str); return 0; }
|
pwngdb调试
在第16行下断点,运行程序,观察输出信息:
![image-20230812113311236](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230812113311236.png)
1 2 3
| /bin/sh的地址为:0x0000000000601010 __free_hook的地址为:0x0000000000600AF0 system函数的地址为:0x00000000004004C0
|
分别查看内存情况:
1 2 3 4 5 6 7 8 9
| pwndbg> x/16gx 0x601000 0x601000: 0x0000000000000000 0x00000000000000b1 #malloc_chunk 0x601010: 0x0068732f6e69622f 0x0000000000000000 #hs/nib/ 0x601020: 0x0000000000000000 0x0000000000000000 0x601030: 0x0000000000000000 0x0000000000000000 0x601040: 0x0000000000000000 0x0000000000000000 0x601050: 0x0000000000000000 0x0000000000000000 0x601060: 0x0000000000000000 0x0000000000000000
|
/bin/sh已经写入到堆空间了。
此时发__free_hook为空:
1 2 3 4 5 6 7 8 9
| pwndbg> x/16gx 0x0000000000600AF0 0x600af0 <__free_hook@@GLIBC_2.2.5>: 0x0000000000000000 0x0000000000000000 0x600b00: 0x0000000000000000 0x0000000000000000 0x600b10: 0x0000000000000000 0x0000000000000000 0x600b20: 0x0000000000000000 0x0000000000000000 0x600b30: 0x0000000000000000 0x0000000000000000 0x600b40: 0x0000000000000000 0x0000000000000000 0x600b50: 0x0000000000000000 0x0000000000000000 0x600b60: 0x0000000000000000 0x0000000000000000
|
单步继续执行 __free_hook = system;
再观察__free_hook处内存情况:
1 2 3 4 5 6 7 8 9 10 11
| pwndbg> x/16gx 0x0000000000600AF0 0x600af0 <__free_hook@@GLIBC_2.2.5>: 0x00000000004004c0 0x0000000000000000 #system函数地址 0x600b00: 0x0000000000000000 0x0000000000000000 0x600b10: 0x0000000000000000 0x0000000000000000 0x600b20: 0x0000000000000000 0x0000000000000000 0x600b30: 0x0000000000000000 0x0000000000000000 0x600b40: 0x0000000000000000 0x0000000000000000 0x600b50: 0x0000000000000000 0x0000000000000000 0x600b60: 0x0000000000000000 0x0000000000000000
|
此时__free_hook处存放着system函数地址。
我们再回顾一下__free_hook函数的定义:
1 2
| void weak_variable (*__free_hook) (void *__ptr, const void *) = NULL;
|
- 第一个参数void* __ptr指向堆中的”/bin/sh”
- 第二个参数const void *指向“system函数地址”
这两个参数准备好,当再次free任意的内容时就会触发__free_hook中的system函数,从而getshell。
Demo2–__malloc_hook
和Demo1原理相同
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
#include<stdio.h> #include<stdlib.h> #include<string.h>
extern void (*__malloc_hook) (size_t __size, const void *);
int main() { char *str = malloc(160); strcpy(str,"/bin/sh"); printf("/bin/sh的地址为:0x%016X\n",str); printf("__malloc_hook的地址为:0x%016X\n",&__malloc_hook); printf("system函数的地址为:0x%016X\n",&system); __malloc_hook = system;
malloc(str); return 0; }
|
编译运行就能getshell。
疑难-程序的内存分布
假若没有关闭ALSR,正常运行程序就会出现下面的情况:
1 2 3 4 5 6 7 8 9 10
| root@ubuntu:~/CTF-PWN/__free_hook# ./__free_hook /bin/sh的地址为:0x0000000000BF1010 __free_hook的地址为:0x0000000000600AF0 system函数的地址为:0x00000000004004C0
root@ubuntu:~/CTF-PWN/__free_hook# ./__free_hook /bin/sh的地址为:0x0000000001A72010 __free_hook的地址为:0x0000000000600AF0 system函数的地址为:0x00000000004004C0
|
从上图可以看出:“/bin/sh”所在的堆地址是随机的。
![image-20230812121347199](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230812121347199.png)
从上面可以看出,编译完成的两个文件是关闭PIE保护的。
使用gdb调试看一下内存分布,第一次调试:
![image-20230812121601003](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230812121601003.png)
第二次调试:
![image-20230812121627292](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230812121627292.png)
可以看见两次调试时,程序的堆地址并没有发生变化。
我们关闭ALSR试试
![image-20230812121907374](https://zhu-yuan.oss-cn-beijing.aliyuncs.com/Blog/image-20230812121907374.png)
1 2 3
| 查看ALSR:sysctl kernel.randomize_va_space 关闭:echo 0 | sudo tee /proc/sys/kernel/randomize_va_space 启用:echo 2 | sudo tee /proc/sys/kernel/randomize_va_space
|
再次运行程序:
1 2 3 4 5 6 7 8 9
| root@ubuntu:~/CTF-PWN/__free_hook# ./__free_hook /bin/sh的地址为:0x0000000000601010 __free_hook的地址为:0x0000000000600AF0 system函数的地址为:0x00000000004004C0 # exit root@ubuntu:~/CTF-PWN/__free_hook# ./__free_hook /bin/sh的地址为:0x0000000000601010 __free_hook的地址为:0x0000000000600AF0 system函数的地址为:0x00000000004004C0
|
关闭ASLR之后堆地址不在随机。
得出结论
当randomize_va_space=2(ALSR全开启)时,且Linux可执行文件未开启PIE保护:
- 正常运行程序(包括root权限):堆地址会随机化,代码段不会随机化
- gdb调试程序(包括root权限):程序的内存分布不会随机化
当randomize_va_space=0(ALSR未开启)时,且Linux可执行文件未开启PIE保护:
- 正常运行程序(包括root权限):堆地址不会随机化,代码段不会随机化
- gdb调试程序(包括root权限):程序的内存分布不会随机化