阿里云 AliyunCTF 2024 Misc「字」个人题解
March 25, 2024 · Legacy Blog ↗
注意到题给文本存在 Unicode「康熙部首」区的字符,进一步分析后假设该隐写与此相关。那么提出设想:在 Unicode 中,康熙部首涉及的文字既在 4E00~9FFF(中日韩统一表意文字)具有码位,又在 2F00~2FDF(康熙部首)存在码位,那么对于未隐写的文字,可以将其中涉及康熙部首的一部分文字从 4E00~9FFF 替换到 2F00~2FDF 的对应字符,在替换与否中做到数据的隐写。所以写出代码:
# U+2F00 ~ U+2FDF 的康熙部首
kangxi = \
"⼀⼁⼂⼃⼄⼅⼆⼇⼈⼉⼊⼋⼌⼍⼎⼏" \
"⼐⼑⼒⼓⼔⼕⼖⼗⼘⼙⼚⼛⼜⼝⼞⼟" \
"⼠⼡⼢⼣⼤⼥⼦⼧⼨⼩⼪⼫⼬⼭⼮⼯" \
"⼰⼱⼲⼳⼴⼵⼶⼷⼸⼹⼺⼻⼼⼽⼾⼿" \
"⽀⽁⽂⽃⽄⽅⽆⽇⽈⽉⽊⽋⽌⽍⽎⽏" \
"⽐⽑⽒⽓⽔⽕⽖⽗⽘⽙⽚⽛⽜⽝⽞⽟" \
"⽠⽡⽢⽣⽤⽥⽦⽧⽨⽩⽪⽫⽬⽭⽮⽯" \
"⽰⽱⽲⽳⽴⽵⽶⽷⽸⽹⽺⽻⽼⽽⽾⽿" \
"⾀⾁⾂⾃⾄⾅⾆⾇⾈⾉⾊⾋⾌⾍⾎⾏" \
"⾐⾑⾒⾓⾔⾕⾖⾗⾘⾙⾚⾛⾜⾝⾞⾟" \
"⾠⾡⾢⾣⾤⾥⾦⾧⾨⾩⾪⾫⾬⾭⾮⾯" \
"⾰⾱⾲⾳⾴⾵⾶⾷⾸⾹⾺⾻⾼⾽⾾⾿" \
"⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏" \
"⿐⿑⿒⿓⿔⿕"
# U+4E00 ~ U+9FFF 的康熙部首
normal = \
"一丨丶丿乙亅二亠人儿入八冂冖冫几" \
"凵刀力勹匕匚匸十卜卩厂厶又口囗土" \
"士夂夊夕大女子宀寸小尢尸屮山巛工" \
"己巾干幺广廴廾弋弓彐彡彳心戈戶手" \
"支攴文斗斤方无日曰月木欠止歹殳毋" \
"比毛氏气水火爪父爻爿片牙牛犬玄玉" \
"瓜瓦甘生用田疋疒癶白皮皿目矛矢石" \
"示禸禾穴立竹米糸缶网羊羽老而耒耳" \
"聿肉臣自至臼舌舛舟艮色艸虍虫血行" \
"衣襾見角言谷豆豕豸貝赤走足身車辛" \
"辰辵邑酉釆里金長門阜隶隹雨靑非面" \
"革韋韭音頁風飛食首香馬骨高髟鬥鬯" \
"鬲鬼魚鳥鹵鹿麥麻黃黍黑黹黽鼎鼓鼠" \
"鼻齊齒龍龜龠"
source = open('汉字.纯文本', 'rt', encoding='utf-8').read()
cnt = 0
for char in source:
if char in kangxi:
# print("["+char+"]", end='')
print(1, end='')
cnt += 1
elif char in normal:
# print("{"+char+"}", end='')
print(0, end='')
cnt += 1
print()
print(cnt)
# 00100000000010010000010011110110100010011000101101000001010011010011000101000101110001101111010011001101100010000100000000100000101101011110010000110110010010110101111001000011011001010111101000100011011000111001011101000101010111010001010101110100010101010110100100011001101100100011011000100001000000001000111111100000000000000000
# 332
可以得到,原文中共有 332 个涉及康熙部首的字符,这与后来 Hint 中提到的「信息容量 332bits」吻合。先假设进行了字符替换为 1 以及未替换为 0,注意到结尾有连续的 7 个 1 以及连续至结尾的 0,认为其是结束标志。结合 Hint 得知下一步仍与汉字有关,分析后猜测该二进制串每 7bit 为一组,两组表示一个汉字,那么该文本共隐藏了 22 个汉字。
对于汉字的编码,在考虑并排除了中文电码后仍然从 GBK 和 Unicode 方向进行分析。考虑到最终 Flag 与汉字有关,而「从二进制推算出汉字,又尝试从汉字解码出 ASCII 的 Flag」并没有实际意义,猜测汉字内容即表达了 Flag 的内容。进行了各种猜测、尝试后发现,隐写内容前三字符的低 5 位和「阿里云」GBK 编码的低 5 位相同:
阿 10110000 101[00010] <-> 0010000 00[00010]
里 11000000 111[01111] <-> 0100000 10[01111]
云 11010100 110[00110] <-> 0110100 01[00110]
所以认为隐写内容是经过额外处理的 GBK 编码的汉字,在进行一番尝试后找到了正确的解码方法:
source = "00100000000010010000010011110110100010011000101101000001010011010011000101000101110001101111010011001101100010000100000000100000101101011110010000110110010010110101111001000011011001010111101000100011011000111001011101000101010111010001010101110100010101010110100100011001101100100011011000100001000000001000111111100000000000000000"
result = []
for i in range(0, len(source), 7):
byte = int(source[i:i+7], 2)
if byte == 0b1111111:
break
result.append(byte + 0b10100000)
print(bytes(result).decode("gbk"))
# 阿里云夺旗赛左花括二六二六下划五五五四右花括 Tags: #CTF #Writeup #Misc #AliyunCTF
This article is authored by luoingly and licensed under CC BY-NC 4.0