排名
初赛决赛均第一
解题情况
checkin_gift
winhex打开,搜索FFD9可以发现一共有两张JPG图片,两张JPG图片之间存在base编码
base64换表N-ZA-Mn-za-m0-9+/=
+base32解密一下即可得到flag,可以直接利用cyberchef的Magic直接爆破得到flag。
Unkn0wnData
下载附件得到一个flag.png,文件尾存在base64编码
V2hlcmUxc0tleT8KCu2gve25g+2gve2yte2gvO28v+2gvO2+pO2gve26qu2gvO28j+2gve2wju2gvu21i+2gve26q+2gve24huKche2gvO29je2gvO2+pO2gve2wmO2gvO28j+KEueKMqO2gve24je2gvO2+iOKcie2gvu20o+2gve27qe2gvO29jO2gve26qu2gvO29tOKEueKYuu2gve26ueKdk+2gvO29tO2gve20rO2gvO28qu2gvO29te2gve2xo+2gve20hOKYg+2gve2xjO2gve24ju2gve2xjO2gve20hO2gve2xjO2gve20qu2gvO29jO2gve2xge2gvO29je2gvO29jO2gvO28j+2gvO2+g+2gve26sO2gvO29te2gve2wje2gvO2+heKche2gvO29je2gvu22k+2gve24ju2gve24iu2gvu20o+2gvO2/ue2gvO29je2gve2yp+2gve20hO2gve20hO2gvu20o+2gve2xge2gvu21i+2gve26q+KYuu2gvO29tO2gve24ge2gve26q+2gve24h+2gve26sOKPqe2gve24je2gvO28v+2gve2yte2gvu22k+2gve24h+2gve27qeKclu2gve21ue2gve2wju2gve2zgu2gve2zgu2gve2yp+2gve23ku2gve23kg==
base64解码一下得到乱码数据
之后将该编码做一个utf-8转码,即可得到aes-emoji字符
当然也可以通过爆破获取编码:
??????????✅????ℹ⌨??✉?????ℹ☺?❓??????☃????????????????✅??????????????☺?????⏩??????✖???????
利用stegsolve对flag.png进行lsb隐写解密,发现504B0304字段
hex解码一下即可保存为zip压缩包
压缩包内是一个txt文件
data:
0000100000000000
00000c0000000000
00000e0000000000
00002a0000000000
0000100000000000
0000040000000000
0000080000000000
00002a0000000000
0000160000000000
00000b0000000000
00000c0000000000
00001c0000000000
00002a0000000000
00002c0000000000
0200340000000000
00002a0000000000
0200090000000000
00000c0000000000
0000110000000000
0000070000000000
0200170000000000
00002a0000000000
0200170000000000
00000b0000000000
0000080000000000
0000120000000000
00002a0000000000
0200150000000000
0000080000000000
0000040000000000
00000f0000000000
00000a0000000000
00002a0000000000
02000e0000000000
0000080000000000
00001c0000000000
00000a0000000000
00002a0000000000
0000040000000000
0000110000000000
0000070000000000
00000f0000000000
00002a0000000000
0200100000000000
0000040000000000
00000e0000000000
0000080000000000
0000080000000000
00002a0000000000
02000c0000000000
0000170000000000
02001e0000000000
0000070000000000
00002a0000000000
写一个python脚本解密键盘流量:
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
keys = open('key.txt')
output = ""
for line in keys:
k = line[1]
n = line[4:6]
if k == '0':
print(normalKeys[n], end='')
elif k == '2':
print(shiftKeys[n], end='')
得到结果:
mik<DEL>mae<DEL>shiy<DEL><SPACE>:<DEL>FindT<DEL>Theo<DEL>Realg<DEL>Keyg<DEL>andl<DEL>Makee<DEL>It!d<DEL>
将DEL的值删除后得到:
mimashi FindTheRealKeyandMakeIt!
解密后,该key的意思是让我们寻找真实的key,说明这是一个假key,仔细观察被DEL的字符,可以发现开头几位是key:
,可知被DEL的字符才是关键。
只读取被DEL的字符的脚本:
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
keys = open('key.txt')
output = ""
for line in keys:
k = line[1]
n = line[4:6]
if n == '2a':
print(output[-1], end='')
if k == '0':
output += normalKeys[n]
elif k == '2':
output += shiftKeys[n]
跑一下即可得到aes-emoji的key
key:Toggled
emoji-aes正常需要在线网站,结果如下:
项目地址:https://aghorler.github.io/emoji-aes/#
但是省赛环境是不能联网的,只能直接写个脚本替换,根据aes-emoji的原理,实际上就只是一个带盐的aes加密,把结果base64一下,然后把表换成了65个emoji,所以只需要进行一个替换即可。
脚本如下:
import base64
from Crypto.Cipher import AES
import string
emojisInit="????????ℹ??✉????????☂??✖☀?????????☃???????⌨???????❓⏩????☺?????✅??"
alpha = string.ascii_lowercase+string.ascii_uppercase+string.digits+"+/="
a = "??????????✅????ℹ⌨??✉?????ℹ☺?❓??????☃????????????????✅??????????????☺?????⏩??????✖???????"
base64data = ""
for i in a:
base64data += alpha[emojisInit.index(i)]
print(base64data)
换表后得到:
U2FsdGVkX1+psEGiQ9Bl3PbdKi4mYKSHJfRIoCoRo/bepbG8tJvD+pzC53ApwRR3ekX4K0X6tZ9F2z6PxNVOOw==
最后进行aes解密即可得到flag
m4a
下载附件得到一个m4a文件,发现打不开,观察一下正常的m4a文件,可以发现第五位到第十一位是固定头文件667479704D3441
,但是题目中的头文件被损坏了,全是00
,修复文件头即可正常打开
m4a是一个音频文件,可以听出是摩斯电码,放不进audacity,用格式工厂转成mp3再放,得到摩斯电码
-... .- ....- ...-- -... -.-. . ..-. -.-. ..--- ----- ....-
解MORSE密码得到:
BA43BCEFC204
文件尾存在一个倒叙的zip压缩包
倒叙一下即可保存为zip压缩包
打开发现需要密码
利用该key解压压缩包,得到atbash.txt
(+w)v&LdG_FhgKhdFfhgahJfKcgcKdc_eeIJ_gFN
根据提示atbash.txt,可知需要解埃特巴什码
可以直接利用cyberchef进行解密,先进行ROT47解密,然后进行atbash解密即可
hard_Digital_plate
下载附件得到一个流量包文件,发现报了长度错误
报了长度错误可知文件尾存在隐藏数据,用winhex打开发现隐藏数据如下:
提取出来发现是一个压缩包,压缩包内存在oursecret.jpg,之后删除隐藏的压缩包数据,流量包就不会报错了
分析流量包发现是一个数位板流量,先利用tshark分离数据
tshark -r hard_Digital_plate.pcapng -T fields -e usbhid.data | sed '/^\s*$/d' > out.txt
得到(数据量过大,随意截取一段展示):
08803708951e000000000000
08803708951e000000000000
08803708951e000000000000
08803708951e000000000000
08803708951e000000000000
08813708951e650000000000
08813808951ec10000000000
08813908951e2e0100000000
08813a08951e940100000000
08813b08951ee20100000000
08813c08951e1c0200000000
08813c08951e440200000000
08813c08951e610200000000
第二个字节代表了是否启用0x81位有效坐标,同时后四位还有数位板的压感值。
当第二字节为0x81时,说明数位板正在作画,且第8字节和第9字节存在压感值,当第二字节为0x80时,说明数位板没有落笔,即没有作画,此时第8字节和第9字节不存在压感,为0x0000。
坐标分析直接说结论,第5-8位是x轴坐标,第9-12位是y轴坐标,并且是小端序储存方法。
例如:
08803708951e000000000000
这个数据,0x3708是x坐标信息,0x951e是y坐标信息,但是由于数据为小端序储存,实际x坐标为0x0837,y坐标为0x1e95。
根据如下规律,写个python脚本提取存在压感的数位板坐标:
nums = []
keys = open('out.txt', 'r')
result = open('result.txt', 'w')
for line in keys:
if int(line[12:16], 16) == 0:
continue
x = int(line[4:6], 16) + int(line[6:8], 16) * 0xff
y = int(line[8:10], 16) + int(line[10:12], 16) * 0xff
result.write(str(x)+' '+str(-y)+'\n')
keys.close()
result.close()
得到最表后,利用kali自带的gnuplot画图得到:
the key is:kfae5y4wi2shwj81y2kda6ax7x
根据jpg文件名提示,可知是oursecret隐写,利用kfae5y4wi2shwj81y2kda6ax7x
解一下oursecret:
解得flag.txt
U2FsdGVkX18jQgWzhln3pPiVK8gaBxIzhY1JWcFlKiRdBkV/jDmEBxJV9PZmwBJ7MU3IdNf4hWryZLYRLuxA4w==
在jpg注释中发现备注,提示需要提取数位板压感低的数据
写个脚本专门提取低压感数据,这里将0xf000作为压感临界值:
nums = []
keys = open('out.txt', 'r')
result = open('result.txt', 'w')
for line in keys:
if int(line[12:16], 16) == 0:
continue
x = int(line[4:6], 16) + int(line[6:8], 16) * 0xff
y = int(line[8:10], 16) + int(line[10:12], 16) * 0xff
if int(line[12:16], 16) < 0xf000:
result.write(str(x)+' '+str(-y)+'\n')
keys.close()
result.close()
画图:
得到:
key is w12kax
最后解一个aes密码即可得到flag