一、PWN
1、easy_pwn
这题是简单题,漏洞点在edit函数:
当我们edit时输入的size大于malloc申请时输入的size,多出10即可实现offbyone,这里malloc时只能小于0x100,所以很明显直接extend我们的chunk,先扩大然后free再malloc回来即可实现下溢出修改,大概思路如下:
1、extend the chunk,切割放真实地址到我们的used的chunk,泄露出来
2、修复chunk,再free,然后通过下溢出修改这个free的chunk,实现fake_chunk链入
3、改malloc_hook为onegadget,realloc调整偏移即可getshell:
1 | #coding=utf8 |
2、realloc
这题比较巧妙,结合的知识点还是不错的,下面来看看:
熟悉的菜单题,free函数有UAF漏洞,这里show函数被限制了,只有变量为0xDEADBEEFDEADBEEF才能输出,但是输入的name和info刚好在0x602090的上面和下面,很自然想到house of spirit去伪造堆块再申请出来,修改变量即可,但是由于没有堆地址覆盖,所以正常free掉这个fake_chunk是无法实现的,但是可以利用UAF漏洞,如果能实现double free的话,就可以写入FD指针,从而申请出来。
malloc的功能,能申请的堆块在fastbin以内(0x80),正常的输入content
这是666时,这里使用第4次时,会提示付出代价,但是跳过再次使用666,就可以无限次使用了,calloc的功能,申请0xA0的堆块,正常读入content,free有UAF漏洞。
好了,到这里程序就分析完了,接着就是漏洞利用思路:
1、double free的实现:
1 | magic(2,'kkkk') |
解释下,先申请0xA0的堆块,后面0x40格挡,再free掉0xA0,malloc切割出0x60,这时,由于UAF,虽然ptr处的指针还是0xA0的堆块指针,但是size变成了0x60,我们再次malloc时,得到的是新的堆块,指针放到buf中,这样buf和ptr中都有0x60的堆块指针,121实现doublefree。
2、将fake_chunk写入FD,申请出来再改写变量,这里同时可以往0x602060的FD写入0x602060,伪造double free,这样就可以再次使用这个堆块了(类似ubuntu18下的tcache的dbfree)。
3、show出puts的got,得到真实地址,接着再申请得到0x602060,改写FD得到malloc_hook-0x23处的fake_chunk,申请出来改写malloc_hook为onegadget
4、由于show后关闭了输出,onegadget一直打不通,realloc调整偏移也是不行,这里师兄提示说dbfree触发malloc_printer,会调用malloc触发malloc_hook,于是才打通了
上exp:
1 | #coding=utf8 |
3、ez_op
模拟虚拟机,没有任何防护,直接改 free 的hook 为 system函数即可,最后留下字符串 sh 为参数就能起shell。
1 | #!/usr/bin/python2 |
具体分析,emmm,跟着师傅的exp学习~
4、checkin
1 | #!/usr/bin/python2 |
用gmp库实现的RSA算法,参数 e 可控,所以可以控制其在内存中的内容。
利用解密函数泄露出heap地址和libc地址,再根据realloc 函数的特性劫持 hook 即可。
这题很秀,RAS算法实现了堆块的处理,这年头算法+二进制已经开始流行了?跟着师傅的exp学习(不会做的意思)
5、easy_rop
这题有个很明显的栈溢出漏洞,但是出题人想坑人,所以设置了个下标在栈中,所以防止下下标覆盖即可,在下标处填写我们ret到下标的偏移即可实现溢出,就这一个小坑,还有就是禁用了execve函数,所以要open,read,write来读取flag,自己写好汇编代码即可,同时要记得利用mprotect函数给bss段附上可读可写可执行的权限来执行shellcode:
1 | #coding=utf8 |
这是一道不错的栈溢出的题目,值得学习,收益就是rop链的新发现,同时锻炼下手写shellcode的能力。
6、realloc_magic
这一道题刚好可以用来复现realloc的知识
1 | realloc(realloc_ptr, size); |
这是源码函数,这里直接记住以下三条即可:(size-pre_size)我们称为阀值,分3种情况分析:
1、当size>pre_size时,如果后面有free状态的堆块,且大小合起来足够,则可以吃掉,但是ptr指针不变,如果不够,就会切割topchunk,free原来的堆块,变成新的堆块,指针变化(当topchunk都不够了,就会free掉原来的堆块,从而申请新的满足size的堆块(mmap申请),再把原来的内容拷贝过去)
2、当size=pre_size时,什么也不做,得到的chunk还是原来的chunk
3、当size<pre_size时,缩小堆块,具体就是先free掉原来的堆块,再malloc(size),而多出的部分就是free状态的
4、当size=0时,也就是说阀值等于-pre_size,那么就是free掉这个chunk,相当于UAF的free
其实重点就是1,3,4,特别是4可以造成UAF的free,漏洞很大
下面开始分析程序:
这道题保护全开:
再看看有漏洞的函数:
free有UAF漏洞
realloc没什么毛病
这是个将指针清空的函数,意味着可以重新申请一个新堆块,和之前的无关
这题就分析完了:知道的内容就这些
1、原本只能realloc一个堆块,free也是对一个堆块操作,利用ba可以申请2个堆块
2、free有UAF漏洞
下面是解题的思路分析:
1、首先没有show函数,肯定是io_file泄露真实地址
2、劫持的话要写0x7f的main_arena的地址到FD指针,因为tcache不检查size,所以直接链接到FD即可
这里实现的方法是利用realloc的拓展实现溢出操作,通过修改下一个堆块的size和FD指针,实现堆块变身从而将其从tcache中取处,再次free时,就是free改了size后的堆块,就会从原来tcache大小的箱子中去除,去到新的tcache大小的箱子中,留下的就是FD指针的堆块,这就是解题的关键!
3、利用UAF漏洞,写free_hook到FD,再次写入onegadget即可getshell
1 | #coding=utf8 |
总结:这题就是IO_File泄露地址+realloc堆块的分配操作,难在把0x7f的地址申请出来,这一步巧妙的是,通过realloc的堆块拓展,往下覆盖,改size,从而实现去除挡在FD前面的堆块,实现申请出来FD指针所在处的堆块,其他都是常规操作。
2、RE
polyre
这题是控制流平坦化,和当时SUCTF那题很像,由于程序这样分析比较复杂,所以可以用anger化简一下:
这是可以看出来,外层6重循环,每重取8个字节,内层64重循环,进行一个比较再加密,简略地看就是:
1 | i=0 |
加密的数据放在栈中,可以从内存中动态调试得到:
1 |
|
3、Misc
坦克大战的题目,挺有意思的,是一个unity 3D的游戏,直接去找Assembly-CSharp.dll文件,用ILspy反编译一下C#的代码,各个函数如下图所示:
可以分析一波各个函数,就知道逻辑在playerManager那里:
这题初始化中,对于图上的每个物品都有相应的标识:
空是8,基地是0,水是4,草地是5,砖块是1,同时打穿砖块,就会从1变成8,而基地爆了就会从0变成9,同时win的条件就是DestroyNum变成4或者5,这里是复现时,看到有张图现用了:
这题到这里就分析的差不多了,现在就是打爆砖块或者基地,使得DestroyNum变成4或者5就可以了,但是这里遇到一个排列组合的问题,由于写不出脚本,当时就gg了没做出来,赛后看了大佬的wp,果然是爆破,这是关键的一步:
1 | using System; |