ISCC 2022

ISCC 2022 中 单板小将苏翊鸣、 藏在星空中的诗、降维打击、2022冬奥会、真相只有一个、GetTheTable与Amy’s Code 的题解

时间挺长的,但是没啥时间来玩。话说为什么没有Crypto方向的

Misc

单板小将苏翊鸣

下载附件后打开,是一张图片和一个压缩包。压缩包加密了,很明显密码应该在图片里。

图片属性和压缩包注释里面都没有有用的信息。用binwalk和foremost也没有分出来东西。

1
IhÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDf�t‘€]DDDDDDdA™hÐEDDDDDDþät:ÿq˜9ñïÕ����IEND®B`‚

用二进制查看器看看里面的内容,发现尾部有一些数据有点规律。而且这个数据是在图片的结束符之前的。所以可以看出来图像藏了东西,把图像的高改大一点就行。

改完之后图像出现了一个二维码。扫描。

得到内容:

1
\u5728\u8fd9\u6b21\u51ac\u5965\u4f1a\u7684\u821e\u53f0\u4e0a\uff0c\u6211\u56fd\u5c0f\u5c06\u82cf\u7fca\u9e23\u65a9\u83b7\u4e00\u91d1\u4e00\u94f6\uff0c\u90a3\u4f60\u77e5\u9053\u6b64\u6b21\u51ac\u5965\u4f1a\u6211\u56fd\u603b\u5171\u83b7\u5f97\u51e0\u679a\u5956\u724c\u5417\uff1f\u53c8\u5206\u522b\u662f\u51e0\u91d1\u51e0\u94f6\u51e0\u94dc\u5462\uff1f

这是unicode编码。转换一下得到:

1
在这次冬奥会的舞台上,我国小将苏翊鸣斩获一金一银,那你知道此次冬奥会我国总共获得几枚奖牌吗?又分别是几金几银几铜呢?

百度一下奥运奖牌榜。按照顺序进行组合。即可得到压缩包的密码。解压即可得到flag。

藏在星空中的诗

下载附件。得到三个文件。一个psd文件。一个压缩包。一个文本文件。文本文件内容如下:

1
2
3
4
5
1:☆✪٭☪✲
2:✡🟇⍟⍟✸
3:🌠⍟🌟✡🟉
4:🟃🟀✪🟀⚝
5:✪🟔⍣☆🞱

emmm… 全是特殊字符。压缩包带密码了,我们需要找到压缩包的密码是多少。

打开psd文件。发现里面有两个图层。第一个图层不透明度为5%。调整到100%。发现了一个五角星。表示的顺序为:

1
1 -> 3 -> 5 -> 2 -> 4 -> 1

构成一个五角星。这里一开始以为最后还要回到1,后来发现不用。

压缩包的密码就是文本文件中的那几行标号按照提示的顺序组合。

1
☆✪٭☪✲🌠⍟🌟✡🟉✪🟔⍣☆🞱✡🟇⍟⍟✸🟃🟀✪🟀⚝

解压后得到一个Excel文件。

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
A	٭	 U+066D
B ≛ U+225B
C ⍟ U+235F
D ⍣ U+2363
E ★ U+2605
F ☆ U+2606
G ☪ U+262A
H ⚝ U+269D
I ✡ U+2721
J ✦ U+2726
K ✧ U+2727
L ✪ U+272A
M ✫ U+272B
N ✮ U+272E
O ✯ U+272F
P ✴ U+2734
Q 🌟 U+1F31F
R 🟌 U+1F7CC
S 🟇 U+1F7C7
T 🌠 U+1F320
U 🟉 U+1F7C9
V 🟀 U+1F7C0
W 🟃 U+1F7C3
X 🟆 U+1F7C6
Y 🟐 U+1F7D0
Z 🟔 U+1F7D4
= ✲ U+2732
{ ✸ U+2738
} 🞱 U+1F7B1

然后把文本文件里面的字符按照表里给的对应英文字母替换即可。最后结果为:

1
2
3
4
5
1:FLAG=
2:ISCC{
3:TCQIU
4:WVLVH
5:LZDF}

降维打击

这题写的我真的是很难受。最后一部分整了半天。

flag格式:ISCC{xxxx-xxxx-xxxx}

首先下载附件,解压得到一个图片。

misc-DimensionalityReductionStrike-19

啊,是伊雷娜。

用binwalk看看有没有文件。

1
2
3
4
5
6
7
8
└─$ binwalk misc-DimensionalityReductionStrike-19.png 

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 PNG image, 1192 x 1656, 8-bit colormap, non-interlaced
882 0x372 Zlib compressed data, best compression
290500 0x46EC4 PNG image, 200 x 400, 8-bit/color RGB, non-interlaced
290541 0x46EED Zlib compressed data, default compression

可以看到这里是有东西的。有一个200*400大小的图像文件。但是binwalk提不出来…所以就换foremost来提了。

00000567

可以看到提出来的图片是这样的。算是二值图像了。结合题目降维打击,应该是要我把这个图像展开为一维了。按行展开肯定不行,因为有一半都是纯黑色,提取出来的数据没有关联。稍微看了下列展开的结果。如果把像素值255表示为1的话。前面几个像素点的转换结果刚好是8950。这是PNG文件的文件头。看来方向对了。

写个脚本提一下数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# extract.py
from PIL import Image
from libnum import b2s

img = Image.open(r"00000567.png")

weight, height = img.size
img_gray = img.convert("L")

bin_data = []
for i in range(weight):
for j in range(height):
if img_gray.getpixel((i,j)) == 255:
bin_data.append("1")
else :
bin_data.append("0")

data = "".join(bin_data)

with open(r"data.png", "wb") as fp:
fp.write(b2s(data))

提取出来的数据可以作为图像阅读。

data

到这里看的我一头雾水。这是什么图像密码。我都没见过,找了一圈图形密码,就是没找到和这个类似的。

想起原图是伊雷娜的图,不会是魔女之旅里面的文字吧?

百度了一下没想带还真有…

https://www.bilibili.com/video/BV1Gq4y1g7yw?spm_id_from=333.999.0.0

image-20220502221726137

然后我就遇到了这道题最大的难点(对我来说)。我找不到对应的字母。或者说找到的都不对。能确定的是C、K、I(i)、U和N。其他的不知道对应哪一个。

后面又找了一个:https://www.bilibili.com/read/cv8724055/

得到答案为:

1
2
fckziuurqknf或者fckziuurpknf
zckfiuurqknz或者zckfiuurpknz

然后按照格式提交上去不对…我很想直到出题人是怎么写的这几个字…

最后尝试了这个

1
ISCC{FCKZ-IUUR-PKNF}

结果过了。

让我们回到题目的flag格式:

1
flag格式:ISCC{xxxx-xxxx-xxxx}

作者你这不是坑爹吗。

2022冬奥会

于2022-05-11新增

与单板小将苏翊鸣题解一致。修改图片高度。得到信息:

1
冰墩墩的小伙伴经常被人冷落,你知道它的原型是什么吗?

unicode编码,问的是雪容融的原型是什么。答案是灯笼。

真相只有一个

于2022-05-12新增

下载文件。里面有一张图片,一个文本,一个未知文件。

文本里面包含了很多的空白字符,空格制表符啥的。应该是snow隐写。试了一下直接用snow提取:

1
2
3
F:\CTFTools\隐写\SNOW>SNOW.EXE -C F:\Download\CTF\ISCC2022\真相只有一个\flag.txt
h
bn1aagwanter h:lwse

看样子不是什么有用的东西。应该是要密码。

图片打开的时候报了一个CRC错误的警告。这个应该是图像的宽度或者高度被修改了才会出现的。但是原图像没有失真扭曲,所以应该是高度被修改了。把高度改大一点,左下角出现了摩斯密码。翻译一下。

1
2
-./---/-/...././.-./.
nothere

嗯…这个可能是密码,但也不一定,尝试用这个密码解snow。

1
2
F:\CTFTools\隐写\SNOW>SNOW.EXE -C -p nothere F:\Download\CTF\ISCC2022\真相只有一个\flag.txt
y .bpti awds1)n.. n aWarning: residual of 5 bits not uncompressed

失败了,看来这个应该就是提示你flag不在这。

那么现在就剩下一个文件了。这个文件不知道是什么类型的。先用二进制看看。

1
2
3
00 00 03 04 14 00 01 00 08 00 08 8B 49 54 87 DA 	�����‹IT‡Ú
DD 97 95 D2 22 00 88 D3 2C 00 0D 00 00 00 73 74 Ý—•Ò"�ˆÓ,� ���st
72 65 61 6D 2E 70 63 61 70 6E 67 4F 15 F0 01 EF ream.pcapngOðï

可以看到有个流量包。而且看文件开头的那些数据。14 00 01 00 如果经常做压缩包相关的题的,这个是加密压缩包会出现的特征。所以判断这是一个压缩包,但是缺少了头。所以我们补上即可。修复完之后,再看压缩包内文件PK头部分,也有加密特征,说明这个应该是真加密,我们需要找到对应的密码。

翻了一圈在图像里面找到了。

1
2
3
706173737764efbc 9a313939382f7878  passwd.. .1998/xx
2f78782492492492 4924924924924920 /xx$.I$. I$.I$.I
248eda97b24fc049 53b6b6db6db6db6d $....O.I S...m..m

LSB提一下,看到有个passwd,后面是个日期。这个提示我们密码是个8位数字。所以直接爆破。得到密码19981111。

解压后得到一个包文件。用wireshark打开看看。可以看到几乎全部是TFTP报文,说明这个里面有个传输的文件。TFTP是不加密的,所以我们直接将文件提取出来。

菜单选择“文件”,“导出对象”,“TFTP”。可以看到有个password.mp3的文件。选中保存。

将这个mp3文件放入Audacity。

password

可以看到后方有不规则的波形。是摩斯电码。解密得到isccmisc。这个文件的名字就叫password。所以这个结果应该就是snow的密码。

1
2
F:\CTFTools\隐写\SNOW>SNOW.EXE -C -p isccmisc F:\Download\CTF\ISCC2022\真相只有一个\flag.txt
94jN-itGW-A9OH

得到flag。

1
ISCC{94jN-itGW-A9OH}

Reverse

Amy’s Code

逆向还没入门,所以挑了简单的题练手。哎,没有师傅带自己学是真的进展缓慢。

文件下载下来,StuPE看一下是32位程序。

运行一下。

1
2
Please input flag:wafsafwfaw
Wrong!

看样子是我要自己逆向出flag了。

IDA打开看看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
char Destination[520]; // [esp+DCh] [ebp-410h] BYREF
char Source[516]; // [esp+2E4h] [ebp-208h] BYREF

j__printf(aPleaseInputFla);
sub_411717((va_list)"%s", (char)Source);
j__strcpy(Destination, Source);
sub_4115FF(Destination);
if ( sub_411433(Destination) )
j__printf("Correct!\n");
else
j__printf("Wrong!\n");
j__system("pause");
return 0;
}

流程很简单。

首先读入,然后进入sub_4115FF这个函数处理一下输入的字符串。然后使用sub_411433函数进行判断。重点应该就是这两个函数了。

先进入sub_4115FF这个函数看看。

1
2
3
4
5
// attributes: thunk
int __cdecl sub_4115FF(char *Str)
{
return sub_4128A0(Str);
}

跳转到新函数sub_4128A0。跟进。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int __cdecl sub_4128A0(char *Str)
{
int result; // eax
int i; // [esp+D0h] [ebp-14h]
signed int v3; // [esp+DCh] [ebp-8h]

v3 = j__strlen(Str);
for ( i = 0; ; ++i )
{
result = i;
if ( i >= v3 )
break;
Str[i] ^= i;
}
return result;
}

这个函数逻辑还是很好理解的。就是把对应字符串的字符异或上他的索引值。

在到sub_411433函数看看。其跳转到sub_412550了,我们也跟进。

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
int __cdecl sub_412550(char *Str)
{
int j; // [esp+D0h] [ebp-14Ch]
int i; // [esp+DCh] [ebp-140h]
int v4[32]; // [esp+E8h] [ebp-134h] BYREF
int v5; // [esp+168h] [ebp-B4h]
char v6[24]; // [esp+174h] [ebp-A8h] BYREF
int v7; // [esp+18Ch] [ebp-90h]
__int16 v8; // [esp+190h] [ebp-8Ch]
int v9[31]; // [esp+19Ch] [ebp-80h]

v9[0] = 149;v9[1] = 169;v9[2] = 137;v9[3] = 134;
v9[4] = 212;v9[5] = 188;v9[6] = 177;v9[7] = 184;
v9[8] = 177;v9[9] = 197;v9[10] = 192;v9[11] = 179;
v9[12] = 153;v9[13] = 197;v9[14] = 159;v9[15] = 163;
v9[16] = 160;v9[17] = 167;v9[18] = 169;v9[19] = 184;
v9[20] = 0;v9[21] = 0;v9[22] = 0;v9[23] = 0;
v9[24] = 0;v9[25] = 0;v9[26] = 0;v9[27] = 0;
v9[28] = 0;v9[29] = 0;
strcpy(v6, "LWHFUENGDJGEFHYDHIGJ"); //len = 20
v7 = 0;
v8 = 0;
v5 = j__strlen(Str);
j__memset(v4, 0, 0x78u);
for ( i = 0; i < v5; ++i )
v4[i] = v6[i] + Str[i];
for ( j = 0; j < v5; ++j )
{
if ( v4[j] != v9[j] )
return 0;
}
return 1;
}

接下来只要逆这个运算过程即可。

1
2
for ( i = 0; i < v5; ++i )
v4[i] = v6[i] + Str[i];

首先我们来解出Str是什么。看样子str长度应该要为20。由此得到我们这个函数期望输入的字符串。接下来再反向sub_4128A0函数即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# solve.py

v9 = [
149, 169, 137, 134,
212, 188, 177, 184,
177, 197, 192, 179,
153, 197, 159, 163,
160, 167, 169, 184,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0]

v6 = "LWHFUENGDJGEFHYDHIGJ"

inputStr = []
for i in range(len(v6)):
inputStr.append(v9[i] - ord(v6[i]))

for i in range(len(inputStr)):
inputStr[i] ^= i

print([chr(x) for x in inputStr])

# ISCC{reverse_pHPHOp}

GetTheTable

于2022-05-11新增

下载附件IDA打开。

1
2
3
4
5
6
7
8
9
10
11
n1 = 18;
strcpy(str, "ERaQux2uV3u5F736EjkECSDVLp");
scanf("%s", plainText);
n = strlen(plainText);
if ( n <= 32 )
{
*(_QWORD *)&len[4] = 0i64;
*(_QWORD *)len = (unsigned int)(138 * strlen(plainText) / 0x64) + 1;
strcpy(str12581, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
encryption = (char *)malloc(*(int *)len);
index = 0;

是base58加密。str应该就是我们加密过后的字符串。把字符串拿出来进行base58解密即可得到flag。

未完成

藏在星空中的诗-2

于2022-05-12新增

下载附件,里面就一个文本文件。

1
\🌟🌠🌠✴🟉\🌟🌠🌠★⍣\🌟🌠🌠✴⍣\🌟🌠🌠✴⍣\🌟🌠🌠✧≛\🌟🌠🌠✧🟉\🌟🌠🌠✴🟉\🌟🌠🌠✴🟌\🌟🌠🌠✧✧\🌟🌠🌠✲≛\🌟🌠🌠☆🟌\🌟🌠🌠✧✡\🌟🌠🌠☆🟌\🌟🌠🌠★✧\🌟🌠🌠⍣✸\🌟🌠🌠✴⍣\🌟🌠🌠✧🟉\🌟🌠🌠✴✡\🌟🌠🌠★★\🌟🌠🌠✧⚝

可以看到有个斜杠。这个应该是unicode。Unicode有好几种分隔符,使用\开头的有\u和\u+,这个看样子是\u。所以🌟可以替换位u。观察到每个unicode前面都有🌠🌠,而英文字符的unicode前面都是00。猜测这个替换了00,所以将其替换回去。

这里猜测前五个字符是“ISCC{”而最后一个字符是"}"。可以得到对应的Unicode编码。

1
2
3
4
ISCC{
\u0049\u0053\u0043\u0043\u007b
}
\u007d

可以发现前面其实可以对上的。你看文件中第三个和第四个编码,是一样的。很有可能就是我们猜测的样子。得到编码后对应替换。

1
\u0049\u0053\u0043\u0043\u007b\u0079\u0049\u004🟌\u0077\u00✲b\u00☆🟌\u007✡\u00☆🟌\u0057\u003✸\u0043\u0079\u004✡\u0055\u007d

最后得到这个。这里面最后还有几个字符不知道。看看能不能再找出几个替代。

对于当前的十六进制我们已经有了[0,3,4,5,7,9,b,d],那么还剩下[1,2,6,8,a,c,e,f]。

对于\u00✲b

1
2
\u002b	: +
\u006b : k

所以应该是6。

对于\u007✡,可选的只有[1,2,8,a,c,e,f]

1
2
3
4
5
6
7
\u0071	:q
\u0072 :r
\u0078 :x
\u007a :z
\u007c :|
\u007e :~
\u007f :不可见

c,e,f被排除。当前可选1,2,8,a

对于\u003✸,可选[1,2,8,a,c,e,f]

1
2
3
4
5
6
7
\u0031	:1
\u0032 :2
\u0038 :8
\u003a ::
\u003c :<
\u003e :>
\u003f :?

可选1,2,8