XYCTF2025RE(部分解)
CTF
XYCTF RE(部分解)
签到
vbs逆向,放到visual里面提取文本,拿正则表达式匹配一下,得到代码逻辑,就是一个rc4加密,key="rc4key"密文:”90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4“
正则得到的结果:
MsgBox "Dear CTFER. Have fun in XYCTF 2025!"
flag = InputBox("Enter the FLAG:", "XYCTF")
wefbuwiue = "90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4" ' \x-165E\x-7B18\x-5141\x-1866\x-7BAEC4\x-1A76\x-5F1B\x-507A\x-1845\x-6C1A\x-6163\x-1044\x-771B\x-727F\x-1A7B\x-5218\x-4065\x-1A77\x-491A\x-5F43\x-1A44\x-7011\x-4377
qwfe = "rc4key"
' \x-1B40\x-511B\x-5B73\x-1A70\x-7119\x-657CRC4\x-1A76\x-5F1B\x-507A\x-1A79\x-421A\x-6A50
Function RunRC(sMessage, strKey)
Dim kLen, i, j, temp, pos, outHex
Dim s(255), k(255)
' \x-1A78\x-621B\x-5874\x-1A74\x-691B\x-507A\x-166E?
kLen = Len(strKey)
For i = 0 To 255
s(i) = i
kssage, pos, 1)) ' \x-1967\x-7119\x-6979\x-1974\x-76BFSCII\x-1A5C\x-7B19\x-6F7A
ciphe = s((s(i) + s(j)) Mod 256) Xor plainChar
outHex = outHex & Right("0" & Hex(cipherByte), 2)
Next
RunRC = outHex
End Runction
' \x-1B48\x-4417\x-5574\x-1750\x-7E17\x-4418\x-416F
If LCase(RunRC(flag, qwfe)) = LCase(wefbuwiue) Then
MsgBox "Congratulatie
MsgBox "Wrong flag."
End Ifdef rc4_crypt(data: bytes, key: bytes) -> bytes:
S = list(range(256))
j = 0
# KSA
for i in range(256):
j = (j + S[i] + key[i % len(key)]) % 256
S[i], S[j] = S[j], S[i]
# PRGA
i = j = 0
result = bytearray()
for byte in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
K = S[(S[i] + S[j]) % 256]
result.append(byte ^ K)
return bytes(result)
# 密文(十六进制字符串)
cipher_hex = "90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4"
# 转换为字节
cipher_bytes = bytes.fromhex(cipher_hex)
# RC4 解密
key = b"rc4key"
plain_bytes = rc4_crypt(cipher_bytes, key)
# 输出 flag
flag = plain_bytes.decode('utf-8', errors='ignore') # 忽略一些不可打印字符
print("FLAG:", flag)
在线解密网站也可以
得到flag:flag{We1c0me_t0_XYCTF_2025_reverse_ch@lleng3_by_th3_w@y_p3cd0wn's_chall_is_r3@lly_gr3@t_&_fuN!}
dragon
bc文件逆向,先用clang编译成可执行exe文件,ida64位打开
crc64算法
import itertools
def crc64(data: bytes) -> int:
poly = 0x42F0E1EBA9EA3693
crc = 0xFFFFFFFFFFFFFFFF
for b in data:
crc ^= b << 56
for _ in range(8):
if (crc & (1 << 63)) == 0:
crc <<= 1
else:
crc = (crc << 1) ^ poly
crc &= 0xFFFFFFFFFFFFFFFF
return ~crc & 0xFFFFFFFFFFFFFFFF
raw = bytes([
0x47, 0x7B, 0x9F, 0x41, 0x4E, 0xE3, 0x63, 0xDC, 0xC6, 0xBF,
0xB2, 0xE7, 0xD4, 0xF8, 0x1E, 0x03, 0x9E, 0xD8, 0x5F, 0x62,
0xBC, 0x2F, 0xD6, 0x12, 0xE8, 0x55, 0x57, 0xCC, 0xE1, 0xB6,
0xE8, 0x83, 0xCC, 0x65, 0xB6, 0x2A, 0xEB, 0xB1, 0x7B, 0xFC,
0x6B, 0xD9, 0x62, 0x2A, 0x1B, 0xCA, 0x82, 0x93, 0x87, 0xC3,
0x73, 0x76, 0xA0, 0xF8, 0xFF, 0xB1, 0xE1, 0x05, 0x8E, 0x38,
0x27, 0x16, 0xA8, 0x0D, 0xB7, 0xAA, 0xD0, 0xE8, 0x1A, 0xE6,
0xF1, 0x9E, 0x45, 0x61, 0xF2, 0xE7, 0xD2, 0x3F, 0x78, 0x92,
0x0B, 0xE6, 0x6F, 0xF5, 0xA1, 0x7C, 0xC9, 0x63, 0xAB, 0x3A,
0xB7, 0x43, 0xB0, 0xA8, 0xD3, 0x9B
])
targets = [int.from_bytes(raw[i:i+8], 'little') for i in range(0, len(raw), 8)]
charset = [chr(i) for i in range(0, 256)]
flag = ""
found_all = True
max_blocks = len(targets)
for idx, target in enumerate(targets[:max_blocks]):
found = False
for a, b in itertools.product(charset, repeat=2):
data = bytes([ord(a), ord(b)])
if crc64(data) == target:
print(f"[{idx}] Found: {a}{b} -> {hex(target)}")
flag += a + b
found = True
break
if not found:
print(f"[{idx}] Not found for target: {hex(target)}")
found_all = False
break
print("\n Recovered flag so far:")
print(flag)
if found_all:
print(" 全部匹配成功!")
else:
print(" 有部分未匹配,可能需调整字节序或字符集。")
flag:flag{LLVM_1s_Fun_Ri9h7?}
moon
pyd文件逆向,搜索字串定位到加密部分,分析得到密文(16进制数字):”426b87abd0ceaa3c58761bbb0172606dd8ab064491a2a76af9a93e1ae56fa84206a2f7“
然后直接调用pyd文件里面的异或加密函数解密,密钥我是直接爆破的
import moon
for i in range(2000000):
xor_result = moon.xor_crypt(i,b'Bk\x87\xab\xd0\xce\xaa<Xv\x1b\xbb\x01r`m\xd8\xab\x06D\x91\xa2\xa7j\xf9\xa9>\x1a\xe5o\xa8B\x06\xa2\xf7')
if xor_result[:4] == b'flag':
break
print(xor_result)lake
ida打开,直接上动调,定位到主要逻辑
这是第一部分的加密逻辑,就是flag[index]和inc进行加减乘除等运算
进入sub_1000019B0函数
很清晰的逻辑
直接上z3解密
from z3 import *
# 加密后的数据
enc = [
0x4A, 0xAB, 0x9B, 0x1B, 0x61, 0xB1, 0xF3, 0x32, 0xD1, 0x8B,
0x73, 0xEB, 0xE9, 0x73, 0x6B, 0x22, 0x81, 0x83, 0x23, 0x31,
0xCB, 0x1B, 0x22, 0xFB, 0x25, 0xC2, 0x81, 0x81, 0x73, 0x22,
0xFA, 0x03, 0x9C, 0x4B, 0x5B, 0x49, 0x97, 0x87, 0xDB, 0x51
]
# 创建符号变量 (每个字节为 8 位向量)
s = [BitVec(f's_{i}', 8) for i in range(40)]
solver = Solver()
# 添加每 4 字节的约束条件
for i in range(0, 40, 4):
s0, s1, s2, s3 = s[i], s[i+1], s[i+2], s[i+3]
e0, e1, e2, e3 = enc[i], enc[i+1], enc[i+2], enc[i+3]
# 核心约束条件 (使用逻辑右移 LShR)
solver.add( ((s1 << 3) | LShR(s2, 5)) & 0xFF == e0 )
solver.add( ((s2 << 3) | LShR(s3, 5)) & 0xFF == e1 )
solver.add( ((s3 << 3) | LShR(s0, 5)) & 0xFF == e2 )
solver.add( ((s0 << 3) | LShR(s1, 5)) & 0xFF == e3 )
# 求解并输出结果
if solver.check() == sat:
model = solver.model()
decrypted = bytes([model.eval(s[i]).as_long() for i in range(40)])
# 将解密结果转换为16进制字符串
hex_result = ',0x'.join(format(byte, '0x') for byte in decrypted)
print("解密结果(16进制):", hex_result)
else:
print("未找到有效解")得到的结果:0x63,0x69,0x55,0x73,0x66,0x4c,0x36,0x3e,0x7d,0x7a,0x31,0x6e,0x64,0x5d,0x2e,0x6d,0x66,0x30,0x30,0x64,0x5f,0x79,0x63,0x64,0x30,0x24,0xb8,0x50,0x40,0x6e,0x64,0x5f,0x69,0x33,0x89,0x6b,0x6a,0x32,0xf0,0xfb
第一部分解密脚本:
#include <iostream>
int main()
{
int enc[40] = { 0x63,0x69,0x55,0x73,0x66,0x4c,0x36,0x3e,0x7d,0x7a,0x31,0x6e,0x64,0x5d,0x2e,0x6d,0x66,0x30,0x30,0x64,0x5f,0x79,0x63,0x64,0x30,0x24,0xb8,0x50,0x40,0x6e,0x64,0x5f,0x69,0x33,0x89,0x6b,0x6a,0x32,0xf0,0xfb
};
int encc[123] = { 0x2,0x2,0xc,0x1,0x1a,0x55,0x1,0x23,0xc,0x2,0xe,0x9,0x1,0x1b,0x6,0x8,0x6,0x5,0x8,0x1,0x5,0x2,0x1b,0xe,0x2,0x19,0x3,0x2,0x1a,0x4,0x8,0x4,0x8,0x1,0x3,0xc,0x2,0xc,0xa,0x1,0x25,0x2,0x1,0x20,0x2,0x1,0x9,0xc,0x8,0x1a,0x5,0x2,0x4,0xd,0x8,0x8,0xf,0x2,0xa,0xe,0x1,0x10,0x7,0x1,0xc,0x7,0x8,0x22,0x8,0x8,0x15,0xa,0x1,0x27,0x7e,0x2,0x7,0x2,0x8,0xf,0x3,0x8,0xa,0xa,0x1,0x22,0xb,0x2,0x12,0x8,0x2,0x19,0x9,0x8,0xe,0x6,0x8,0x0,0x5,0x1,0xa,0x8,0x8,0x1b,0x7,0x8,0xd,0x6,0x8,0xd,0x4,0x8,0x17,0xc,0x8,0x22,0xe,0x2,0x12,0x34,0x1,0x26,0x77 };
for (int i = 0; i < 123; i += 3) {
int switch_ = encc[i];
int index = encc[i + 1];
int inc = encc[i + 2];
switch (switch_) {
case 1:
enc[index] -= inc;
break;
case 2:
enc[index] += inc;
break;
case 3:
enc[index] /= inc;
break;
case 4:
enc[index] *= inc;
break;
case 5:
{
int c = 0;
for (;;) {
if (c % inc == enc[index])break;
}
enc[index] = c;
break;
}
case 6:
{
int b = 0;
for (;;) {
if ((b & inc) == enc[index])break;
}
enc[index] = b;
break;
}
case 7: {
int a = 0;
for (;;) {
if ((a | inc) == enc[index])break;
a++;
}
enc[index] = a;
break;
}
case 8:
enc[index] ^= inc;
break;
}
}
for (int i = 0; i < 40; i++) {
printf("%c", enc[i]);
}
}得到flag:flag{L3@rn-ng_1n_0ld_sch00b_@nd_g3x_j0y}
有些部分有点问题,手动改一下,修正后的结果:flag{L3@rn1ng_1n_0ld_sch00l_@nd_g3t_j0y}