0%

网鼎&拟态总结

​ 上一个星期去了强网拟态和网鼎杯的线下赛,总计参与做出了3道pwn题。强网拟态的强度是让人一直在打并且沉浸在里面的,网鼎杯只有4小时ctf时间说实话对我来说是真的太短了,我出的这3道pwn题跟平时的堆题不一样,这三道堆题让我得到了更广阔的视野和更有用的shellcode编写能力,简单来说就是对我的影响很大,这里就来简单分析一下一路上做题的心得和感受。

QWNT

​ 如果要我选择这两个比赛谁带给我的影响最大?那么我将毫不犹豫地选择强网拟态,强网拟态ctf上了三波题,我只看pwn,但是我菜,题目看上去很难,其实一点也不简单。

​ 不过这里并不急着聊聊CTF,而是聊聊qwnt的iot/车联网和无人机固件,本来以为就是简单的用firmware之类的固件分析软件分析,找到一个vuln相关的ELF文件,但是呢实际上并不是这样的。在qwnt的前几天的突击学习也让我学到了很多车联网安全的系统理论,虽然比赛题目一个都不会(也不能这么说,有一些场景题目,其系统崩溃就有分,只不过我们不是很懂要做什么而搞崩溃的,其实不是很有含金量),但是这一两天的学习速度相当的可怕,对车的理解也是比较清晰了。固件分析其实可以先问问AI这个固件后缀怎么分析,另一个就是搜相关产品的固件分析的方法,有一些人已经分析过了会提前写在blog上面。这里就简单说下.fw.sig,一开始想用开源的解密软件去解密sig文件,但是没有秘钥,其实怎么解密都是失败。偶然间看了别人blog,其实可以改后缀自己解压缩,就会提取出来一个bin文件,然后分析固件即可(但是我后面遇到了很大的问题,就是一个1g的bin提取了超过40G的二进制文件,我并不知道这是正常的还是非正常的。)

​ qwnt其他部分基本上就聊完了,真没做什么,因为真不会做,后来问了圈圈,发现圈圈也是这么想的,那我就放心了img。那么就来聊聊我们最熟悉的pwn吧。

jemalloc浅谈

​ 第一道放的是一道jemalloc,当时我们是大概三四个小时找不到漏洞,后来跟圈圈聊,圈圈直接说他一眼丁真就看出来了,我当时想上去就是一拳img。这并不是常规的堆分配器,而是新遇到的jemalloc,它的堆分配方式和内核真的非常相像,都有slab的概念,其实简单调一调不难理解其的堆分配过程。

​ 以我的话来概括,有一个地方存着各个大小freelist,一个地方存放着相同大小的object指针以供后来分配或者释放使用,再有一个地方就是我们的chunk了/object了,其是由一个slab切割相同大小得到的小块。

​ 漏洞不仔细看真不好看出来,之前确实没有想过这方面的问题,关注到case4和case6的free函数,其对指针的解析并不相同,如果你进一步fuzz,程序就会发生崩溃。

img

​ 问题就出在这里。解决了这个,后面就很简单了,就是覆写堆指针和func指针,还有泄露libc地址之类的。

heap_legend浅谈

堆风水杂谈

​ 说到这道题,就不得不艾特一下圈圈img了,tql,如果他亲手来做应该是很快秒了拿一血。但是他们当时去看kernel了(OTZ,kernel还是二血)。这道题的限制可能相对没有那么多,因为存在EAF,但是不能泄露使得这道题必定走上难题的道路。

​ 那么这道题就首先面临两个问题:“要爆破,还是要泄露?”。好的,其实两个都要,那我们要确定如何去leak?这里就涉及IO_leak stdout了,但是在2.39攻击stdout并不容易。

​ 因为我们一开始并不能拿到堆地址,而且如果使用house of rust等无需leak的方法,实际上会受到tcache的加密和unsorted 双链检查的限制。

​ 不过我们再次确定思路,如果我们一定要IOLeak,就必须要分配到libc的地址,什么bin中的chunk可以帮助我们达到这个目的呢?那必须是tcache,如果风水构造妥当,它必然是可以任意分配造成任意写的最佳答案。那么就有另一个问题出来了,就是如何利用tcache去分配libc地址的chunk。我们现在不能够泄露堆地址和libc地址,只有一个EAF,能够打largebin attack,只有tcache加解密的部分秘钥。其实让tcache分配到libc上最简单的方法就是让tcache_struct上面能够写有libc地址,如何做到呢?不急,我们先来总结我们能够做什么?

​ 基于上述条件largebin attack只能够堆地址范围内写一个堆地址,largebin可以帮助我们伪造双链,unsorted bin和small bin都有libc地址,同时双链比largebin更好伪造。那么这有一个思路就是基于unsorted bin和small bin在tcache_struct上伪造双链,这样一来就能够在在tcache_struct上面能够写有libc地址(当时就是这么想的,只不过真的没想到要怎么做)。

img

​ 如果要伪造双链,就得在它上面写两个堆地址,其实这正是largebin attack能做到的,但是我一开始尝试没有漏洞的堆风水去做,结果是并不太如意,就差一点点,不知道能不能够实现。写上libc地址之后,或者说tcache_struct染上libc之后,首先要考虑的就是如何去改写上面的libc地址。这表明我们要通过双链检测机制和unsorted bin分配机制,把chunk分配在tcache_struct上面,这一步就得去用house of water手法了,这里由于不是我做的前半部分,我就不做解析,就选择和你们一起学习去了。

​ 至此对于heap_legend的攻击思路明确,就很简单了,当然后面还有io_uring。我后面简单说一说编写经验吧。

​ 这题因为EAF的漏洞,其实我们堆的能力还是很强,这里还有第二种思路去打IO_leak。

​ 首先其实一个关键性的问题就是我们如何能够控制tcache_struct,第二个就是如何写上libc地址。我们如果先思考第一个问题,再思考我们能够打largebin attack写一个堆地址。其实也不难想到可以用largebin attack部分地位写tcache_struct上的指针。如果我们恰好第一个分配的chunk(也就是紧紧跟在tcache_struct后面的chunk)能够被覆盖,那么我们就能够控制tcache_struct的后半部分,紧跟着再写一个堆地址,再通过控制的chunk去改写,就存在可能控制整一个tcache_struct。之后也是简单的伪造双链,让tcache_struct上染上libc地址。

​ 至此第二种思路结束。

​ 对比:第一种思路利用unsorted bin两次分配通过unsorted bin拿到了unsorted chunk在tcache_struct上面。第二种思路只利用了一次unsorted bin一次分配让tcache_struct上染上libc地址。这里我就不说多了,你细品,如果品出来了,这道题绝对能给巨大的收获。

io_uring编写杂谈

​ 这道题的后半部分由我来完成:那就是io_uring的编写,以前懒得学的,还是要补回来的,┭┮﹏┭┮,也是边吃边玩边写,最后wdb的前一个晚上一鼓作气两点半写完shellcode,打通远程。

​ 这道题目ban了所有的open函数,这就必须要用到最极端的io_uring了,如何去编写io_uring的orw版本必然是shellcode学习者很难解决的一个大问题。

​ 我们这里简单说一下编写思路(用musl和glibc编译都行,看你选择用什么),具体shellcode真要学习,非常建议根据下面步骤具体写一遍。

​ 首先肯定先用c去写一遍,要用liburing库区简化整一个过程,最好只是实现一个open操作;第二就是编译出一个静态文件,拖进IDA里面去分析;第三,根据ACTF已经存在的wp,其中的io_uring shellcode其实只是完成了关键部分(比如初始化uring结构体),并且可能存在汇编代码偏差,你需要根据这些部分去完善你的orw操作(根据IDA去copy,让AI改写语法格式等)。第四,就是在简单编写的shellcode题上测试,看到底卡在哪里了,是初始化分配错误吗?还是地址分配的有问题?

​ 走完上面这四步,恭喜你,成功学会了io_uring的编写!

​ pwntools貌似有把ELF文件解析成shellcode代码的函数?这个听圈圈了解,不过我们两个都不熟悉,还是尝试手搓+copy。

wdb浅谈

​ wdb4小时的ctf pwn我只能出一题(当时就是想能出就是win),card_master。我出的时候是七解,此时距离ctf比赛结束还有一个半小时。非CTF方向的我是一点不会,web和渗透方面我也只是会简单的用用扫描工具罢了。。。

CardMaster

​ 本题libc版本2.27,Ubuntu GLIBC 2.27-3ubuntu1,老版本的2.27tcache是可以直接double free的。

​ 根据纸牌来分配堆,纸牌的花色数量和每个花色拥有的纸牌数量由你来指定。存储纸牌的信息堆块和还有花色的堆块指针的集合堆指针都在一个大堆上管理。并且有func函数指针,那么只要我们劫持func,就可以打通本题。

​ 如果你能够fuzz出来,或者能够看出来,其实这道题是存在非常好用的double free的,让我没想到的是,这道题竟然让圈圈苦苦盯了四个小时img(因为找洞的事情,那个free函数看起来太正常了,按照平常来说应该是没有问题的,但是这是libc2.27老版本)。不过后面其实测出了double free,或者看出具体有什么问题,发现之后也是很快就秒了。

总结

​ 这三天打的挺累的,因为自己确实菜,水平有限,很多不会的题目,上面解出来的题目对于我来说都是相对不那么容易的。时间过得真快,转眼过去已经大三上快结束了,回想过去,那个沉迷于pwn的少年还在图书馆苦苦研究准备新生赛ret2libc的记忆并不久远,但时间就是白驹过隙,如大江一般奔流而不复回。个人的进步遇到的阻碍却依然是以前一样的挑战,不禁让人感慨,这两年半,我到底改变了什么,我很难说出来。我选择考研,是为了更好的学习安全的知识,这确实是我热爱的,但是为什么我的热爱无法击败我面对的阻碍呢?答案或许很重要,但是眼下更重要的是,明白怎么去做。时间不等人,平生心力为何尽?一事无成空相守。剩下的时间,做自己喜欢的事情就好。

​ 我很喜欢《揪心的玩笑和漫长的白日梦》的一句词:“就在一瞬间,握紧我矛盾密布的手”,喜欢的原因可能是很有感触吧。