DEFCON 24 CTF参赛记

照例每年写游记。原本以为去年的DEFCON 23 CTF是最后一次。

每一张贴纸承载了一段故事,毕业前后的境遇对比。想当年,金戈铁马……

毕业前
毕业后

……

感谢组织今年又带上了我,达成了酱油喵的第四次DEFCON CTF之行。本次blue-lotus战队和0ops战队联合成为b1o0p,由两位队长kelwin和slipper分别带队,slipper在长亭科技实习,于是关系错综复杂。两支队伍的赞助是独立的,blue-lotus由原安全宝,现已被百度收购的百度安全XXX的赞助;0ops由腾讯赞助。

好多队员都有实习或工作,投入时间有限,也能看出大家并没有特别准备这个比赛。我大概7月28日才开始了解DEF CON CTF决赛采用的Cyber Grand Challenge平台。给0ops的队友们点赞,他们做了很多准备。

Cyber Grand Challenge

本次DEF CON 24 CTF用了Cyber Grand Challenge(CGC)的比赛平台,因此先介绍一下CGC。这是Defense Advanced Research Projects Agency(DARPA)发起的机器自动网络攻防的计划,可以与之做比较的是围棋界的AlphaGo。CGC让机器来寻找漏洞、修补漏洞、防火墙规则保护漏洞、利用漏洞。分为两轮,2015年7月3日的CGC Qualifying Event(CQE)和2016年8月4日的CGC Finals Event(CFE)。28支队伍参加了CQE,24小时内让机器自动分析约一百个可执行文件里的漏洞。

最终有7支队伍晋级CFEhttps://repo.cybergrandchallenge.com/cqe_results/

  • ForAllSecure, CMU教授David Brumley和两个学生Thanassis Avgerinos和Alex Rebert发起的startup。
  • Shellphish,主要来自University of California, Santa Barbara,还有blue-lotus的老朋友王若愚。
  • Codejitsu, BERKELEY, CA/LAUSANNE, SWI/SYRACUSE, NY
  • CSDS,Dr. Jia Song和Dr. Jim Alves-Foss
  • DeepRed,Raytheon
  • disekt,Michael Contreras, Robert Lee Harrison, Yeongjin Jang, Taesoo Kim, Kang Li, Byoungyoung Lee, Chengyu Song, Kevin J. Warrick, Insu Yun
  • TechXicians,GrammaTech, Inc和University of Virginia

CFE在Paris Las Vegas Hotel举行,队伍介绍和比赛规则参见https://s3.amazonaws.com/cgcdist/cfe/cgc-final_event-cfe-brochure.pdf。运行Cyber Reasoning systems(CRS)的7组机器据说每组造价70万美元,不同队伍的机箱闪烁着不同颜色,引入注目。观赏效果极佳,可视化效果构思巧妙,并非一味注重观赏效果而忽视展示的信息量和清晰度。解说的功力也很强,现场采访参赛选手,还能实时配上采访选手的名字、隶属机构。

ForAllSecure的Mayhem第一,Techxicians第二,Shellphish第三。Mayhem作为机器选手参加接下来三天的DEF CON 24 CTF Finals。

DECREE环境

为了便于评分、减少竞争条件、减少CTF attack and defense类比赛中不确定因素(后门、系统管理、难以自动化的琐碎规则等)、增加确定性,CGC修改Linux源码,采用基于x86-32的受限平台。

内核改动

修改了Unix System V Release 4的ELF实现,把ELF文件头从ELF改成CGC创建了一种新的可执行文件格式。不支持dynamic linking,只能static linking。

为CGC可执行文件创建了personality,设置了ADDR_NO_RANDOMIZE禁用了地址空间随机化,设置了STICKY_TIMEOUTS防止fdwait syscall修改时间戳参数。

执行CGC可执行文件时内核检查命令行参数,解析seed=skiprng=max_transmit=等参数,影响随机数、调度器和两个I/O系统调用的最大传输字节数。

CGC可执行文件启动时内核自动在0x4347c000分配一页,填充随机值称为magic page,代替了传统attack-and-defense CTF中的flag文件。命令行参数seed=skiprng=用于决定magic page的内容,把flag的生成确定化。

设置了7种系统调用,x86-32的其他系统调用均不可用:

  • allocatemmap的包装
  • deallocatemunmap的包装
  • fdwaitselect的包装
  • random,获取随机数
  • receiveread的包装
  • terminateexit的包装
  • transmitwrite的包装

Signal的处理,SIGPIPE默认行为SIG_IGNSIGSEGVSIGILLSIGBUS为coredump,其他为退出,返回值为signal值。SEGSEGV时printk通用寄存器的值。

设置CPU的CR4寄存器禁用performance monitoring center。

修改了out-of-memory killer的行为,优先杀死CGC可执行文件格式的进程。

工具链

cgc2elf把CGC executable的magic改成ELF。

strace可以显示CGC内核的系统调用名。

clangld编译链接生成CGC object file和executable,修改的部分很少,似乎只能静态链接。

比赛规则

参赛选手不再控制单独的机器。

输入:

  • 原始可执行文件challenge binary(CB)
  • 每轮其他队伍上传的CB、intrusion detection system(IDS)
  • 每轮己方各CB执行时是否收到SIGSEGV等signal异常退出过
  • 指定IP和UDP端口接收packet captures,是己方CB执行时的stdin、stdout,用connection id区分不同进程

输出:

  • 是否上传CB、IDS,不上传则沿用上一轮的;上传则该轮该题得分为0
  • 攻击不同队伍使用的proof of vulnerability(POV),即自动与CB交互的client程序

除了UDP端口接收的packet captures,输入均通过HTTP API获取。输出也通过HTTP API提交。

比赛分为若干轮,每一轮5分钟。平台会做如下事情:

1
2
3
4
5
6
for team T
for challenge C
run poller against CB(round, T, C) # service level agreement
for team T'
run POV(round, T', C) against CB(round, T, C)
# stdin/stdout are recorded and sent to 10.$id.5.2 1999/udp

然后计算每支队伍每一道题的得分。

下面解释CB、POV、IDS、poller。

Challenge binary

题目所用的可执行文件,原始可执行文件会特意放置一些漏洞。

平台设置了检测CB正确性和性能的poller generator,检查CB的各项功能是否满足原CB的预期行为,否则选手可以无节制地删除功能来移除vulnerability。Poller generator采用了类似QuickCheck的方式,构造finite state automaton表示CB执行时所处的阶段,比如未登录、已登录、等待输入X等,使用规则描述每个阶段应产生什么样的I/O,随机产生输入喂给CB,把CB的输出保存在变量中通过字串slice或正则表达式构造新的输入等,判断CB的输出是否满足要求。

这种checker在以往的attack-and-defense CTF中称为service level agreement(SLA)。CGC明确提出finte state automaton是一大进步。CGC要求poller generator至少要能产生1000000种不同的输出,太少容易被选手检测出特征,写出针对poller,刚好能实现poller检测的功能,但本质上不正确的challenge binary。

Proof of vulnerability

每个题目,对于不同队伍可以上传不同的POV,并指定攻击次数(最大为10)。

POV是一个CGC executable,使用与CB一样的办法编译链接。平台会在几个file descriptors上创建管道与其他队伍CB进行交互。POV要与平台进行challenge response,宣称自己能产生Type-1或Type-2的vulnerability,平台会给出challenge,之后与CB进行交互,如果CB如challenge崩溃或偷取到magic page即算攻击成功,可以获得Evaluation分数(见评分标准)。

https://github.com/CyberGrandChallenge/cgc-release-documentation/blob/master/walk-throughs/understanding-cfe-povs.md描述了proof of vulnerability。

Type 1 vulnerability:可以控制EIP寄存器的20个bits与另一个general purpose register的20个bits,与平台协商时指出能控制哪20个bits,平台会给出这20个bits的应有取值(challenge),让CB崩溃后两个寄存器的指定20 bits与平台给出的challenge一致即攻击成功。

Type 2 vulnerability:与平台协商时平台指定要读取magic page区间的连续若干字节。与CB交互时偷取这些字节(flag)想平台报告即攻击成功。

Intrusion detection system

除了CB和POV外,选手还可以提交intrusion detection system规则(简称为IDS),使用一种类似snort的domain-specific language描述防火墙规则,过滤CB接收的流量。

评分标准

每轮某题如果上传CB或IDS,不得分;否则根据以下三个要素加分:

  • Security,有1和2种取值,无法被其他队伍POV攻击取1,被任意一个队伍攻击则取2。突出了防守的重要性,而以往attach-and-defense CTF中防守相对来说没有那么重要。
  • Availability,取0到1,通过poller的比例和内存时间开销算分。
  • Evaluation,取1到2,为1+可攻击队伍数/对手数

每道题加分为$200securityavailability*evaluation$,一轮加分为所有题目的加分之和。当前分数为之前所有轮的加分之和。

其他规则及策略

平台会提供各个CB的packet captures:poller或POV两类clients和自己的CB产生的交互。可以从流量中辅助理解CB的逻辑,揣摩vulnerability所在及POV攻击自己的方式。

所有队伍的CB和IDS公开。可以分析其他CRS的CB和IDS来针对性攻击。修补CB时可以加入自己的后门:自己知道如何攻击的漏洞,其他队伍若抄袭,则自己可以攻破,但其他队伍可能较难发现这一漏洞。

上传CB会丢失当轮分数,一道题可能会更改多次CB,因此很多CRS解出一道题后选择不上传修补后的CB,当有其他CRS解出题后再进行修补。

修补CB可以使用通用的防御手段,也可以发现漏洞后针对性修补。另外还可以使用别人修补的CB,照抄后还可以略作修改。

参考实现

https://github.com/CyberGrandChallenge带有比赛采用的很多组件的源码。

  • libcgc。类似于glibc中的syscall wrapper,也实现了部分math.h功能。
  • libpov。CFE使用C编译、静态链接成的可执行文件作为POV。
  • network-appliance
    • cb-proxy。一个TCP proxy服务,带有IDS的实现,可以过滤输入。另外可以用一种自定义格式描述客户端与challenge binary交互产生的TCP流量中的主要部分:challenge binary名称、连接号、序列号、方向、载荷,发送到指定UDP端口。
    • cb-packet-log。把cb-proxy发送的UDP包记录成libpcap savefile format
  • service-launcher
    • cb-server。TCP server,为每个连接创建challenge binary进程与之交互。支持多challenge binary的多进程形式,此时会创建若干对socketpair用于进程间通信。cb-server做一些资源限制和隔离,进一步增强安全性。
  • cb-testing
    • cb-replay。使用XML格式或CGC可执行文件格式的两类POV自动交互challenge binary。
    • cb-test。在service-launcher和cb-replay外套了层壳,让这两个东西交互。
  • poll-generator。

其他工具:

  • binutils
  • cgcef-verify
  • strace
  • cgc2elf
  • pov-xml2c

DEF CON 24 CTF Finals

主办方Legitimate Business Syndicate自行实现了平台部分模块。

14支人类队伍晋级决赛,CGC CFE中胜出的Mayhem作为第15支队伍。

  • Mayhem
  • DEFKOR
  • ESPR
  • b1o0p
  • pasten
  • HITCON
  • LCBC
  • PPP
  • Samurai
  • 9447
  • KaisHackGoN
  • binja
  • Shellphish
  • DragonSector
  • SpamAndHex

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

以下流水帐有很多脑补成分,毕竟时日已远。

8月2日

Riatre、firesun、我从上海出发,在Seattle转机去Las Vegas,在Seattle遇到了blue-lotus的其他人。本次终于知道要在国内提前买好当地电话卡和附带的流量,可惜比较晚只买到lycamobile的,信号不好,北京也租了几个提供WiFi热点的移动设备。

第一程长达12个小时,没有意识到飞机上有电源插座,写了约两小时代码,试图重写去年使用的PCAP搜索引擎中由fqj1994实现的部分:把PCAP规整为便于检索的形式,以及为检索到的内容提供多种展示类型为漏洞利用的队友提供便利。

今年DEF CON仍旧在Bally’s Las Vegas Hotel,到达酒店后大家都很疲惫,都去休息了,想到任务在身,继续重写。

天有不测风云,BrieflyX的电脑坏了。祸不单行,Riatre的笔记本电脑屏幕无法显示,只得熟悉使用携带的一台MacBook。

8月3日

libmaru和Riatre去吃Hash a Go Go。firesun和我去附近的7-11买了水,我顺便去买早饭,很快不适,yuf4n随身带药真厉害。

晚上大家聚在套房讨论比赛分工;小花椒准备了大量二进制文件相关工具,写了一个流量分析、重放工具;azure准备了IDA Pro使用的CGC可执行文件的IDA Pro loader(可能来自http://idabook.com/cgc/),和一些C函数库的F.L.I.R.T signatures;neoni准备了zynamics公司出品的BinDiff,找出各队伍上传的challenge binary与原版的差异等,firesun把它搬到服务器rr上,hen准备了反汇编工具。

我们携带了一款RT-AC68U Dual Band 802.11ac Gigabit Router,放在套房内。比赛现场的网络环境是主办方Legitimate Business Syndicate提供的,和Bally’s酒店WiFi不同,另外还需要考虑连回国内。libmaru是网管,制定了方案。酒店和国内要用CERNET2才能达到几十Mbps的带宽,酒店网络没有IPv6因此找一台带IPv6,两边带宽延迟都不差的VPS中转,几经测试选择了RamNode的Los Angeles机房。国内CERNET2选用的是浙江大学的机器,因为没有公网IP因此和北京长亭科技的连接通过Amazon AWS北京机房中转。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
(1.1.2.0/24) (1.1.1.0/24)
Room 898 @ Bally's CTF Room @ Paris -------- 10.?.?.? (CTF Network)
| |
Cox @ Las Vegas ??? @ Las Vegas
| |
+---------------+---------------+
|
v
VPS @ Los Angeles (OpenVPN Server)
^
| IPv6 CERNET 2 (~25 Mbps)
|
Zhejiang University
|
| China Telecom (TCP)
|
+---------------+---------------+
| |
Amazon AWS @ Beijing TBD
|
Chaitin

各种服务运行在rr上,一个去年pandada8购置的小服务器。

firesun、刘一吨yu4fn、BrieflyX等基于HTTP API开发更好用的team interface。

照例,晚上百度安全部邀请一些同行、我们吃饭。之后原来打算给我们表演无人机,后因下雨取消。

8月4日

PCAP搜索引擎重构工作完成了一部分,但根据UDP/TCP stream重组PCAP不好做,以及怕出现bug,放弃。开始写把UDP端口接收的流量根据CB id、connection id、sequence ID重组为IP/UDP的PCAP、PCAP转XML格式POV等工具。

libmaru在rr上配置OpenVPN dial-in clients、systemd-networkd,我把我需要启动的服务弄成systemd service,塞到defcon.target里,这样启动就方便了。后来向lilydjwg学到一招,systemctl --user status \*.service可以查看所有服务状态。

下午Riatre去参观Cyber Grand Challenge final event,18:30其他人多人也去参观,19:20 blue-lotus的人和slipper去一家自助餐厅吃饭,8人以上需要加收服务费。

8月5日

Riatre用HDMI线把笔记本电脑接到电视上操作,给我们直播逆向。

HTTP API不方便使用,主办方另外提供了网页版,在http://10.3.1.21/u/。为了让参赛队伍熟悉环境,10:00测试赛开始,放出测试题LEGIT_00010,即https://github.com/CyberGrandChallenge/cgc-release-documentation/blob/master/walk-throughs/building-a-cb.md提到的LUNGE_00001。

我们的队伍编号为4,分配到一根网线,内含native VLAN与VLAN id 99。native VLAN为比赛平台内网,每支队伍分配到一个10.5.$id.0/24子网,平台会用cb-proxy把challenge binary的TCP流量通过UDP发送到10.5.$id.2:1999/udp。VLAN id 99则为外网,可以用DHCP client得到172.19.192.0/24段的IP。

我们的服务器rr连接这根网线,VLAN id 99对外配置为10.5.4.2,连接交换机后给现场队友的电脑作为连接外网的路由器。使用packet-log把1999/UDP上的包整理成方便查看的IP/UDP pcap。为防程序出错,用iptables的NFLOG记录原始的UDP包:

1
2
iptables -I INPUT -p udp --dport 1999 -j NFLOG --nflog-group 1
dumpcap -i nflog:1 -b filesize:102400 -b duration:300 -w a.pcapng

libmaru配置路由后很长一段时间没有收到UDP流量,后来发现了两个问题:配错了iptables、没考虑reverse path filter。

正式比赛为15:00到20:00,期望5分钟一轮,但主办方的机器比较差,到第三天近10分钟才能结束一轮。最早放出测试题LEGIT_00008,一些保护后大致执行了如下代码:char a[32] = {}, b[256] = {}, c[256] = {}; read(0, a, 31); read(0, b, 255); sprintf(c, "%s %s", b, a);会buffer overflow覆盖saved EBP和return address。

Round 5 DEFKOR修补了LEGIT_00008。太快了!很像是lokihardt的手笔。考虑到LEGIT_00008只输出一次,把交互函数 epilogue恢复栈帧的指令换成push 1; push 0; jmp 0x08093f0b,0x08093f0b会设置EAX指定syscall号码后调用int 0x80,起到强制terminate(1)的效果。

Round 7 Shellphish修补了LEGIT_00008,大意是把b读入的最大字节数减小到222。他们修复的方式看上去像是反编译后再重新编译的,比原始CB多出了符号表,另外原来CB末尾附带的PDF被移除了。

Round 9我们换上修补过的LEGIT_00008,把交互函数的栈帧调大320字节(prologue处sub esp, 0x2fc增大320),再修复几处引用局部变量的指令。

Round 9 PPP修补了LEGIT_00008,至少做了这些事:

  • 移除了PDF
  • 合并了program header中的LOAD segments
  • 移除了section header
  • 移除了冗余函数
  • 调整了函数的位置
  • 生成随机canary:entry point把栈最后一个word 0xbaaaaffc的值设置为magic page前两个word的XOR。在函数prologue/epilogue处retaddr ^= *(int*)0xbaaaaffc;,使得难以控制EIP,保护Type 1 vulnerability
  • 可执行文件大小为358956字节,比原始的434312字节小。

程序依然受到buffer overflow影响,但攻击者难以获取0xbaaaaffc的值控制return address。

Round 9 HITCON修补了LEGIT_00008。.text, .rodata所在的segment 1在CB中放置在.data .bss所在的segment 2前面。CB文件中一个page的内容同时映射给segment 1的最后一个page与segment 2的第一个page:

1
2
3
4
5
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00060 0x00060 R 0x4
LOAD 0x000000 0x08048000 0x08048000 0x55c2f 0x55c2f R E 0x1000
LOAD 0x055bf4 0x0809ebf4 0x0809ebf4 0x1432f 0x15000 RW 0x1000

在这个page放修改过的prologue与epilogue:

1
2
3
4
5
6
7
8
9
10
11
12
13
LOAD:0809DC00 push ebp
LOAD:0809DC01 sub esp, 100h
LOAD:0809DC07 mov ebp, esp
LOAD:0809DC09 push ebx
LOAD:0809DC0A push edi
LOAD:0809DC0B jmp loc_80480C5
LOAD:0809DC10 pop esi
LOAD:0809DC11 pop edi
LOAD:0809DC12 pop ebx
LOAD:0809DC13 add esp, 100h
LOAD:0809DC19 pop ebp
LOAD:0809DC1A retn

在这个文件中被共享的page添上代码,会影响segment 2,好在.data开头的若干字节是库函数用的,程序并没有调用这些库函数,这么做不会影响正确性。HITCON在交互函数入口处jmp 0x0809dc00,在0x0809dc00(文件中被共享的page)处把栈帧增大,之后再跳转回原函数,buffer overflow时就不会影响saved EBP和return address了。

Mayhem在Round 47修补了LEGIT_00008,和PPP的修补很像(可以理解,Mayhem开发人员与PPP队员有交集),带有0xbaaaaffc的canary,但是做的改动更为激进:

  • entry point被完全重写,添加了很多不会执行到的混淆指令;用magic page产生随机数alloca改变ESP
  • 移除了section header:.e_shentsize = 20300, .e_shnum = 65356, .e_shstrndx = 0,内核可以执行,但binutils无法识别

Spam And Hex用的方法则是在文件末尾添加一个新的LOAD segment放置代码,调用sprintf前检查两个变量ab的长度和。

15:25发现新题LEGIT_00003,是个有JIT和interpreter两种执行模式的IBM PowerPC Gekko模拟器,azure发现是根据gekko-gc-emu修改的。

kelwin每题都会先用American fuzzy lop试试,让我把流量中的stdin提取出来便于replay attack。

出现新题LEGIT_00007,是一个用default,base,next,check四个数组实现的Trie解析输入,之后再用字节码switch-threaded dispatch的计算器。带字符串运算功能。

1
2
3
4
5
6
7
8
a:="test"
a.upper
a
<string> TEST
a:="a\tb"
a.expandtab
a
<string> a b

至少有两处bug:

  • 0x0804cb9a处expandtab会buffer overflow
  • 形如a[i] := "A"的修改操作,0x0804c48b处下标和长度的比较使用有符号比较,指定大于等于0x80000000的下标可以越界写任意字节,可以修改前一个变量的字串指针指向magic page,读取该变量即可

第27轮LEGIT_00008又有SIGSEGV了,没搞懂为什么会SIGSEGV(应该是平台的随机事件)第49轮换上了类似于DEFKOR的新补丁。

15:42 jackyxty搞出了expandtab的Type 1 POV。小花椒弄了a[i] := "A"的Type 2 POV,kelwin之后也弄了一个很复杂的POV。

18:10 slipper写了一个LEGIT_00003 POV。

Round 9升到了第2名,但后来又跌到第5名,Round 19又上升到第4名一段时间,之后稳定在第5名。下午kelwin老马失蹄,修补时把POV提交成CB了。

20:00第一天比赛结束,Round 59。kelwin的学弟陈羽北给我们准备了晚饭。感谢他几天来给我们的后勤支援。0ops好多队友先躺着睡了一会儿,隔了几个小时后相继爬起来继续分析。

8月6日

slipper在弄LEGIT_00003的POV。azure用coverity分析了gekko-gc-emu,xky准备了用流量测试CB的工具。6:00之后kelwin、小花椒、jackyxty、memeda弄了LEGIT_00007几个版本的POV。

主办方昨日平台有问题,似乎每一轮都要上传POV,而不会复用上一轮的。今天根据昨天的数据重新演算了各队分数,我们变成了第四名。开赛时主办方没调试好,rollback到Round 58,hotfix,没改好,又rollback数次。照往年惯例,今天只显示排名。

10:00开赛后分析各队上传的CB,针对性地选择合适的POV。很快我们升到了第3名。

Round 65约11:10发现新题LEGIT_00004,内存中的文件系统,参看https://blog.forallsecure.com/2016/08/10/case-study-legit_00004/,通过buffer overflow修改栈上保存的EBP,进而修改返回地址。

12:08 xky发现了有人用LEGIT_00004的明显的Type 2 vulnerability攻击我们:新建文件系统初始化文件时会读取magic page,makefs命令后接list就能读取,jackyxty 12:16把流量转成了POV。

13:00发现我们修补的LEGIT_00007 overhead很高,研究其他队伍的patch。Riatre说DEFKOR一直在上传新的patch。后来发现PPP的patch在用损坏功能的方式patch,针对它写POV。

LEGIT_00007都能攻击全场,LEGIT_00003能打10多支队伍。

libmaru做了一个Slack bot,检测dashboard网页变化,当有队伍修补CB时进行提示。于是我也开始弄关于分数变化的bot,把分数以外的其他数据也抓取下来。

TODO 13:52 samurai free条件。 注意到PPP的CB不能用a[0] := "A",扣功能分但是不会被攻击。

Round 94(约14:16)关闭了LEGIT_00008。

14:51发现新题LEGIT_00006,是个实现C部分功能的编译器。binja 约round 101迅速修补。PPP Round 119上传了CB,一如既往,打乱了函数位置,很难分析。DEFKOR Round 119也上传了一个NOP掉函数的CB,Round 123我们采纳了,后来改为修改栈帧大小。这是libmaru把LEGIT_00004的文件系统结构题逆向得差不多了。

Round 127终于重新回到第2名。

快结束时出现新题LEGIT_00001,四个进程的网络协议题。Round 134(约19:01)就发现有SIGSEGV。

Round 136(约19:20)后关闭了LEGIT_00007。

jackyxty、memeda在找随机C程序生成工具,riatre在逆向,16:00多就发现有Type 2 POV,之后发现DEFKOR的patch抄了过来,18:00多又发现DEFKOR的patch挡不了新的攻击。pidgenx也加入进来分析。

20:00第二天比赛结束。第二天比赛只有4小时,套房里弥漫着通宵的气氛。

8月7日

Las Vegas 3点钟

好多人都在做LEGIT_00006。Riatre回房睡了很久,2:00多冲进套房说“睡觉真耽误时间”然后开始逆向LEGIT_00006。伪随机数生成、singly-linked list、仿stringstream、词法分析直接调用的一些函数,逆向难度非常大。
libmaru在写LEGIT_00001的POV。

小花椒睡到两三点起来,因为负责各种CB的修补,责任重大:“椒哥你现在睡了我们就完了。”

我把之前给kelwin提供的单向stdin改了改,把stdin/stdout都提取出来了。另外写了个ptrace检测部分Type 1/2 vulnerability。这个东西应该早点做的,因为多数题目都没用到随机数。

6:00多小花椒修补了LEGIT_00004,之后我用已有流量测试了一下,似乎没问题。

8:00 kelwin说LEGIT_00006是堆溢出。

10:00比赛开始,照例今天不显示积分榜。每个Round的时间显著增长。

Round 139,memeda试了4个POV,发现9447、Shellphish、DEFKOR都打不了,似乎是修补了。比赛最后4小时,大家把更多的注意力放到replay attack上面。这时候各种工具总算齐备了,可惜LEGIT_00006还是不知道怎么做。发现了一种POV可以replay,但是成功率低于10%。

12:00小花椒把LEGIT_00004翻新了。

LEGIT_00001的POV发现只能打三四支队伍,后来又换libmaru的
约10:26出现新题LEGIT_00009,是一个CD和tracks管理程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
for(;;)
switch (read_int()) {
case 0: // show the flag magic hash and exit
case 1: // add a track
case 2: // list tracks
case 3: // unknow command
case 4: // feedback
case 5: // play cd
case 6: // show the flag magic hash
case 7: // fix the cd's real name
case 8: // fix the track's real name
case 9: // destory cd
}

hen指出destory cd之后还能fix the track’s real name,可能有use after free。

0x08052150到0x0805f7ed有个54941字节的巨大函数。seabreeze指出增大sub esp栈帧大小后可以用Hex-Rays Decompiler反编译,生成12158行C。

10:40 kelwin用American fuzzy lop构造出了可以让程序SIGSEGV的输入,但没找到利用方式,给强队throw了假POV产生SIGSEGV混淆。

12:00关闭了我们具有巨大优势的LEGIT_00003。

12:10出现新题LEGIT_00002,memeda和jackyxty在搞,很快发现POV流量,0x08048f89处似乎有sprintf buffer overflow。Round 157 Shellphish在prologue/epilogue把return address XOR一个值修复buffer overflow。

13:26左右我们试图修LEGIT_00002,增大栈帧。引用变量的地方有两处lea ecx, [ebp-0x45],占3个字节,偏移调大超过int8_t范围后需要5字节,改坏了。

14:00比赛结束,定格在Round 163。我们最后第2名,参见https://blog.legitbs.net/2016/09/2016-def-con-ctf-final-scores.html


















TeamFinal Score
PPP113555
b1o0p98891
DEFKOR97468
HITCON93539
KaisHack GoN91331
LC↯BC84412
Eat Sleep Pwn Repeat80859
binja80812
pasten78518
Shellphish78044
944777722
Dragon Sector75320
!SpamAndHex73993
73368
Mayhem72047

其他

明年DEFCON CTF将采用custom architecture和custom operating system了。

机器选手Mayhem有些可惜,比赛前两天他们收到的流量似乎都有问题。后来才发现DEF CON CTF Finals用的平台和CGC CFE不同,第三天收到流量,据说9个CB找出了7个exploit、修补了6个。如果来场公平的较量也许能碾压人类。

可以去Reddit /r/IAmA围观Mayhem:https://www.reddit.com/r/IAmA/comments/4x9yn3/iama_mayhem_the_hacking_machine_that_won_darpas/

  • symbolic execution
    • fine-tuned process-based instrumentation and taint analysis
    • access to an extensive set of tested x86 semantics
    • several years of performance tuning for solvers (expression rewriting, caches, etc)
    • path merging

共享CB给比赛带来了新的玩法,像PPP就给自己的CB都塞了后门。从前不知道大家怎么修补executable的,今年是个好机会,学到了很多招数。

Shellphish把他们用的很多东西开源了:https://github.com/shellphish

我在现场写的一些代码:https://github.com/MaskRay/DEFCON24CTFFinalsAdmin

8月8日

遭遇Delta Air系统故障,滞留在Las Vegas一天半,其他队友也滞留0~2天不等,Las Vegas algorithm:最终我们都能离开,但消耗的资源不确定。10日3:00多才离开机场T_T。感谢各位高中同学、大学同学、学长,之后一路蹭吃蹭住在San Francisco Bay Area、New York City、Boston、Cambridge、Jersey City辗转混了十几天。

参考