上海网络安全大赛2025"磐石行动"re

w1n9 Lv1

My-key

两个标志位反调试,改条件绕过

image-20250806194749626
image-20250806194749626

获取输入并验证的最上层函数在这里

image-20250806194830809
image-20250806194830809

调试到加密函数,key,iv,cipher是被硬编码到程序里的,资源id分别为201,202,203,有两种方法可以获得,1是直接解包MFC程序,在资源文件string里可以看到;2是工具Restorator

image-20250806195153997
image-20250806195153997

image-20250806195212937
image-20250806195212937

加密逻辑在这里

image-20250806195251653
image-20250806195251653

逻辑就是先通过RC6 CBC加密模式 PKCS#7的填充模式来加密输入,然后base64编码

脚本如下(我的RC6库不知道为什么导入一直不成功,网上工具也用不了,这里是直接在代码里嵌入了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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import base64
import struct

class RC6:
def __init__(self, key, rounds=20, word_size=32):
self.rounds = rounds
self.word_size = word_size
self.mod = 2 ** word_size
self.block_size = 16
self.S = self._expand_key(key)

def _expand_key(self, key):
if len(key) < 16:
pad_len = 16 - len(key)
key = key + bytes([pad_len] * pad_len)
elif len(key) > 16:
key = key[:16]

P = 0xB7E15163
Q = 0x9E3779B9
c = 4
L = [0] * c

for i in range(c):
word_bytes = key[i*4:(i+1)*4]
L[i] = struct.unpack('<I', word_bytes)[0]

t = 2 * (self.rounds + 2)
S = [P]
for i in range(1, t):
S.append((S[i-1] + Q) % self.mod)

A = B = 0
i = j = 0
v = 3 * max(t, c)

for _ in range(v):
A = S[i] = self._rotl((S[i] + A + B) % self.mod, 3, self.word_size)
B = L[j] = self._rotl((L[j] + A + B) % self.mod, (A + B) % self.word_size, self.word_size)
i = (i + 1) % t
j = (j + 1) % c

return S

@staticmethod
def _rotl(x, n, w):
n %= w
return ((x << n) & ((1 << w) - 1)) | (x >> (w - n))

@staticmethod
def _rotr(x, n, w):
n %= w
return (x >> n) | ((x << (w - n)) & ((1 << w) - 1))

def decrypt_block(self, block):
if len(block) != self.block_size:
raise ValueError(f"Block must be {self.block_size} bytes")

A, B, C, D = struct.unpack('<4I', block)
C = (C - self.S[2*self.rounds+3]) % self.mod
A = (A - self.S[2*self.rounds+2]) % self.mod

for i in range(self.rounds, 0, -1):
A, B, C, D = D, A, B, C
u = self._rotl((D * (2*D + 1)) % self.mod, 5, self.word_size)
t = self._rotl((B * (2*B + 1)) % self.mod, 5, self.word_size)
C = self._rotr((C - self.S[2*i+1]) % self.mod, t % self.word_size, self.word_size) ^ u
A = self._rotr((A - self.S[2*i]) % self.mod, u % self.word_size, self.word_size) ^ t

D = (D - self.S[1]) % self.mod
B = (B - self.S[0]) % self.mod
return struct.pack('<4I', A, B, C, D)

def decrypt_cbc(self, ciphertext, iv):
blocks = [ciphertext[i:i+self.block_size] for i in range(0, len(ciphertext), self.block_size)]
plaintext = b''
prev = iv

for block in blocks:
decrypted_block = self.decrypt_block(block)
plaintext_block = bytes(a ^ b for a, b in zip(decrypted_block, prev))
plaintext += plaintext_block
prev = block

return plaintext

def main():
key = b"FSZ36f3vU8s5"
iv = b"WcE4Bbm4kHYQsAcX"
ciphertext_b64 = "RKCTaz+fty1J2qsz4DI6t9bmMiLBxqFrpI70fU4IMemczIlM+z1IoVQobIt1MbXF"
ciphertext = base64.b64decode(ciphertext_b64)

rc6 = RC6(key, rounds=20)
raw_plaintext = rc6.decrypt_cbc(ciphertext, iv)

pad_len = raw_plaintext[-1]
if 1 <= pad_len <= 16:
license_key = raw_plaintext[:-pad_len].decode('utf-8')
print(license_key)
else:
print(raw_plaintext.decode('utf-8', errors='replace'))

if __name__ == "__main__":
main()

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

EasyRe

第二次处理函数

image-20250806195549713
image-20250806195549713

ai一把梭了,前半段是个KSA和PRGA,类似于RC4的加密流程,不过有点不一样,sub_140001070是个二次处理,每个字节与0x42异或后,再与前一个字节异或(第一个字节除外)

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
ciphertext = [
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
]

def reverse_final_transformation(data):
length = len(data)
result = list(data)
for i in range(length - 1, 0, -1):
result[i] ^= result[i - 1]
for i in range(length):
result[i] ^= 0x42
return result

def decrypt_rc4_like_stream(encrypted_data):
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]
i = 0
j = 0
decrypted_bytes = []
for idx, encrypted_byte in enumerate(encrypted_data):
i = (i + 1) % 256
if i % 3 == 0:
k = (S[3 * i % 256] + j) % 256
else:
k = (S[i] + j) % 256
j = k
S[i], S[j] = S[j], S[i]
extra_value = (i * j) % 16
intermediate_value = ((encrypted_byte >> 3) | (encrypted_byte << 5)) & 0xFF
decrypted_value = (intermediate_value - extra_value) & 0xFF
key_stream_byte = S[(S[i] + S[j]) % 256]
original_byte = decrypted_value ^ key_stream_byte
decrypted_bytes.append(original_byte)
return bytes(decrypted_bytes)

intermediate_ciphertext = reverse_final_transformation(ciphertext)
flag_bytes = decrypt_rc4_like_stream(intermediate_ciphertext)

print(flag_bytes.decode('ascii'))

#flag{Th1s_1s_A_Fl4w3d_Crypt0}

花指令有五个(main两个,加密函数三个),不过形式都是一样的,都是构造永真永假跳转,直接main函数下断点通过动调去除,得到主要的加密逻辑

image-20250806202521662
image-20250806202521662

结构非常的清晰,就是一个tea加密,密文密钥直接给了,脚本如下

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
import struct

key = [2, 0, 2, 2]
ciphertext = [
0x569A1C45, 0xEF2C6A10, 0xFB440BD6, 0x5797F41D,
0x523FF2C3, 0x48337CD9, 0x3616AC2D, 0x6B6312D
]

DELTA = 0x768CAB2E
NUM_ROUNDS = 32
MOD = 2**32

def decrypt_tea_block(v4, v5, K):
v6 = 0

v6 = (-NUM_ROUNDS * DELTA) & (MOD - 1)

for _ in range(NUM_ROUNDS):
v5 = (v5 - (v6 ^ (v4 + v6) ^ (16 * v4 + K[2]) ^ ((v4 >> 5) + K[3]))) & (MOD - 1)
v4 = (v4 - (v6 ^ (v5 + v6) ^ (16 * v5 + K[0]) ^ ((v5 >> 5) + K[1]))) & (MOD - 1)
v6 = (v6 + DELTA) & (MOD - 1)

return v4, v5

def decrypt_all_blocks(ciphertext, key):
plaintext = []

for i in range(4):
v4 = ciphertext[2*i]
v5 = ciphertext[2*i+1]

decrypted_v4, decrypted_v5 = decrypt_tea_block(v4, v5, key)

plaintext.append(decrypted_v4)
plaintext.append(decrypted_v5)

return plaintext

def main():
decrypted_words = decrypt_all_blocks(ciphertext, key)

flag_bytes = b''
for word in decrypted_words:
flag_bytes += struct.pack('<I', word)

try:
print(flag_bytes.decode('utf-8'))
except UnicodeDecodeError:
print(flag_bytes.hex())

if __name__ == "__main__":
main()


# flag{b3d06a66f8aa86e3e6390f615e389e55}
  • 标题: 上海网络安全大赛2025"磐石行动"re
  • 作者: w1n9
  • 创建于 : 2025-08-07 12:03:58
  • 更新于 : 2025-09-03 22:05:29
  • 链接: https://vv1n9.github.io/2025/08/07/上海网络安全大赛2025”磐石行动“re/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
上海网络安全大赛2025"磐石行动"re