和学长学弟一起组成CaTForce参加了这次熵密杯,最后做出了除最终挑战以外的所有赛题拿到了第九名。
由于这次真的算是超大型面基现场,所以和上次密码挑战赛的wp一样,不仅包含题解也包含一些游记。
第一部分:初始谜题
这一部分算是开胃菜,形式也更像平时见到的CTF题目,三个题目都是python加密的,做出其中任意一个就可以进入第二部分,也就是一个更类似真实情境的大型密码渗透系统。
但每个初始谜题都是有分数的,所以就算开了第二部分也当然要接着做TT。
每个题目也都有前三血的加成,一血5%,二血3%,三血1%,在最后排名的时候会先根据分数再根据解题时间,所以血量分其实很重要,但是手速实在不太够
然后就是他每个初始谜题下发的附件不仅包含加密用的.py文件,还有一个.exe文件,开启实例并输入ip和端口,之后题目就会下发加密数据,与他进行正确交互后就能拿到flag了。
初始谜题一(300 pts)
题目:
1 | from sympy import Mod, Integer |
题目加密流程大概如下:
有一个未知的initial_key,与一个未知的message
对于这个message,题目会在他前面填上一个固定的前缀”CryptoCup message:”,并在最后补充上”\x00”使得整个消息长为16的倍数
将填充了前后缀的消息按16字节为一组分组
从第一个分组开始,将该分组消息转化为整数,记为mi,并计算:
其中ki是key在对应分组的值(key每个分组之后会自增一)
将所有ci转成32字节,并连接在一起得到密文
靶机只会发送encrypted_message,要发送给他message来拿到flag。这个可以说是相当轻松了,由于有一个已知的前缀,并且他超过了16字节,因此就有第一个分组对应的明文和密文,所以就可以直接求出key来。
exp:
1 | from Crypto.Util.number import * |
发送message回去之后就会拿到flag,以及一个登录Gitea的帐号密码:
1 | 验证通过 |
后面两个初始谜题也都是给一个拿分的flag,以及一个账号密码作为开第二部分的钥匙,所以后面两个初始谜题就不写这个了
初始谜题二(300 pts)
题目:
1 | import binascii |
题目内容很简单:
- 读取一个未知的hmac_key,并生成一个随机的counter
- 将hmac_key控制在32字节(不足则填充”\x00”,超出则截断)
- 将hmac_key与counter拼接起来进行SM3哈希
然后下发的数据有:
- SM3得到的哈希值
- counter值
我们需要完成的事情是:
- 找到一个新的counter,使得新counter的低32位比原来的counter大
- 计算出hmac_key与新counter拼接后的SM3哈希值
- 发送新counter和这个哈希值就能拿到flag
看明白题意就会知道这是一个基于SM3的哈希长度扩展攻击,由于控制了hmac_key为32字节,并且counter只有4字节,而SM3的分组长度是64字节,所以说我们拿到的哈希值是只有一个分组的。而按照SM3的填充规则,这个分组哈希的完整分组其实是下面这部分内容的part1 + part2:(单引号代表字节串,双引号代表比特串)
1 | #448 bits |
这两部分拼起来就得到了完整的第一个分组。
SM3的哈希长度扩展攻击基于其Merkle Damgard结构,我们可以用一个已知分组的哈希值,去继续迭代计算更长的含有该分组消息的哈希值,而不需要知道这个分组对应的明文是什么。所以我们完全可以构造下面这样的counter:
1 | New_counter = 'counter'(4 bytes) + "1" + "00...0" + bin(8*(len(hmac_key + counter)))[2:].zfill(64) + '\xff\xff\xff\xff' |
那么hmac_key拼接上这个counter后,其用于SM3哈希的消息就会按64字节分为两组,而第一组是和靶机发送的消息完全一样的,因此我们就可以利用哈希长度扩展攻击迭代计算整个消息的哈希值了,具体实现代码是赛前那天晚上在github上随便找的:
KKrias/length-extension-attack-for-SM3 (github.com)
稍微对着题意改一改就好。
exp:
1 | def zero_fill(a,n): |
初始谜题三(300 pts)
题目:
1 | import sympy as sp |
题目名字叫lwe,具体来说给了一些如下数据:
随机生成16维的01向量e
随机生成16维的向量s以及16x16的可逆矩阵A,并计算:
将m转化为比特串,并进一步变为长度为16的01向量(也就是说m本身也只有2字节)
随机生成16x16的矩阵x以及另一个16维的01向量e1,并计算:
给出A、b、c1、c2,要求还原message并发送给他
虽然说题目叫lwe,似乎也可以通过lwe的方法求出s来,但是很显眼的一点是维数仅仅为16,实在太小了,只需要琼剧2^16其中就一定有正确的e、e1了。
然而再仔细看发现有更离谱的一点,既然A、c1都给好了并且A可逆,那么x直接求就好了,然后就可以轻松得到:
而由于e1也是01向量,他对向量t的大小影响可以忽略不计,所以t中大于等于q/2的位置就是m中为1的位置,否则就是0。
exp:
1 | A = Matrix(ZZ,[[139, 63, 18, 202, 166, 185, 85, 108, 58, 90, 211, 248, 240, 44, 137, 39], [5, 230, 89, 226, 139, 24, 233, 20, 12, 108, 127, 11, 52, 64, 188, 156], [80, 61, 105, 3, 165, 96, 154, 40, 62, 103, 157, 75, 190, 101, 31, 239], [193, 100, 124, 216, 248, 95, 241, 196, 67, 192, 217, 114, 171, 248, 219, 169], [116, 71, 221, 105, 167, 153, 22, 124, 178, 45, 7, 183, 125, 8, 127, 123], [182, 162, 164, 184, 27, 148, 206, 73, 217, 86, 187, 137, 82, 150, 99, 65], [106, 60, 153, 91, 213, 41, 188, 92, 121, 246, 164, 223, 199, 85, 161, 25], [93, 97, 145, 31, 48, 36, 7, 110, 56, 47, 108, 79, 233, 186, 93, 181], [195, 98, 47, 147, 49, 40, 158, 89, 218, 8, 23, 118, 170, 19, 50, 17], [127, 95, 37, 48, 230, 244, 130, 37, 75, 125, 103, 154, 148, 218, 227, 178], [162, 235, 129, 44, 204, 228, 221, 130, 239, 36, 57, 38, 41, 74, 61, 155], [246, 11, 11, 97, 218, 57, 209, 72, 229, 27, 250, 73, 19, 64, 25, 62], [60, 162, 1, 110, 191, 130, 120, 227, 214, 98, 165, 245, 28, 55, 94, 190], [129, 212, 185, 156, 119, 239, 83, 221, 4, 174, 65, 218, 32, 211, 213, 223], [80, 218, 135, 245, 238, 127, 55, 68, 113, 145, 110, 59, 50, 177, 159, 146], [68, 239, 36, 166, 206, 23, 59, 126, 67, 152, 99, 189, 133, 113, 243, 198]]) |
第二部分:大型密码系统
这一部分共有4个题目和一个最终挑战,题目之间是有顺序关系的,也就是要先做出某些题目,才能得到后续题目的附件、数据、登录密码之类的相关信息,具体来说这次挑战的先后顺序是:
- flag1和flag3可以同时挑战
- 做出flag1可以开启flag2
- 做出flag3可以开启flag4
- 全部完成后可以开启最终挑战
flag1(600 pts)
题目:
passwordEncryptorV2.c:
1 |
|
题目基于一个对称加密,给出了其具体实现步骤。连接靶机之后会给出密文,要求求出password,来解压带密码的协同签名源码文件压缩包,压缩包内含有本题的flag值以及flag2的源码。
可以看出在有key的情况下,解密就是把整个加密过程逆一下,这一部分交给学长很快就写好了。
然而学长发现对于靶机给出的密文,用题目给定的0xF0FFFFFF当作key是解不出他要求的”pwd:”开头的password的,所以我猜测这个key只是个示例,实际上要用这个已知的开头来爆破4字节的key。4字节对于c来说似乎也不算很大,因此简单修改下解密部分就开爆了。但是,实际效果并不是很理想,如果要爆破完所有解空间的话,差不多需要2^16秒,这对于仅仅6h的比赛来说太长了,所以要考虑一些优化。而比起仔细查看代码来说,最简单的优化当然是直接用多进程来做。
可是我只用过python的多进程,并且考虑到python本身的速度,为了用个多进程把整个求解代码转成python实在是不太划算。可是比赛不出网,要查询资料不仅需要申请,时间也只限10min,还会对整个队伍的成绩产生影响,更不划算。所以想来想去也只能三个人都多开点窗口,然后从不同的位置开爆。
也算是一种多进程了。
然而这样做有意想不到的效果——我让学弟倒着爆破的那个窗口过了一段时间真的跑出了结果,这个题也就顺利解掉了。
实际上最后一轮提示中有提到,因为某些原因,key首字节一定是F,所以倒着爆才更加快;此外还有一些其他地方可以减少耗时。
这里就不仔细研究产生这些优化的原因了,多进程肯定是最有力的XD,做出来就行。
exp:(header.h就是题目加密源码里的函数)
1 |
|
flag2(900 pts)
题目:
co-signing_client.js:
1 | const form = ref({ |
co-signing_client.c:
1 |
|
这个题目代码特别特别的长,具体细节可以慢慢读。
.js文件是交互部分,梳理一下主要交互流程是:
用户输入口令和消息摘要,并发送给服务器
用户本地计算出如下数据,这些数据可以在发送包的负载里找到:
1
e, p1x, p1y, q1x, q1y, r1, s1
服务器接收到数据后,进行协同签名,并发送以下数据返回:
1
s2, s3, r
我们需要计算出服务器的私钥d2,d2就是flag2的值
而.c文件则是告诉我们协同签名流程,这些数据主要有以下一些关系(运算均在模n下,n是曲线阶):
使用SM2的标准曲线,参数及生成元G均已知,服务器私钥为d2,并有以下P点坐标:
使用用户发送来的p1x, p1y, q1x, q1y这几个数据设置点P1、Q1
使用用户发送来的e、r1、s1计算u1、u2:
计算中间点T(x’,y’),验证r1=x’:
生成随机数k2、k3,并计算:
计算r:
计算s2、s3:
返回r、s2、s3
整个步骤就是看注释一步步梳理出来的,我们的目的是算出d2来,而s2、s3中一共有三个变量d2、k2、k3,并不足以求出所有未知数,所以可能需要利用r再构造一个等式才行。
然而这个题藏了个相当阴的地方,仔细观察可以发现一行代码:
1 | BN_copy(k3, k2) |
这也就是说k3=k2,因此未知数实际上就只有两个,所以很轻松就可以拿到d2了XD。
exp:
1 | from Crypto.Util.number import * |
flag3(500 pts)
题目:
login.go:
1 | package controllers |
数据库管理系统管理员证书.cer:
1 | -----BEGIN CERTIFICATE----- |
题目连接上之后有一个简易的网站,由于复现不了所以只能大致描述一下它的功能:
- 有一个登录界面,可以输入用户名、私钥以及公钥文件,如果能通过login.go中的所有check就能成功登录
- 还有一个注册界面,可以输入用户名和裸公钥,如果裸公钥格式正确,服务器就会用根证书发放一个完整公钥文件给你
我们的目标是用“shangmibeiadmin”成功登录,就可以拿到flag3的值以及flag4的源码。
已知的这个证书文件是个公钥文件,查看一下发现这个证书的用户就是“shangmibeiadmin”,所以如果我们能知道他的私钥的话就可以直接登录了。结合这个题只有500分这个事实,我第一反应是私钥相当小,可以直接爆出来,但是用mitm爆了2^50无果,所以只能从其他部分入手。
用gmssl这个工具可以比较轻松的生成一对公私钥证书,我们只需要把公钥里的裸公钥拆出来,然后自己随便生成个用户名就可以注册一个用户,并得到服务器颁发的公钥证书。
这里需要注意一下不能直接注册“shangmibeiadmin”,它会显示已注册
然后查看login.go可以发现他似乎根本没检验证书持有者是不是和用户名一样,所以按理来说接下来的步骤很简单,我们只需要在用户名一栏输入“shangmibeiadmin”,然后输入刚才我们生成的公私钥证书中的私钥,再输入刚才服务器下发的证书就可以成功登录。
然而我们实在是不熟悉gmssl乃至openssl这些工具,并且不出网,不能自由查找怎么使用,所以只能一直用help来看有什么参数可以用。我们遇到的最大问题是:gmssl必须要一个密码,才能生成sm2私钥文件,而这个私钥文件是用这个密码加密过的,但是我们怎么找都找不到怎么解密这个私钥文件并解析他。
这里花了很长很长时间,最后离比赛结束不到一小时的时候想了一个笨办法出来——直接去源码c文件里面加几行打印私钥d的文件,并重新编译一下再用这个工具:
这个方法很笨但是确实有效,由于脑子有点混乱,也想不太清楚d具体该怎么拼,就用从前往后和从后往前两种顺序得到两个d,并用是否满足P=dG这个式子来进行核验,最后好歹是把自己生成的私钥d搞出来了:
1 | from Crypto.Util.number import * |
之后按刚才的方式就可以登录上网站拿到flag3以及flag4的源码。
flag4(1000 pts)
题目:
SM4加密解密代码.py:
1 | from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT |
总经理协同签名流量包加密使用的iv.txt:
1 | 90fc5cf2e2f47488a257fd51e0ae615b |
终于是一个python加密了,倍感亲切。题目主要流程是:
- 读取seed.txt文件得到初始seed
- 用genSM4KeyOrIV函数连续生成16字节的iv和key
- 读取一个流量包文件,并用iv、key对流量包文件进行SM4加密
- 给出密文文件以及iv,要求还原流量包
有古怪的地方只可能在genSM4KeyOrIV函数里,查看一下发现其是连续调用四次genRandom函数并拼接而成,而genRandom函数是:
1 | def genRandom(): |
可以看出这是一个LCG过程,其会返回seed迭代一千次之后的高32位。
我们知道IV,也就是我们知道连续四次迭代一千次之后的seed高位,这就变成了一个简单的HNP问题。由于LCG迭代过程可以写为如下矩阵乘法:
所以一千次迭代也就是:
对于题目来说是已知高32位,那么以IV的第一个分组和第二个分组为例,式子就可以写成:
所以对IV所有连续的两组用第一行对应的线性等式,就可以把问题转化成规约低32位的HNP问题了,得到所有低位之后就可以向后迭代得到key,从而恢复流量包。
exp:
get xl:
1 | c = "90fc5cf2e2f47488a257fd51e0ae615b" |
decrypt:
1 | from gmssl.sm4 import CryptSM4, SM4_ENCRYPT, SM4_DECRYPT |
然后就可以在流量包里找到flag4。
最终挑战 *
在比赛还是不到半分钟的时候,我们队才惊险地交上flag4,完全没有时间看最终挑战了,因此只能赛后复现一下。
flag4的流量包跟踪TCP流,可以看到里面有以下内容:
除了flag4外,剩下的数据很显然是和flag2的协同签名有关的,而相比于flag2来说,这里多给了一个client_sign字段的值,再回头看看.js文件可以发现这是clientSign2函数的返回值,其流程为:
在clientSign1的过程里会生成一个随机数k1,满足:
传入未知的用户私钥d1,以及已知的s2、s3、r
计算s:
可以看出s1、s的生成等式其实分别就是关于d1、k1的两个变量的方程,所以就可以解出d1了。而我们的目的是伪造一个签名,解出d1之后走一遍协同签名的流程就好了,自然也就没有难度。
没有交互部分了,但可以用d1联系的两个点来检验d1的正确性
exp:
1 | from Crypto.Util.number import * |
总结
熵密杯总共进行6小时,从上午10点打到下午16点,最终是拿到第九名,得了个二等奖。这次参赛让我认为这个比赛最鲜明的几个特点是:
- 最终求解题目用到的核心思路很简单
- 主要难度在于审代码、运用工具、编写代码,而不出网会极大幅度的提升这几个步骤的难度
不出网带来的不便利是非常非常巨大的:
- 平时对于不熟悉的语言,结合gpt之类的工具可以快速理清楚大意,甚至直接找到一些不合理的洞。但是赛中只能自己一点点慢慢读去找不对劲的地方。
- 没有提前准备一些工具是很麻烦的,比如初始谜题二的哈希长度扩展攻击,虽然说没有也可以搓一个,但是比起直接准备了工具去做肯定是很不占优;再比如gmssl这个库,要是准备了对好些题都有帮助。
- 用工具遇到问题没办法及时上网搜,这个问题最突出,以下是好些例子:
- 不知道证书格式,只能读一下提前准备好的sm2签名流程,然后base64解码,并连蒙带猜手动按十六进制一点点拆出来点坐标、颁发方之类的字段
- 不知道怎么用gmssl、openssl去生成一对能够解析的公私钥对,很难想象我们在有这两个工具的情况下怎么都解析不了自己生成的加密私钥证书,最后还是在源码里加东西重新编译才解决的。
- 一些平时用gpt秒生成的代码只能手写,比如flag1的解密代码以及多进程。
我们前面的题目做的还是相当顺利,虽然由于分工的问题,一个血都没有抢到,但是依然保持住了一段时间的前五。然而这个证书题让我们队直接尬住了,从午饭时候差不多就开始,一直到三点半才解决。解决掉之后拿到flag4的源码,匆匆忙忙做的时候还把格造错了,差点没交上flag。
如果熟悉工具使用的话,就算只多剩个二十分钟出来,我都还是挺有信心把最终挑战给完成的——但是事实就是连个半分钟都没给我剩下,还是有一点点可惜吧。
不过还是比预想的好了很多,因为看昨年的wp觉得Crypto味似乎不是很浓,并且必须做完一道才能开新题,所以担心太偏misc或者web了自己会做不太动,实际体验下来感觉也还好,虽然Crypto味确实也不算很浓就是了XD
游记
线下赛的机会很难得,而且这次9.2就出发来银川了,9.6才离开,玩了算比较久,所以当然也要写篇游记才行。
9.2
由于主办方只报销火车的二等座的票钱,否则都需要补差价,所以我和学长学弟一合计——既然包差旅,就最好一分钱都不自己出吧!就这样我们往返都选了高铁票。不过上海到银川实在有点远,所以也意味着我们要花接近24h的时间在赶路上了:
9.2号早上九点从学校出发去虹桥坐高铁,上高铁之前空白在呼叫去打BlackHat,所以本来是想在车上睡一睡的,但现在就只能开电脑研究下那个剩下来的题目了。
然而上了高铁找到座位发现是第一排,而且是那种小桌板都没对齐的第一排,压根就没有地方放电脑:
但打还是得打啊,问了问似乎也在做这题的rec,他让我上notion先同步一下进度,但是因为不好开电脑,就只能手机下个notion看题目了。
再问一问rec发现他也在火车上,只是在赶回南京XD。我们两个就在那里拿着个手机没纸没笔地硬看题目,能开电脑做的似乎就只有一个想要LLL 2049x2049矩阵的越南老哥,我和rec提一个思路否定一个思路,也没啥新进展。
比赛18:00结束,rec下午还要开会,我本来就没有新思路,就算有思路也开不了电脑写,所以到结束的时候我们也没搞定这题,有点难受。赛后空白上discord看了看其他老哥的思路,告诉我们这是一篇paper题,那我们两个拿手机的确实没啥办法了。
晚上九点四十多准时下车,一出列车门,马上就感觉到一点点凉意,到酒店办入住的时候发现自己单出来了,而且很巧地和sh1kaku的一个队友分到了一间。
可能也不能算很巧,因为都在上海(⌒ω⌒)
酒店虽然也不能说多好,但是比起前些天高校密码挑战赛安排的实在是好了很多倍,让我不得不夸赞。美中不足的地方是空调似乎完全没效果,但是银川这几天的天气本身并不热,所以影响也不大。
到酒店后大家都想休息了,也就各自点外卖吃,没有出门去逛。睡前按照惯例还是和高中同学来了几局无限火力,玩着玩着突然下大雨了,明天一整天只有报道一件事,所以我们三个还想出门逛逛景点之类的,希望这场雨不要影响到我们的出行。
9.3
这个酒店早餐开放时间又早又短,7:00-8:30,对于最近晚睡晚起惯了的我简直是种折磨。本身早饭也没啥胃口,所以没有去尝当地的特色羊杂碎,就喝了碗粥、吃了几瓣苹果之后就没吃了。
后来Zima尝了下酒店的羊杂碎,说是有点膻,我完全吃不下有膻味的羊肉,幸好没尝
然后我们去了距离酒店最近的一个知名景点——镇北堡西部影城。其实宁夏在我小学的时候和一大群小学同学一起来玩过一次,沙坡头、沙湖、镇北堡这些出名一点的都来过了,这次算是故地重游。
昨晚下的雨应该早就停了,但是多少还是影响了道路状况,对于这个黄沙漫过的土地来说多了很多需要绕着走的泥泞。一路上有很多电影介绍+剧照,但是我在观影方面实在太小资历了,确实没看过几部,所以也就认得出大话西游的一些场景,剩下的就只有拍拍拍了:
然后中午一点左右我们差不多逛完了影视城,然后一起张罗着去酒店旁边一个大广场尝一尝当地特色,到了广场之后我们选了一家之前从来没见过的叫“冰煮羊”的东西吃。
锅里肉块混着冰一起端上来,然后店长拿着4L的农夫山泉往里咕咕倒,倒的差不多了就盖上锅开煮,视觉效果确实很神奇:
吃着也确实不错,肉块的口感很奇妙,奇妙到我不知道怎么形容,可能就是和冰一起煮的原因。
吃完之后和Cain一起去上网,我们选了一家离酒店比较近的网吧,去网吧的一路上四面八方都是宁夏大学的校区,里面的小登们正在军训,看着他们军训有一种说不清的感觉,这种感觉让我回想起我高中军训的那段日子,短短七天的回忆比大学半个月的军训回忆却要多很多:
三点接近四点的时候,我和Cain到了网吧,网吧是新开的,充30送100,由于晚上还要和NK的师傅们聚餐,所以六点多差不多就要走,所以感觉充30妥妥够了,然后就开始上网,我把号借给了他,自己上了个同学的号:
六点多一点的时候,我和Cain正在玩最后一把无限火力,他小鱼人我奥拉夫。我们把对面杀穿之后去对面泉水前面开始爽钢,对面打Cain压根不掉血,打我没我吸得多。然而,然而,打着打着他的机子突然就没网费,直接下机了。
这么一把爽局怎么能不玩完!所以Cain马上跑去前台续网费。我这边应该还剩一点,所以就继续打,然而过了可能两分钟,在Cain还没充完网费回来的时候,我的网费也没了,当场下机。
Cain续完费火速回来重连,但是连上来过后战场已经从他们的泉水转移到我们的泉水了,虽然打还是打不死他,但是耐不住对面格温小丑直接开偷啊,很快这把就输掉了——新充的网费都还没怎么花呢。细算了一下,充30送100,结果两个小时出头这网费就花干净了,这网费至少得50一个小时吧,有点小坑。
然后我们就润了,我不会骑电瓶,我们就一个自行车一个电瓶车去火车站晃悠了一圈之后,去一个烩肉餐厅和来熵密杯的NK的师傅们聚餐(此处偷Cain的图):
由于本身现实里不太会说话,所以吃饭的时候就听师傅们聊,听到了不少趣事,甚至还有一些猛料XD。最后还上了一盘手抓羊肉,但是我真的一块都干不下了,遗憾离场。
吃完饭后我们走路回酒店,路上给缺水的sh1kaku他们几个捎了些饮料和水(我今早上把酒店里送的两瓶水全部拿走了(* Ŏ∀Ŏ)),也见到了我的室友。明天就要比赛了,回酒店后和学长学弟一起准备了点明天可能用的脚本、资料和工具,发现确实也不太好急急忙忙的准备出个什么名堂,所以就休息了。
9.4
一早起来发现外面在下雨,出门就感觉到温度也突然变得有点低,对于没带外套的我有点难顶,幸好会场不远,稍微冻几步路就到了。
比赛完全断网,并且要收手机,我们三个也都在紧张比赛,所以没什么特别好记录的,就放一张赛前的现场图吧:
下午四点比赛结束,回酒店休息了会儿后和Zima两个人出来吃了个饭,吃的是大盘鸡,我们就点了个中份也超大一盘:
最后也没吃完,去逛就在旁边的怀远夜市。Zima还能买点羊肉串吃,然而我真的什么都吃不下,只喝了一杯Zima请我的宁夏特色热饮,叫做“牛奶鸡蛋醪糟”,味道对于我来说过于甜了。
七点出头正在逛街的时候发个通知来说拿了二等奖,要七点半赶去宁大一个教学楼彩排颁奖仪式。但是通知这么晚,想也知道大多数队伍都不会太准时,问了问Lvsun他们队去没去,果然是还没去XD。所以我和Zima还是逛完了夜市之后慢慢走着去参加彩排。彩排其实也就是提前熟悉下明天颁奖时侯坐的位置、上的顺序而已,也很快就结束了,我和Zima就回了酒店。
回了酒店想洗漱一下开始无限火力,结果还没坐定Cain就叫我和Zima一起去K歌,听Zima说这里的KTV都是烧烤+KTV一起开的,感觉应该会很新奇就拉着Zima一起去了,到地方发现确实很新奇,可惜真的吃不下:
气氛真的很好,开始觉得不太好意思,结果听着听着就想唱歌,就唱了几首歌
9.5
今天上午就是平平无奇的颁奖仪式:
9:45颁奖仪式就结束了,之后一直到十二点都基本上是一些讲座,好多队早早就跑路了(比如yolbby和Cain),我们队还是一直待到特等奖分享完解题思路才走:
然后和队友去吃了Zima推荐的一家吴忠麻辣烫,感觉麻酱味有些重,而且有一点甜,不是很适合我:
下午本来说去沙湖,但是天一直在下雨,外面很冷,我又没带外套,加上沙湖五点就关门,所以作罢,在酒店打无限火力。sh1kaku他们下午走,打到四五点钟的时候告别了他们。
晚饭本来是叫了Zima、yolbby一起吃,结果yolbby要带学弟一起去逛一逛鼓楼,Zima更牛皮,下午直接跑出去和学妹看电影+吃饭,所以晚上随便吃了点之后我就继续无限火力。
第二天早上7:40就发车,所以还要早点休息才好。
9.6
今天踏上归程,不知不觉就正好翘掉了一周的课,幸好大四没啥课。