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+可攻击队伍数/对手数

每道题加分为,一轮加分为所有题目的加分之和。当前分数为之前所有轮的加分之和。

其他规则及策略

平台会提供各个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.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

Team Final Score
PPP 113555
b1o0p 98891
DEFKOR 97468
HITCON 93539
KaisHack GoN 91331
LC↯BC 84412
Eat Sleep Pwn Repeat 80859
binja 80812
pasten 78518
Shellphish 78044
9447 77722
Dragon Sector 75320
!SpamAndHex 73993
73368
Mayhem 72047

其他

明年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辗转混了十几天。

参考