SSSCTF 2024 Writeup
Reverse
1. checkin
IDA打开直接出flag
Crypto
1. 原神(签到)
提瓦特符文
2. 체력 4700 방어력 329(简单)
你说得对但这就是奎桑提
一眼维吉尼亚爆破
3. 小小RSA(中等)
先简单跑一下,发现e与(p-1)或(q-1)均不互素
解法:
- 先利用sagemath求解一个模质数p意义下的方程的解;
- 然后利用中国剩余定理遍历得到的根的列表。
SageMath:
R = Zmod(p)['x']; (x,) = R._first_ngens(1) #模q的意义下定义了一个多项式环R
f = x ** e - c
f = f.monic()
res1 = f.roots()
print(res1)
R = Zmod(q)['x']; (x,) = R._first_ngens(1) #模q的意义下定义了一个多项式环R
f = x ** e - c
f = f.monic()
res2 = f.roots()
print(res2)
Python:
import gmpy2
import libnum
c = 71169875189850572113777292593419365066568714962659459887887057825765932879627373444241237658536711790761727048963108419031305925551095519312885510028734978296846109483788143386218693133005090042977765436091355422587099782896436564691824732238054978244017015673314259383682751917339927833598920446225314327796
e = 27
p = 11953760443569136629362149103663808170500109727046051609146588793477906801446269513662279449629673020674587669890939380916105255552623253806604660037904381
q = 8861458201455119766910033315624439770717944707672559115128871223956609341165561169077567163208984303574227957326576092874935144092007970387545781227984601
n = p * q
res1 = [(11577619797277421855736320880786377819943747771290215542782809587991881113533353394910690043409957889525162860279825793445633799714836124353232789913611809, 1), (376140646291714773625828222877430350556361955755836066363779205486025687912915937785174180647008804598458554580241812569850772112914480178642343631213663, 1), (180966415225572706326550966255030871774900620683724872649274729526493078909, 1)]
res2 = [(6464282590942715771670662599348296245764004243928449548575967256858675619164507005299731587480690509249196417351733080430555793939011074159164970867786062, 1), (2397175610512403995239370716276143524953940463744109566552903967097933722001053982811420350155587467774065284943971237543758666428124246953651283867119630, 1), (180966415225572706326550966255030871774900620683724872649274729526493078909, 1)]
phi = (p - 1) * (q - 1)
for i in res1:
for j in res2:
m = libnum.solve_crt([int(i[0]),int(j[0])],[p,q])
flag = long_to_bytes(m)
if b'flag' in flag:
print(flag)
得到flag
flag{R5A_1s_4w3s0m3_4nd_5ecure}
Misc
1. The Siege
玩游戏即可
胜利后在对话栏找到flag
2. 攘外必先安内
Everything got to have its own lsb steganography!
根据提示猜测是 .flac
格式的LSB隐写,但是flac结构比较复杂不好分析。由于flac是无损压缩格式,可以考虑转换成 .wav
文件在提取采样点数据。
ffmpeg -i output.flac out.wav
转换后文件头部分有一大段注释,删了以后就得到了比较标准的 .wav
文件(即从索引为44的十六进制数开始存储data数据)。
观察发现前半段有 01
信息,推测就是在此处进行了LSB隐写。了解 .wav
文件结构得知:data是奇数位存放左声道数据,偶数位存放右声道数据。提取左声道数据后,将最低有效位按每八个为一组转换为十进制数,再转换为相应的ASCII码字符就可以得到隐藏的数据。
Python脚本实现:
import binascii
filename = 'out.wav'
with open(filename, 'rb') as f:
file_data = f.read()
# 将二进制数据转换为十六进制字符串
hex_data = binascii.hexlify(file_data).decode()
# 获取从第 44 个十六进制数开始的十六进制值
start_index = 44 * 2
hex_values = hex_data[start_index:]
# 隔一个数取以提取左声道数据
step = 2
hex_list = [hex_values[i:i+step] for i in range(0, len(hex_values), 4)]
# 转换为二进制数并读取最低有效位
binary_list = [bin(int(hv, 16))[2:].zfill(8) for hv in hex_list]
least_significant_bits = [b[-1] for b in binary_list]
# 将最低有效位按每八个为一组转换为十进制数
decimal_values = []
for i in range(0, len(least_significant_bits), 8):
bits = least_significant_bits[i:i+8]
bit_string = ''.join(bits)
decimal_value = int(bit_string, 2)
decimal_values.append(decimal_value)
for i in decimal_values:
print(chr(i),end='')
得到以下数据:
NGQ1MzQzNDYwMDAwMDAwMDQ3MDEwMDAwMDAwMDAwMDAyYzAwMDAwMDAwMDAwMDAwMDMwMTAxMDAwMTAwMDAwMDAwMDAwMDAwNDUwMDAwMDAwMTAwMDMxNWU1MDAwMDAwMDAwMDAwMDAwMDAwN2M1OGJjOTQyMDAwNjY2YzYxNjcyZTcyNjE3MjAwN2IwNWE4OGVmYTAwZTUwMDViODA4MDhkMDAzMDUwMGUxZDAwMDAwMDA3MDAwMDAwMDMwMDAwMDA1MjYxNzIyMTFhMDcwMTAwMzM5MmI1ZTUwYTAxMDUwNjAwMDUwMTAxODA4MDAwZjFlNjYzNWQxMzAzMDI4NDAwMDQ4NDAwMDBjNGFjMzYzZjgwMDAwMDAzNDM0ZDU0Nzc2NTYxNmI1YmRlNjAzMTU1MDIwMzNjZDAwMDA0YzQwMDIwYThkYjViZmM4MDAzMDAwODY2NmM2MTY3MmU3NDc4NzQzMDAxMDAwMzBmNGMzNGYwMzZiZDYyMzk3ZjYyODkwYThkOGUxMjYyZjY4Njc4NDZhNjM5NDQ0MDA3NmYxNGI0N2EzMjdiYmJlZjc0ZjJiZmQ5ZTUzMDlkODY5MmU4YzA1NzBhMDMwMjRhZDY1NzcxZmE4MGRhMDFhOWY3NTg0YjVhNWVkMTFhOTg1MzNmZjI1OWJlZDE5ZDY4NmI2ODBmNDRhMGJiZTllNTgzMzM5MTk3MDg2ZDg5MDVkYWYyOWZmZDJkMTUwZGEwNDdjOWVkMDUyOGYyODQ4Y2RlNDU4MGM5ODZhOWI3OTVjYWM2MDM3MDdhMTBiNDkwY2NhZTFjYTcxMjBjOGY2MDkwMzMyM2ZlNmYwZWNiMWQ3NzU2NTEwMzA1MDQwMDAw
容易看出是base64编码,解码后的数据头数据为 4d 53 43 46
搜一下发现是 MicrosoftCABFileFormat
,是windows的压缩格式,直接解压得到 flag.rar。尝试解压发现有密码。
在注释中发现提示:
ARCHPR爆破即可
解压得到flag
flag{Wie_zum_Teufel_bist_du_auf_diese_Art_des_Versteckens_gekommen?}
3. 红色无九零倍速之第二人格妄图夺取身体窃取我的脑内机密爱来自icu奈何我的兄弟叫顺溜替我删除了浏览记录
过滤http包发现可疑操作,找到Request URL:
定位到出题人的博客,由于博客是基于hexo+github仓库搭建的,直接找到出题人的博客仓库
得到两张图
先解决下面那张 Im_the_real_topsecret.png
010打开发现末尾有数据
提取压缩包,观察可知是伪加密,09 00
改成 00 00
,解压出来发现是fake flag,于是处理第一张图
根据提示,提取第一张图的R通道数据保存
def randomized_image_to_binary(input_image, output_file):
img = Image.open(input_image)
# 获取图像的宽度和高度
width, height = img.size
# 将图像像素转换为二进制数据,只保留红色通道
binary_data = bytearray()
for y in range(height):
for x in range(width):
r, _, _ = img.getpixel((x, y))
binary_data.append(r)
# 保存二进制数据到文件
with open(output_file, 'wb') as binary_file:
binary_file.write(binary_data)
randomized_image_to_binary('top_secret.png', 'pic1.bin')
对第二张图同样处理,比较两个文件后截取不同的片段,也就是最前面一段数据。
再根据提示 what is LSB in decimal?
对每个十六进制数进行十进制转换,再提取十进制最低位,把得到的数连接起来
122333333333345333333333326753381223333333333453333333333267533333333812233333333345333333333326753333333812233333333334533333333332675333812233333333333345333333333326753338122333333333333333345333326753381223333333333333333453333333267533812233333333333333334533333326753812233333334533333332675812233333333333333334533332675333333333333338122333333333333333333345333332675812233333333333333334533333267533333812233333333333333334533333332675812233333333334533333333332675333812233333333333333334533333332675338122333333334533333332675812233333333333333334533333326753333381223333333333453333333333267581223333333333333333453333333267533333333333338
这是个啥?
根据提示 you need a key to unlock a secretbox
以及第一个提示中的 无90 得知,想得到真正的数据还需要解密的key,再回到流量包中寻找即可发现
也就是 key(8)={,>+[<-].}
按’1’ 对应 ‘,’ ‘2’ 对应 ‘>’, … 以此类推
key = ['0',',','>','+','[','<','-',']','.']
secret = "122333333333345333333333326753381223333333333453333333333267533333333812233333333345333333333326753333333812233333333334533333333332675333812233333333333345333333333326753338122333333333333333345333326753381223333333333333333453333333267533812233333333333333334533333326753812233333334533333332675812233333333333333334533332675333333333333338122333333333333333333345333332675812233333333333333334533333267533333812233333333333333334533333332675812233333333334533333333332675333812233333333333333334533333332675338122333333334533333332675812233333333333333334533333326753333381223333333333453333333333267581223333333333333333453333333267533333333333338"
for i in secret:
print(key[int(i)], end='')
得到
,>>++++++++++[<++++++++++>-]<++.,>>++++++++++[<++++++++++>-]<++++++++.,>>+++++++++[<++++++++++>-]<+++++++.,>>++++++++++[<++++++++++>-]<+++.,>>++++++++++++[<++++++++++>-]<+++.,>>++++++++++++++++[<++++>-]<++.,>>++++++++++++++++[<+++++++>-]<++.,>>++++++++++++++++[<++++++>-]<+.,>>+++++++[<+++++++>-]<.,>>++++++++++++++++[<++++>-]<++++++++++++++.,>>+++++++++++++++++++[<+++++>-]<.,>>++++++++++++++++[<+++++>-]<+++++.,>>++++++++++++++++[<+++++++>-]<.,>>++++++++++[<++++++++++>-]<+++.,>>++++++++++++++++[<+++++++>-]<++.,>>++++++++[<+++++++>-]<.,>>++++++++++++++++[<++++++>-]<+++++.,>>++++++++++[<++++++++++>-]<.,>>++++++++++++++++[<+++++++>-]<+++++++++++++.
一眼brainfuck,解码得到flag
大脑升级了!