DEFCON 25 CTF参赛记

很荣幸今年成为Tea Deliverers一员参加DEFCON 25 CTF,照例每年写游记。因为错综复杂的原因,kelwin联合blue-lotus、Nu1L、110066以及长亭科技一些实习生组成Tea Deliverers,在Plaid CTF 2017中晋级DEFCON 25 CTF Finals。

我大概两周前开始学习radare2,在缺乏实践的情况下发点微小的pull requests,很遗憾确实如所想的那样,没有在比赛中用上。正如slipper后来所说,这些人(crowell,XVilka,me(?))都喜欢折腾些奇怪的东西(radare2),然而他们的队友都不理睬他们的玩具……

DEF CON CTF PPP
RuCTFE Eat Sleep Pwn Repeat
HITCON CTF Cykorkinesis
33C3 CTF pasten
Boston Key Party HITCON
UCSB iCTF Bushwhackers
PlaidCTF Tea Deliverers
DEF CON CTF Qualifiers Shellphish
DEF CON CTF Qualifiers A0E
DEF CON CTF Qualifiers hacking4danbi
DEF CON CTF Qualifiers !SpamAndHex
DEF CON CTF Qualifiers RRR
DEF CON CTF Qualifiers Team Rocket ☠︎
DEF CON CTF Qualifiers Lab RATs
DEF CON CTF Qualifiers koreanbadass

另一支大陆战队A*0*E是上海交通大学0ops、腾讯eee、浙江大学AAA、复旦******四支队伍组成的联队,30多人,由腾讯赞助。

7月25日

libmaru做网管和系统配置。我在他的VPS上装了一个gogs用于比赛时协作开发,晚上写了一个把PCAPNG按服务端口号拆分的工具。

7月26日

我打车到San Francisco International Airport,14:00多到达Las Vegas,带了两个kelwin前几天在Amazon买的交换机给他们。kelwin、slipper、marche147 24日抵达,参加Black Hat USA 2017。slipper不愿意参赛,滞留几天观战。其他队友们昨日从北京出发,已提前两个小时抵达Flamingo Las Vegas Hotel,共11名队员来现场。libmaru似乎越来越喜欢做网管,这次用上了systemd-networkd。我们的服务器是一个Intel NUC7i3BNK,16GB内存,100GB硬盘。

晚上百度安全宴请来Las Vegas参加Black Hat USA、DEFCON等的中国信息安全人员,我见到了少量熟面孔。回酒店时,我当了回Computer Deliverer,kelwin让我给Riatre递电脑,Pwn2Own 2017长亭科技的奖品,回来后整理比赛会用到的一些工具。

在长亭科技远程参与的gyc990326之前写了RISC-V到ARM的汇编转译工具,提交到我们的git repo。

7月27日

9:00主办方Legitimate Business Syndicate发布https://blog.legitbs.net/2017/07/the-clemency-architecture.html,公布了比赛会用到的自定义架构cLEMENCy,提供了手册(指令集说明、内存映射、中断等)、去年闭幕式时有消息会用custom hardware, custom architecture, custom operating system,OS和硬件跳票了,不过自定义架构还在。这是个9-bit byte,27-bit register width,middle-endian的奇异架构。

cLEMENCy is the LEgitbs Middle ENdian Computer architecture developed by Lightning for DEF CON CTF.

Each byte is 9 bits of data, bit 0 is the left most significant bit. Middle-Endian data stores bits 9 to 17, followed by bits 0 to 8, then bits 18 to 27 in memory when handling three bytes. Two bytes of data will have bits 9-17 then bits 0 to 8 written to memory.

Register XXYYZZ → Memory YYXXZZ

Register XXYY → Memory YYXX

内存中存储的常用单位为3字节27-bit,以middle-endian形式存储的整数。而从内存中指令解码也要经过middle-endian处理。长为2~4字节的指令需要交换前两字节;6字节指令需要分成两个三字节组,交换两次。

[0000000,4000000) Main Program Memory
[4000000,400001e) Clock IO
[4010000,4011000) Flag IO
[5000000,5002000) Data Received
[5002000,5002003) Data Received Size
[5010000,5012000) Data Sent
[5012000,5012003) Data Sent Size
[5100000,5104000) NFO file
[6000000,6800000) Shared Memory
[6800000,7000000) NVRAM Memory
[7ffff00,7ffff1c) Interrupt Pointers
[7ffff80,8000000) Processor Identification and Features

NFO file是手册没有提到的section,塞了很多ROP gadget。遗憾的是比赛时我们没有发现。

与之一起发布的还有clemency-emu,一个带调试功能的cLEMENCy架构模拟器,运行在x86-64上。可执行文件称为firmware,由模拟器解释执行。

众人从Flamingo搬到Caesars Palace。explorer、gyc990326、hankein95、spine在长亭科技远程参与。我们决定用IDAPython写processor和loader插件,实现cLEMENCy架构firmware的加载、反汇编、交叉引用、函数分析。gyc990326之前一个月用RISC-V练手,写了很多IDA plugin代码,熬夜把之前写的东西改写成cLEMENCy的IDA loader和processor。他用了bitstringpydevd等库,我把bitstring去掉了。libmaru一年半前写过一些IDA plugin,在现场的其他人都不熟悉。在长亭科技远程协作的hankein95等整理了cLEMENCy一百多条指令的编码表。

14:00 kelwin去领DEFCON badge。每支队伍得到8块badge,即只有8人能去现场,想要同时去更多人就得买badge。尽管今年现场嘈杂情况比往年有所改善,大家还是更喜欢待在酒店干活。

eadom改写pwntools,把pwntools.pwnlib.tubes.sock里的recv,send改写成9-bit读写。BrieflyX在研发ROP gadget工具,实现了一些基础I/O函数。 晚上cxm搜索hello.bin里的字串,发现这个firmware静态链接了neatlibc。wxy191和marche147在逆向clemency-emu,研究函数签名。Atum提出可以使用rizzo制作签名,第二天大家做好。libmaru、Riatre等把IDA loader/processor改好。赛后和HITCON交流,他们是自行写插件制作签名的,开发能力超强。

下午大家都陆续注册了git repo帐号。

我跑去101 Track 2,radare2开发者Maijin给我展示了radare2的一些用法。radare2用于cLEMENCy的难点是9-bit需要pad 16-bit才能让IDA、radare2等工具用。radare2 disassembly是基于字节的,虚拟地址和文件偏移增长速度是一致的,难以实现。而IDA Pro虚拟地址增长速度可以和文件偏移不同,因此我们把9-bit pad成16-bit后可以正常显示,但指令读取、字符串显示等地方还有许多需要处理的。

21:00多我开始根据指令编码表写汇编器。

7月28日Day 1

2:30我的assembler已经基本能用了。gyc990326的IDA processor样板代码很多,容易滋生bug,Riatre在重构,到4:00多已经修复了大量bug。之前的processor是大量elif串起来判断是否是各条指令的,性能很低。Riatre把指令按长度分类后再用dict查询,性能提升了很多。

10:00比赛开始。主办方使用类似去年的网页界面,可以查看积分榜、下载其他队伍的firmware、上传firmware。赛制仍是零和游戏,15支队伍初始13370分。显示服务是否通过主办方的poller(服务可用性检测),但不再显示服务被攻击的标志。每5分钟一轮。为了扩大first blood的优势,PCAPNG延后30分钟才能通过sftp下载。

第一个题目是rubix,一个变体的魔方游戏,输入54字节,把魔方还原后即把输入的54字节作为shellcode执行。wxy191发现不是标准魔方,u后接u'不会还原。marche147发现以输入的前3字节作为种子生成30个随机数为魔方旋转操作。11:55 HITCON first blood。

我给PCAP search加上9-bit搜索支持,不过之后也没有人用。

出现新题quarter,是个后缀表达式计算器。13:25 HITCON再次first blood。

14:00多A*0*E的人发送恶意流量,利用腾讯挖掘的Wireshark的Multicast Source Discovery Protocol dissector漏洞,让选手们的Wireshark无法打开PCAPNG。我放弃使用tshark,根据IP/port/TCP sequence写了粗糙的TCP流拆分工具应对。 15:00多出现新题internet3,是个类似PPPoE的网络协议题,使用upwards-growing stack。marche147在做。 BrieflyX一直在写rubix的shellcode,先写了一个调用firmware里原有指令的ROP的,后来又转成纯shellcode的。 一直到15:00多才吃到午饭,呜呜。 16:00 Riatre给IDA processor加了函数识别。 eadom在弄rubix的重放。 18:10 HITCON internet3 first blood。 19:00 Riatre给IDA processor加了trace_sp支持。gyc990326加了多行字符串显示。晚上kelwin在写fuzzing工具,后来说没什么用。

7月29日Day 2

我给IDA processor加了adi/sbitrace_sp,之后加了load/store指令。 1:00多gyc990326的cLEMENCy到ARM的汇编转译工具做完预览版,但有一处segment permission的地方没有改,需要做一番修改才能用。还有不少bug,用于看程序结构还是不错的,但运算部分都不能信任。

10:00开赛,出现新题babysfirst,是一个模仿PHP的题。

11:00 marche147提出把PCAPNG弄出类似hexdump那样的9-bit dump会方便分析流量。我把这个功能整合到重组流量的工具中。

大约12:30出现新题half,也是后缀表达式计算。Riatre说这很有趣,quarter在比赛进行到1/4时发布,half则是比赛进行到1/2时。kelwin写出了exploit。

很多队伍在用PPP的patch。我们知道PPP的patch有后门,chao和Atum一直在逆向他们的RSA后门。

大约14:20出现新题legitbbs,是一个字符串处理题目,会在flag page里搜索字串。cxm在做。

libmaru发现主办方Day 2修改积分榜代码出现漏洞,可以按照firmware序列号下载到未公布的题目。slipper虽然宣称不参赛,但觉得-1 day比较有趣还是做了babyecho,用%+n解出。

slipper说为什么不愿意参赛,觉得做别人做过的题没意思,要玩0day。

我们的NUC磁盘100GB,我根据TCP流生成的文件是存储在磁盘上的,不得不定期删除一些旧流量生成的文件。

16:25 PPP legitbbs first blood。

大约17:15出现新题picturemgr。它有agency和image两个单链表,可以执行添加删除列出等操作。

大约19:35出现新题trackerd,有120KiB,五六十个命令,逆向很麻烦。赛后Shellphish的王若愚说他们发现10+洞,他修补了7个。

PASTEN picturemgr first blood。

晚上kelwin又弄出half三个exploit。

7月30日Day 3

我写了能比较精确判断flag被读的工具,筛选出攻击流量。

10:00开赛。PPP trackerd first blood。出现新题babyecho,是一个输入一个字符串,执行printf的简单题。neatlibc不带%n,主办方添加了这个格式化字符串功能,题目中对此进行了判断。kelwin等待宣布新题后约1分钟根据slipper的exploit实现first blood。主办方过来说“It's good”,因为机会对所有队伍都是公平的。HITCON确认他们也提前获得了题目,从PPP的表现来看他们也获得了。之后其他队伍修补时,有的把这个功能去掉,有的把n换成s等。

libmaru指出主办方提供的sftp可以实施directory traversal attack,有几个挂载tmpfs的目录可写,但没有任何有价值的可读文件。

14:00比赛结束,在套房的人(包括我)吃完饭,折腾到14:40到比赛现场,和A*0*E、HITCON、Shellphish等交流。Shellphish的crowell是个radare2 contributor,给了我Boston Key Party CTF的贴纸……但我好想要radare2的啊。

17:00 DEFCON闭幕式,有一段Pac-Man视频,工作人员展示,各个比赛的颁奖。最后是最受瞩目的Capture the Flag项目的颁奖,A*0*E第三名,HITCON第二名,PPP第一名(五年四冠,主办方都觉得说烦了)。Legitimate Business Syndicate从2013年起担任DEFCON CTF主办方,到今年已连续当了五年。今年是他们的谢幕演出,为此特意搞了大新闻,弄出了cLEMENCy,让大家的准备都派不上用场。这也像是他们一贯的作风,当大家都用x86时,2013年gamebox使用ARM环境。当时,没有decompiler也不懂ARM汇编、没有ARM设备、不会配环境的我们手忙脚乱;2015年弄了ARM、MIPS、x86甚至还有Windows的大杂烩;2016年顺应时势用Cyber Grand Challenge赛制;2017年引入cLEMENCy。新的DEFCON CTF主办方还在招标中,讲道理PPP当主办方是最合适的,但他们似乎不愿意。

place team id score
1 PPP 1 33850
2 HITCON 5 30631
3 A0E 10 19730
4 DEFKOR 3 18474
5 Tea Deliverers 8 13941
6 pasten 4 11332
7 Shellphish 9 10452
8 Eat Sleep Pwn Repeat 2 9369
9 RRR 13 9088
10 Lab RATs 15 8564
11 hacking4danbi 11 8521
12 Team Rocket 14 8496
13 Bushwhackers 6 6894
14 koreanbadass 7 6766
15 !SpamAndHex 12 4405
n/a Legitimate Business Syndicate 16 37

主办方说很高兴看到大家在比赛中开发了这么多工具,还特意提到了有队伍甚至实现了cLEMENCy转ARM汇编的工具(gyc990326的),很不容易。 Jeff Moss在最后提到要举办DEFCON北京分会,联想到26日百度安全晚宴出现和总裁谈笑风生的Dark Tangent……你们会看到DEFCON北京CTF吗?(喵呜呜呜,edge triggered签证过期了回国麻烦……)

Orange Tsai: PPP won so many times. Give me a chance, plz :(

robbje: Just pretend order is given in middle endian

23:00多王若愚和slipper在北京9号面馆吃饭,kelwin和我下楼找他们。slipper谈论为什么不愿参赛,因为觉得学不到新东西,觉得国内太看重比赛成绩。kelwin说大家战意低迷,他觉得队伍里还有人想玩,所以今年才又组织了一场。今年大家状态萎靡让他觉得很失望,明年也许就不玩了。

7月31日

从Caesars Palace回到Flamingo Las Vegas。下午很多队友们去Las Vegas North Premium Outlets购物,marche147、wxy和我留在Flamingo。晚上kelwin、eadom、cxm、Atum和我去Wynn Las Vegas,吃完饭后,21:30看Le Rêve表演。23:00结束,打车回Flamingo Las Vegas。

8月1日

可怜的slipper睡了好几天沙发。libmaru作息上来看似乎去了欧洲时区。众人吃了一顿自助早午餐。

PPP开源了他们的工具https://github.com/pwning/defcon25-public,代码很干净。可以看出他们赛前以RISC-V练手,各主力都参与了开发,diff RISC-V和cLEMENCy可以发现改动的代码很少。C写disassembler使得既能当IDA plugin用,又能standalone。assembler可以集成进IDA使用,nc、strings、xxd等工具也都很小但实用。我们的队员都用着自己做的方的轮子,别扭但却用得不亦乐乎。我作为一个工具提供者应该造更多轮子的,Riatre说应该赛前review gyc990326代码。能反省的地方很多。A*0*E拿了季军,老板也觉得有很多值得总结反思的地方。

8月2日

9:00我出发去McCarran International Airport,坐飞机到San Francisco后回Redwood City。大部队20:00到达机场,乘坐海南航空回北京。

感想

今年主办方准备很充分,失误很少。积分榜用递增id作为firmware链接是个安全隐患,应该使用hash或其他不易猜解的标识符。提供PCAPNG的sftp未使用ChrootDirectory,可以访问上级目录。

还有什么能做的:fuzzing、无源码给模拟器加功能、使用gdb经由模拟器调试firmware、反编译器、IDA compiler/ABI/type system支持、radare2支持。

对于没有decompiler的架构,IDA Pro、Binary Ninja、radare2等逆向框架的差距被缩小了,差别更多体现在哪一个更hackable。很可惜,熟练使用的IDA Pro的人比用其他工具的多多了。

  • 服务器100GB硬盘太紧,我不得不删除大量PCAPNG及流量分析创建的文件。对于9-bit dump的文本文件,空间浪费严重。客户端请求时即时生成比较费时,可以考虑压缩,请求时动态生成,或设法利用nginx的gzip模块。
  • 今年是五年来唯一一次每天结束后没有聚在一起总结反思,讨论战术。
  • 分工不明确,没有分享解题过程,浪费了稀缺的逆向人力。
  • 工具协作不佳。发生了若干起“不知道队友做了xx”、“不知道队友没做xx”、“不知道队友需要什么”的事件,比赛中耽搁了很长时间。BrieflyX写的shellcode手动用ml,mh拼凑一个27-bit立即数,而这个功能应该实现在assembler里。
  • 思想境界上的差异。跟风重放攻击可以进前一半,积极研发exploit才能更上一层楼。我们还在苦于如何修补服务,抄袭他人firmware,A*0*E等都在思考如何研制后门了。

PPP明洞、暗洞兼具,分工明确,研发力强,工具齐备,准备充分,求胜心切,辅以策略。差距巨大,心服口服。

Riatre出了道填空题,“五年比赛,三年第五。”(不是“五年高考,三年模拟。”)作为经历了每一场legitbs的DEFCON CTF的老人,很惭愧至今也写不出exploit。

参考