 
  2021长城杯PWN
前言
这次一共三题pwn,两题其实都是比较常见的堆题,可惜只做出了一题,还有一题堆上的orw在比赛前没能出 。不过总的来说:比之前还是进步了很多,加油
K1ng_in_h3Ap_I

毫无疑问的64位,保护全开
程序一共有着三个功能以及一个好心送我们的三字节libc地址

输入666会打印出后三字节地址
申请堆块没有特殊的,只是不能申请大于0xF0的堆块

写入功能存在着offbyone,还要注意的就是交互要输入’\n’才能结束,否则就要输入完所有长度数据

释放功能存在UAF
所以我的思路是借着offbyone生成unsorted chunk,得到libc地址,然后再将他分为一块大小为为0x70的fast chunk,借用UAF对着libc后三位进行覆盖,覆盖成stdout的地址,将堆块分配到stdout上,吐出libc地址。然后故技重施,再分配到__malloc_hook上,但是还要借用relloc调整一下才行
看了别人的wp,对于第一次把chunk分配到stdout还有别的思路:先释放一块unsorted chunk,然后申请回来0x70大小的fast chunk,此时这块chunk上也是会残留着libc地址(正常的malloc是不会清零的),然后释放两个fast chunk进入bin链,将后进的那块,借用UAF把fd指针修改成指向有着libc地址的那个chunk,这时也能将堆块申请到stdout上
| 1 |  | 
K1ng_in_h3Ap_II
来源:https://blog.csdn.net/eeeeeight/article/details/120386415

常规checksec,64位保护全开。在程序上跟上题是差不多的,少了666的地址泄露以及offbyone漏洞,但是多了打印功能,以及libc版本提升至2.27,至于2.27,就是标志性的tcache bin

然后申请的size只能是在0x10~0x60

UAF依然存在


多了一层沙箱,看到这个基本都是orw的思路:借用setcontext + 53上的gadgets,调用mprotect使得堆可执行,然后执行布置在堆上的rop链,读取flag

申请0x50的堆块是因为链上没有0x60的空闲堆块,所以申请出来的堆块是在最底下的(与top chunk相近的)并且两块是连续的,好算偏移


然后先后释放,借用UAF泄露出堆上地址,进而计算tcache地址

然后把我们之后要申请用到的堆块的count数量改为2,以及把unsorted chunk的count全部一次性改为7,为后续释放unsorted chunk进入bin链泄露libc基址做工作
| 1 |  | 

修改之前释放堆块的fd指针指向0x20堆块,而前面也修改了0x60堆块的count数量为2,所以可以申请,造成overlap,之后修改0x20堆块的size,申请0x30的堆块,(原因是这个大小的堆块是不存在空闲的堆块,所以可以全部相邻在一起,方便操作)。把底下的堆块都包含在内,记得要留一个防止与top chunk进行合并


然后释放得到libc地址
| 1 |  | 

往free_hook里面写入setcontext+53的地址
然后根据setcontext+53上的寄存器布置环境:而rdi的值是我们等下要释放的堆块的地址,根据这个计算出偏移,在对应的地址为rdi,rsi,rdx设置参数,然后设置rcx的值为mprotect的地址,去执行mprotect,再跳转回来执行shellcode读取flag

成功读取flag!
| 1 |  | 
完整exp:
| 1 |  | 
easy_vm
以后学到了,再回来复现(可能是近期 吧,近期决定爆肝学习,希望能)
- 本文作者:ShouCheng
- 本文链接:http://shoucheng3.github.io/2021/09/21/2021-09-21-2021%E9%95%BF%E5%9F%8E%E6%9D%AFPWN/index.html
- 版权声明:本博客所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!