VNCTF2021 Pwn
一点废话 2021年三月某个周日,安排本来是上午运动,下午打这个比赛. 然而篮球斗牛过程中被对手爆了头,昏了一整天,遂将这比赛鸽了… 过了一个月,回头看下比赛中的pwn题. ff glibc 2.32, 需要疯狂调试的一道题,令人昏迷. 程序分析 漏洞 free 后指针未清空. 坑点 没用数组存储指针, 只能控制上一个malloc()的chunk 能malloc()的最大大小为0x7F (之后会发现这点把最后利用时使用的size卡的很死) show() 只能用一次, 应该是要打stdout了 edit() 只能用两次… 2.32中, tcache_entry 中的next指针会被PROTECT_PTR函数异或处理, 使用的mask为其地址»12. 思路 利用PROTECT_PTR: 利用next值为0的chunk, 和 mask ⊕ 0 = mask 以上这个特性, show()泄露出 mask. mask存放着 堆地址 » 12. show()次数用尽. 通过UAF漏洞, edit()修改tcache_entry中的key值. tcache_entry使用用户chunk中的用户数据,key就在所谓bk指针的位置. 修改完key值,就可以绕过检查进行double free(). 通过edit()做tcache poisoning, 劫持到tcache_perthread_struct. 需注意tcache_entry->next 指向的是用户数据段, 因此需要劫持的地址需要加上0x10. 还需要用之前泄露出的mask对其做一次异或. edit()次数用尽. edit(p64(mask ^ (heap_base + 0x10))+p64(0)) tcache_perthread_struct大小为0x290, 我们把counts[0x290]覆盖成大于等于7,就能将其释放到unsortedbin中. 非常重要的一点: 记得我们在tcache_perthread_struct操作, 该chunk进入unsortedbin中会对counts[]进行污染,我们要将其清零. 同时,我们也应当为之后的利用entries[]的操作做准备,设置对应的counts[]值使其大于零. 利用unsortedbin中chunk的分割,将main_arena地址写到entries[目标大小]中. 通过partial overwrite 打到_IO_2_1_stdout_ (需要爆破,1 / 2^4). ...