XYCTF2025 Reverse 方向复现
CrackMe
ida 打开看到 WinMain 函数,同时注意到有一个 TlsCallback_0 函数
1
2
3
4
5
6
>VOID NTAPI TlsCallback(PVOID DllHandle, DWORD dwReason, PVOID Reserved) {
//DllHandle:对于 exe 是进程句柄,对于 dll 是模块句柄;dwReason:回调原因;Reserved:保留参数,一般用不到
if (dwReason == DLL_PROCESS_ATTACH) {
MessageBoxA(NULL, "TlsCallback Triggered!", "Info", 0);
}
>}
点进 WinMain,有反调试,先打断点运行起来用 ScyllaHide 去一下反调;很多传入了多个参数的 sub 函数点进去看发现没有什么重要信息,找到 sub_xxxAC00(v39),点进去后同样注意到 v6 = sub_7FF7AD959470;
sub_xxx8770 里面像是一个消息处理器,根据不同的参数值分发不同的处理逻辑
而 Tlscallback 这边,进入 sub_xxx2370
switch 下有五个 case,分别对应不同的参数,case0 里面带点进 sub_xxxF280 挺复杂的,留到后面看,case1、case2、case3 没什么东西,case4 和 case5 有可疑的函数
case4 的 sub_xxxD010 里面有个异或
1 |
|
解出来是 flag{
,由此可知此处是校验 flag 的格式
case5 的 sub_xxxC850 里看到了 CRC 校验
爆破出输入
1 |
|
所以这里得到部分flag moshui_
case0 的 sub_xxxF280
里面依旧有 crc ,不过这里的 crc 不是进行校验,而是使用输入的前 5 个字节(“flag{“)加上 {} 内部的前 7 个字节(v7 数组里面)生成了两个四字节的密钥(v6[0]和v6[2]),再加上另外连个直接赋值的即可得到完整密钥
1 |
|
密钥 :0x42b2986c,0x12345678,0xe40ecf0a,0x89abcdef
同时在里面发现sub_xxx1500sub_7FF7AD961500(v6, *(_QWORD *)(v5 + 8) + 12LL, 16LL, v8);
分析后可知 a1 传入的是原始密钥
sub_xxx1FF0 :将128位原始密钥扩展为52个16位轮密钥(符合IDEA标准)
sub_xxx1640 :IDEA 加密
分组长度:64 位
密钥长度:128 位
共 8 轮 + 1 次输出变换
每轮用到了三种不同的运算:
模 2¹⁶ 加法(模加)
模 2¹⁶ + 1 乘法(模乘)
按位异或 XOR
主要特点包括使用模乘(模65537)和模加(模65536)运算,以及大量的异或操作
1 |
|
密文在 v7 数组中:
解出第二部分:
1 |
|
所以第一部分的 moshui_ 和第二部分的 build_this_block 拼接起来就是完整的 flag{moshui_build_this_block}
Dragon
附件是一个 .bc 文件,用 file Dragon.bc
查看文件类型
得到Dragon.bc: LLVM IR bitcode
继续往下编译 clang Dragon.bc -o Dragon
然后 ida 打开编译好的 Dragon 文件,main 函数
读取输入后进入一个加密函数(CRC 64),最后又字符串比较,动调提取出密文
1 |
|
密文有 96 字节 -> 12 个 64 位整数,每两个字符为一组,生成一个 64 位的 CRC 值,与密文对比
因此可以得出输入是 24 个字符,需要爆破 12 组的 2 字符组合
加密函数
1 |
|
解密脚本:
1 |
|
flag 为flag{LLVM_1s_Fun_Ri9h7?}
WARMUP
附件是一个 .vbs
文件,是一种包含用Visual Basic Scripting Edition编写的脚本代码的文本文件,不需要编译,直接由Windows Script Host (WSH)解释执行
在网上看到相关处理方式是:用 vscode 或者 其他文本编辑器打开,把开头的 Execute 改为 wscript.echo
直接运行即可得到源代码
Execute 是用来执行代码
wscript.echo 的作用是将一个或多个字符串作为输出打印到控制台(或者在图形界面中弹出一个对话框)
运行后果然看到了源代码
不难看出这是一个标准的 rc4 ,
密文是 “90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4”
密钥是
“rc4key”
解密脚本
def rc4_decrypt(ciphertext_hex, key_string):
try:
ciphertext = bytes.fromhex(ciphertext_hex)
except ValueError:
return "WRONG FORMAT"
S = list(range(256))
key_length = len(key_string)
T = [ord(key_string[i % key_length]) for i in range(256)]
j = 0
for i in range(256):
j = (j + S[i] + T[i]) % 256
S[i], S[j] = S[j], S[i]
key_stream = []
i = 0
j = 0
for byte in ciphertext:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
t = (S[i] + S[j]) % 256
key_stream.append(S[t])
plaintext_bytes = bytearray()
for i in range(len(ciphertext)):
plaintext_bytes.append(ciphertext[i] ^ key_stream[i])
return plaintext_bytes.decode('utf-8', errors='ignore')
ciphertext_given = "90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4"
key = "rc4key"
decrypted_text = rc4_decrypt(ciphertext_given, key)
print(f"Flag is: {decrypted_text}")
# Flag is: flag{We1c0me_t0_XYCTF_2025_reverse_ch@lleng3_by_th3_w@y_p3cd0wn's_chall_is_r3@lly_gr3@t_&_fuN!}
题目中说 flag为flag{}包含的内容进行md5加密并用XYCTF{}包含
所以最终的 flag 为 XYCTF{5f9f46c147645dd1e2c8044325d4f93c}