ISCC 2022 中 单板小将苏翊鸣、 藏在星空中的诗、降维打击、2022冬奥会、真相只有一个、GetTheTable与Amy’s Code 的题解
时间挺长的,但是没啥时间来玩。话说为什么没有Crypto方向的
Misc
单板小将苏翊鸣
下载附件后打开,是一张图片和一个压缩包。压缩包加密了,很明显密码应该在图片里。
图片属性和压缩包注释里面都没有有用的信息。用binwalk和foremost也没有分出来东西。
Ih ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™h ÐEDDDDDDf �t ‘€]DDDDDDd A ™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+066 D B ≛ U+225 B C ⍟ U+235 F D ⍣ U+2363 E ★ U+2605 F ☆ U+2606 G ☪ U+262 A H ⚝ U+269 D I ✡ U+2721 J ✦ U+2726 K ✧ U+2727 L ✪ U+272 A M ✫ U+272 B N ✮ U+272 E O ✯ U+272 F P ✴ U+2734 Q 🌟 U+1 F31F R 🟌 U+1 F7CC S 🟇 U+1 F7C7 T 🌠 U+1 F320 U 🟉 U+1 F7C9 V 🟀 U+1 F7C0 W 🟃 U+1 F7C3 X 🟆 U+1 F7C6 Y 🟐 U+1 F7D0 Z 🟔 U+1 F7D4 = ✲ U+2732 { ✸ U+2738 } 🞱 U+1 F7B1
然后把文本文件里面的字符按照表里给的对应英文字母替换即可。最后结果为:
1 2 3 4 5 1 :FLAG= 2 :ISCC{3 :TCQIU4 :WVLVH5 :LZDF}
降维打击
这题写的我真的是很难受。最后一部分整了半天。
flag格式:ISCC{xxxx-xxxx-xxxx}
首先下载附件,解压得到一个图片。
啊,是伊雷娜。
用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来提了。
可以看到提出来的图片是这样的。算是二值图像了。结合题目降维打击,应该是要我把这个图像展开为一维了。按行展开肯定不行,因为有一半都是纯黑色,提取出来的数据没有关联。稍微看了下列展开的结果。如果把像素值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 from PIL import Imagefrom 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))
提取出来的数据可以作为图像阅读。
到这里看的我一头雾水。这是什么图像密码。我都没见过,找了一圈图形密码,就是没找到和这个类似的。
想起原图是伊雷娜的图,不会是魔女之旅里面的文字吧?
百度了一下没想带还真有…
https://www.bilibili.com/video/BV1Gq4y1g7yw?spm_id_from=333.999.0.0
然后我就遇到了这道题最大的难点(对我来说)。我找不到对应的字母。或者说找到的都不对。能确定的是C、K、I(i)、U和N。其他的不知道对应哪一个。
后面又找了一个:https://www.bilibili.com/read/cv8724055/
得到答案为:
1 2 fckziuurqknf或者fckziuurpknf zckfiuurqknz或者zckfiuurpknz
然后按照格式提交上去不对…我很想直到出题人是怎么写的这几个字…
最后尝试了这个
结果过了。
…
让我们回到题目的flag格式:
1 flag格式:ISCC {xxxx-xxxx-xxxx}
作者你这不是坑爹吗。
2022冬奥会
与单板小将苏翊鸣题解一致。修改图片高度。得到信息:
1 冰 墩 墩 的 小 伙 伴 经 常 被 人 冷 落 , 你 知 道 它 的 原 型 是 什 么 吗 ?
unicode编码,问的是雪容融的原型是什么。答案是灯笼。
真相只有一个
下载文件。里面有一张图片,一个文本,一个未知文件。
文本里面包含了很多的空白字符,空格制表符啥的。应该是snow隐写。试了一下直接用snow提取:
1 2 3 F:\CTFTools\隐写\SNOW>SNOW.EXE -C F:\Download\CTF\ISCC2022\真相只有一个\flag.txth 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。
可以看到后方有不规则的波形。是摩斯电码。解密得到isccmisc。这个文件的名字就叫password。所以这个结果应该就是snow的密码。
1 2 F:\CTFTools\隐写\SNOW>SNOW.EXE -C -p isccmisc F:\Download\CTF\ISCC2022\真相只有一个\flag.txt94 jN-itGW-A9OH
得到flag。
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 ]; char Source[516 ]; 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 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; int i; signed int v3; 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; int i; int v4[32 ]; int v5; char v6[24 ]; int v7; __int16 v8; int v9[31 ]; 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" ); v7 = 0 ; v8 = 0 ; v5 = j__strlen(Str); j__memset(v4, 0 , 0x78 u); 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 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] ^= iprint ([chr (x) for x in inputStr])
GetTheTable
下载附件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 ] = 0 i64; *(_QWORD *)len = (unsigned int )(138 * strlen (plainText) / 0x64 ) + 1 ; strcpy (str12581, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" ); encryption = (char *)malloc (*(int *)len); index = 0 ;
是base58加密。str应该就是我们加密过后的字符串。把字符串拿出来进行base58解密即可得到flag。
未完成
藏在星空中的诗-2
下载附件,里面就一个文本文件。
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
所以应该是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