LOADING

加载过慢请开启缓存 浏览器默认开启

SSSCTF 2024

2024/5/3 题解 CTF

SSSCTF 2024 Writeup

Reverse

1. checkin

IDA打开直接出flag

image-20240430160141949

Crypto

1. 原神(签到)

提瓦特符文

img

2. 체력 4700 방어력 329(简单)

你说得对但这就是奎桑提

一眼维吉尼亚爆破

image-20240430160848283

3. 小小RSA(中等)

先简单跑一下,发现e与(p-1)或(q-1)均不互素

解法:

  1. 先利用sagemath求解一个模质数p意义下的方程x^{e}=c的解;
  2. 然后利用中国剩余定理遍历得到的根的列表。

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

玩游戏即可

screenshot

胜利后在对话栏找到flag

2. 攘外必先安内

Everything got to have its own lsb steganography!

根据提示猜测是 .flac 格式的LSB隐写,但是flac结构比较复杂不好分析。由于flac是无损压缩格式,可以考虑转换成 .wav 文件在提取采样点数据。

ffmpeg -i output.flac out.wav

image-20240430162258878

转换后文件头部分有一大段注释,删了以后就得到了比较标准的 .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。尝试解压发现有密码。

在注释中发现提示:

image-20240430163550233

ARCHPR爆破即可

image-20240430163728804

解压得到flag

flag{Wie_zum_Teufel_bist_du_auf_diese_Art_des_Versteckens_gekommen?}

3. 红色无九零倍速之第二人格妄图夺取身体窃取我的脑内机密爱来自icu奈何我的兄弟叫顺溜替我删除了浏览记录

过滤http包发现可疑操作,找到Request URL:

image-20240430164013756

定位到出题人的博客,由于博客是基于hexo+github仓库搭建的,直接找到出题人的博客仓库

image-20240430164149881

得到两张图

image-20240430164250198

先解决下面那张 Im_the_real_topsecret.png

010打开发现末尾有数据

image-20240430164345889

提取压缩包,观察可知是伪加密,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')

对第二张图同样处理,比较两个文件后截取不同的片段,也就是最前面一段数据。

image-20240430165146089

再根据提示 what is LSB in decimal? 对每个十六进制数进行十进制转换,再提取十进制最低位,把得到的数连接起来

122333333333345333333333326753381223333333333453333333333267533333333812233333333345333333333326753333333812233333333334533333333332675333812233333333333345333333333326753338122333333333333333345333326753381223333333333333333453333333267533812233333333333333334533333326753812233333334533333332675812233333333333333334533332675333333333333338122333333333333333333345333332675812233333333333333334533333267533333812233333333333333334533333332675812233333333334533333333332675333812233333333333333334533333332675338122333333334533333332675812233333333333333334533333326753333381223333333333453333333333267581223333333333333333453333333267533333333333338

这是个啥?

根据提示 you need a key to unlock a secretbox 以及第一个提示中的 无90 得知,想得到真正的数据还需要解密的key,再回到流量包中寻找即可发现

image-20240430165523247

也就是 key(8)={,>+[<-].} 按’1’ 对应 ‘,’ ‘2’ 对应 ‘>’, … 以此类推

key = ['0',',','>','+','[','<','-',']','.']
secret = "122333333333345333333333326753381223333333333453333333333267533333333812233333333345333333333326753333333812233333333334533333333332675333812233333333333345333333333326753338122333333333333333345333326753381223333333333333333453333333267533812233333333333333334533333326753812233333334533333332675812233333333333333334533332675333333333333338122333333333333333333345333332675812233333333333333334533333267533333812233333333333333334533333332675812233333333334533333333332675333812233333333333333334533333332675338122333333334533333332675812233333333333333334533333326753333381223333333333453333333333267581223333333333333333453333333267533333333333338"

for i in secret:
    print(key[int(i)], end='')

得到

,>>++++++++++[<++++++++++>-]<++.,>>++++++++++[<++++++++++>-]<++++++++.,>>+++++++++[<++++++++++>-]<+++++++.,>>++++++++++[<++++++++++>-]<+++.,>>++++++++++++[<++++++++++>-]<+++.,>>++++++++++++++++[<++++>-]<++.,>>++++++++++++++++[<+++++++>-]<++.,>>++++++++++++++++[<++++++>-]<+.,>>+++++++[<+++++++>-]<.,>>++++++++++++++++[<++++>-]<++++++++++++++.,>>+++++++++++++++++++[<+++++>-]<.,>>++++++++++++++++[<+++++>-]<+++++.,>>++++++++++++++++[<+++++++>-]<.,>>++++++++++[<++++++++++>-]<+++.,>>++++++++++++++++[<+++++++>-]<++.,>>++++++++[<+++++++>-]<.,>>++++++++++++++++[<++++++>-]<+++++.,>>++++++++++[<++++++++++>-]<.,>>++++++++++++++++[<+++++++>-]<+++++++++++++.

一眼brainfuck,解码得到flag

image-20240430165917414

大脑升级了!