8月4日
从北京出发,起飞前两小时发现机票没有买成功,立即买了一张,感谢诸位队友。到达San Francisco后与昨日航班延迟一天的队友会合,21:00多飞往Las Vegas。今年DEFCON会场从Rio迁到了Paris & Bally's。我们提前到达的在这里订了几间房间。
8月5日
在LINQ吃了一顿Hash a Go Go,一顿管一天,吃完就难受了,疼了一天,这一天什么都没做就过去了……
8月6日
准备了一天binary hardening。
8月7日
比赛分三天进行,前两天从11:00到20:00,第三天从11:00到14:00。
10:00入场,CTF比赛和其他一些活动共用一个分会场,找到会场就花了不少工夫。参赛队伍的桌上有LED灯,每轮开始会闪烁一下,似乎还能表示攻击和被打,具体规则不明。大屏幕可视化各战队攻击情况。
比赛为攻防形式(attack and defense),每5分钟为一轮,每轮主办方更新各个服务的flag文件,分析题目程序、挖掘漏洞、编写exploit攻破其他队伍的服务,获取权限访问flag以得分。主办方有service level agreement,会检测各服务的可用性,如果判断为down也会扣分。具体分数计算规则不明。
10:40左右通网,我们可以访问gamebox了,ctf@10.5.8.4,~/README
提供了一些说明。开赛前必须修改初始密码后,否则会扣分。
1 | - Important IP addresses |
队伍编号是根据决赛晋级顺序得到的。
前两年的决赛平台都是armv7,大家都觉得今年仍是ARM的可能性很大,结果是个x86-64的机器,CPU是AMD
Opteron(tm) Processor 6128 HE,Ubuntu
14.04,uname信息是Linux version 3.16.7-ckt13 (root@lxc1)
。可能所有队伍共享一个机器,用lxc隔离,每支队伍分到20GB磁盘空间。
11:00比赛开始,每5分钟为一轮,每轮主办方会更新各个服务的flag文件,分析题目程序、挖掘漏洞、编写exploit攻破其他队伍的服务,获取权限访问flag以得分。主办方有service level agreement,会检测各服务的可用性,如果判断为down也会扣分。具体分数计算规则不明。
首先开放的服务是rxc,程序在/home/rxc/rxc
,所有者是ctf;flag文件在/home/flags/rxc
,rxc用户可以读取。我们用Dropbox把文件分享给场外套房选手。
10.5.8.6
开放了sftp服务提供PCAPNG格式的流量文件,数据包文件会延迟一段时间提供。今年流量文件被处理过了,所有IP都被改成了1.1.1.1,无法判断连接发起的来源。这可能有几方面原因,如更好地隐藏service
level agreement检查流量、让选手难以根据连接发起源做检查。
服务都是使用标准输入输出进行交互的,使用xinetd
监听端口,xinetd
运行服务时会把权限drop至服务名对应的用户比如rxc
,配置文件/etc/xinetd.d/rxc
如下:
1 | service bluelotus-service |
后两个选项是主办方修改的xinetd特有的,其中killafter
用setitimer
设置了连接的超时时间,杀死卡死的进程。比如去年决赛的eliza用qemu-i386-aslr执行,CPU占用很大,经常有长时间不退出的连接,造成DoS攻击。seccomp_whitelist
结合NO_NEW_PRIVS
、SECCOMP_MODE_FILTER
等,设置了进程及子进程允许使用的系统调用。
主办方在gamebox安全上花了很大工夫,做的防护还有:
/home/ctf
的权限会被定期改成0700,大概是怕选手不慎把重要资料泄漏出去。/proc/net/tcp
等无法读取,netstat
、ss
等工具无法看到TCP连接。- 进程自身的
/proc/self/{personality,stack,syscall}
无法读取。 - 无法读取相同用户其他进程的
/proc/$pid/{auxv,environ,maps,mountstats}
等。
近15:00主办方宣布DEFKOR获得rxc的first blood,DEFKOR against PPP。实际发生的first blood应该还在这之前,开始吊打全场,比分逐步拉开。其他队伍分数相差不大,Shellphish、0daysober不久即相继防御成功,分数比余下队伍稍高些。
16:00多发现了新题ombdsu,在另外一个gamebox 10.5.8.2上,似乎是MIPS Creator Ci20,CPU是Ingenic JZRISC V4.15 FPU V0.0。
发现新题hearye.zip,ARM64的,做题得一次性分。我们没有在意,回去后才做,第二天准备提交时发现主办方关闭了题目,第一天做出来的才有分。
第一天流量混淆已经非常严重了。
HITCON似乎重放rxc成功,名次逐步上升。
19:00改了改之前ISC'14时的监控,写了一个积分榜。
第一天结束时DEFKOR领先第二名7334分。
晚上回去换了一种思路写binary hardening工具,稍晚研究MIPS的方案,希望第二天能用上。我们写出了rxc的exploit,ombdsu也有replay和exploit。
8月8日
可能大学都觉得现场嘈杂不适于解体,都不愿意来现场。10:00多来到现场,仍旧是先搭建环境。
10:40+允许访问外网,可以连接两个gamebox了,看到i386的新题hackermud,这是一个MUD游戏的客户端,程序启动时会连接主办方控制的10.5.17.4的5050/tcp。10.5.17.4:5050只允许gamebox连接,因此要让场外选手连接的话,得用SSH
port
forwarding等方式以gamebox为跳板连接。今天https://10.3.1.7/scoreboard
不再显示积分,只能看到排名。
HITCON开赛即发动第一波攻击取得tachikoma first blood。
tachikoma似乎被主办方更新了,因此没有立即换上我们的patch。换了多个修补版本,改缓冲区大小,关闭NX等,但服务持续down,不知道主办方怎么检查的。折腾了好久,13:20服务状态终于up了,再改了一会儿终于不丢flag了。
12:31给rxc换上patch似乎不再掉分。
近15:00主办方宣布有新题。发现说明文件~/readme-rpi
,是Raspberry
Pi 2上的ARM Windows
10。参赛选手无法直接管理题目所在的平台10.5.8.3,只能通过主办方提供的简易FTP更新程序,以及通过PowerShell编写的、8989/tcp上的管理服务停止、启动服务。
16:00多放出mipsel新题irkd。以/home/irkd/irkd -i 10.5.17.4 -p 666 -n /home/flags/irk_nick
的方式执行,需要连接服务端10.5.17.4
,是个类似IRC的服务。
19:00多有队员失误踢掉电源线,服务器关机,几乎所有攻击都无法打出,图为这段持续20分钟的艰难时刻:
第二天结束时名次依次为:
1 | DEFKOR |
8月9日
为了悬念,今天不再显示排名。每轮时间从300秒缩短到150秒,今天三小时大概有72轮。
开场就看到DEFKOR的badlogger first blood。
badlogger的PowerShell管理界面更新了,可以一次性kill所有进程。我们上传了修补后的badlogger,但写好的exploit打不了。之后一直在修改badlogger的exploit,比赛快结束时才弄好,提交了十几个flag。
比赛前几分钟LED狂闪,循环播放The Final Countdown,震耳欲聋,14:00比赛结束。队员们这几天睡眠缺乏,大多去睡觉了。
闭幕式
16:00闭幕式。
DEFCON一共有8个urban gaming,Capture the Flag是压轴项目。第一名是韩国DEFKOR,成员大多来自首尔大学,似乎都是Best of the Best项目的成员,这是一个培养网络安全人才的计划。第二名是两届DEFCON CTF决赛冠军PPP (Plaid Parliament of Pwning)。第三名是0daysober,欧洲多国联队,成员主要来自瑞士法语地区和法国。
结束后送出了一些吉祥物……但镇宅之宝我们队员都没拿到……
准备
参加完ISC'15 Student Cluster Competition回来已经被剥夺学校寝室居住资格了,这段故事也许之后应该再写篇文章记录。飘零,搬到了一个赛前备战的地方,做了一些东西:
系统管理脚本
下载流量文件自动切分、杀死后门进程等。今年主办方在封杀后门,营造一个纯粹的逆向、漏洞利用的比赛环境上作出的努力不可谓不大。杀死后门我着实思考了很多,不过在这次比赛上都没用上。
左上读取积分,右上下载流量,左下更新badlogger,右下用coproc实现semaphore,并行化PCAP/PCAPNG的预处理供索引工具使用。
GitHub项目:https://github.com/MaskRay/DEFCONCTFFinalsGameboxAdmin
搜索flag
在流量文件中找到flag定位攻击流量是流量分析的关键。以往使用wireshark的display
filter搜索flag,性能很差。因此我写了一个多串匹配工具搜索flag,定位后解析PCAP/PCAPNG,按frame拆分后把偏移量转换成frame.number==1337
式样的filter,方便深入检查。多串匹配采用Multi
Backward DAWG
Matching算法,网上没有找到字串长短不一时的构造算法,自己揣摩并实现了一个。大意是取最短的模式串为窗口大小,初始时窗口左端与文本对齐,检查所有与窗口右端对齐的模式串能否匹配文本。若找不到则对于所有模式串的所有前缀,找到其中最长的落在窗口右端的前缀,滑动窗口使之与该前缀对齐。
该算法需要实现多串suffix automaton/suffix oracle。General Suffix Automaton Construction Algorithm and Space Bounds提到了一种多串构建方法,但只对suffix-unique的字串集有效。研究后发现常规的单串构造算法稍加修改即可用于多串。
PCAP搜索引擎
流量分析时经幢需要搜索字串。Wireshark display
filter中的contains
很慢,因此打算自行实现。全文搜索有inverted
index和stringology算法两套思路,调研后决定使用stringology流派的FM
index。FM-index以Burrows-Wheeler Transform为核心,集成了Wavelet
Matrix、succinct bit
sequence等,趁着这次要写全文搜索引擎的机会实现了各种succinct data
structure:RRR、Elias-Fano encoding、Wavelet Matrix等。
fqj1994编写了预处理PCAP/PCAPNG,以stream为单元重组PCAP;我在对预处理后的文件建立索引FM-index;pandada8用riot.js写了前端。
计分方式和成绩
最终名次是第5名,参见http://blog.legitbs.net/2015/08/2015-def-con-ctf-final-scores.html。
15支队伍和主办方Legitimate Business Syndicate的虚拟队伍参与计分。x86-64和mipsel两个gamebox上最终开放的服务计有6个:rxc,irkd,tachikoma,ombdsu,hackermud,badlogger。每支队伍的每个服务初始被分配1337个flag。每一轮若service level agreement不通过则丢失14个flag,平均分配给其余14支参赛队伍;若token被其他队伍提交,则丢失14个flag,平均分给攻击者,余数给legitbs,legitbs趱到的flag会参与以后的分配。不清楚SLA不通过且被攻击会如何计分。最终得分是所有服务flag数和+4011。
ARM64题hearye.zip即为livectf_quals
,只有第一天解出的队伍才有分,前三名分别得到600、300、200个flag,其他得到100个。第二天被允许参加livectf_finals
的队伍中第一个解出的PPP得到1000个flag。这些flag参与到计分,一个即为一分。
我希望flag数用浮点数表示。
Team | Score | rxc | irkd | tachikoma | ombdsu | hackermud | badlogger | livectf_quals | livectf_finals |
---|---|---|---|---|---|---|---|---|---|
legitbs | 41524 | 2 | 0 | 0 | 1 | 0 | 0 | 18455 | 19055 |
defkor | 23949 | 6746 | 1359 | 2624 | 3731 | 1368 | 3510 | 600 | 0 |
ppp | 19896 | 3488 | 1179 | 3859 | 2528 | 1368 | 2263 | 200 | 1000 |
0daysober | 17943 | 2095 | 1284 | 1605 | 6216 | 1338 | 1294 | 100 | 0 |
hitcon | 13560 | 2304 | 1329 | 3871 | 3 | 1338 | 604 | 100 | 0 |
blue-lotus | 12442 | 876 | 1299 | 1465 | 2078 | 1323 | 1390 | 0 | 0 |
0ops | 11306 | 2170 | 1389 | 1103 | 1 | 1383 | 1249 | 0 | 0 |
dragonsector | 11288 | 2190 | 1389 | 1220 | 461 | 1323 | 694 | 0 | 0 |
samurai | 10742 | 0 | 1254 | 1129 | 802 | 1278 | 2168 | 100 | 0 |
shellphish | 10591 | 128 | 1419 | 379 | 2057 | 1338 | 1159 | 100 | 0 |
lcbc | 9941 | 0 | 1359 | 1600 | 39 | 1353 | 1279 | 300 | 0 |
spamandhex | 9461 | 0 | 1344 | 286 | 1578 | 1368 | 874 | 0 | 0 |
team-9447 | 8410 | 55 | 1404 | 387 | 1 | 1383 | 1069 | 100 | 0 |
gallopsled | 8608 | 0 | 1359 | 527 | 559 | 1353 | 799 | 0 | 0 |
corndump | 7508 | 1 | 1299 | 0 | 0 | 1338 | 859 | 0 | 0 |
bushwhackers | 7447 | 0 | 1389 | 0 | 0 | 1203 | 844 | 0 | 0 |
评论和爆料
今年不限制决赛参赛人数,得以成行。每年都希望多做一些,今年又朝这个目标多努力了一些。遗憾:尽管参加了三年DEFCON,但一直都没机会参加Capture the Flag以外的其他活动。
今年DEFCON CTF决赛的特点是可执行文件变得很大,梳理脉络变得尤为困难(这点向PPP讨教过,他们也这么认为),我们可以从中看到题目向实际应用靠拢的趋势。
三年参赛,我们也是一支经验较充足的队伍了,但也能看到名次进一步提升的天花板。对于很多成员不是安全专业从业者的我们来说,取得这个名次已属不易,算是发挥出了正常水平,在协作和准备上做出的准备也看到了成果。CTF竞赛和安全有很大关联,但水平到一定程度后还需要大量训练才能继续提高。对于大多数人而言,把精力投资在这方面价值远不如花在其他领域大。赛棍也许是存在的,但和算法竞赛相比仍差得很多。
提升竞争力的核心是逆向工程和漏洞利用能力。这方面我们与顶级强队仍有巨大差距,在其他方面如流量分析还有一定增长空间。Day 1四个小时后DEFKOR rxc first blood吊打全场,各队分数都差不多,随后HITCON成功重放,升到第二。善于防御的Shellphish很快修补服务。即使如此,各队分数差不了太多,攻击速度至关重要。小道消息:Day 1 geohot没来助力PPP,但晚上就到了,莫非是第一天状态太差就立马赶来救援?geohot震惊自己一晚上才解出来的题竟然被那个韩国人(lokihardt)用4个小时做出来了……最后PPP应该解出了所有的题目。但是主办方没通知irkd服务从监听0.0.0.0改为监听127.0.0.1,让ricky以为此题一直在维护状态而少拿了好多分。颁奖时韩国领队(?)说lokihardt "solved all the challenges"。关于我们,引用一句话:以其努力程度之低,还不到拼天赋的程度。