DASCTF 2025上半年赛 reverse wp
鱼音乐

如果直接通过打开.xianyu文件播放的话出现这个
没有flag
反编译main.pyc
# Source Generated with Decompyle++
# File: main.pyc (Python 3.8)
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QPushButton, QLabel, QVBoxLayout, QFileDialog, QMessageBox
from PyQt5.QtGui import QPixmap
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
from PyQt5.QtCore import QUrl
from xianyu_decrypt import load_and_decrypt_xianyu
class MainWindow(QMainWindow):
def __init__(self = None):
super().__init__()
self.setWindowTitle('Fish Player - 楸奸煶涔愷煇?
导入了xianyu_decrypt库
但是只能找到xianyu_decrypt.cp38-win_amd64.pydpyd文件
import xianyu_decrypt
print(dir(xianyu_decrypt))
print(help(xianyu_decrypt))
输出为
['AES', 'MASTER_KEY', 'XIANYU_HEADER', '__builtins__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__test__', 'decrypt_aes_ecb', 'json', 'load_and_decrypt_xianyu', 'os', 'read_part1', 'read_part2', 'read_part3', 'read_part4', 'read_part5', 'struct', 'tempfile', 'unpad']
Help on module xianyu_decrypt:
NAME
xianyu_decrypt
FUNCTIONS
decrypt_aes_ecb(enc_data: 'bytes', key: 'bytes') -> 'bytes'
decrypt_aes_ecb(bytes enc_data: bytes, bytes key: bytes) -> bytes
load_and_decrypt_xianyu(xianyu_path: 'str') -> 'dict'
load_and_decrypt_xianyu(unicode xianyu_path: str) -> dict
read_part1(data, offset)
read_part1(data, offset)
read_part2(data, offset)
read_part2(data, offset)
read_part3(data, offset)
read_part3(data, offset)
read_part4(data, offset, file_key, meta_length)
read_part4(data, offset, file_key, meta_length)
read_part5(data, offset, file_key)
read_part5(data, offset, file_key)
unpad(data: 'bytes') -> 'bytes'
unpad(bytes data: bytes) -> bytes
DATA
MASTER_KEY = b'XianYuAESKey0000'
XIANYU_HEADER = b'XIANYUFS'
__test__ = {}
FILE
e:\comp\das\das6-_35d00818974deefff91f84abdb0815ea\tempdir\reverse附件\xianyu_decrypt.cp38-win_amd64.pyd
None
decrypt_aes_ecb函数参数为(enc_data,key)
key为XianYuAESKey0000
但是没有找到enc_data
load_and_decrypt_xianyu函数的参数只有.xianyu文件的path
所以可以使用load_and_decrypt_xianyu函数解密
from xianyu_decrypt import load_and_decrypt_xianyu
result = load_and_decrypt_xianyu("E:\\comp\\das\\DAS6-_35d00818974deefff91f84abdb0815ea\\tempdir\\REVERSE附件\\miao.xianyu")
print(result)
输出为
Traceback (most recent call last):
File "E:\comp\das\DAS6-_35d00818974deefff91f84abdb0815ea\tempdir\REVERSE附件\temp.py", line 2, in <module>
load_and_decrypt_xianyu("E:\\comp\\das\\DAS6-_35d00818974deefff91f84abdb0815ea\\tempdir\\REVERSE附件\\miao.xianyu")
NameError: name 'load_and_decrypt_xianyu' is not defined
(py38) E:\CTF\tool\pypypy\pyinstxtractor>python E:\comp\das\DAS6-_35d00818974deefff91f84abdb0815ea\tempdir\REVERSE附件\temp.py
{'meta': {'name': '耄耋A梦', 'artist': '圆头🐱', 'fl4g': '(=ↀωↀ=)哈~!!!我听说就在音乐的“信息文件”里!!', 'flag': 'DASCTF{fl5h_mus1c_miao_m1a0_mlaO}'},
flag:DASCTF{fl5h_mus1c_miao_m1a0_mlaO}
xuans(复现)
参考wp
https://su-team.cn/2025/06/21/2025-DASCTF上半年/#xuans
https://blog.rkk.moe/2025/06/23/DASCTF-2025-First-Writeup/#xuans
https://matriy330.github.io/f1dd543a/#xuans

根据这里可以判定是sm4加密

在main函数里面,sm4加密前有shellcode,这是在对key进行加密

shellcode放进ida看出是异或
异或得到真正的key
#include<stdio.h>
int main(){
int a[]={0x39,0x5A,0x3B,0x5D,0x3C,0xA,0x3E,0x8,0x3E,0x5F,0x6F,0x5D,0x65,0x7,0x61,0x3};
int len=sizeof(a)/sizeof(a[0]);
int b[len];
for(int i=len-1;i>0;i--){
a[i]=a[i]^a[i-1];
}
for(int i=0;i<sizeof(a)/sizeof(a[0]);i++){
printf("0x%x,",a[i]);
}
}
//0x39,0x63,0x61,0x66,0x61,0x36,0x34,0x36,0x36,0x61,0x30,0x32,0x38,0x62,0x66,0x62
但是解出fakeflag

真正的密文大概两种方法找到,一是手翻函数,二是动调方式追踪到替换函数(没有复现成功)
找到sub_4019A5函数

z3求解
from z3 import *
s = Solver() # 创建了一个 Solver 对象 s
a1 = [BitVec('a%d' % i,16) for i in range(32)] # 变量
s.add(118 * a1[2] + 173 * a1[0] + 48 * a1[1] + 193 * a1[3] == 66131)
s.add(196 * a1[1] + 68 * a1[0] + 104 * a1[2] + 10 * a1[3] == 52620)
s.add(88 * a1[2] + 22 * a1[0] + 37 * a1[1] + 71 * a1[3] == 36011)
s.add(59 * a1[2] + 141 * a1[1] + 89 * a1[0] + 194 * a1[3] == 61842)
s.add(175 * a1[6] + 88 * a1[5] + 40 * a1[4] + 89 * a1[7] == 65258)
s.add(26 * a1[6] + 166 * a1[5] + 82 * a1[4] + 78 * a1[7] == 58176)
s.add(149 * a1[6] + 73 * a1[4] + 10 * a1[5] + 116 * a1[7] == 62478)
s.add(176 * a1[6] + 198 * a1[4] + 80 * a1[5] + 193 * a1[7] == 114069)
s.add(178 * a1[10] + 100 * a1[9] + 83 * a1[8] + 30 * a1[11] == 56170)
s.add(143 * a1[10] + 148 * (a1[8] + a1[9]) + 168 * a1[11] == 70647)
s.add(33 * a1[8] + 194 * a1[9] + 10 * a1[10] + 186 * a1[11] == 53174)
s.add(32 * a1[10] + (a1[8] << 7) + 33 * a1[9] + 152 * a1[11] == 26118)
s.add(184 * a1[14] + 115 * a1[13] + 164 * a1[12] + 29 * a1[15] == 81254)
s.add(129 * a1[13] + 35 * a1[12] + 129 * a1[14] + 165 * a1[15] == 78646)
s.add(134 * a1[13] + 54 * a1[12] + 39 * a1[14] + 18 * a1[15] == 29827)
s.add(106 * a1[14] + 133 * a1[13] + 80 * a1[12] + 43 * a1[15] == 53660)
s.add(121 * a1[18] + 187 * a1[16] + 32 * a1[17] + 2 * a1[19] == 24667)
s.add(170 * a1[17] + 66 * a1[16] + 58 * a1[18] + 36 * a1[19] == 44188)
s.add(103 * a1[16] + 120 * a1[17] + 12 * a1[18] + 175 * a1[19] == 52310)
s.add(83 * a1[16] + 92 * a1[17] + 129 * a1[18] + 143 * a1[19] == 46020)
s.add(141 * a1[22] + 54 * a1[21] + 100 * a1[20] + 122 * a1[23] == 66732)
s.add(85 * a1[21] + 171 * a1[20] + 69 * a1[22] + 7 * a1[23] == 46817)
s.add((a1[22] << 7) + 197 * a1[20] + 48 * a1[21] + 132 * a1[23] == 83536)
s.add(181 * a1[21] + 101 * a1[20] + 79 * a1[22] + 144 * a1[23] == 80587)
s.add(149 * a1[24] + 187 * a1[25] + 24 * a1[26] + 142 * a1[27] == 92687)
s.add(49 * a1[26] + 86 * a1[25] + 118 * a1[24] + 50 * a1[27] == 49285)
s.add(164 * a1[26] + 170 * a1[25] + 70 * a1[24] + 193 * a1[27] == 92711)
s.add(95 * a1[26] + 198 * a1[25] + 96 * a1[24] + a1[27] == 61904)
s.add(114 * a1[28] + 179 * a1[29] + 37 * a1[30] + 163 * a1[31] == 53864)
s.add(132 * a1[30] + 94 * a1[29] + 49 * a1[28] + 99 * a1[31] == 36980)
s.add(150 * a1[30] + 113 * a1[29] + 43 * a1[28] + (a1[31] << 7) == 40829)
s.add(115 * a1[30] + 139 * a1[29] + a1[28] + 44 * a1[31] == 22448)
if s.check() == sat: #检查当前添加的所有约束条件是否存在满足的解,sat为满足
m = s.model()
# 按顺序打印所有变量的值
result = [m[a1[i]].as_long() % 0xff for i in range(32)]
print(','.join([hex(x) for x in result]))
#0x1d,0x7f,0xea,0x8e,0x9b,0x89,0x91,0xf3,0x50,0xe6,0x91,0x18,0xd7,0x32,0xb3,0xfc,0x49,0xc1,0x26,0x79,0xa8,0x71,0x62,0xf6,0xa1,0xd4,0x2d,0xc5,0xe4,0x3b,0x59,0x56
因为有移位操作,所以用BitVec,并且是16位二进制


浙公网安备 33010602011771号