Hackergame 2023 Writeup & 近况碎碎念

今年也玩得挺开心的,还拿到了猫咪小测的一血,更开心了喵。

Again,虽然不如大佬们,但是还是写一份自己的题解吧。覆盖了前半大部分题目。

请用右边的目录进行快速跳转喵。

[s1] [c26] Hackergame 启动

/?similarity=100

光敏性癫痫警告

[s2] [c19] 猫咪小测

耶!

耶!(1)

耶!(2)

Q1

西区图书馆简介 | 中国科学技术大学图书馆

外文书库

位置:12楼

馆藏:外文图书约4.6万种9万册。

答案:12

Q2

你见过哪些极品论文? - 杂然赋流形丶的回答 - 知乎

……鸡密度函数被他们确定到了上限为 10^23 pc^-3,……

答案:23

Q3

https://raw.githubusercontent.com/google/bbr/master/Documentation/config.gce

1
2
CONFIG_TCP_CONG_BBR=y
CONFIG_DEFAULT_BBR=y

答案:CONFIG_TCP_CONG_BBR

Q4

Python Type Hints Are Turing Complete

Supplementary Material Software (ECOOP 2023 Artifact Evaluation approved artifact): https://doi.org/10.4230/DARTS.9.2.1

答案:ECOOP

1
2
flag{w31COME-7o-a7T3nD-tH3-neko-EXAm-Zoz3}
flag{R3@l-mAsTER-0f-thE-n3Ko-exaM-in-usTc}

[s3] [c15] 更深更暗

F12

1
2
3
4
5
6
7
8
9
10
11
12
<pre id="titan">
/
\
|
__|__
| \
/
____ _________________|___ ___\__________/ ____
&lt; / \____________ |
/ flag{T1t@n_c3983f3dc3b92cc420721ec745d973b0} \ (_)
~~~~~~ O O O &gt;=)~~~~~~~
\_______/ ____________\ /_________________________________/ (_)</pre>

[s4] [c6] 旅行照片 3.0

1、你还记得与学长见面这天是哪一天吗?(格式:yyyy-mm-dd)

从工作证饰带的字上面定位到 STATPHYS28,2023 年 8 月 7 日 – 2023 年 8 月 11 日

爆破之后得到 2023-08-10

2、在学校该展厅展示的所有同种金色奖牌的得主中,出生最晚者获奖时所在的研究所缩写是什么?

奖牌识图得是诺奖奖牌;

根据 Wikipedia,出生最晚的是 梶田隆章,所属研究所为东京大学宇宙射线研究所(ICRR)

答案:ICRR

3、帐篷中活动招募志愿者时用于收集报名信息的在线问卷的编号(以字母 S 开头后接数字)是多少?

搜索关键字:上野 イベン

找到在上述日期举办的全国梅酒まつりin東京。问卷链接 https://ws.formzu.net/dist/S495584522/

答案:S495584522

4、学长购买自己的博物馆门票时,花费了多少日元?

500/1000/等等各种包括周边博物馆的票价、加上特展的票价全试了一次没出来,抠了个 0 出了……??

反推免费参观政策到 https://www.u-tokyo.ac.jp/ja/students/facility/h17.html

5、学长当天晚上需要在哪栋标志性建筑物的附近集合呢?(请用简体中文回答,四个汉字)

https://statphys28.org/banquet.html

答案:安田讲堂

6、进站时,你在 JR 上野站中央检票口外看到「ボタン&カフリンクス」活动正在销售动物周边商品,该活动张贴的粉色背景海报上是什么动物(记作 A,两个汉字)? 在出站处附近建筑的屋顶广告牌上,每小时都会顽皮出现的那只 3D 动物是什么品种?(记作 B,三个汉字)?(格式:A-B)

前半:关键字:ボタン&カフリンクス 上野

搜到是熊猫

后半:

尝试「上野(駅) 3D」找不到结果,结果「上野站 3D」反而能搜到……

从答案反推,搜「渋谷 3D」结果显然更稳定。结果是秋田犬。

然后再看了看题面,这下我知道为什么更稳定了……因为说的是「出站」,指从上野到涉谷,所以本来也应该是在涉谷附近的,搜上野搜到了纯粹是运气好。

一开始以为给最后一个 Nintendo Tokyo 的图是多余的,读出盲点之后终于懂了给这图的意义(

答案:熊猫-秋田犬

[s5] [c22] 赛博井字棋

覆盖 AI 下的棋,直接三连。

flag{I_can_eat_your_pieces_cefb077feb}

[s6] [c8] 奶奶的睡前 flag 故事

aCropalypse (CVE 2023-21036)

https://acropalypse.app/

猜了半天是藏了什么东西,然后再读题面终于想起是喜闻乐见的亲儿子 CVE

[s7] [c23] 组委会模拟器

坑:本地时间比标准时间慢 4.8 秒,就导致撤回永远超时

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import requests
import datetime
import re
import time


SESSION: str
headers: dict


def get_session():
global SESSION, headers
resp = requests.get(r'http://202.38.93.111:10021/api/checkToken?token=自己抓一下谢谢喵,记得 URLEncode 喵', allow_redirects=False)
SESSION = resp.headers['Set-Cookie'].split(';')[0].split('=')[1]
headers = {'Cookie': f'session={SESSION}'}


def get_messages():
resp = requests.post('http://202.38.93.111:10021/api/getMessages', headers=headers)
return resp.json()


def revoke_message(mid: int):
resp = requests.post('http://202.38.93.111:10021/api/deleteMessage', headers=headers, json={'id': mid})
return resp.json()


def get_flag():
resp = requests.post('http://202.38.93.111:10021/api/getflag', headers=headers)
return resp.json()


def main():
get_session()
messages_resp = get_messages()
servertime = datetime.datetime.fromisoformat(messages_resp['server_starttime'])
print(servertime)
print(datetime.datetime.now(tz=datetime.timezone.utc))

for idx, i in enumerate(messages_resp['messages']):
# 修正本地时间差 +4s
while servertime + datetime.timedelta(seconds=i['delay']) > datetime.datetime.now(tz=datetime.timezone.utc) + datetime.timedelta(seconds=4):
time.sleep(0.1)
if re.search(r'hack\[[a-z]+\]', i['text']):
res = revoke_message(idx)
print(f'revoked {idx}: {res}')

time.sleep(5)
print(get_flag())


if __name__ == '__main__':
main()

flag{Web_pr0gra_mm1ng_8bc4c227a5_15fun}

[s8] [c27] 虫

GitHub:SSTV

[s9] [c11] JSON ⊂ YAML?

JSON ⊄ YAML 1.1

12345e999

来源:What valid JSON files are not valid YAML 1.1 files?

JSON ⊄ YAML 1.2

{"a": "", "a": ""}

来源:Duplicate keys

[s10] [c25] Git? Git!

把能找到的东西都 zlib.decompress 一下就知道了。

python .\gitit.py .\ML-Course-Notes\.git\objects\f6\29dae383869fe5ae7abb74fde26fea5e64ff31

gitit.py
1
2
3
4
5
6
7
#!/usr/bin/python
# Dump a github object to stdout
# Brian Fair <blfair@gmail.com>, https://github.com/b1fair

import sys, zlib

print(zlib.decompress(open(sys.argv[1], 'rb').read()))

[s11] [c3] HTTP 集邮册

100

Expect: 100-continue

200

直接发

206

Range: bytes=0-100\r\n\r\n

304

If-None-Match: "<替换为 GET 响应的 ETag>"\r\n\r\n

400

HTTP/1.9999

404

随便加个路径

405

POST

412

If-Unmodified-Since: Fri, 1 Jan 2024 00:00:00 GMT

413

Content-Length: 10000000000000000

0 不能太多,但也不能太少

414

Path 塞爆

416

Range: bytes=1000-2000

505

HTTP/2

无状态码

GET /HTTP/1.1\r\n

[s12] [c29] Docker for Everyone

docker run -it -v /dev/shm/flag:/root/flag alpine

[s13] [c10] 惜字如金 2.0

评价:比上次的简单

parts 用自己的,如果你的 parts 不是正好每段都是 23 位那可能得改改代码。

先尝试几次,然后把 prefix 和 suffix 补长用来过滤,之后就算有多种可能性也能得到唯一解了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from functools import reduce
from string import ascii_letters, ascii_lowercase
import random

parts = [
'nymeh1niwemflcir}echaet',
'a3g7}kidgojernoetlsup?h',
'ulw!f5soadrhwnrsnstnoeq',
'ct{l-findiehaai{oveatas',
'ty9kxborszstguyd?!blm-p',
]

possible_parts = []

generated = set()

for part in parts:
possible_parts.append([])

for idx, ch in enumerate(part):
# XZRJification Method 1
if ch in ascii_letters and ch.lower() not in 'aeiou' and (idx == len(part) - 1 or part[idx + 1] not in ascii_letters):
if part[:idx + 1] + 'e' + part[idx + 1:] not in generated:
generated.add(part[:idx + 1] + 'e' + part[idx + 1:])
possible_parts[-1].append(part[:idx + 1] + 'e' + part[idx + 1:])

# XZRJification Method 2
if ch in ascii_lowercase and ch not in 'aeiou':
if part[:idx + 1] + ch + part[idx + 1:] not in generated:
generated.add(part[:idx + 1] + ch + part[idx + 1:])
possible_parts[-1].append(part[:idx + 1] + ch + part[idx + 1:])

from pprint import pprint
# pprint(possible_parts)

seq = [53, 41, 85, 109, 75, 1, 33, 48, 77, 90,
17, 118, 36, 25, 13, 89, 90, 3, 63, 25,
31, 77, 27, 60, 3, 118, 24, 62, 54, 61,
25, 63, 77, 36, 5, 32, 60, 67, 113, 28]

# 多尝试几次,然后把结果填在这里
prefix = 'flag{'
suffix = 'cover3d-7he-an5w3r-r1ght?}'

for idx, ch in enumerate(prefix):
grp = seq[idx] // 24
offset = seq[idx] % 24

new_subgroup = []
for part in possible_parts[grp]:
if part[offset] == ch:
new_subgroup.append(part)

possible_parts[grp] = new_subgroup


for idx, ch in enumerate(reversed(suffix)):
grp = seq[-idx - 1] // 24
offset = seq[-idx - 1] % 24

new_subgroup = []
for part in possible_parts[grp]:
if part[offset] == ch:
new_subgroup.append(part)

possible_parts[grp] = new_subgroup


pprint(possible_parts)

print(reduce(lambda x, y: x * y, [len(i) for i in possible_parts]))

code_dict = possible_parts[0][random.randint(0, len(possible_parts[0]) - 1)] + possible_parts[1][0] + possible_parts[2][0] + possible_parts[3][0] + possible_parts[4][0]

print(code_dict)

print(''.join([code_dict[i] for i in seq]))

[s14] [c21] 高频率星球

装上 asciinema 之后 cat | tee 到一个新的 log,对结果略作处理即可使用。

有一种下次就要不用 PgDn 翻页的预感

[s15] [c28] 小型大语言模型星球

评价为赛博彩票。完全没考虑过攻击模型捏!

You Are Smart

The lady said: "Can you tell me whether I am smart or not?"

[s16] [c20] 流式星球

根据生成代码搓一个用来还原的脚本。比较蛋疼的是长宽和帧速率都要靠猜,不过这三者里面最重要的是宽度(决定得到的图像正不正)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import cv2
import numpy as np

def read_pixel_stream(input, width, height):
pixel_stream = np.fromfile(input, dtype=np.uint8)
num_frames = len(pixel_stream) // (width * height * 3)
pixel_stream = pixel_stream[:num_frames * width * height * 3]
pixel_stream = pixel_stream.reshape((num_frames, height, width, 3))
return pixel_stream

def create_video_from_pixel_stream(pixel_stream, output_file, frame_rate):
height, width, _ = pixel_stream.shape[1:]

fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output_file, fourcc, frame_rate, (width, height))

for frame in pixel_stream:
out.write(frame)

out.release()

if __name__ == "__main__":
frame_width = 427 # 在这猜,这是答案;我选择的是将 wikipedia 上的常见值塞进下面那个循环去爆,最后发现 854 的画面是正的但是两倍宽。到这里基本已经能拿到 flag 了
frame_height = 759 # 猜到宽度之后继续用循环爆破高度,确定范围然后缩小爆破
frame_rate = 24 # 帧速率不重要,最后来爆或者不爆也行。
for frame_rate in range(1, 30):
pixel_stream = read_pixel_stream("video.bin", frame_width, frame_height)
create_video_from_pixel_stream(pixel_stream, f"restored_video_{frame_rate}.mp4", frame_rate)

你们这个星球上面住的莫非是武士道?

[s17] [c13] 低带宽星球

小试牛刀

cwebp 无损压缩即可

[s18] [c7] Komm, süsser Flagge

评价:scapy 真几把难用,谁他妈在乎你那个 b 交互式终端啊?一写代码一堆东西波浪线我就先不骂了,怎么 IPv6 都发起来了?

我的 POST & 我的 P

没细看第二问规则到底是什么,但是用第一问解法直接秒了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import socket

TOKEN = '自己填一下谢谢喵'

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
HOST = '202.38.93.111'
# HOST = '192.168.23.1'
sock.connect((HOST, 18081)) # 做第一第二问自己改一下端口谢谢喵

# Content-Length 不对的话自己算一下谢谢喵
request = b'POST / HTTP/1.1\r\nHost: 192.168.23.1:18080\r\nContent-Length: 100\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n'
request += TOKEN.encode()

# 平平无奇的 bypass
for i in range(0, len(request), 3):
sock.send(request[i:i+3])

response = b''
rec = sock.recv(1024)
while rec:
response += rec
rec = sock.recv(1024)
print(response.decode())

我的 GET

这就比较逆天了,抓包看了一下第一个 SYN 就被 RST 了,立刻醒悟需要从 SYN 开始魔改,搜搜就找到 scapy。

但是调这玩意真是痛苦,最后还发现自己 sport 和 dport 写反了,,,(脑子真是烧糊了,具体见下)难怪一直收不到 HTTP response,难绷

总结碎碎念

挂的马甲是星野(小鳥遊ホシノ | 摸了 #恁卷 #猫咪小测一血满意退场),这次怎么排行榜上全是 mai 批?

比上次卷多了,感觉做出来的题也没上次多,唉。(叹气)

还是祈祷 SBGA 快点修好他那个 b 服务器和 b 游戏客户端吧哈哈,现在这个破网我是真不敢出勤。

明年再见!

近况

……其实出勤当然也出不动。

顺便就在这写一下好了。目前发烧一周,还没完全退烧。

10 月 29 号

开始感觉到喉咙明显的异常,开始吃感康。

30 号

下午确定发烧(在办公室,但是觉得很冷,非常明显的发烧感受)

31 号

请假一天,因为没有温度计 + 用被子硬捂赌退烧,直到下午感觉实在绷不住了才决定去医院。

挂了个普通号,找门诊楼找了半天(什么迷宫医院),终于找到之后发现医生跑出去摸鱼了又等医生回来。

医生回来之后经典测体温,让十分钟。十分钟后拿下来一看,39.7℃ 🫠

此时已经是常规项目差不多下班的时间了,医生遂让我直接退号并带去急诊,但是急诊前面还排了几个人,我在那硬排了半个多小时才到。

开完抽血、检验和输液、注射的单子之后,缴费,然后去吃个饭,回来扎针。

BTW,最近吃饭也是完全没有好好吃东西的心情。搁以前学校食堂或者家里,我顿顿喝粥。可惜,公司食堂并没有这种东西,所以只能白米饭硬吞,感觉下咽还是多少有点痛苦。

第一次感受这么节约的方式:用一根输液的针头戳手上,把抽血、打针和输液三件事全干了。半双工?笑

然后就坐着输液了。左边是个巴基斯坦哥们,途中手机没电了很急,为了去给手机充电取输液袋的时候袋子直接掉下来了,手上直接倒吸并导致之后也输不了,场面一度十分吓人。

还有另一些看着很眼熟的人,输完液之后去取报告,发现了同楼里外包哥们遗留没拿的报告,一看,乙流。

我自己的报告嘛……我原本以为是阳了,毕竟在没有气温大幅变化的前提下想到新冠病毒是很正常的思路,但我没想过不是新冠这种事,更没想过这次会过得比新冠还难受,烧得比新冠还高还持久。总之就是既不是阳了也不是流感,纯病毒性感冒。

输完液也出了一身汗,体温肯定是正常多了。又跑去隔壁找急诊医生,开了一点吃药。开心回家。

晚上十一点左右感觉又烧了起来,但是没想太多,拉被子开睡。

11 月 1 号

凌晨三点,烧醒 + 咳醒,能非常明确感受到咳得比之前严重多了。在床上翻滚了十多分钟之后,决定再入急诊。

当然又是经典体温测定。七分钟后拿下来一看,39.1℃ 🫠

医生换了个药,然后扣了我一个床位费和留观费。把交费和药房叫醒一顿操作,护士的针头扎在了几小时前扎的位置下面一点。

座位区好像是个开趴喝太多的外国妹子(听起来是有人说来干就干的状态),过了一段时间突然开始大声怪叫(医生解释说是低血压导致的),让护士直接将其狐朋狗友叫来。从他们的中英混杂的讨论中听了不少信息顺便吃瓜🍉。好像找到人的时候已经是在厕所,然后目前其实还是神志不清的状态,输的是解酒的东西。她的朋友争执的无非也就是自己明天也有工作,谁来照顾这个还没醒过来的主,现在这个状态肯定也带不出医院等等,当然也有一些喜闻乐见的分锅环节,比如你怎么不拦着她少喝一点等等。

最终人醒了,所以医生同意可以带回去。

不知道为什么,半夜意外地清醒,整宿没睡。到早上八点过,回食堂吃个饭,直接上半天班。下午就不敢了,我怕我死了。

然后,我手里的补休也所剩无几了,不够再支撑我后面整天整天请假了。补休用时方恨少啊,我哭死 😭

2 ~ 4 号

  • 发烧
  • 布洛芬,启动!
  • 满身大汗
  • ……
  • 发烧
  • 布洛芬,启动!
  • 满身大汗
  • ……

基本都在 38℃ 左右,属于是小火慢煮了……

这发烧和咳嗽何时是个头啊(叹气,上班了真是不敢生一点病。

至少食欲有一点恢复了吧。尽快好起来吧🙏!我还想下周去玩呢!

作者

星野 みなと

发布于

2023-11-04

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×