磐石行动2025初赛逆向wp

磐石行动初赛2025逆向wp

My-key

有好几处反调试,可以交叉引用

img

img

调试时改zf

img

sub_1400040A0是主函数位置,sub_140003A40是一个主要加密函数,动调的时候可以看到密钥的使用

img

sub_140003840是一个自定义的类似tea加密的函数,其实是rc6的加密方式, v37[j] = v36[j] ^ *v8;这里是对key的xor

img

密钥可以通过动调得到,但在函数开头的img我们可以通过ResourceHacker工具找到img

201, “FSZ36f3vU8s5”

202, “WcE4Bbm4kHYQsAcX”

203, “RKCTaz+fty1J2qsz4DI6t9bmMiLBxqFrpI70fU4IMemczIlM+z1IoVQobIt1MbXF”

异或的是WcE4Bbm4kHYQsAcX,密钥FSZ36f3vU8s5,密文RKCTaz+fty1J2qsz4DI6t9bmMiLBxqFrpI70fU4IMemczIlM+z1IoVQobIt1MbXF

这里给出解密代码,由于最后一步是base64加密,这里先将密文用base64解密得到hex,再进行后续的rc6解密

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import struct

w = 32
r = 20

def ROTL(x, y):
return ((x << (y & (w-1))) | (x >> (w - (y & (w-1))))) & 0xFFFFFFFF

def ROTR(x, y):
return ((x >> (y & (w-1))) | (x << (w - (y & (w-1))))) & 0xFFFFFFFF

S_char = bytes([
0xE0, 0xAA, 0x68, 0x73, 0x7D, 0xCD, 0x54, 0x72, 0xE2, 0xAA,
0xD4, 0xFA, 0x41, 0x0C, 0x03, 0x9C, 0x51, 0xCA, 0x72, 0x5D,
0xF4, 0x53, 0xCA, 0xAD, 0x25, 0xEF, 0x26, 0x13, 0x8F, 0x14,
0xC1, 0x48, 0x40, 0x26, 0x1C, 0x0D, 0x6D, 0x91, 0x32, 0x16,
0xF8, 0xFC, 0x4F, 0xB5, 0xF9, 0x5F, 0x2C, 0x97, 0xEC, 0x64,
0x34, 0x6B, 0xB3, 0xFD, 0xB4, 0x89, 0xBE, 0xA5, 0x2D, 0x51,
0x04, 0x37, 0x18, 0x85, 0xB3, 0x88, 0x0D, 0xB8, 0x52, 0x05,
0x8E, 0xCD, 0x8C, 0xD8, 0xB3, 0x4F, 0x74, 0x81, 0xA6, 0xE2,
0xDF, 0x35, 0x68, 0x40, 0xA5, 0x1A, 0x49, 0x53, 0x05, 0x7C,
0x44, 0x53, 0xFA, 0xCB, 0x4F, 0xDB, 0xD8, 0xDC, 0x04, 0x31,
0x22, 0xF9, 0xD6, 0xB9, 0x6E, 0x1F, 0x53, 0xE5, 0x4E, 0xB6,
0x30, 0xAB, 0xA0, 0x4B, 0x7B, 0xC8, 0x7E, 0xB1, 0x21, 0x98,
0xDC, 0xAA, 0xFB, 0xB0, 0xC2, 0x72, 0x39, 0xD8, 0x11, 0xFE,
0x81, 0x7C, 0xE0, 0x6E, 0xBC, 0x99, 0x68, 0x6A, 0xA1, 0xBA,
0xA9, 0xED, 0x8E, 0x15, 0x5B, 0x20, 0x58, 0x2A, 0xCC, 0xB1,
0x85, 0xC9, 0xE3, 0x0B, 0x21, 0xD7, 0x7B, 0xBF, 0x5B, 0x5D,
0xC2, 0x76, 0xEB, 0x64, 0xD8, 0xC8, 0xE3, 0x44, 0x5F, 0xC7,
0xDF, 0xD9, 0x8D, 0x23, 0x1C, 0x54
])
S = [struct.unpack("<I", S_char[i*4:i*4+4])[0] for i in range(len(S_char)//4)]

def rc6_decrypt_block(block):
A, B, C, D = block
C = (C - S[2*r+3]) & 0xFFFFFFFF
A = (A - S[2*r+2]) & 0xFFFFFFFF
for i in range(r, 0, -1):
A, B, C, D = D, A, B, C
t = ROTL(B * (2*B + 1) & 0xFFFFFFFF, 5)
u = ROTL(D * (2*D + 1) & 0xFFFFFFFF, 5)
C = ROTR((C - S[2*i+1]) & 0xFFFFFFFF, t) ^ u
A = ROTR((A - S[2*i]) & 0xFFFFFFFF, u) ^ t
D = (D - S[1]) & 0xFFFFFFFF
B = (B - S[0]) & 0xFFFFFFFF
return [A, B, C, D]

data = bytes([
0x44,0xa0,0x93,0x6b,0x3f,0x9f,0xb7,0x2d,
0x49,0xda,0xab,0x33,0xe0,0x32,0x3a,0xb7,
0xd6,0xe6,0x32,0x22,0xc1,0xc6,0xa1,0x6b,
0xa4,0x8e,0xf4,0x7d,0x4e,0x08,0x31,0xe9,
0x9c,0xcc,0x89,0x4c,0xfb,0x3d,0x48,0xa1,
0x54,0x28,0x6c,0x8b,0x75,0x31,0xb5,0xc5
])

xor_key = b"WcE4Bbm4kHYQsAcX"

plain = b""
for i in range(0, 48, 16):
block = struct.unpack("<4I", data[i:i+16])
decrypted = rc6_decrypt_block(block)
plain += struct.pack("<4I", *decrypted)


plain = bytearray(plain)
for j in range(16):
plain[j] ^= xor_key[j]
for j in range(16, 48):
plain[j] ^= data[j-16]

print(plain.decode(errors='ignore'))

flag{68f25cc8-1a9f-40e8-ac3b-a85982a52f8f}

cooki

有花指令,看汇编,在爆红的地方按d,这个E1是垃圾指令,nop就行,后续有好几处e1,都直接nop掉之后再选中主函数进行编译就能得到主加密函数

img

加密函数就是一个tea加密

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
37
38
39
40
41
42
43
44
45
46
47
48
49
import struct

a2 = [2, 0, 2, 2]
step = 0x768CAB2E
v7 = [
0x569A1C45, 0xEF2C6A10,
0xFB440BD6, 0x5797F41D,
0x523FF2C3, 0x48337CD9,
0x3616AC2D, 0x06B6312D
]


def decrypt_block(v4_enc, v5_enc):
v4 = v4_enc
v5 = v5_enc

for k in range(32):
current_step = 32 - k
v6 = (-step * current_step) & 0xFFFFFFFF

term1 = v6
term2 = (v4 + v6) & 0xFFFFFFFF
term3 = (16 * v4 + a2[2]) & 0xFFFFFFFF
term4 = ((v4 >> 5) + a2[3]) & 0xFFFFFFFF
delta2 = (term1 ^ term2 ^ term3 ^ term4) & 0xFFFFFFFF
v5_old = (v5 - delta2) & 0xFFFFFFFF

term1_d1 = v6
term2_d1 = (v5_old + v6) & 0xFFFFFFFF
term3_d1 = (16 * v5_old + a2[0]) & 0xFFFFFFFF
term4_d1 = ((v5_old >> 5) + a2[1]) & 0xFFFFFFFF
delta1 = (term1_d1 ^ term2_d1 ^ term3_d1 ^ term4_d1) & 0xFFFFFFFF
v4_old = (v4 - delta1) & 0xFFFFFFFF

v4, v5 = v4_old, v5_old
return v4, v5


flag_bytes = b""
for i in range(4):
v4_enc = v7[2 * i]
v5_enc = v7[2 * i + 1]
v4_orig, v5_orig = decrypt_block(v4_enc, v5_enc)
flag_bytes += struct.pack("<I", v4_orig) + struct.pack("<I", v5_orig)

try:
print("Flag:", flag_bytes.decode("ascii"))
except UnicodeDecodeError:
print("解密字节:", flag_bytes.hex())

flag{b3d06a66f8aa86e3e6390f615e389e55}

EasyRE

这题没管反调试,可以直接看加密逻辑,自定义的rc4加密算法,最后与密文比较

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def ror3(x, n):
return ((x >> n) | (x << (8 - n))) & 0xFF

target = [
0x93, 0xF9, 0x8D, 0x92, 0x52, 0x57, 0xD9, 0x05, 0xC6, 0x0A, 0x50, 0xC7, 0xDB, 0x4F, 0xCB, 0xD8,
0x5D, 0xA6, 0xB9, 0x40, 0x95, 0x70, 0xE7, 0x9A, 0x37, 0x72, 0x4D, 0xEF, 0x57
]

T = []
prev = 0
for x in target:
t = (x ^ prev) ^ 0x42
T.append(t)
prev = x

# Step 2: Simulate KSA
S = list(range(256))
j = 0
for i in range(256):
j = (j + S[i] - 7 * (i // 7) + i + 4919) % 256
S[i], S[j] = S[j], S[i]

# Step 3: PRGA - collect r and k for 29 bytes
i = 0
j = 0
ks = []
rs = []

for _ in range(29):
i = (i + 1) % 256
if i % 3 == 0:
j = (j + S[3 * i % 256]) % 256
else:
j = (j + S[i]) % 256

old_si = S[i]
old_sj = S[j]
S[i], S[j] = S[j], S[i] # swap

r = (i * j) % 16
k = S[(old_si + old_sj) % 256] # 修正:k = S[old_S[i] + old_S[j]]

rs.append(r)
ks.append(k)

# Step 4: Recover input
flag = []
for idx in range(29):
t_val = T[idx]
r_val = rs[idx]
k_val = ks[idx]

x = ror3(t_val, 3) # undo ROL3
input_byte = (x - r_val) & 0xFF
input_byte ^= k_val

flag.append(input_byte)

flag_str = ''.join(chr(b) for b in flag)
print("Flag:", flag_str)

Flag: flag{Th1s_1s_A_Fl4w3d_Crypt0}


磐石行动2025初赛逆向wp
https://j1nxem-o.github.io/2025/08/16/磐石行动2025初赛逆向wp/
作者
J1NXEM
发布于
2025年8月16日
更新于
2025年8月23日
许可协议