xctf_BuggyAllocator复现
程序有 alloc 和dealloc两个选项
1 | __int64 menu() |
,其中alloc申请大于 0x80 会使用malloc函数分配内存(ptmalloc2),小于等于 0x80会使用自定义的堆管理器去分配内存
1 | _QWORD *__fastcall alloc_memory(size_t size) |
自定义的堆管理器维护一个free_list,申请内存的时候,当free list中没有申请大小的堆块时,就会调用refill 填充空闲区域(arena_end - arena_start),填充完后free list中拿,当空闲区域不够refill的时候会判断free list中有没有更大的堆块可以进行refill,如果都不满足会调用malloc申请名称
1 | _QWORD *__fastcall refill(unsigned __int64 size) |
存在漏洞的地方是建立链表的时候不会将最后一个obj的next指针置空,可以通过堆块上残留的数据伪造一个指针破坏链表,实现任意地址分配
1 | for ( i = 0; i != nobjs - 1; ++i ) |
利用的思路是,首先申请大量的堆块,使arena_end - arena_start尽可能的小,这样申请小块内存的时候,建立freelist,会优先从free list中的大堆块中建立,而不是从后面空闲内存那建立,利用大堆块中残留的数据伪造next指针破坏freelist实现任意地址写,写IO_2_1_stdout 通过puts的利用链将libc的地址泄露出来后,再通过environ泄露栈地址,最后写rop
关于puts函数泄露任意地址 IO_2_1_stdout利用链的分析
https://a1ex.online/2020/08/31/IO-FILE%E6%B3%84%E9%9C%B2libc%E5%9C%B0%E5%9D%80/
简单来说 当 write_ptr > write_base时 ,会将write_base这个地址中大小为 (write_ptr - write_base)的数据泄露出来,
其中flag要为特定值才能绕过前面几个cmp,write_end要小于等于 write_ptr
exp
1 | from pwn import * |