DASCTF2025下半年赛Misc 官方wp:
https://www.yuque.com/chuangfeimeiyigeren/eeii37/pyuic5kgzp3xe3tg?singleDoc#RCpLM
DigitalSignature 题目描述:
1 2 Find out the signer. Maybe you need EIP-191. Flag is account address that wrapped by DASCTF{}. 找出签名者。可能需要使用EIP-191。Flag是包裹在DASCTF{}中的账户地址。
附件task.py内容为:
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 from web3 import Web3 from eth_account.messages import encode_defunct from Crypto.Util.number import bytes_to_long def SignMessage(Message: str, PrivateKey: str) -> dict: Provider = Web3() Temp = encode_defunct(text=Message) SignedMessage = Provider.eth.account.sign_message(Temp, private_key=PrivateKey) SignedMessageHash = SignedMessage.messageHash.hex() SignedMessageSignature = SignedMessage.signature.hex() return {"Message": Message, "SignedMessageHash": SignedMessageHash, "SignedMessageSignature": SignedMessageSignature} def CreateNewAccount() -> tuple: Provider = Web3() Keys = Provider.eth.account.create() Address = Provider.toChecksumAddress(Keys.address) PrivateKey = hex(bytes_to_long(Keys.privateKey)) return (Address, PrivateKey) (Address, PrivateKey) = CreateNewAccount() SignData = SignMessage("Find out the signer. Flag is account address that wrapped by DASCTF{}.", PrivateKey) print(f"MessageHash:{SignData['SignedMessageHash']}\nSignature:{SignData['SignedMessageSignature']}") ''' MessageHash:0x61a78e3c572c1615a6ddd0a0e20157d22b72b8c217cb247318f2c791f4ab6b85 Signature:0x019c4c2968032373cb8e19f13450e93a1abf8658097405cda5489ea22d3779b57815a7e27498057a8c29bcd38f9678b917a887665c1f0d970761cacdd8c41fb61b '''
这是一道与区块链合约有关的赛题,通过题目代码分析得知,需要根据给出的MessageHash和Signature还原出签名该消息的账户的地址。随便问问ai就能解决
exp:
1 2 3 4 5 6 7 8 9 from eth_account import Account msg_hash = "0x61a78e3c572c1615a6ddd0a0e20157d22b72b8c217cb247318f2c791f4ab6b85" signature = "0x019c4c2968032373cb8e19f13450e93a1abf8658097405cda5489ea22d3779b57815a7e27498057a8c29bcd38f9678b917a887665c1f0d970761cacdd8c41fb61b" signer_address = Account._recover_hash(msg_hash, signature=signature) print(f"Signer Address: {signer_address}") print(f"Flag: DASCTF{{{signer_address}}}")
得到
1 2 Signer Address: 0x2b2D44D5325F0d3550296686BE2a7b5Fecb952cB Flag: DASCTF{0x2b2D44D5325F0d3550296686BE2a7b5Fecb952cB}
stegh小鬼 提示是
1 新佛曰挂了,解码出来--pass:2333333
下载附件,发现是一个加密压缩包和一个无后缀文件
将无后缀文件拖入010editor里面查看文件结构
发现这是一个反转的jpg文件,脚本反转
1 2 3 4 5 6 7 with open('快乐小鬼', 'rb') as f: hex_data = f.read().hex()[::-1] with open('1.jpg', 'wb') as f: f.write(bytes.fromhex(hex_data)) print("转换完成,已生成 1.jpg")
得到以下图片
将图片拖入随波逐流会发现还有一个jpg文件,分离文件
cGFzczpLQUdfZ2thX2thZ19HS0E=解码为pass:KAG_gka_kag_GKA
其中分离出来的jpg中有新佛曰
也就是提示说的pass:2333333
这里有两个pass,经过尝试,被分离出的这张图片有steghide隐写,pass为2333333
能发现有一堆的颜文字,但是中间穿插了许多表情,根据表情和颜文字的编码能想到这是aaencode和base100编码,将表情单独按照顺序分出来,作为base100解密
aaencode:
1 Look carefully at the middle of the picture
去看了一下,其实就是前面的cGFzczpLQUdfZ2thX2thZ19HS0E=解码为pass:KAG_gka_kag_GKA,也就是解压加密压缩包的密码
base100:
This_1s_P4ssw0rd
加密压缩包里面的flag.txt内容是:
1 🙃💵🌿🎤🚪🌏🐎🥋🚫😆🎃😊😆🎅🚫👉❓💧🌿🍍✉🐎📮☺☀🙃🛩🔬🚰✖😎🍵👣🌿👉🚪🍎😍🤣😎🍌🖐🌏👌👌🥋👑🍎🍵🍌😎☃🍌🐎✖🔪📂😁👣✖🐘👑📮ℹ
可以联想到emoji-AES解密,还有This_1s_P4ssw0rd没有用到
https://ruotian.io/2020/02/emoji-aes/
解密得到DASCTF{Y0u_are_4_1ovely_Gh0st}
Steganography_challenges0.2 附件只有一张图片,很奇怪,拖入随波逐流得到字符串
1 ZnJvbSBQSUwgaW1wb3J0IEltYWdlDQpFPXJhbmdlDQpSPWJ5dGVzDQpGPUltYWdlLm5ldw0KeD1JbWFnZS5vcGVuDQpmcm9tIENyeXB0by5DaXBoZXIgaW1wb3J0IEFSQzQNCmk9QVJDNC5uZXcNCmRlZiB0KGRhdGEsTyk6DQogcmV0dXJuDQpkZWYgdyhkYXRhLE8pOg0KIGE9aShPLmVuY29kZSgpKQ0KIHJldHVybiBhLncoZGF0YSkNCkk9eCgneW91cl9pbWFnZS5wbmcnKS5jb252ZXJ0KCdSR0InKQ0KTSxqPUkuc2l6ZQ0KWT1GKCdSR0InLChNLGopKQ0KTz0nbW9ua2V5Jw0KZm9yIHkgaW4gRShqKToNCiBmb3IgeCBpbiBFKE0pOg0KICByLGcsYj1JLmdldHBpeGVsKCh4LHkpKQ0KICBuPVIoW3IsZyxiXSkNCiAgSj13KG4sTykNCiAgWS5wdXRwaXhlbCgoeCx5KSwoSlswXSxKWzFdLEpbMl0pKQ0KWS5zYXZlKCdlbmNyeXB0ZWRfaW1hZ2UucG5nJykNCiMgQ3JlYXRlZCBieSBweW1pbmlmaWVyIChodHRwczovL2dpdGh1Yi5jb20vbGlmdG9mZi9weW1pbmlmaWVyKQ0KDQo=
base64解码得到
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from PIL import Image E=range R=bytes F=Image.new x=Image.open from Crypto.Cipher import ARC4 i=ARC4.new def t(data,O): return def w(data,O): a=i(O.encode()) return a.w(data) I=x('your_image.png').convert('RGB') M,j=I.size Y=F('RGB',(M,j)) O='monkey' for y in E(j): for x in E(M): r,g,b=I.getpixel((x,y)) n=R([r,g,b]) J=w(n,O) Y.putpixel((x,y),(J[0],J[1],J[2])) Y.save('encrypted_image.png') # Created by pyminifier (https://github.com/liftoff/pyminifier)
可读性很差,我们打开后面的注释https://github.com/liftoff/pyminifier,发现这是有python混淆
这里可以直接使用ai还原出可读性较好的python代码
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 34 35 36 37 38 39 40 41 42 43 from PIL import Image from Crypto.Cipher import ARC4 def encrypt_pixel(data, key): """ 使用 RC4 算法加密单个像素点的 RGB 数据。 注意:这里的逻辑会在每次调用时重新初始化 Cipher, 这意味着每个像素都使用相同的密钥流进行异或 (XOR) 操作。 """ cipher = ARC4.new(key.encode()) return cipher.encrypt(data) def main(): # 加载原始图片 original_img = Image.open('Steganography_challenges0.2.png').convert('RGB') width, height = original_img.size # 创建一个新的画布用于存放加密后的像素 encrypted_img = Image.new('RGB', (width, height)) # 密钥 key_string = 'monkey' # 遍历每一个像素点 for y in range(height): for x in range(width): # 获取原始像素 (R, G, B) r, g, b = original_img.getpixel((x, y)) # 将 RGB 转为 bytes pixel_data = bytes([r, g, b]) # 加密像素 encrypted_pixel = encrypt_pixel(pixel_data, key_string) # 将加密后的数据填入新图片 encrypted_img.putpixel((x, y), (encrypted_pixel[0], encrypted_pixel[1], encrypted_pixel[2])) # 保存加密图片 encrypted_img.save('encrypted_image.png') if __name__ == '__main__': main()
写一个解密脚本:
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 34 35 36 37 38 39 40 41 42 43 44 from PIL import Image from Crypto.Cipher import ARC4 import os def decrypt_pixel(data, key): """ RC4 是对称加密 (异或运算)。 对密文再次进行相同的异或操作,即可还原明文。 """ cipher = ARC4.new(key.encode()) return cipher.encrypt(data) def main(): input_filename = 'Steganography_challenges0.2.png' output_filename = 'decrypted_image.png' if not os.path.exists(input_filename): print(f"错误: 找不到文件 {input_filename}") return encrypted_img = Image.open(input_filename).convert('RGB') width, height = encrypted_img.size decrypted_img = Image.new('RGB', (width, height)) key_string = 'monkey' print("正在解密,请稍候... (由于是像素级循环,大图可能比较慢)") for y in range(height): for x in range(width): r, g, b = encrypted_img.getpixel((x, y)) pixel_data = bytes([r, g, b]) decrypted_pixel_data = decrypt_pixel(pixel_data, key_string) decrypted_img.putpixel((x, y), (decrypted_pixel_data[0], decrypted_pixel_data[1], decrypted_pixel_data[2])) decrypted_img.save(output_filename) print(f"解密完成! 已保存为 {output_filename}") if __name__ == '__main__': main()
得到decrypted_image.png
stegsolve打开发现存在LSB隐写
坐标问题:
接下来可以参考官方wp,像这样取一小块部分解隐写比全部解隐写方便多了,针对性更强
先确认小块部分的隐写区域(1243,1243)(1257,1254)
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 34 35 36 37 from PIL import Image def extract_lsb(image_path, start_x, start_y, end_x, end_y): img = Image.open(image_path) pixels = img.load() binary_data = "" for y in range(start_y, end_y + 1): for x in range(start_x, end_x + 1): pixel = pixels[x, y] if len(pixel) == 4: r, g, b, _ = pixel else: r, g, b = pixel binary_data += bin(r)[-1] # Red channel LSB binary_data += bin(g)[-1] # Green channel LSB binary_data += bin(b)[-1] # Blue channel LSB hidden_data = "" for i in range(0, len(binary_data), 8): byte = binary_data[i:i + 8] hidden_data += chr(int(byte, 2)) return hidden_data image_path = "decrypted_image.png" start_x, start_y = 1243, 1243 end_x, end_y = 1257,1254 hidden_message = extract_lsb(image_path, start_x, start_y, end_x, end_y) print("Hidden Message:", hidden_message)
得到加密lsb的key:Oversized_chips
1 python2 lsb.py extract decrypted_image.png 11 Oversized_chips
得到图片
猜测是盲水印,对该图片进行单图盲水印提取:
得到flag