原理
在调用malloc或者free的时候,如果 malloc_hook 和free_hook的值存在,则会调用malloc_hook或者free_hook指向的地址,假设在使用one_gadget的时候满足one_gadget的调用条件,当overwrite malloc_hook和free_hook的时候,便可以getshell,执行malloc的时候,其参数是size大小,所以overwrite malloc_hook的时候使用one_gadget的地址可以getshell。执行free的时候,可以将__free_hook的值overwrite为system的地址,通过释放(/bin/sh\x00)的chunk,可以达到system(/bin/sh)来getshell
- malloc_hook位于main_arena下方的位置(绝大多时候是-0x10),可以通过fake chunk来overwrite该值实现getshell
- free_hook 位于libc上_free_hook上,可以通过fake chunk来overwrite该值达到劫持程序流的目的
malloc_hook利用
1 | void *(*hook) (size_t, const void *) |
- 利用思路:在执行malloc时,会检测__malloc_hook的值,如果malloc_hook的值存在,将调用malloc_hook指向的地址call rax,如果我们将该值overite 为one_gadget,当程序执行malloc的时候,便可以getshell
free_hook利用
1 | void (*hook) (void *, const void *) |
- 利用思路:
- 通过改写main_arena中的top_chunk的地址,将top_chunk的值改写到free_hook上方指定的位置,通过不断向top_chunk申请chunk,最终可以分配到包含free_hook的区块,从而可以改写__free_hook的值。
- 通过改写global_max_fast的值,可以在free_hook的上方找到一个足够大包含free_hook的块,当改写了global_max_fast后,向heap申请的块都将按照fastbin来处理
- 通过unsorted bin attack 在free_hook上方伪造 0x7f大小的chunk,再通过fastbin attack 来修改free_hoook的值
realloc_hook与malloc_hook的联合利用
因为
realloc_hook与malloc_hook 相似是一个弱类型的指针.在调用realloc()函数是会判断realloc_hook的值是否为空,不为空则执行其执行的代码.这是realloc_hook的一种用法。
大多时候在执行onegadget时,并不容易满足限制条件,故而可以利用realloc()来调整栈帧以满足条件
即可以用malloc_hook来指向_libc_realloc()函数内部(即强行调用realloc())然后通过realloc_hook来触发one_gadget.
1 | void *(*hook) (void *, size_t, const void *) = |
1 | .text:000000000009AE84 41 57 push r15 |
malloc -> malloc_hook -> realloc -> realloc_hook -> onegadget
我们可以将realloc_hook改为onegadget,然后通过这些push和sub操作”微调”rsp寄存器,使其能够满足在调用realloc_hook(也就是onegadget)的时候满足相应的rsp条件。相应的利用方法就是由传统的直接修改malloc_hook变为先修改realloc_hook为onegadget之后,修改malloc_hook到特定的一个push处或sub处,然后调用malloc便相当于执行了满足条件的onegadget。
此外符号__malloc_hook与__realloc_hook在数据段中是相邻的,realloc在前
__free_hook的位置与前二者不相邻
不过_malloc_hook_ptr和\_free_hook_ptr倒是相邻的
参数也有差异,_malloc_hook与__realloc_hook的参数为申请的chunk的大小
__free_hook的参数则为释放的chunk的地址
v&n2020招新赛simpleheap
核心利用是off-by-one以及unsortedbin attack
程序的漏洞在于其edit函数存在off-by-one,以此来修改下一个chunk的size域
并利用unsortedbin的切割特性来泄露mainarena+88,来得到libc_base
再通过伪造一个fakechunk(可写hook)到fastbins链上,使得两次分配得到该chunk并覆写mallochook和reallochook
不直接覆盖mallochook为onegadget的原因是,四个onegadget的条件都不满足,故只能通过realloc函数来调整栈帧并调用reallochook为one_gadget
exp:
1 | from pwn import * |
运行有小几率会发生段错误