记录一些堆题的练习。
gdb调试命令
1 | p *_IO_list_all |
libc2.27
特征
引入了tcache
堆管理机制,__free_hook
和__malloc_hook
都还在,通过bk
指针检测是否存在double free
。
UAF
例题信息:
1 | 来源:zjctf2022省赛初赛-babyheap |
MENU:
1 | int menu() |
ADD:
1 | int add() |
EDIT:
1 | ssize_t edit() |
SHOW:
1 | int show() |
DELETE:
1 | void delete() |
思路1,也是EXP的思路
1 | 1. 构造double free,泄露出heap_base的地址 |
EXP1
1 | from pwn import * |
思路2,参考Nameless_a
1 | 1. 构造double free,泄露出heap_base的地址 |
EXP2
1 | def exp(): |
libc2.31
特征
__free_hook
和__malloc_hook
都还在,可以劫持。
libc2.35
特征
libc2.34
之后的版本利用手法暂时无差别,__free_hook
、__malloc_hook
和__realloc_hook
已被删除,基本是IO
链利用的主场。
UAF1
例题信息:
1 | 来源:柏鹭杯-note2 |
MENU:
1 | int print_menu() |
ADD:
1 | int op_malloc() |
DELETE:
1 | void op_free() |
VIEW:
1 | int op_view() |
LEAVE:
1 | if ( number == 4 ) |
思路
1 | 1.申请并释放0x80的堆块,填满tcache bin,溢出一个到unsorted bin,即可泄露出libc_base、heap_base |
调试信息
劫持 _IO_list_all
为目标堆:
目标堆即fake_IO_list_all
结构体构造如下:
伪造的_wide_data
结构体如下,其余值均为0,伪造了_wide_vtable
:
伪造的_wide_vtable
结构体如下:
最后通过exit()
触发如下的链子:
1 | ► f 0 0x7fa1a3283c14 _IO_wdoallocbuf+36 |
EXP
1 | from pwn import * |
UAF2
例题信息:
1 | 来源:zjctf2022决赛-HodgePodge |
ADD:
1 | ssize_t menu() |
DELETE:
1 | void sub_144C() |
EDIT:
1 | __int64 sub_13B6() |
SHOW:
1 | __int64 sub_14B9() |
思路
1 | 1. 申请一系列的largebin大小的堆,释放一个进入unsorted bin,泄露出libc_base,申请一个比unsorted bin中堆块大的chunk,则unsorted bin中的free_chunk进入large bin,泄露出heap_base |
调试信息
劫持stdout
为目标堆:
目标堆即fake_IO_2_1_stdout_
结构体如下:
伪造的_wide_data
结构体如下:
伪造的_wide_vtable
结构体如下:
最后通过puts
触发如下链子:
1 | ► f 0 0x7f840de83c14 _IO_wdoallocbuf+36 |
EXP
1 | import logging |