中科大每年一度 hackgame 比赛,感觉是参加过最最最有意思的 ctf 比赛了!!!(虽然也没打过几场):还有中科大的 cwk 的空间也太搞笑了,比赛网址

# 签到

谢邀,利益相关:老签到出题人了。

今年出题组的要求是「来参加我们比赛的同学很多都是初学者,我们的签到题要清晰明确一点,让同学们轻松签到。」

我完全明白了,签到题就是送 flag,送就送,我最会送了.jpg

首先写好题目介绍:「你需要点击下面蓝色的 “打开 / 下载题目” 按钮,在打开的网页上获取到形如 flag{...} 的 flag,回到本页面,将其完整填写到下面的文本框中,并点击灰色的 “提交” 按钮即可完成本题。」

然后写一个 flag 提取器,选手要多少个 flag,我就给多少个 flag,绿色背景,红色加粗,显眼的位置,标准的格式,这都不叫送,那还有什么叫做送。

点击 「打开 / 下载题目」 按钮,打开 flag 提取器,获取第一个 flag 吧!

# 遇事不决 查看源码

右键点击查看源代码发现

<script type="text/javascript">
            var prevVal = 0;
            $(document).ready(function() {
                $("#show").text($('#number')[0].value);
                $('#number').on('input', function() {
                    if ($('#number')[0].value.toString() === "1") {
                        console.log('没想到吧!');
                        $('#number')[0].value = 1.00001;
                        if (prevVal == 1.00001)  $('#number')[0].value = 0.99999;
                        if (prevVal == 0.99999)  $('#number')[0].value = 1.00001;
                    }
                    $("#show").text($('#number')[0].value.toString());
                    prevVal = $('#number')[0].value;
            });
        });
        </script>
<input type="range" id="number" name="number" class="form-control" value="0" min="0" max="1.5" step="0.00001"/>

上段 js 代码就是永远无法得到 1 个 flag 的原因,分析下方代码推断出可以把 max 改为 1,或者步长改为 0.2 即可(复杂解法俺还不会)

image-20210201225326433

修改元素的代码与属性:点击元素,然查看右键菜单,可以看到 chrome 提供的可对元素进行的操作:包括编辑元素代码(Edit as HTML)、修改属性(Add attribute、Edit attribute)等。选择 Edit as HTML 选项时,元素进入编辑模式,可以对元素的代码进行任意的修改。当然,这个修改也仅对当前的页面渲染生效,不会修改服务器的源代码,故而这个功能也是作为调试页面效果而使用。

参考 f12 开发者工具的使用

# 猫咪问答

image-20210201230226069

这道题把我手都搜酸了(

看群里大佬说可以用脚本爆破来做(可惜我不会

第一问

应该是哺乳动物的有:

Docker,Golang,PHP,Plan 9,GNU,FireFox,MySQL,PostgreSQL,MariaDB,Apache Tomcat,Xfce

其中 GitHub 对应的动物章鱼猫有一定争议,但是从其生理结构判断,不是哺乳动物的可能性更大。

从第二问开始搜索 以鸟类为载体的网际协议到 wiki 百科

在 wiki 百科上发现

image-20210201231913712

发现 RFC 文档的编号 1149

参考文章

image-20210201232259788

找到这篇发布于 1990 年的恶搞文章然后发现关键字 MTU is 256 milligrams,得到结果 256

第三问搜索后不难发现 USTC Linux 用户协会的一篇文章

image-20210201233021140

一共 9 个 字母

第四问过分了。。。

中国科学技术大学西校区图书馆正前方(西南方向) 50 米 L 型灌木处共有几个连通的划线停车位? 百度实景地图 yyds

image-20210201234050145

9

第五问

image-20210201234322172

17098

# flxg

通关或者(

image-20210201235342421

# 查看源码发现奇怪注释

 <!-- 
    changelog:
    - 2020/10/31 getflxg @ static/js/html_actuator.js
  -->

访问康康

发现是 js 写的 2048

想要赢要达到 2 的 14 次方(只有 16 格害怕

仔细阅读又发现奇怪代码

var url;
  if (won) {
    url = "/getflxg?my_favorite_fruit=" + ('b'+'a'+ +'a'+'a').toLowerCase();
  } else {
    url = "/getflxg?my_favorite_fruit=";
  }

知识点

一个表达式中如果有减号 (-)、乘号 (*) 或 除号 (/) 等运算符时 zhi,JS 引擎在计算之前,会试图将表达式的每个分项 shu 转化为 Number 类型(使用 Number (x) 做转换)。如果转换失败,表达式将返回 NaN 。如果其中有一个变量是字符串,则会将两边都作为字符串相加。

分析 'b'+'a'+ +'a'+'a'

上面的表达式相当于 'b'+'a'+ (+'a')+'a'

因为 (+'a') 等于 NaN,所以:

'b'+'a'+ (+'a')+'a' = 'b'+'a'+ "NaN"+'a'='baNaNa'

🆗访问 /getflxg?my_favorite_fruit=banana

# 一闪而过的 Flag

深秋清晨,也西湖畔。一位可怜的同学蜷在路边的长椅上,用粗糙的手指敲击着残旧的神船笔记本,反复试图打开桌面上的一个程序。程序每次运行时隐约可见黑色控制台上有 flag 一闪而过。

在他的脚边搭着一块用废弃纸箱剪成的牌子,上面写着「我很可爱,请给我 flag」。路上的人行色匆匆,而那地上用来盛 flag 的饭盒依旧空空如也。

一位诗人同学路过,见此情景,遂把牌子改成了:「flag 来了,可是我什么也看不见!」

而你作为一名新生,不由动了恻隐之心。望着诗人潇洒远去的背影,你可以赶在下午诗人回来之前,帮助这位可怜的人,用 flag 装满他的饭盒吗?

。。。。

这题欺负我不会截图嘛

打开是一个很快结束的 exe 文件可是它有我的手快吗

截图后图片转文字识别得到 flag

# 正解

在开始菜单中查找 cmd 或者 powershell 并打开,再将 Untitled01.exe 拖进去,回车,结束。从零开始的记账工具人

# 从零开始的记账工具人

如同往常一样,你的 npy 突然丢给你一个购物账单:“我今天买了几个小玩意,你能帮我算一下一共花了多少钱吗?”

你心想:又双叒叕要开始吃土了 这不是很简单吗?电子表格里面一拖动就算出来了

只不过拿到账单之后你才注意到,似乎是为了剁手时更加的安心,这次的账单上面的金额全使用了中文大写数字

image-20210202001831918

啊这

估计要写脚本了主要是中文数字太难受了

解法

使用任意文本编辑器(或者 Excel 本身)做字符串替换,替换规则如下:

'零' -> ''
'壹' -> '1'
'贰' -> '2'
'叁' -> '3'
'肆' -> '4'
'伍' -> '5'
'陆' -> '6'
'柒' -> '7'
'捌' -> '8'
'玖' -> '9'
'拾' -> '*10+'
'佰' -> '*100+'
'仟' -> '*1000+'
'元' -> '+'
'角' -> '/10+'
'分' -> '/100'
'++' -> '+'
'整' -> ''

。。。。python 操作 excel 还不会

总共有 1000 行数据,本来想在里面直接转换的,但试了一下发现没找到自带的工具,于是用 Python 写个脚本算算好了。

首先用正则匹配先把元、角、分给提取出来,然后写个字典转换就好了。

这里的转换参考了 Python 中文 (大写) 数字转阿拉伯数字,在此基础上结合这题改了改代码。

另外考虑到浮点运算可能带来的精度问题,元、角、分单独统计,最后进行合并。

康康其他大佬的写法

# -*- coding: utf-8 -*-
"""
Hackergame 2020
从零开始的记账工具人
@Author: MiaoTony
@Time: 20201031
"""
# constants for chinese_to_arabic
CN_NUM = {
    '〇': 0, '一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '零': 0,
    '壹': 1, '贰': 2, '叁': 3, '肆': 4, '伍': 5, '陆': 6, '柒': 7, '捌': 8, '玖': 9, '貮': 2, '两': 2,
}
CN_UNIT = {
    '十': 10,
    '拾': 10,
    '百': 100,
    '佰': 100,
    '千': 1000,
    '仟': 1000,
    '万': 10000,
    '萬': 10000,
    '亿': 100000000,
    '億': 100000000,
    '兆': 1000000000000,
}
def chinese_to_arabic(cn: str) -> int:
    unit = 0   # current
    ldig = []  # digest
    for cndig in reversed(cn):
        if cndig in CN_UNIT:
            unit = CN_UNIT.get(cndig)
            if unit == 10000 or unit == 100000000:
                ldig.append(unit)
                unit = 1
        else:
            dig = CN_NUM.get(cndig)
            if unit:
                dig *= unit
                unit = 0
            ldig.append(dig)
    if unit == 10:
        ldig.append(10)
    val, tmp = 0, 0
    for x in reversed(ldig):
        if x == 10000 or x == 100000000:
            val += tmp * x
            tmp = 0
        else:
            tmp += x
    val += tmp
    return val
if __name__ == '__main__':
    s = """贰拾元陆角伍分    1
    壹元壹角贰分    4
    拾捌元伍角壹分    1
    ...
    """
    l = s.split('\n')
    # print(len(l))
    re_split = re.compile(r'(.*元)?(.*角)?(.*分)?')
    total_yuan = 0
    total_jiao = 0
    total_fen = 0
    for row in l:
        yuan_int = 0
        jiao_int = 0
        fen_int = 0
        print(row)
        money = row.split('\t')[0]
        count = row.split('\t')[1]
        count_int = int(count)
        money_group = re_split.search(money)
        if money_group.group(1):
            yuan = money_group.group(1)[:-1]
            yuan_int = chinese_to_arabic(yuan)
        if money_group.group(2):
            jiao = money_group.group(2)[:-1]
            jiao_int = chinese_to_arabic(jiao)
        if money_group.group(3):
            fen = money_group.group(3)[:-1]
            fen_int = chinese_to_arabic(fen)
        print(yuan_int, jiao_int, fen_int)
        total_yuan += yuan_int * count_int
        total_jiao += jiao_int * count_int
        total_fen += fen_int * count_int
    total = total_yuan + total_jiao * 0.1 + total_fen * 0.01
    print("total:", total)

# 超简单的世界模拟器

comic

以上漫画译自 https://xkcd.com/505/,并以 Creative Commons Attribution-NonCommercial 2.5 License 许可证发布。

你知道生命游戏(Conway's Game of Life)吗?

你的任务是在生命游戏的世界中,复现出蝴蝶扇动翅膀,引起大洋彼岸风暴的效应。

通过改变左上角 15x15 的区域,在游戏演化 200 代之后,如果被特殊标注的正方形内的细胞被 “清除”,你将会得到对应的 flag:

“清除” 任意一个正方形,你将会得到第一个 flag。同时 “清除” 两个正方形,你将会得到第二个 flag。

注:你的输入是 15 行文本,每行由 15 个 0 或者 1 组成,代表该区域的内容。

参考:

[wikipedia: Conway’s Game of Life](https://en.wikipedia.org/wiki/Conway' target=)

学术干货 | Conway’s Game of Life 生命游戏的建筑设计应用

https://nealwang.net/JustForFun/GameOfLife.html

image-20210202194150238

# 从零开始的火星文生活

一年一度的 Hackergame 就要到了,L 同学打算叫上 Q 同学一起去参加,却一连几天都见不到 Q 同学的人影。然而在比赛开始的前一天晚上却收到了来自 Q 同学的邮件:

Subject: 绝密!不要外传!!!
Body: 详情见附件
From: Q

L 同学打开附件一看,傻眼了,全都是意义不明的汉字。机智的 L 同学想到 Q 同学平时喜欢使用 GBK 编码,也许是打开方式不对。结果用 GBK 打开却看到了一堆夹杂着日语和数字的火星文……

L 同学彻底懵逼了,几经周折,TA 找到了科大最负盛名的火星文专家 (你)。依靠多年的字符编码解码的经验,你可以破译 Q 同学发来的火星文是什么意思吗?

注:正确的 flag 全部由 ASCII 字符组成!

字符集和字符编码

看完这篇文章感觉头又秃了点

对就比如就比如好些那个那个需要努力