太久没有做堆题了,突然做一道感觉还挺有意思的(主要全都忘完了/(ㄒoㄒ)/~~)
题目考点
UAF
unsorted bin(glibc 2.31)
题目分析
题目是经典的堆题,给了2.31的libc:
1 | Arch: amd64-64-little |
分析代码,分析提供四个功能:
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
1.添加功能(add)
1 | __int64 add() |
2.显示info内容功能(show_info)
1 | __int64 __usercall show_info@<rax>(__int64 a1@<rbp>) |
3.修改密码(find_password)
1 | __int64 find_password() |
4.释放堆块(delete)
1 | __int64 __usercall delete@<rax>(__int64 a1@<rbp>) |
解题分析
在释放堆块(free
)时,题目有个if ( v2 < 0 || v2 > 10 || !chunk_state_check[4 * v2] )
来限制操作的chunk只能是未释放的。但是find_password
和show_info
并没有限制。同时,由于free功能里,清除的chunk_state_check[4 * v2] = 0;
被不是存储的chunk指针而是chunk的大小。因此造成了UAF利用。
于是,我们可以利用申请两个unsorted bin chunk 释放让其合并,再制造错位放第二个chunk的残留指针刚好可以修改password同时,info泄露出libc_addr.同时,利用残留指针修改unsorted bin chunk 大小,制造出chunk重叠,从而修改free chunk fd从而修改free_hook为system
地址。
具体步骤
1.申请chunk,制造出uaf。
1 | add(129,'lex',800,'1'*6,'y'*128)#0 |
2.通过chunk_4的残留指针 ,修改0x420 chunk的密码。再通过show功能
1 | edit(3,0,'x'*6) |
3.利用第一步就布局的chunk_5和chunk_6,来制造重叠。
通过chunk_4的残留指针,修改new_chunk_0大小0x411为0x4f1.从而为一个0xb0合并成一个unsorted bin chunk。
1 | edit(3,0,p64( 0x411+0xb0+0x30)[:-1]) |
4.然后释放unsorted chunk,而释放被包含的0xb0 chunk从而制造出堆重叠。修改0xb0 chunk的fd为__free_hook
,修改__free_hook
的值的system
.从而get shell
1 | free(4,'1'*6) |
完整exp
1 | #!/usr/bin/env python |