xyctf复现:

一:vbs:

WScript.Echo

标准RC4:

密文:

90df4407ee093d309098d85a42be57a2979f1e51463a31e8d15e2fac4e84ea0df622a55c4ddfb535ef3e51e8b2528b826d5347e165912e99118333151273cc3fa8b2b3b413cf2bdb1e8c9c52865efc095a8dd89b3b3cfbb200bbadbf4a6cd4

密钥:

img

flag:flag{We1c0me_t0_XYCTF_2025_reverse_ch@lleng3_by_th3_w@y_p3cd0wn‘s_chall_is_r3@lly_gr3@t_&_fuN!}

二:moon

一进去没有main函数;

img

shift+F12;

img

x交叉引用,分析函数

img

img

可以猜出来是c语言里的random(seed)函数,可能是明文xor random(seed)里的其中一个随机数,可以爆破也可能是伪随机数数组对应xor

尝试找密钥

img

img

这是xor的的函数

三:Dragon:

给的是一个.bc文件查阅发现需要用clang来编译 编译完之后就可以在ida里反编译

放入ida

img

每次放入

img

分析了一下

发现就只有个crc破解所以写一个crc爆破的代码检测前几个字符flag{就好:

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
49
50
51
52
53
import itertools

# CRC-64 ECMA 多项式
POLY = 0x42F0E1EBA9EA3693

def crc64_custom(data: bytes) -> int:
crc = 0xFFFFFFFFFFFFFFFF
for b in data:
crc ^= b << 56
for _ in range(8):
if crc & (1 << 63):
crc = (crc << 1) ^ POLY
else:
crc <<= 1
crc &= 0xFFFFFFFFFFFFFFFF
return ~crc & 0xFFFFFFFFFFFFFFFF

# 你提供的 12 个 CRC-64 密文
target_crcs = [
0xDC63E34E419F7B47, 0x031EF8D4E7B2BFC6, 0x12D62FBC625FD89E,
0x83E8B6E1CC5755E8, 0xFC7BB1EB2AB665CC, 0x9382CA1B2A62D96B,
0xB1FFF8A07673C387, 0x0DA81627388E05E1, 0x9EF1E61AE8D0AAB7,
0x92783FD2E7F26145, 0x63C97CA1F56FE60B, 0x9BD3A8B043B73AAB
]

# 可见字符集(你可以限制为更小范围加快速度)
visible_chars = [chr(c) for c in range(0x20, 0x7F)]

# 保存每组2字节明文
results = []

# 开始逐个爆破
for index, crc_target in enumerate(target_crcs):
print(f"[+] 爆破第 {index + 1} 个 CRC: {crc_target:016X}")
found = False
for a, b in itertools.product(visible_chars, repeat=2):
pair = (a + b).encode()
if crc64_custom(pair) == crc_target:
print(f" -> 找到: '{a + b}'")
results.append(a + b)
found = True
break
if not found:
print(" -> ❌ 未找到匹配!")
results.append('??') # 占位符

# 拼接 flag
flag_body = ''.join(results)
final_flag = f"flag{{{flag_body}}}"

print("\n爆破完成!")
print("最终 flag =>", final_flag)

img

四lake:

一拿到打开程序一个字母一个字母的进行输出;提示我们可以能用sleep来找到主函数:

之后去ida里找

img

一直交叉引用找到了这个函数

img

动态调试发现前面的几个函数都是输出语句用的;

一直到

img

都是输出字符:下面的byte_100020090[0]是input

img

img

例如

操作 操作下标 操作数

Sub 2, 0x0c

img

这就是全部的逻辑了;先进行vm模拟,然后进行位移操作,这就是大概的逻辑

所以我们逆向的思路就是,先进行位移操作然后在进行vm爆破

img

看位移加密:

img

img

他是这个意思所以脚本是:

img

然后爆破

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
flag=[0]*len(data)
flag1=[0]*len(data)
for j in range(len(data)):
for k in range(32,127):
flag[j]=k
for i in range(0,len(table),3):
if table[i]==1:
flag[table[i+1]]+=table[i+2]
flag[table[i+1]]&=0xff
elif table[i]==2:
flag[table[i+1]]-=table[i+2]
flag[table[i+1]]&=0xff
elif table[i]==3:
flag[table[i+1]]*=table[i+2]
flag[table[i+1]]&=0xff
elif table[i]==4:
flag[table[i+1]]//=table[i+2]
flag[table[i+1]]&=0xff
elif table[i] == 5:
flag[table[i + 1]] %= table[i + 2]
flag[table[i + 1]] &= 0xff
elif table[i] == 6:
flag[table[i + 1]] &= table[i + 2]
flag[table[i + 1]] &= 0xff
elif table[i] == 7:
flag[table[i + 1]] |= table[i + 2]
flag[table[i + 1]] &= 0xff
elif table[i] == 8:
flag[table[i + 1]] ^= table[i + 2]
flag[table[i + 1]] &= 0xff
if flag[j]==s[j]:
flag1[j]=k
break
#爆破vm
for i in range(len(flag1)):
print(chr(flag1[i]),end="")

这个样子爆破

就能得到flag:

flag{L3@rn1ng_1n_0ld_sch00l_@nd_g3t_j0y}

全部代码如下:

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
49
#第一次复刻vm的逆向;
table=[0x0002, 0x0002, 0x000C, 0x0001, 0x001A, 0x0055, 0x0001, 0x0023, 0x000C, 0x0002, 0x000E, 0x0009, 0x0001, 0x001B, 0x0006, 0x0008, 0x0006, 0x0005, 0x0008, 0x0001, 0x0005, 0x0002, 0x001B, 0x000E, 0x0002, 0x0019, 0x0003, 0x0002, 0x001A, 0x0004, 0x0008, 0x0004, 0x0008, 0x0001, 0x0003, 0x000C, 0x0002, 0x000C, 0x000A, 0x0001, 0x0025, 0x0002, 0x0001, 0x0020, 0x0002, 0x0001, 0x0009, 0x000C, 0x0008, 0x001A, 0x0005, 0x0002, 0x0004, 0x000D, 0x0008, 0x0008, 0x000F, 0x0002, 0x000A, 0x000E, 0x0001, 0x0010, 0x0007, 0x0001, 0x000C, 0x0007, 0x0008, 0x0022, 0x0008, 0x0008, 0x0015, 0x000A, 0x0001, 0x0027, 0x007E, 0x0002, 0x0007, 0x0002, 0x0008, 0x000F, 0x0003, 0x0008, 0x000A, 0x000A, 0x0001, 0x0022, 0x000B, 0x0002, 0x0012, 0x0008, 0x0002, 0x0019, 0x0009, 0x0008, 0x000E, 0x0006, 0x0008, 0x0000, 0x0005, 0x0001, 0x000A, 0x0008, 0x0008, 0x001B, 0x0007, 0x0008, 0x000D, 0x0006, 0x0008, 0x000D, 0x0004, 0x0008, 0x0017, 0x000C, 0x0008, 0x0022, 0x000E, 0x0002, 0x0012, 0x0034, 0x0001, 0x0026, 0x0077]
data=[ 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]
s=[]*len(data)
for i in range(0,len(data),4):
s.append(((data[i+2]<<5)|(data[i+3]>>3))&0xff)
s.append((((data[i + 3] << 5) | (data[i] >> 3))&0xff))
s.append(((data[i ] << 5) | (data[i +1] >> 3))&0xff)
s.append(((data[i + 1] << 5) | (data[i + 2] >> 3))&0xff)#位移操作的逆向
#print(s)
flag=[0]*len(data)
flag1=[0]*len(data)
for j in range(len(data)):
for k in range(32,127):
flag[j]=k
for i in range(0,len(table),3):
if table[i]==1:
flag[table[i+1]]+=table[i+2]
flag[table[i+1]]&=0xff
elif table[i]==2:
flag[table[i+1]]-=table[i+2]
flag[table[i+1]]&=0xff
elif table[i]==3:A
flag[table[i+1]]*=table[i+2]
flag[table[i+1]]&=0xff
elif table[i]==4:
flag[table[i+1]]//=table[i+2]
flag[table[i+1]]&=0xff
elif table[i] == 5:
flag[table[i + 1]] %= table[i + 2]
flag[table[i + 1]] &= 0xff
elif table[i] == 6:
flag[table[i + 1]] &= table[i + 2]
flag[table[i + 1]] &= 0xff
elif table[i] == 7:
flag[table[i + 1]] |= table[i + 2]
flag[table[i + 1]] &= 0xff
elif table[i] == 8:
flag[table[i + 1]] ^= table[i + 2]
flag[table[i + 1]] &= 0xff
if flag[j]==s[j]:
flag1[j]=k
break
#爆破vm
for i in range(len(flag1)):
print(chr(flag1[i]),end="")