初赛

Reverse

Lesscommon

去平坦化

python deflat.py -f 1.exe –addr 0x140001000

1757124066286-747e18ca-2011-4ec7-b2ef-f38e596720f4.png

1
IDA_14002d420 = [0x4C, 0x6F, 0xAB, 0xF3, 0x13, 0x78, 0xE2, 0xF6, 0x86, 0x9D, 0x1C, 0x99, 0xDE, 0x85, 0xCC, 0x10, 0xE8, 0x28, 0xEE, 0x5, 0x92, 0x21, 0x4B, 0x34, 0x43, 0x28, 0x17, 0x3C, 0x56, 0x5B, 0x73, 0x51, 0x9F, 0x8A, 0x1D, 0xF, 0x97, 0x34, 0x2C, 0x56, 0x42, 0x9F, 0x69, 0x48, 0xA3, 0xD5, 0x8A, 0xF5]

满足v2,v4,v5 成功

1757124355832-88dc35cb-528c-4c91-845d-ab90d13ee327.png

tea

1757125310034-34b37719-75de-47cd-9e4e-530b31ba8105.png

未跑通解密

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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
def rotate_left(val, shift):
"""
循环左移函数
:param val: 要移位的32位无符号整数
:param shift: 移位位数
:return: 循环左移后的结果
"""
shift = shift & 0x1F # 确保移位位数在0-31之间(32位整数的有效移位范围)
return ((val << shift) | (val >> (32 - shift))) & 0xFFFFFFFF


def main():
# 初始密钥字节
key_bytes = bytes([0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10])

# 计算密钥字数
data_length = len(key_bytes)
v26 = (data_length + 3) // 4 # 密钥字数
if v26 == 0:
v26 = 1

# 初始化v25数组
v25 = [0] * v26

# 将密钥字节按小端序组合成字存入v25
for i in range(data_length - 1, -1, -1):
idx = i // 4
v25[idx] = ((v25[idx] << 8) | key_bytes[i]) & 0xFFFFFFFF

# 初始化状态数组(子密钥)
state_length = v26 # 状态数组长度与v25相同
state = [0] * state_length
state[0] = 0x694CEF8C
for j in range(1, state_length):
state[j] = (state[j - 1] + 0x54C9C307) & 0xFFFFFFFF

# 密钥扩展过程
v14 = 0
v15 = 0
v17 = 0
v16 = 0
k_1 = 3 * max(state_length, v26) # 循环次数

for k in range(k_1):
# 第一轮混合
state_val = state[v17]
temp = (v14 + v15 + state_val) & 0xFFFFFFFF
v6 = k ^ rotate_left(temp, 3)
state[v17] = v6
v15 = v6

# 第二轮混合
v25_val = v25[v16]
temp2 = (v14 + v15 + v25_val) & 0xFFFFFFFF
shift_amount = (v6 & 0xFF) + (v14 & 0xFF)
v7 = rotate_left(temp2, shift_amount & 0x1F)
v25[v16] = v7
v14 = v7

# 更新索引
v17 = (v17 + 1) % state_length
v16 = (v16 + 1) % v26

# 将state作为子密钥用于解密
subkeys = state

# 加密数据
enc_data = bytes([
0x4C, 0x6F, 0xAB, 0xF3, 0x13, 0x78, 0xE2, 0xF6,
0x86, 0x9D, 0x1C, 0x99, 0xDE, 0x85, 0xCC, 0x10,
0xE8, 0x28, 0xEE, 0x05, 0x92, 0x21, 0x4B, 0x34,
0x43, 0x28, 0x17, 0x3C, 0x56, 0x5B, 0x73, 0x51,
0x9F, 0x8A, 0x1D, 0x0F, 0x97, 0x34, 0x2C, 0x56,
0x42, 0x9F, 0x69, 0x48, 0xA3, 0xD5, 0x8A, 0xF5
])

# 将加密数据分成8字节块
blocks = []
for i in range(0, len(enc_data), 8):
blocks.append(enc_data[i:i + 8])

def decrypt_block(block, subkeys):
"""
解密单个数据块
:param block: 8字节加密数据块
:param subkeys: 子密钥数组
:return: 解密后的8字节数据块
"""
# 将8字节块分成左右两部分(各4字节)
left = (block[0] << 24) | (block[1] << 16) | (block[2] << 8) | block[3]
right = (block[4] << 24) | (block[5] << 16) | (block[6] << 8) | block[7]

# 根据子密钥数量调整轮数
rounds = min(12, len(subkeys) // 2)

# Feistel网络解密(反向操作)
for round in range(rounds, 0, -1): # 反向轮次
sk1 = subkeys[(2 * round) % len(subkeys)] # 第一子密钥
sk2 = subkeys[(2 * round + 1) % len(subkeys)] # 第二子密钥

# Feistel轮函数操作
temp = rotate_left((sk2 + right) & 0xFFFFFFFF, left & 0x1F)
new_left = right ^ temp # 异或操作

temp2 = rotate_left((sk1 + new_left) & 0xFFFFFFFF, right & 0x1F)
new_right = left ^ temp2 # 异或操作

# 更新左右部分
left = new_left
right = new_right

# 最终处理:减去初始子密钥
left = (left - subkeys[0]) & 0xFFFFFFFF
right = (right - subkeys[1 % len(subkeys)]) & 0xFFFFFFFF

# 将32位整数转换回字节
left_bytes = [(left >> 24) & 0xFF, (left >> 16) & 0xFF, (left >> 8) & 0xFF, left & 0xFF]
right_bytes = [(right >> 24) & 0xFF, (right >> 16) & 0xFF, (right >> 8) & 0xFF, right & 0xFF]

return bytes(left_bytes + right_bytes)

# 解密所有数据块
decrypted_blocks = []
for block in blocks:
decrypted_blocks.append(decrypt_block(block, subkeys))

# 合并所有解密后的块
decrypted_data = b''.join(decrypted_blocks)

# 去除PKCS#7填充
padding_len = decrypted_data[-1]
decrypted_data = decrypted_data[:-padding_len]

# 输出解密结果
print(decrypted_data.decode('utf-8'))


if __name__ == '__main__':
main()

Prover

1
2
IDA_6085 = [0x3, 0x5, 0x9, 0xB, 0xD]
IDA_608a = [0xA5, 0x5C, 0xC3, 0x96, 0x3E, 0xD7, 0x21]

Z3约束求解

Crypto

RSA.iso

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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re
from math import gcd

def inv_mod(a: int, m: int) -> int:
a %= m
return pow(a, -1, m)

def long_to_bytes(n: int) -> bytes:
if n == 0:
return b"\x00"
out = []
while n:
out.append(n & 0xff)
n >>= 8
return bytes(reversed(out))


txt = open("output.txt", "r", encoding="utf-8", errors="ignore").read()
a = int(re.search(r'a\s*=\s*(\d+)', txt).group(1))
r = int(re.search(r'r\s*=\s*(\d+)', txt).group(1))
n = int(re.search(r'\bn\s*=\s*(\d+)', txt).group(1))
c = int(re.search(r'\bc\s*=\s*(\d+)', txt).group(1))
e = 65537

pre, giftblock = txt.split("gift =", 1)

def parse_fp2_scalar(s: str):
s = s.strip()
if "*i" not in s:
return (0, int(s))
s2 = s.replace(" ", "").replace("+i", "+1*i").replace("-i", "-1*i")
m = re.match(r'^(-?\d+)\*i([+-]?\d+)$', s2)
if not m:
raise ValueError(f"无法解析 Fp2 标量: {s}")
return (int(m.group(1)), int(m.group(2)))

def parse_point(pair):
x = parse_fp2_scalar(pair[0])
y = parse_fp2_scalar(pair[1])
return (x, y)

pair_re = re.compile(r'\(\s*([^)]+?)\s*,\s*([^)]+?)\s*\)')

pairs_pre = pair_re.findall(pre)
if len(pairs_pre) < 2:
raise ValueError("未解析到 P、Q。")
P_xy = parse_point(pairs_pre[0])
Q_xy = parse_point(pairs_pre[1])

pairs_gift = pair_re.findall(giftblock)
if len(pairs_gift) % 2 != 0:
raise ValueError("gift 点对数量异常。")
gift_points = []
for i in range(0, len(pairs_gift), 2):
gift_points.append((parse_point(pairs_gift[i]), parse_point(pairs_gift[i+1])))


def lcm(a, b): return a // gcd(a, b) * b
L = 1
for t in range(1, 256):
L = lcm(L, t)
p = (pow(2, a) * r * L) - 1
MOD = p


class Fp2:
__slots__ = ("a", "b")
def __init__(self, a, b):
self.a = a % MOD
self.b = b % MOD
def __add__(self, other): return Fp2(self.a + other.a, self.b + other.b)
def __sub__(self, other): return Fp2(self.a - other.a, self.b - other.b)
def __neg__(self): return Fp2(-self.a, -self.b)
def __mul__(self, other):
ai = (self.a * other.b + self.b * other.a) % MOD
br = (self.b * other.b - self.a * other.a) % MOD
return Fp2(ai, br)
def inv(self):
den = (self.a * self.a + self.b * self.b) % MOD
invden = pow(den, -1, MOD)
return Fp2(-self.a * invden, self.b * invden)
def __truediv__(self, other): return self * other.inv()
def __pow__(self, e):
e = int(e)
out = Fp2(0, 1)
base = self
while e:
if e & 1: out = out * base
base = base * base
e >>= 1
return out
def __eq__(self, other):
return (self.a - other.a) % MOD == 0 and (self.b - other.b) % MOD == 0
def __repr__(self): return f"{self.a}*i+{self.b}"

def F(e):
if isinstance(e, Fp2): return e
return Fp2(0, e)

def from_tuple(t): return Fp2(t[0], t[1])


class ECPoint:
__slots__ = ("x", "y", "inf", "E")
def __init__(self, E, x=None, y=None, inf=False):
self.E = E; self.x = x; self.y = y; self.inf = inf
@staticmethod
def infinity(E): return ECPoint(E, None, None, True)
def copy(self): return ECPoint.infinity(self.E) if self.inf else ECPoint(self.E, self.x, self.y, False)

class EllipticCurve:
__slots__ = ("A", "B")
def __init__(self, A, B):
self.A = F(A); self.B = F(B)
def add_with_slope(self, P: ECPoint, Q: ECPoint):
if P.inf: return Q.copy(), None
if Q.inf: return P.copy(), None
if P.x == Q.x:
if (P.y + Q.y) == Fp2(0,0):
return ECPoint.infinity(self), None
lam = (F(3)*P.x*P.x + self.A) / (F(2)*P.y)
else:
lam = (Q.y - P.y) / (Q.x - P.x)
if P.x == Q.x and P.y == Q.y:
x3 = lam*lam - F(2)*P.x
y3 = lam*(P.x - x3) - P.y
else:
x3 = lam*lam - P.x - Q.x
y3 = lam*(P.x - x3) - P.y
return ECPoint(self, x3, y3, False), lam
def add(self, P, Q): return self.add_with_slope(P, Q)[0]
def mul(self, P: ECPoint, k: int):
if P.inf or k == 0: return ECPoint.infinity(self)
if k < 0: return self.mul(ECPoint(self, P.x, -P.y, False), -k)
R = ECPoint.infinity(self); B = P.copy()
while k:
if k & 1: R = self.add(R, B)
B = self.add(B, B)
k >>= 1
return R
def miller_raw(self, P: ECPoint, Q: ECPoint, r: int):
if P.inf or Q.inf: return Fp2(0,1)
f = Fp2(0,1)
T = P.copy()
bits = bin(r)[3:]
for b in bits:
R, lam = self.add_with_slope(T, T)
if lam is None:
g = Fp2(0,1)
else:
nu = T.y - lam*T.x
num = (Q.y - lam*Q.x - nu)
den = (Q.x - R.x)
g = num / den
f = (f*f) * g
T = R
if b == '1':
R, lam = self.add_with_slope(T, P)
if lam is None:
g = Fp2(0,1)
else:
nu = T.y - lam*T.x
num = (Q.y - lam*Q.x - nu)
den = (Q.x - R.x)
g = num / den
f = f * g
T = R
return f
def weil_pairing_red(self, P: ECPoint, Q: ECPoint, r: int):
fPQ = self.miller_raw(P, Q, r)
fQP = self.miller_raw(Q, P, r)
val = fPQ / fQP
if r % 2 == 1: val = val * Fp2(0, -1)
return val ** ((MOD*MOD - 1)//r)

# ----------------- 初始化 P0, Q0 -----------------
E0 = EllipticCurve(0, 1)
P0 = ECPoint(E0, from_tuple(P_xy[0]), from_tuple(P_xy[1]), False)
Q0 = ECPoint(E0, from_tuple(Q_xy[0]), from_tuple(Q_xy[1]), False)
co_r = (p + 1) // r
P_r = E0.mul(P0, co_r)
Q_r = E0.mul(Q0, co_r)
w_base = E0.weil_pairing_red(P_r, Q_r, r)


table = {}
val = Fp2(0,1)
for j in range(r):
key = (val.a % r, val.b % r)
if key not in table: # 避免重复
table[key] = j
val = val * w_base

inv_2a_mod_r = inv_mod(pow(2, a, r), r)
xs_le = []

for idx, (phiP_xy, phiQ_xy) in enumerate(gift_points):
x1 = from_tuple(phiP_xy[0]); y1 = from_tuple(phiP_xy[1])
x2 = from_tuple(phiQ_xy[0]); y2 = from_tuple(phiQ_xy[1])
S1 = y1*y1 - x1*x1*x1
S2 = y2*y2 - x2*x2*x2
dx = x1 - x2
if dx == Fp2(0,0):
raise RuntimeError(f"退化 x1==x2 at gift {idx}")
A1 = (S1 - S2) / dx
B1 = S1 - A1*x1
E1 = EllipticCurve(A1, B1)
phiP = ECPoint(E1, x1, y1, False)
phiQ = ECPoint(E1, x2, y2, False)
phiP_r = E1.mul(phiP, co_r)
phiQ_r = E1.mul(phiQ, co_r)
w1 = E1.weil_pairing_red(phiP_r, phiQ_r, r)
key = (w1.a % r, w1.b % r)
j = table.get(key)
if j is None:
cur = Fp2(0,1); j = None
for t in range(r):
cur_key = (cur.a % r, cur.b % r)
if cur_key == key:
j = t; break
cur = cur * w_base
if j is None:
raise RuntimeError(f"离散对数失败 at gift {idx}")
x_byte = (j * inv_2a_mod_r) % r
if not (1 <= x_byte <= 255):
raise RuntimeError(f"异常字节 {x_byte} 不在 1..255")
xs_le.append(x_byte)


pp = sum(b << (8*i) for i, b in enumerate(xs_le))
if n % pp != 0:
raise RuntimeError("pp 不能整除 n")
qq = n // pp
phi_n = (pp - 1) * (qq - 1)
d = inv_mod(e, phi_n)
m = pow(c, d, n)
flag = long_to_bytes(m)

print("r =", r, "a =", a)
print("pp bits:", pp.bit_length())
print("pp | n ?", n % pp == 0)
print("flag =", flag.decode("utf-8", errors="ignore"))

1757131678002-6851b30d-f3b0-4ac3-b933-d30f1161009e.png

应急响应

siem

虚拟机系统密码:wazuh-user/wazuh

Web地址:http://IP:80 账号密码admin/admin

ssh wazuh-user@192.168.198.142

http://192.168.198.142:80

1757133180852-4fe20de1-b420-444b-b792-dbde4033e1c0.png

更新: 2025-09-06 14:45:25
原文: https://www.yuque.com/chaye-apqbl/vsc85q/iquz26q5yg7lvr1s


http://example.com/2026/01/19/WP/2025/陇剑杯报名/初赛/
Author
chaye
Posted on
January 19, 2026
Licensed under