【平安CTF赛题】解题思路总结
第五届平安集团CTF大赛已经顺利落下帷幕,本文将对本届比赛的初赛和决赛进行出题思路与解题思路的分析和总结,供新老参赛选手参考。文中的例题均为本届CTF真题,可以在零号平台进行练习。
初赛
初赛是典型的CTF模式,即解题模式。解题模式的赛题之间没有关联性,因此参赛队伍可以任意选择擅长的题型进行解答。赛制采用均分制和一血制,即每道题的分值由解答出该题的队伍均分,并且前三个解答出某道题目的队伍会有额外加分。
这就意味为了获取胜利,参赛队伍需要尽可能快地解答出容易题以获得一血加分,尽可能多地解答出困难题以避免分数被稀释,所以参赛队伍内部可以提前分工,按照各自擅长的领域,快速浏览各题型的题目,对于直觉上比较有把握的题优先解答,争取获得一血加分。
回到题目本身,总体而言CTF考察的是套路,即对各类知识点和解题方法的熟悉程度,如果能够掌握常见套路,在比赛时看到题目,基本上就能把考点猜个八九不离十,进而使用对应的解题方式去尝试。
与真实世界的黑盒测试不同,CTF的题名和题干是包含解题线索的,所以选手在答题过程中要仔细审题。
从出题角度来看,常见的考点就那么些,为了确保题目的难度,通常有两种做法,一种是在一道题中加入多个考点,另一种是挖掘新的考点。
对于第一种方式,我们在出题时会尽量避免单纯的堆砌考点,保持题目的连贯性,保证选手在解决了一个考点后能够得到下一个考点的线索。对于第二种方式,命题组中确实有大神能够编写出没见过的题,但多数情况还是参考商业比赛中的新题的出题思路进行出题,即使是没见过的题,知识点总是见过的,无非是换种方式表现出来,所有总体而言,平时多做题,举一反三是非常有用的。
CTF中常见的题型包括MISC、WEB、REVERSE(MOBILE也是REVERSE的一种)、PWN、CRYPTO等,下面按照题型分别介绍出题与解题思路。
MISC

以“大隐隐于市”为例:
首先拿到的是一张图片,显然按照一般思路这是一道图片隐写题。查找flag字符串和查看文件属性,发现有flag字符串,通过观察图片标志位,显然这里已经在图片外面了。

那么尝试使用binwalk分析以下文件尾部是否有拼接其他文件,显然拼接了一个压缩包。

但是这个压缩包并不在flag字符串的位置,仔细观察flag位置,发现上面有残缺的zip文件头,补全后可以获取flag所在的压缩包,需要密码,先放一放。
文件尾部的压缩包也有密码,先不急着爆破,观察后发现压缩包内部的文件都是四个字节,符合CRC碰撞的要求,那么使用CRC碰撞即可知道文件内容。

显然这不是flag,只是部分线索,需要进一步分析题目。使用stegsolve观察图片的最低有效位和各个通道,没有发现可疑内容,那么很可能使用了专用的隐写算法。经过尝试发现使用了盲水印,得到第二个线索。

使用线索中的密码解压含flag的压缩包,获得flag。
WEB
WEB题是比赛中题目占比最大的题型之一,主要考察选手对常见web漏洞的了解,代码审计以及绕waf能力,一般而言考点都是出题者构造的漏洞,并且有一定的防护手段,因此常见的扫描器都是无效的,选手需要手动测试。考点涉及的漏洞都是常见类型的漏洞,比如sql注入、文件上传、命令注入、反序列化等。
对于代码审计题,需要选手掌握java、python、php等常见服务端编程语言的语法和漏洞成因,根据源码构造payload。
对于黑盒测试题,可以根据返回页面的功能大致确定漏洞点,在尝试利用过程中如果发现了waf,需要针对性地绕过,使用常见的绕过方式进行尝试,确定绕过方式,最后编写绕waf的payload获取flag。
以“来找茬”为例
根据题目说明以及页面返回的内容基本可以确定是针对nodejs服务的攻击。

首先需要绕过登录认证,使用nosql注入进行绕过,登录后看一个上传页面,那么可能是nodejs的express-upload组件漏洞以及nodejs的原型污染导致的rce,构造相应payload即可,不需要绕过waf。

REVERSE和PWN
REVERSE和PWN题本质上属于一类题,主要考察选手的二进制分析能力,门槛较高,但是脑洞较少,只要选手基本功扎实就能拿到分数。REVERSE针对Windows、Linux、Android和iOS下的可执行文件和固件。iOS题和固件逆向题由于需要专用的硬件设备,考察的知识点也比较冷门,选手可以选择性放弃。
拿到REVERSE题的第一步是以通过后缀名和文件头确定二进制文件的类型,并使用对应的反编译工具对二进制文件进行反编译,可常见的二进制文件及对应的反编译工具见下表。
较低难度的题目在逆向后能拿到完整的汇编和源码,flag可能直接硬编码在代码中或是资源文件中,仔细阅读代码即可。
中等难度的题目会在代码中实现一个编码或是加密算法,需要根据算法和题干倒推flag,此时就要确定使用的编码或者加密算法。
选手需要熟悉常见编码和加密算法的特征,比较简单的算法如异或、ASCII和HEX等可以直接看出来,自定义的算法一般也不会很复杂,可以通过阅读源码分析出来,较为复杂的标准加密算法一般出题者不会去修改内部实现,最多修改一下配置,如Base64修改一个字典,MD5修改初始向量,可以使用一些算法识别插件辅助分析。如果代码量比较大,可以通过执行题目程序时的提示信息反向查找字符串引用,在从打印字符串的位置向上查找考点算法。
较高难度的题目会增加反调试或是加壳,此时就需要动态分析,调试工具包括windows下的od、windbg、x64dbg,linux下的gdb,android的android killer等。反编译工具IDA也可以进行调试,主要针对Android的so文件。
对于反调试,需要选手熟悉常见的反调试方式,找到对应的反调试代码进行patch。对于加壳,可以使用脱壳机试试,不行的话可以使用esp平衡原理手动脱壳。
PWN题一般是Linux下的可执行文件,和REVERSE类似,拿到题第一步是使用IDA逆向成汇编,查看代码逻辑。
PWN题的代码逻辑一般比较简单,在查看代码的过程中需要关注常见的可能有溢出漏洞的函数,如scanf、puts、gets、fputs、fgets、read、write等,通常都是没有严格校验输入长度导致溢出。
确定漏洞点后使用gdb进行安全性检查和调试,根据安全性配置确定payload,根据题目给与的条件确定system函数的地址或是构造gadget,使用pwntools编写poc脚本进行验证。
以“simple-antidebug为例”
拿到apk包后进行反编译,看到主界面onClick的回调调用了native层的submit函数。

进一步反编译so文件,从导出表中找到导出的submit函数,查看伪代码,发现调用了encode函数并和固定字符串比较。

其实这里根据字符串的特征基本推测可能是base64编码,观察encode的算法,进一步确认是base64算法,并且使用了自定义的字典table。

直接使用table的内容解码发现错误,通过查找交叉引用发现table经过transform函数的处理,而transform函数通过initialize函数的调用,在初始化时自动执行。根据transform函数的逻辑,转换字典即可解码。
CRYPTO
决赛
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/